Skip to content

Conversation

@0xClandestine
Copy link

Fixes #????

Likely doesn't follow style guidelines, but I wanted to better communicate the idea. Proofs are always provided by a caller as calldata, thus we should use calldata to avoid memory expansion. Proving an account alone with optimisms SecureMerkleTrie implementation is over 400k gas for reference.

PR Checklist

  • Tests
  • Documentation
  • Changeset entry (run npx changeset add)

@changeset-bot
Copy link

changeset-bot bot commented Jul 26, 2025

⚠️ No Changeset found

Latest commit: 175348c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@0xClandestine
Copy link
Author

0xClandestine commented Jul 26, 2025

Comment on lines +249 to +254
function _hashCalldata(uint256 offset, uint256 length) private pure returns (bytes32 hash) {
assembly ("memory-safe") {
calldatacopy(mload(0x40), offset, length)
hash := keccak256(mload(0x40), length)
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than adjusting the free memory pointer at the end we allow previous proofs (in memory) to be overwritten. Avoiding unnecessary memory expansion.

Comment on lines +259 to +264
function _calldataOffsetAndLength(bytes calldata proof) private pure returns (uint256 offset, uint256 length) {
assembly ("memory-safe") {
offset := proof.offset
length := proof.length
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High level Solidity doesn't allow us to do this for whatever reason...

Comment on lines -145 to +150
if (keyIndex == 0 && !string(bytes.concat(keccak256(node.encoded))).equal(string(nodeId)))
return ProofError.INVALID_ROOT_HASH; // Root node must match root hash
if (node.encoded.length >= 32 && !string(bytes.concat(keccak256(node.encoded))).equal(string(nodeId)))
return ProofError.INVALID_LARGE_INTERNAL_HASH; // Large nodes are stored as hashes
if (!string(node.encoded).equal(string(nodeId))) return ProofError.INVALID_INTERNAL_NODE_HASH; // Small nodes must match directly
bytes32 nodeHash = _hashCalldata(node.offset, node.length);
bool nodeHashMatches = string(bytes.concat(nodeHash)).equal(string(nodeId));
if (keyIndex == 0 && !nodeHashMatches) return ProofError.INVALID_ROOT_HASH; // Root node must match root hash
if (node.length >= 32 && !nodeHashMatches) return ProofError.INVALID_LARGE_INTERNAL_HASH; // Large nodes are stored as hashes
if (!(nodeHash == keccak256(nodeId))) return ProofError.INVALID_INTERNAL_NODE_HASH; // Small nodes must match directly
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a variable avoids subsequent branches from expanding memory further.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think my updated L150 is functionally equivalent just avoids loading the proof into memory again.

Comment on lines +44 to +45
uint256 offset; // Raw RLP encoded node calldata offset
uint256 length; // Raw RLP encoded node calldata length
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually makes more sense to simply store the proof elements index.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant