Skip to content
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
5 changes: 5 additions & 0 deletions .changeset/lemon-pianos-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/contracts': patch
---

Deleted update and helper functions/tests from Lib_MerkleTrie.sol and Lib_SecureMerkleTrie.sol
526 changes: 0 additions & 526 deletions packages/contracts/contracts/libraries/trie/Lib_MerkleTrie.sol

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,6 @@ library Lib_SecureMerkleTrie {
return Lib_MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);
}

/**
* @notice Updates a Merkle trie and returns a new root hash.
* @param _key Key of the node to update, as a hex string.
* @param _value Value of the node to update, as a hex string.
* @param _proof Merkle trie inclusion proof for the node *nearest* the
* target node. If the key exists, we can simply update the value.
* Otherwise, we need to modify the trie to handle the new k/v pair.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return _updatedRoot Root hash of the newly constructed trie.
*/
function update(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
) internal pure returns (bytes32 _updatedRoot) {
bytes memory key = _getSecureKey(_key);
return Lib_MerkleTrie.update(key, _value, _proof, _root);
}

/**
* @notice Retrieves the value associated with a given key.
* @param _key Key to search for, as hex bytes.
Expand All @@ -72,21 +51,6 @@ library Lib_SecureMerkleTrie {
return Lib_MerkleTrie.get(key, _proof, _root);
}

/**
* Computes the root hash for a trie with a single node.
* @param _key Key for the single node.
* @param _value Value for the single node.
* @return _updatedRoot Hash of the trie.
*/
function getSingleNodeRootHash(bytes memory _key, bytes memory _value)
internal
pure
returns (bytes32 _updatedRoot)
{
bytes memory key = _getSecureKey(_key);
return Lib_MerkleTrie.getSingleNodeRootHash(key, _value);
}

/*********************
* Private Functions *
*********************/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,11 @@ contract TestLib_MerkleTrie {
return Lib_MerkleTrie.verifyInclusionProof(_key, _value, _proof, _root);
}

function update(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
) public pure returns (bytes32) {
return Lib_MerkleTrie.update(_key, _value, _proof, _root);
}

function get(
bytes memory _key,
bytes memory _proof,
bytes32 _root
) public pure returns (bool, bytes memory) {
return Lib_MerkleTrie.get(_key, _proof, _root);
}

function getSingleNodeRootHash(bytes memory _key, bytes memory _value)
public
pure
returns (bytes32)
{
return Lib_MerkleTrie.getSingleNodeRootHash(_key, _value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,11 @@ contract TestLib_SecureMerkleTrie {
return Lib_SecureMerkleTrie.verifyInclusionProof(_key, _value, _proof, _root);
}

function update(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
) public pure returns (bytes32) {
return Lib_SecureMerkleTrie.update(_key, _value, _proof, _root);
}

function get(
bytes memory _key,
bytes memory _proof,
bytes32 _root
) public pure returns (bool, bytes memory) {
return Lib_SecureMerkleTrie.get(_key, _proof, _root);
}

function getSingleNodeRootHash(bytes memory _key, bytes memory _value)
public
pure
returns (bytes32)
{
return Lib_SecureMerkleTrie.getSingleNodeRootHash(_key, _value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@
import * as rlp from 'rlp'
import { ethers } from 'hardhat'
import { Contract } from 'ethers'
import { fromHexString, toHexString } from '@eth-optimism/core-utils'
import { Trie } from 'merkle-patricia-tree/dist/baseTrie'
import { toHexString } from '@eth-optimism/core-utils'

/* Internal Imports */
import { expect } from '../../../setup'
import { TrieTestGenerator } from '../../../helpers'
import * as officialTestJson from '../../../data/json/libraries/trie/trietest.json'
import * as officialTestAnyOrderJson from '../../../data/json/libraries/trie/trieanyorder.json'

const NODE_COUNTS = [1, 2, 32, 128]

Expand All @@ -22,100 +19,6 @@ describe('Lib_MerkleTrie', () => {
})

// Eth-foundation tests: https://github.com/ethereum/tests/tree/develop/TrieTests
describe('official tests', () => {
for (const testName of Object.keys(officialTestJson.tests)) {
it(`should perform official test: ${testName}`, async () => {
const trie = new Trie()
const inputs = officialTestJson.tests[testName].in
const expected = officialTestJson.tests[testName].root

for (const input of inputs) {
let key: Buffer
if (input[0].startsWith('0x')) {
key = fromHexString(input[0])
} else {
key = fromHexString(
ethers.utils.hexlify(ethers.utils.toUtf8Bytes(input[0]))
)
}

let val: Buffer
if (input[1] === null) {
throw new Error('deletions not supported, check your tests')
} else if (input[1].startsWith('0x')) {
val = fromHexString(input[1])
} else {
val = fromHexString(
ethers.utils.hexlify(ethers.utils.toUtf8Bytes(input[1]))
)
}

const proof = await Trie.createProof(trie, key)
const root = trie.root
await trie.put(key, val)

const out = await Lib_MerkleTrie.update(
toHexString(key),
toHexString(val),
toHexString(rlp.encode(proof)),
root
)

expect(out).to.equal(toHexString(trie.root))
}

expect(toHexString(trie.root)).to.equal(expected)
})
}
})

describe('official tests - trie any order', () => {
for (const testName of Object.keys(officialTestAnyOrderJson.tests)) {
it(`should perform official test: ${testName}`, async () => {
const trie = new Trie()
const inputs = officialTestAnyOrderJson.tests[testName].in
const expected = officialTestAnyOrderJson.tests[testName].root

for (const input of Object.keys(inputs)) {
let key: Buffer
if (input.startsWith('0x')) {
key = fromHexString(input)
} else {
key = fromHexString(
ethers.utils.hexlify(ethers.utils.toUtf8Bytes(input))
)
}

let val: Buffer
if (inputs[input] === null) {
throw new Error('deletions not supported, check your tests')
} else if (inputs[input].startsWith('0x')) {
val = fromHexString(inputs[input])
} else {
val = fromHexString(
ethers.utils.hexlify(ethers.utils.toUtf8Bytes(inputs[input]))
)
}

const proof = await Trie.createProof(trie, key)
const root = trie.root
await trie.put(key, val)

const out = await Lib_MerkleTrie.update(
toHexString(key),
toHexString(val),
toHexString(rlp.encode(proof)),
root
)

expect(out).to.equal(toHexString(trie.root))
}

expect(toHexString(trie.root)).to.equal(expected)
})
}
})

describe('verifyInclusionProof', () => {
for (const nodeCount of NODE_COUNTS) {
describe(`inside a trie with ${nodeCount} nodes and keys/vals of size ${nodeCount} bytes`, () => {
Expand Down Expand Up @@ -152,62 +55,6 @@ describe('Lib_MerkleTrie', () => {
}
})

describe('update', () => {
for (const nodeCount of NODE_COUNTS) {
describe(`inside a trie with ${nodeCount} nodes and keys/vals of size ${nodeCount} bytes`, () => {
let generator: TrieTestGenerator
before(async () => {
generator = await TrieTestGenerator.fromRandom({
seed: `seed.update.${nodeCount}`,
nodeCount,
secure: false,
keySize: nodeCount,
valSize: nodeCount,
})
})

for (
let i = 0;
i < nodeCount;
i += nodeCount / (nodeCount > 8 ? 8 : 1)
) {
it(`should correctly update node #${i}`, async () => {
const test = await generator.makeNodeUpdateTest(
i,
'0x1234123412341234'
)

expect(
await Lib_MerkleTrie.update(
test.key,
test.val,
test.proof,
test.root
)
).to.equal(test.newRoot)
})
}
})
}

it('should return the single-node root hash if the trie was previously empty', async () => {
const key = '0x1234'
const val = '0x5678'

const trie = new Trie()
await trie.put(fromHexString(key), fromHexString(val))

expect(
await Lib_MerkleTrie.update(
key,
val,
'0x', // Doesn't require a proof
ethers.utils.keccak256('0x80') // Empty Merkle trie root hash
)
).to.equal(toHexString(trie.root))
})
})

describe('get', () => {
for (const nodeCount of NODE_COUNTS) {
describe(`inside a trie with ${nodeCount} nodes and keys/vals of size ${nodeCount} bytes`, () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,43 +50,6 @@ describe('Lib_SecureMerkleTrie', () => {
}
})

describe('update', () => {
for (const nodeCount of NODE_COUNTS) {
describe(`inside a trie with ${nodeCount} nodes`, () => {
let generator: TrieTestGenerator
before(async () => {
generator = await TrieTestGenerator.fromRandom({
seed: `seed.update.${nodeCount}`,
nodeCount,
secure: true,
})
})

for (
let i = 0;
i < nodeCount;
i += nodeCount / (nodeCount > 8 ? 8 : 1)
) {
it(`should correctly update node #${i}`, async () => {
const test = await generator.makeNodeUpdateTest(
i,
'0x1234123412341234'
)

expect(
await Lib_SecureMerkleTrie.update(
test.key,
test.val,
test.proof,
test.root
)
).to.equal(test.newRoot)
})
}
})
}
})

describe('get', () => {
for (const nodeCount of NODE_COUNTS) {
describe(`inside a trie with ${nodeCount} nodes`, () => {
Expand Down Expand Up @@ -115,22 +78,4 @@ describe('Lib_SecureMerkleTrie', () => {
})
}
})

describe('getSingleNodeRootHash', () => {
let generator: TrieTestGenerator
before(async () => {
generator = await TrieTestGenerator.fromRandom({
seed: `seed.get.${1}`,
nodeCount: 1,
secure: true,
})
})

it(`should get the root hash of a trie with a single node`, async () => {
const test = await generator.makeInclusionProofTest(0)
expect(
await Lib_SecureMerkleTrie.getSingleNodeRootHash(test.key, test.val)
).to.equal(test.root)
})
})
})