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