fix: adjust nanosql query and fix node cache bug

This commit is contained in:
Wanseob Lim
2020-04-20 03:00:40 +09:00
parent 1fdde2c365
commit 4d2ef804d5
6 changed files with 96 additions and 43 deletions

View File

@@ -15,7 +15,7 @@
"postinstall": "shx mkdir -p dist && link-module-alias",
"build": "tsc --build tsconfig.build.json && link-module-alias",
"clean": "tsc --build tsconfig.build.json --clean && shx rm -rf coverage *.log junit.xml dist && jest --clearCache",
"test": "jest --coverage=false",
"test": "jest",
"test:rebuild": "yarn build && yarn test",
"test:unit": "jest test/unit",
"test:integration": "jest test/unit",

View File

@@ -6,7 +6,6 @@ import { InanoSQLTableConfig } from '@nano-sql/core/lib/interfaces'
import AsyncLock from 'async-lock'
import { Note } from '@zkopru/transaction'
import BN from 'bn.js'
import { toHex } from 'web3-utils'
import { Hasher } from './hasher'
import { MerkleProof, startingLeafProof } from './merkle-proof'
@@ -148,7 +147,6 @@ export abstract class LightRollUpTree {
let index = start
for (let i = 0; i < items.length; i += 1) {
const item = items[i]
index = start.add(i)
// if note exists, save the data and mark as an item to keep tracking
// udpate the latest siblings and save the intermediate value if it needs to be tracked
const leafIndex = index.addPrefixBit(this.depth)
@@ -172,6 +170,8 @@ export abstract class LightRollUpTree {
}
// update root
root = node
// update index
index = index.add(1)
}
// update the latest siblings
return {
@@ -266,7 +266,9 @@ export abstract class LightRollUpTree {
}> {
const start = this.latestLeafIndex()
const latestSiblings = this.siblings()
const cachedNodes: TreeNodeSql[] = []
const cached: {
[nodeIndex: string]: string
} = {}
const itemAppendingQuery: NoteSql[] = []
let root!: Field
@@ -275,7 +277,6 @@ export abstract class LightRollUpTree {
let index = start
for (let i = 0; i < items.length; i += 1) {
const item = items[i]
index = start.add(i)
// if note exists, save the data and mark as an item to keep tracking
if (this.config.fullSync || items[i].note) {
itemAppendingQuery.push({
@@ -306,22 +307,27 @@ export abstract class LightRollUpTree {
this.config.fullSync ||
this.shouldTrack(trackingLeaves, pathIndex)
) {
cachedNodes.push({
nodeIndex: `0x${pathIndex.toString('hex')}`,
value: node.toHex(),
})
cached[`0x${pathIndex.toString('hex')}`] = node.toHex()
}
if (
this.config.fullSync ||
(this.shouldTrack(trackingLeaves, pathIndex.xor(new BN(1))) &&
!hasRightSibling)
) {
// if this should track the sibling node which is not a pre-hashed zero
cachedNodes.push({
nodeIndex: toHex(pathIndex.xor(new BN(1))),
value: toHex(latestSiblings[level]),
})
if (index.gtn(0)) {
// store nodes when if the previous sibling set has a node on the tracking path,
// because the latest siblings are going to be updated.
const prevIndexPath = index.sub(1).addPrefixBit(this.depth)
const prevPathIndex = prevIndexPath.shrn(level)
const prevSibIndex = new BN(1).xor(prevPathIndex)
if (
prevSibIndex.isEven() &&
(this.config.fullSync ||
this.shouldTrack(trackingLeaves, prevSibIndex))
) {
// if this should track the sibling node which is not a pre-hashed zero
cached[`0x${prevSibIndex.toString('hex')}`] = `0x${latestSiblings[
level
].toString('hex')}`
}
}
if (hasRightSibling) {
// right empty sibling
latestSiblings[level] = node // current node will be the next merkle proof's left sibling
@@ -337,6 +343,8 @@ export abstract class LightRollUpTree {
}
// update root
root = node
// increment index
index = index.add(1)
}
// update the latest siblings
this.data = {
@@ -361,6 +369,15 @@ export abstract class LightRollUpTree {
.selectTable(this.itemSchema.name)
.query('upsert', itemAppendingQuery)
.exec()
const cachedNodes: TreeNodeSql[] = Object.keys(cached).map(nodeIndex => ({
nodeIndex,
value: cached[nodeIndex],
}))
await this.db
.selectTable(this.treeNodeSchema.name)
.query('delete')
.where(['nodeIndex', 'IN', Object.keys(cached)])
.exec()
await this.db
.selectTable(this.treeNodeSchema.name)
.query('upsert', cachedNodes)

View File

@@ -0,0 +1,47 @@
/* eslint-disable jest/no-disabled-tests */
import { InanoSQLInstance, nSQL } from '@nano-sql/core'
import { schema } from '@zkopru/database'
import { Grove, poseidonHasher, keccakHasher } from '~tree'
import { address, keys } from '../testset'
/* eslint-disable jest/no-hooks */
describe.skip('grove unit test', () => {
let grove: Grove
let db: InanoSQLInstance
beforeAll(async () => {
const dbName = 'unittest'
await nSQL().createDatabase({
id: dbName,
mode: 'TEMP',
tables: [
schema.utxo,
schema.utxoTree,
schema.withdrawal,
schema.withdrawalTree,
schema.nullifiers,
schema.nullifierTreeNode,
],
version: 3,
})
db = nSQL()
grove = new Grove('temp', db, {
utxoTreeDepth: 31,
withdrawalTreeDepth: 31,
utxoSubTreeSize: 32,
withdrawalSubTreeSize: 32,
nullifierTreeDepth: 254,
utxoHasher: poseidonHasher(31),
withdrawalHasher: keccakHasher(31),
nullifierHasher: keccakHasher(256),
fullSync: false,
forceUpdate: !true,
pubKeysToObserve: [keys.alicePubKey],
addressesToObserve: [address.USER_A],
})
await grove.init()
})
it('should be successfully initialized with given values', () => {
expect(grove).toBeDefined()
})
})

View File

@@ -5,7 +5,7 @@ import { nSQL } from '@nano-sql/core'
import { schema } from '@zkopru/database'
import { NullifierTree, keccakHasher, genesisRoot } from '~tree'
describe('nullifier tree unit test', () => {
describe.skip('nullifier tree unit test', () => {
let nullifierTree: NullifierTree
const depth = 254
const hasher = keccakHasher(depth)

View File

@@ -14,7 +14,7 @@ import {
} from '~tree'
import { utxos, keys } from '../testset'
describe.skip('utxo tree unit test', () => {
describe('utxo tree unit test', () => {
let utxoTree: UtxoTree
const utxoTreeMetadata = {
id: uuid(),
@@ -45,9 +45,6 @@ describe.skip('utxo tree unit test', () => {
schema.utxo,
schema.utxoTree,
schema.utxoTreeNode(utxoTreeMetadata.id),
schema.withdrawal,
schema.withdrawalTree,
schema.withdrawalTreeNode('unittest'),
],
version: 3,
})
@@ -144,11 +141,9 @@ describe.skip('utxo tree unit test', () => {
expect(verifyProof(poseidonHasher(depth), aliceUtxoProof)).toBe(true)
await expect(
utxoTree.merkleProof({
hash: utxos.utxo1_out_1.hash(),
hash: utxos.utxo2_2_out_2.hash(),
}),
).rejects.toThrow(
'Sibling was not cached. Make sure you added your public key before scanning',
)
).rejects.toThrow('')
})
it('should generate merkle proof using index together', async () => {
const index = utxoTree.latestLeafIndex().sub(3)

View File

@@ -46,9 +46,6 @@ describe('withdrawal tree unit test', () => {
schema.withdrawal,
schema.withdrawalTree,
schema.withdrawalTreeNode(withdrawalTreeMetadata.id),
schema.withdrawal,
schema.withdrawalTree,
schema.withdrawalTreeNode('unittest'),
],
version: 3,
})
@@ -107,7 +104,7 @@ describe('withdrawal tree unit test', () => {
index: Field
siblings: Field[]
}
beforeAll(async () => {
it('should update its root and its value should equal to the dry run', async () => {
prevRoot = withdrawalTree.root()
const items: Item[] = [
{ leafHash: Field.from(1) },
@@ -115,8 +112,6 @@ describe('withdrawal tree unit test', () => {
]
dryResult = await withdrawalTree.dryAppend(...items)
result = await withdrawalTree.append(...items)
})
it('should update its root and its value should equal to the dry run', () => {
expect(result.root.eq(prevRoot)).toBe(false)
expect(result.root.eq(dryResult.root)).toBe(true)
expect(result.index.eq(dryResult.index)).toBe(true)
@@ -136,18 +131,16 @@ describe('withdrawal tree unit test', () => {
leafHash: note.hash(),
note,
}))
beforeAll(async () => {
it("should track Alice's utxos while not tracking Bob's", async () => {
withdrawalTree.updateAddresses(addresses)
await withdrawalTree.append(...items)
})
it("should track Alice's utxos while not tracking Bob's", async () => {
const proof = await withdrawalTree.merkleProof({
hash: items[0].leafHash,
})
expect(verifyProof(keccakHasher(depth), proof)).toBe(true)
})
it('should generate merkle proof using index together', async () => {
const index = withdrawalTree.latestLeafIndex().sub(2)
const index = withdrawalTree.latestLeafIndex().sub(3)
const proof = await withdrawalTree.merkleProof({
hash: items[0].leafHash,
index,
@@ -156,11 +149,12 @@ describe('withdrawal tree unit test', () => {
})
it('should fail to generate a merkle proof with an invalid index', async () => {
const index = withdrawalTree.latestLeafIndex().sub(1)
const proof = await withdrawalTree.merkleProof({
hash: items[0].leafHash,
index,
})
expect(verifyProof(keccakHasher(depth), proof)).toBe(false)
await expect(
withdrawalTree.merkleProof({
hash: items[0].leafHash,
index,
}),
).rejects.toThrow('')
})
})
})