Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rocksdb: update storage format #530

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 20 additions & 22 deletions lib/merkle-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ class NodeQueue {
class MerkleTreeBatch {
constructor (tree) {
this.fork = tree.fork
this.batchId = tree.batchId
this.roots = [...tree.roots]
this.length = tree.length
this.ancestors = tree.length
Expand Down Expand Up @@ -219,7 +218,7 @@ class MerkleTreeBatch {

for (let i = 0; i < this.nodes.length; i++) {
const node = this.nodes[i]
writeBatch.putTreeNode(this.batchId, node)
writeBatch.putTreeNode(node)
}

return writeBatch.flush()
Expand All @@ -230,14 +229,14 @@ class MerkleTreeBatch {
// change. Will only happen on user error so mostly to prevent that.

if (this.ancestors < this.treeLength) {
writeBatch.deleteTreeNodeRange(this.batchId, this.ancestors, this.treeLength)
writeBatch.deleteTreeNodeRange(this.ancestors, this.treeLength)

const head = this.ancestors * 2
const ite = flat.iterator(head - 2)

while (true) {
if (ite.contains(head) && ite.index < head) {
writeBatch.deleteTreeNode(this.batchId, ite.index)
writeBatch.deleteTreeNode(ite.index)
}
if (ite.offset === 0) break
ite.parent()
Expand Down Expand Up @@ -418,9 +417,8 @@ class ByteSeeker {
}

module.exports = class MerkleTree {
constructor (storage, batchId, roots, fork, signature, prologue) {
constructor (storage, roots, fork, signature, prologue) {
this.storage = storage
this.batchId = batchId
this.crypto = crypto
this.fork = fork
this.roots = roots
Expand Down Expand Up @@ -468,7 +466,7 @@ module.exports = class MerkleTree {
const readBatch = this.storage.createReadBatch()

for (let i = 0; i < indexes.length; i++) {
roots[i] = readBatch.getTreeNode(this.batchId, indexes[i], true)
roots[i] = readBatch.getTreeNode(indexes[i], true)
}

readBatch.tryFlush()
Expand Down Expand Up @@ -510,7 +508,7 @@ module.exports = class MerkleTree {
const readBatch = this.storage.createReadBatch()

for (let i = 0; i < indexes.length; i++) {
roots[i] = readBatch.getTreeNode(this.batchId, indexes[i], false)
roots[i] = readBatch.getTreeNode(indexes[i], false)
}

readBatch.tryFlush()
Expand All @@ -523,14 +521,14 @@ module.exports = class MerkleTree {
}

get (index, error = true, readBatch = null) {
if (readBatch) return readBatch.getTreeNode(this.batchId, index, error)
if (readBatch) return readBatch.getTreeNode(index, error)

return this.storage.getTreeNode(this.batchId, index, error)
return this.storage.getTreeNode(index, error)
}

clear () {
const readBatch = this.storage.createWriteBatch()
readBatch.deleteTreeNodeRange(this.batchId, 0, this.length)
readBatch.deleteTreeNodeRange(0, this.length)

this.truncated = true
this.truncateTo = 0
Expand Down Expand Up @@ -661,7 +659,7 @@ module.exports = class MerkleTree {

let cnt = 0
// TODO: we could prop use a read batch here and do this in blocks of X for perf
while (!ite.contains(head) && !(await this.storage.hasTreeNode(this.batchId, ite.index, false))) {
while (!ite.contains(head) && !(await this.storage.hasTreeNode(ite.index, false))) {
cnt++
ite.parent()
}
Expand Down Expand Up @@ -691,20 +689,20 @@ module.exports = class MerkleTree {
return getByteOffset(this, index, null)
}

static async open (storage, batchId, opts = {}) {
const length = typeof opts.length === 'number' ? opts.length : await autoLength(storage, batchId)
static async open (storage, opts = {}) {
const length = typeof opts.length === 'number' ? opts.length : await autoLength(storage)

const roots = []
for (const index of flat.fullRoots(2 * length)) {
roots.push(await storage.getTreeNode(batchId, index, true))
roots.push(await storage.getTreeNode(index, true))
}

return new MerkleTree(storage, batchId, roots, opts.fork || 0, opts.signature || null, opts.prologue || null)
return new MerkleTree(storage, roots, opts.fork || 0, opts.signature || null, opts.prologue || null)
}
}

async function getNodeSize (tree, index, readBatch) {
return (await readBatch.getTreeNode(tree.batchId, index, true)).size
async function getNodeSize (index, readBatch) {
return (await readBatch.getTreeNode(index, true)).size
}

async function getByteOffset (tree, index, readBatch) {
Expand Down Expand Up @@ -754,7 +752,7 @@ function getByteRange (tree, index, readBatch) {
if (readBatch === null) readBatch = tree.storage.createReadBatch()

const offset = tree.byteOffset(index, readBatch)
const size = getNodeSize(tree, index, readBatch)
const size = getNodeSize(index, readBatch)

const result = Promise.all([offset, size])

Expand Down Expand Up @@ -1007,7 +1005,7 @@ function upgradeProof (tree, batch, node, seek, from, to, subTree, p) {
if (p.node === null && p.seek === null && ite.contains(subTree)) {
blockAndSeekProof(tree, batch, node, seek, subTree, ite.index, p)
} else {
p.upgrade.push(batch.getTreeNode(tree.batchId, ite.index, true))
p.upgrade.push(batch.getTreeNode(ite.index, true))
}
}
ite.parent()
Expand Down Expand Up @@ -1099,8 +1097,8 @@ function parentNode (crypto, index, a, b) {
return { index, size: a.size + b.size, hash: crypto.parent(a, b) }
}

async function autoLength (storage, batchId) {
const node = await storage.peakLastTreeNode(batchId)
async function autoLength (storage) {
const node = await storage.peakLastTreeNode()
if (!node) return 0

return flat.rightSpan(node.index) / 2 + 1
Expand Down
5 changes: 2 additions & 3 deletions test/merkle-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,10 +690,9 @@ async function create (t, length = 0, dir) {
const dkey = b4a.alloc(32)

const storage = db.get(dkey)
if (!await storage.open()) await storage.create({})
if (!await storage.open()) await storage.create({ key: b4a.alloc(32) })

const batchId = 0
const tree = await Tree.open(storage, batchId)
const tree = await Tree.open(storage)

t.teardown(() => tree.close())

Expand Down
Loading