From 8f81aeeed1037eb854429a5de627753e939c5fd7 Mon Sep 17 00:00:00 2001 From: Karl Floersch <karl@karlfloersch.com> Date: Tue, 13 Oct 2020 03:38:12 -0400 Subject: [PATCH] Add optimized merkle tree --- .../chain/OVM_CanonicalTransactionChain.sol | 3 +- .../libraries/utils/Lib_MerkleRoot.sol | 59 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 packages/contracts/contracts/optimistic-ethereum/libraries/utils/Lib_MerkleRoot.sol diff --git a/packages/contracts/contracts/optimistic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol b/packages/contracts/contracts/optimistic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol index 0793f7188..a26f28153 100644 --- a/packages/contracts/contracts/optimistic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol +++ b/packages/contracts/contracts/optimistic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol @@ -6,6 +6,7 @@ pragma experimental ABIEncoderV2; import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; import { Lib_MerkleUtils } from "../../libraries/utils/Lib_MerkleUtils.sol"; +import { Lib_MerkleRoot } from "../../libraries/utils/Lib_MerkleRoot.sol"; import { TimeboundRingBuffer, Lib_TimeboundRingBuffer } from "../../libraries/utils/Lib_TimeboundRingBuffer.sol"; import { console } from "@nomiclabs/buidler/console.sol"; @@ -342,6 +343,6 @@ contract OVM_CanonicalTransactionChain is OVM_BaseChain, Lib_AddressResolver { / } function _getRoot(bytes32[] memory leaves) internal returns(bytes32) { - return 0x0101010101010101010101010101010101010101010101010101010101010101; + return Lib_MerkleRoot.getMerkleRoot(leaves); } } \ No newline at end of file diff --git a/packages/contracts/contracts/optimistic-ethereum/libraries/utils/Lib_MerkleRoot.sol b/packages/contracts/contracts/optimistic-ethereum/libraries/utils/Lib_MerkleRoot.sol new file mode 100644 index 000000000..0ba7d4493 --- /dev/null +++ b/packages/contracts/contracts/optimistic-ethereum/libraries/utils/Lib_MerkleRoot.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.7.0; + +// author: cobaltedge + +library Lib_MerkleRoot { + + function getMerkleRoot(bytes32[] memory elements) + internal view returns (bytes32) { + + // compute tree depth + uint pow2 = 1; + uint depth = 0; + while (pow2 < elements.length) { + pow2 <<= 1; + depth++; + } + + bytes memory buf = new bytes(64); + bytes32 left; bytes32 right; + + for (uint i = 0; i < elements.length / 2; i++) { + left = elements[2 * i ]; + right = elements[2 * i + 1]; + assembly { + mstore(add(buf, 32), left) + mstore(add(buf, 64), right) + } + elements[i] = keccak256(buf); + } + + for (uint i = elements.length; i < pow2 >> 1; i++) { + elements[i] = 0x0000000000000000000000000000000000000000000000000000000000000000; + } + + uint diff = (pow2 - elements.length) / 2; + uint pow2_ = pow2 >> 1; + for (uint d = 2; d <= depth; d++) { + pow2_ >>= 1; + diff /= 2; + uint midpoint = pow2_ - diff; + + for (uint i = 0; i < midpoint; i++) { + left = elements[2 * i ]; + right = elements[2 * i + 1]; + assembly { + mstore(add(buf, 32), left) + mstore(add(buf, 64), right) + } + elements[i] = keccak256(buf); + } + + for (uint i = midpoint; i < pow2_; i++) { + elements[i] = 0x0000000000000000000000000000000000000000000000000000000000000000; + } + } + + return elements[0]; + } +} \ No newline at end of file -- 2.23.0