Skip to content

Commit

Permalink
refactor(imt.sol): cache tree depth to optimize gas in insert many fu…
Browse files Browse the repository at this point in the history
…nction in the lean imt

re #209
  • Loading branch information
vplasencia committed Mar 20, 2024
1 parent 464a4ae commit f9f409f
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions packages/imt.sol/contracts/internal/InternalLeanIMT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,18 @@ library InternalLeanIMT {

currentLevel = leaves;

// Cache tree depth to optimize gas
uint256 treeDepth = self.depth;

// Calculate the depth of the tree after adding the new values.
// Unlike the 'insert' function, we need a while here as
// N insertions can increase the tree's depth more than once.
while (2 ** self.depth < treeSize + leaves.length) {
++self.depth;
while (2 ** treeDepth < treeSize + leaves.length) {
++treeDepth;
}

self.depth = treeDepth;

// First index to change in every level.
uint256 currentLevelStartIndex = treeSize;

Expand All @@ -133,27 +138,28 @@ library InternalLeanIMT {
// The size of the next level.
uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;

for (uint256 level = 0; level < self.depth; ) {
for (uint256 level = 0; level < treeDepth; ) {
// The number of nodes for the new level that will be created,
// only the new values, not the entire level.
uint256 numberOfNodes = nextLevelSize - nextLevelStartIndex;
uint256[] memory nextLevel = new uint256[](numberOfNodes);
for (uint256 i = 0; i < numberOfNodes; ) {
uint256 rightNode;
uint256 leftNode;

// Assign the right node if the value exists.
if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {
rightNode = currentLevel[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];
}

// Assign the left node using the saved path or the position in the array.
if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {
leftNode = self.sideNodes[level];
} else {
leftNode = currentLevel[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];
}

uint256 rightNode;

// Assign the right node if the value exists.
if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {
rightNode = currentLevel[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];
}

uint256 parentNode;

// Assign the parent node.
Expand Down Expand Up @@ -208,7 +214,7 @@ library InternalLeanIMT {
self.size = treeSize + leaves.length;

// Update tree root
self.sideNodes[self.depth] = currentLevel[0];
self.sideNodes[treeDepth] = currentLevel[0];

return currentLevel[0];
}
Expand Down

0 comments on commit f9f409f

Please sign in to comment.