UNPKG

ox

Version:

Ethereum Standard Library

183 lines (170 loc) 5.88 kB
import { BinaryStateTree, Bytes, Hex } from 'ox' import { describe, expect, test } from 'vp/test' import type { Node } from '../BinaryStateTree.js' function getHeight(node: Node): number { if (node.type === 'empty') return 0 if (node.type === 'stem') return 1 return 1 + Math.max(getHeight(node.left), getHeight(node.right)) } describe('insert', () => { test('behavior: single entry', () => { const tree = BinaryStateTree.create() BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(32)) as Hex.Hex), Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), ) expect(getHeight(tree.root)).toBe(1) expect( Hex.fromBytes(BinaryStateTree.merkelize(tree)), ).toMatchInlineSnapshot( `"0x694545468677064fd833cddc8455762fe6b21c6cabe2fc172529e0f573181cd5"`, ) }) test('behavior: two entries, diff first bit', () => { const tree = BinaryStateTree.create() BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(32)) as Hex.Hex), Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '80' + '00'.repeat(31)) as Hex.Hex), Bytes.fromHex(('0x' + '02'.repeat(32)) as Hex.Hex), ) expect(getHeight(tree.root)).toBe(2) expect( Hex.fromBytes(BinaryStateTree.merkelize(tree)), ).toMatchInlineSnapshot( `"0x85fc622076752a6fcda2c886c18058d639066a83473d9684704b5a29455ed2ed"`, ) }) test('behavior: one stem, colocated values', () => { const tree = BinaryStateTree.create() BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(31) + '03') as Hex.Hex), Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(31) + '04') as Hex.Hex), Bytes.fromHex(('0x' + '02'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(31) + '09') as Hex.Hex), Bytes.fromHex(('0x' + '03'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(31) + 'ff') as Hex.Hex), Bytes.fromHex(('0x' + '04'.repeat(32)) as Hex.Hex), ) expect(getHeight(tree.root)).toBe(1) expect( Hex.fromBytes(BinaryStateTree.merkelize(tree)), ).toMatchInlineSnapshot( `"0xaa12acb5689a2dc03e9d7ab0350449c70cdad286750dc8ba1dd092f5e100191a"`, ) }) test('behavior: two stems, colocated values', () => { const tree = BinaryStateTree.create() BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(31) + '03') as Hex.Hex), Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(31) + '04') as Hex.Hex), Bytes.fromHex(('0x' + '02'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '80'.repeat(31) + '03') as Hex.Hex), Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '80'.repeat(31) + '04') as Hex.Hex), Bytes.fromHex(('0x' + '02'.repeat(32)) as Hex.Hex), ) expect(getHeight(tree.root)).toBe(2) expect( Hex.fromBytes(BinaryStateTree.merkelize(tree)), ).toMatchInlineSnapshot( `"0xd8cb5a1f0611c2af9413c9fa179a4a1bf0eb6debc8d9e10d439b3e32371085ad"`, ) }) test('behavior: two keys match first 42 bits', () => { const tree = BinaryStateTree.create() BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '00'.repeat(5) + 'C0'.repeat(27)) as Hex.Hex), Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex( ('0x' + '00'.repeat(5) + 'E0' + '00'.repeat(26)) as Hex.Hex, ), Bytes.fromHex(('0x' + '02'.repeat(32)) as Hex.Hex), ) expect(getHeight(tree.root)).toBe(1 + 42 + 1) }) test('behavior: duplicate key', () => { const tree = BinaryStateTree.create() BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), ) BinaryStateTree.insert( tree, Bytes.fromHex(('0x' + '01'.repeat(32)) as Hex.Hex), Bytes.fromHex(('0x' + '02'.repeat(32)) as Hex.Hex), ) expect(getHeight(tree.root)).toBe(1) expect(Hex.fromBytes(tree.root.values![1]!)).toMatchInlineSnapshot( `"0x0202020202020202020202020202020202020202020202020202020202020202"`, ) }) test('behavior: large number of entries', () => { const tree = BinaryStateTree.create() for (let i = 0; i < 1 << 8; i++) { const key = Bytes.fromHex( ('0x' + i.toString(16).padStart(2, '0') + '00'.repeat(31)) as Hex.Hex, ) BinaryStateTree.insert( tree, key, Bytes.fromHex(('0x' + 'FF'.repeat(32)) as Hex.Hex), ) } expect(getHeight(tree.root)).toBe(1 + 8) }) test('behavior: merkleize multiple entries', () => { const tree = BinaryStateTree.create() const keys = [ Bytes.fromHex(('0x' + '00'.repeat(32)) as Hex.Hex), Bytes.fromHex(('0x' + '80' + '00'.repeat(31)) as Hex.Hex), Bytes.fromHex(('0x' + '01' + '00'.repeat(31)) as Hex.Hex), Bytes.fromHex(('0x' + '81' + '00'.repeat(31)) as Hex.Hex), ] for (let i = 0; i < keys.length; i++) { const value = Bytes.fromHex( ('0x' + (i + 1).toString(16).padStart(2, '0') + '00'.repeat(31)) as Hex.Hex, ) BinaryStateTree.insert(tree, keys[i]!, value) } expect( Hex.fromBytes(BinaryStateTree.merkelize(tree)), ).toMatchInlineSnapshot( `"0xe93c209026b8b00d76062638102ece415028bd104e1d892d5399375a323f2218"`, ) }) })