mirror of
https://github.com/tornadocash/tornado-core.git
synced 2025-01-03 18:35:20 +01:00
batch merkle tree creation
This commit is contained in:
parent
65fd0202c5
commit
ea51af1512
@ -91,6 +91,51 @@ contract('MerkleTreeWithHistory', async accounts => {
|
|||||||
// console.log(root)
|
// console.log(root)
|
||||||
assert.equal(root, calculated_root)
|
assert.equal(root, calculated_root)
|
||||||
})
|
})
|
||||||
|
it('creation odd elements count', async () => {
|
||||||
|
const elements = [12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
for(const [i, el] of Object.entries(elements)) {
|
||||||
|
await tree.update(i, el)
|
||||||
|
}
|
||||||
|
|
||||||
|
const storage = new JsStorage()
|
||||||
|
hasher = new MimcHacher()
|
||||||
|
const batchTree = new MerkleTree(
|
||||||
|
prefix,
|
||||||
|
storage,
|
||||||
|
hasher,
|
||||||
|
levels,
|
||||||
|
zeroValue,
|
||||||
|
elements
|
||||||
|
);
|
||||||
|
for(const [i, el] of Object.entries(elements)) {
|
||||||
|
const pathViaConstructor = await batchTree.path(i)
|
||||||
|
const pathViaUpdate = await tree.path(i)
|
||||||
|
pathViaConstructor.should.be.deep.equal(pathViaUpdate)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('creation even elements count', async () => {
|
||||||
|
const elements = [12, 13, 14, 15, 16, 17]
|
||||||
|
for(const [i, el] of Object.entries(elements)) {
|
||||||
|
await tree.update(i, el)
|
||||||
|
}
|
||||||
|
|
||||||
|
const storage = new JsStorage()
|
||||||
|
hasher = new MimcHacher()
|
||||||
|
const batchTree = new MerkleTree(
|
||||||
|
prefix,
|
||||||
|
storage,
|
||||||
|
hasher,
|
||||||
|
levels,
|
||||||
|
zeroValue,
|
||||||
|
elements
|
||||||
|
);
|
||||||
|
for(const [i, el] of Object.entries(elements)) {
|
||||||
|
const pathViaConstructor = await batchTree.path(i)
|
||||||
|
const pathViaUpdate = await tree.path(i)
|
||||||
|
pathViaConstructor.should.be.deep.equal(pathViaUpdate)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#insert', async () => {
|
describe('#insert', async () => {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
|
|
||||||
// const AwaitLock = require('await-lock');
|
|
||||||
|
|
||||||
class MerkleTree {
|
class MerkleTree {
|
||||||
|
|
||||||
constructor(prefix, storage, hasher, n_levels, zero_value) {
|
constructor(prefix, storage, hasher, n_levels, zero_value, defaultElements) {
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.hasher = hasher;
|
this.hasher = hasher;
|
||||||
@ -18,7 +16,28 @@ class MerkleTree {
|
|||||||
current_zero_value.toString(),
|
current_zero_value.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// this.lock = new AwaitLock();
|
if (defaultElements) {
|
||||||
|
let level = 0
|
||||||
|
defaultElements.forEach((element, i) => {
|
||||||
|
this.storage.put(MerkleTree.element_to_key(prefix, element), i.toString())
|
||||||
|
this.storage.put(MerkleTree.index_to_key(prefix, level, i), element)
|
||||||
|
})
|
||||||
|
level++
|
||||||
|
let numberOfElementInRow = Math.ceil(defaultElements.length / 2)
|
||||||
|
for (level; level <= this.n_levels; level++) {
|
||||||
|
for(let i = 0; i < numberOfElementInRow; i++) {
|
||||||
|
const leftKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i)
|
||||||
|
const rightKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i + 1)
|
||||||
|
|
||||||
|
const left = this.storage.get(leftKey)
|
||||||
|
const right = this.storage.get_or_element(rightKey, this.zero_values[level - 1])
|
||||||
|
|
||||||
|
const subRoot = this.hasher.hash(null, left, right);
|
||||||
|
this.storage.put(MerkleTree.index_to_key(prefix, level, i), subRoot)
|
||||||
|
}
|
||||||
|
numberOfElementInRow = Math.max(Math.ceil(numberOfElementInRow / 2), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static index_to_key(prefix, level, index) {
|
static index_to_key(prefix, level, index) {
|
||||||
@ -121,7 +140,6 @@ class MerkleTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update(index, element, update_log_index) {
|
async update(index, element, update_log_index) {
|
||||||
// await this.lock.acquireAsync();
|
|
||||||
try {
|
try {
|
||||||
//console.log(`updating ${index}, ${element}`);
|
//console.log(`updating ${index}, ${element}`);
|
||||||
class UpdateTraverser {
|
class UpdateTraverser {
|
||||||
@ -198,8 +216,8 @@ class MerkleTree {
|
|||||||
|
|
||||||
const root = await this.root();
|
const root = await this.root();
|
||||||
//console.log(`updated root ${root}`);
|
//console.log(`updated root ${root}`);
|
||||||
} finally {
|
} catch(e) {
|
||||||
// this.lock.release();
|
console.error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +236,6 @@ class MerkleTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async rollback(updates) {
|
async rollback(updates) {
|
||||||
// await this.lock.acquireAsync();
|
|
||||||
try {
|
try {
|
||||||
const update_log_key = MerkleTree.update_log_to_key(this.prefix);
|
const update_log_key = MerkleTree.update_log_to_key(this.prefix);
|
||||||
const update_log_index = await this.storage.get(update_log_key);
|
const update_log_index = await this.storage.get(update_log_key);
|
||||||
@ -228,8 +245,8 @@ class MerkleTree {
|
|||||||
|
|
||||||
await this.update(update_element_log.index, update_element_log.old_element, update_log_index - i - 1);
|
await this.update(update_element_log.index, update_element_log.old_element, update_log_index - i - 1);
|
||||||
}
|
}
|
||||||
} finally {
|
} catch (e) {
|
||||||
// this.lock.release();
|
console.error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,8 +269,8 @@ class MerkleTree {
|
|||||||
if (await this.root() != root) {
|
if (await this.root() != root) {
|
||||||
throw new Error(`could not rollback to root ${root}`);
|
throw new Error(`could not rollback to root ${root}`);
|
||||||
}
|
}
|
||||||
} finally {
|
} catch (e) {
|
||||||
// this.lock.release();
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@ class JsStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
put(key, value) {
|
put(key, value) {
|
||||||
|
if (key === undefined || value === undefined) {
|
||||||
|
throw Error('key or value is undefined')
|
||||||
|
}
|
||||||
this.db[key] = value;
|
this.db[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user