sets seem to be working
This commit is contained in:
parent
1dc4f01371
commit
5c12a926fc
packages/common
@ -34,7 +34,6 @@ export const leadingZerosOnHash = async (key: string): Promise<number> => {
|
||||
}
|
||||
|
||||
const spliceIn = <T>(array: T[], item: T, index: number): T[] => {
|
||||
// const spliceIndex = Math.max(index, 0)
|
||||
return [...array.slice(0, index), item, ...array.slice(index)]
|
||||
}
|
||||
|
||||
@ -64,10 +63,20 @@ export class MST {
|
||||
return new MST(blockstore, cid, node, zeros)
|
||||
}
|
||||
|
||||
static async load(blockstore: IpldStore, cid: CID): Promise<MST> {
|
||||
static async load(
|
||||
blockstore: IpldStore,
|
||||
cid: CID,
|
||||
zeros?: number,
|
||||
): Promise<MST> {
|
||||
const node = await blockstore.get(cid, nodeSchema)
|
||||
|
||||
return new MST(blockstore, cid, node, 0) // @TODO calculate 0s
|
||||
if (!zeros) {
|
||||
const firstLeaf = node.find((entry) => check.is(entry, leafPointer))
|
||||
if (!firstLeaf) {
|
||||
throw new Error('not a valid mst node: no leaves')
|
||||
}
|
||||
zeros = await leadingZerosOnHash(firstLeaf[0])
|
||||
}
|
||||
return new MST(blockstore, cid, node, zeros)
|
||||
}
|
||||
|
||||
async put(): Promise<CID> {
|
||||
@ -77,6 +86,9 @@ export class MST {
|
||||
|
||||
async set(key: string, value: CID): Promise<CID> {
|
||||
const keyZeros = await leadingZerosOnHash(key)
|
||||
if (keyZeros > 1) {
|
||||
console.log('GREATER THAN 1')
|
||||
}
|
||||
// it belongs in this layer
|
||||
if (keyZeros === this.zeros) {
|
||||
const index = this.insertIndex(key)
|
||||
@ -87,18 +99,52 @@ export class MST {
|
||||
return this.put()
|
||||
} else {
|
||||
// else we need to investigate the subtree
|
||||
const subTree = await MST.load(this.blockstore, prevNode)
|
||||
const subTree = await MST.load(
|
||||
this.blockstore,
|
||||
prevNode,
|
||||
this.zeros - 1,
|
||||
)
|
||||
// we try to split the subtree around the key
|
||||
const splitSubTree = await subTree.splitAround(key)
|
||||
const newNode = this.node.slice(0, index - 1)
|
||||
if (splitSubTree[0]) newNode.push(splitSubTree[0])
|
||||
newNode.push(value)
|
||||
newNode.push([key, value])
|
||||
if (splitSubTree[1]) newNode.push(splitSubTree[1])
|
||||
newNode.push(...this.node.slice(index))
|
||||
this.node = newNode
|
||||
return this.put()
|
||||
}
|
||||
} else if (keyZeros < this.zeros) {
|
||||
// it belongs on a lower layer
|
||||
const index = this.insertIndex(key)
|
||||
const prevNode = this.node[index - 1]
|
||||
if (check.is(prevNode, treePointer)) {
|
||||
// if entry before is a tree, we add it to that tree
|
||||
const subTree = await MST.load(
|
||||
this.blockstore,
|
||||
prevNode,
|
||||
this.zeros - 1,
|
||||
)
|
||||
const newSubTreeCid = await subTree.set(key, value)
|
||||
this.node[index - 1] = newSubTreeCid
|
||||
return this.put()
|
||||
} else {
|
||||
// else we need to create the subtree for it to go in
|
||||
const subTree = await MST.create(this.blockstore, this.zeros - 1)
|
||||
const newSubTreeCid = await subTree.set(key, value)
|
||||
this.node = spliceIn(this.node, newSubTreeCid, index)
|
||||
return this.put()
|
||||
}
|
||||
} else {
|
||||
// it belongs in a different layer
|
||||
// it belongs on a higher layer & we must push the rest of the tree down
|
||||
const split = this.splitAround(key)
|
||||
const newNode: Node = []
|
||||
if (split[0]) newNode.push(split[0])
|
||||
newNode.push([key, value])
|
||||
if (split[1]) newNode.push(split[1])
|
||||
this.node = newNode
|
||||
this.zeros++
|
||||
return this.put()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,25 +4,68 @@ import * as uint8arrays from 'uint8arrays'
|
||||
|
||||
import * as util from './_util'
|
||||
import { sha256 } from '@adxp/crypto'
|
||||
import { IpldStore } from '../src'
|
||||
|
||||
describe('Merkle Search Tree', () => {
|
||||
it('blah', async () => {
|
||||
let counts = {
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
}
|
||||
for (let i = 0; i < 1000000; i++) {
|
||||
it('works', async () => {
|
||||
const blockstore = IpldStore.createInMemory()
|
||||
const mst = await MST.create(blockstore)
|
||||
const cid = await util.randomCid()
|
||||
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const tid = TID.next()
|
||||
const count = await leadingZerosOnHash(tid.toString())
|
||||
counts[count]++
|
||||
await mst.set(tid.toString(), cid)
|
||||
}
|
||||
console.log(counts)
|
||||
console.log('zeroes: ', mst.zeros)
|
||||
// await mst.set('1', cid)
|
||||
// await mst.set('2', cid)
|
||||
// await mst.set('3', cid)
|
||||
// await mst.set('4', cid)
|
||||
// await mst.set('5', cid)
|
||||
// await mst.set('3j6ezmyjtgm2n', cid)
|
||||
// await mst.set('6', cid)
|
||||
// await mst.set('7', cid)
|
||||
// await mst.set('8', cid)
|
||||
// await mst.set('9', cid)
|
||||
// await mst.set('10', cid)
|
||||
// await mst.set('11', cid)
|
||||
// await mst.set('12', cid)
|
||||
// await mst.set('13', cid)
|
||||
// await mst.set('14', cid)
|
||||
// await mst.set('15', cid)
|
||||
// await mst.set('16', cid)
|
||||
// await mst.set('17', cid)
|
||||
// await mst.set('18', cid)
|
||||
// await mst.set('19', cid)
|
||||
// await mst.set('20', cid)
|
||||
// await mst.set('21', cid)
|
||||
// await mst.set('22', cid)
|
||||
// await mst.set('23', cid)
|
||||
// await mst.set('24', cid)
|
||||
// await mst.set('25', cid)
|
||||
// await mst.set('26', cid)
|
||||
// await mst.set('27', cid)
|
||||
// await mst.set('28', cid)
|
||||
// await mst.set('29', cid)
|
||||
// await mst.set('30', cid)
|
||||
})
|
||||
// it('blah', async () => {
|
||||
// let counts = {
|
||||
// 0: 0,
|
||||
// 1: 0,
|
||||
// 2: 0,
|
||||
// 3: 0,
|
||||
// 4: 0,
|
||||
// 5: 0,
|
||||
// 6: 0,
|
||||
// }
|
||||
// for (let i = 0; i < 1000000; i++) {
|
||||
// const tid = TID.next()
|
||||
// const count = await leadingZerosOnHash(tid.toString())
|
||||
// counts[count]++
|
||||
// }
|
||||
// console.log(counts)
|
||||
// })
|
||||
// it('does something', async () => {
|
||||
// const mst = new MST()
|
||||
// const cid = await util.randomCid()
|
||||
|
Loading…
x
Reference in New Issue
Block a user