File tree Expand file tree Collapse file tree 4 files changed +16
-14
lines changed Expand file tree Collapse file tree 4 files changed +16
-14
lines changed Original file line number Diff line number Diff line change @@ -39,7 +39,7 @@ contract MerkleProof {
39
39
bytes memory data ,
40
40
bytes32 merkleRoot
41
41
) public pure returns (bool ) {
42
- return validateProof (proof, keccak256 (data), merkleRoot);
42
+ return validateProof (proof, sha256 (data), merkleRoot);
43
43
}
44
44
45
45
/** @dev Calculates merkle root from proof.
Original file line number Diff line number Diff line change @@ -40,32 +40,34 @@ contract MerkleTreeHistory {
40
40
* @param data The data to insert in the merkle tree.
41
41
*/
42
42
function append (bytes memory data ) public {
43
- bytes32 leaf = keccak256 (data);
44
- count += 1 ;
45
- uint256 size = count;
43
+ // Differentiate leaves from interior nodes with different
44
+ // hash functions to prevent 2nd order pre-image attack.
45
+ // https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/
46
+ bytes32 leaf = sha256 (data);
47
+ uint256 size = count + 1 ;
48
+ count = size;
46
49
uint256 hashBitField = (size ^ (size - 1 )) & size;
47
-
48
- for (uint256 height = 0 ; height < 64 ; height++ ) {
49
- if ((hashBitField & 1 ) == 1 ) {
50
- branch[height] = leaf;
51
- return ;
52
- }
50
+ uint256 height;
51
+ while ((hashBitField & 1 ) == 0 ) {
53
52
bytes32 node = branch[height];
54
- // effecient hash
55
53
if (node > leaf)
56
54
assembly {
55
+ // effecient hash
57
56
mstore (0x00 , leaf)
58
57
mstore (0x20 , node)
59
58
leaf := keccak256 (0x00 , 0x40 )
60
59
}
61
60
else
62
61
assembly {
62
+ // effecient hash
63
63
mstore (0x00 , node)
64
64
mstore (0x20 , leaf)
65
65
leaf := keccak256 (0x00 , 0x40 )
66
66
}
67
67
hashBitField /= 2 ;
68
+ height = height + 1 ;
68
69
}
70
+ branch[height] = leaf;
69
71
}
70
72
71
73
/** @dev Saves the merkle root state in history and resets.
@@ -98,8 +100,8 @@ contract MerkleTreeHistory {
98
100
uint256 height = 0 ;
99
101
bool isFirstHash = true ;
100
102
while (size > 0 ) {
101
- // avoid redundant calculation
102
103
if ((size & 1 ) == 1 ) {
104
+ // avoid redundant calculation
103
105
if (isFirstHash) {
104
106
node = branch[height];
105
107
isFirstHash = false ;
Original file line number Diff line number Diff line change @@ -31,7 +31,7 @@ export class MerkleTree {
31
31
* @return node The `sha3` (A.K.A. `keccak256`) hash of `first, ...params` as a 32-byte hex string.
32
32
*/
33
33
public static makeLeafNode ( data : string ) : string {
34
- const result = ethers . utils . keccak256 ( data ) ;
34
+ const result = ethers . utils . sha256 ( data ) ;
35
35
36
36
if ( ! result ) {
37
37
throw new Error ( "Leaf node must not be empty" ) ;
Original file line number Diff line number Diff line change @@ -61,7 +61,7 @@ describe("Merkle", function () {
61
61
} ) ;
62
62
it ( "Should correctly verify all nodes in the tree" , async ( ) => {
63
63
for ( var message of data ) {
64
- const leaf = ethers . utils . keccak256 ( message ) ;
64
+ const leaf = ethers . utils . sha256 ( message ) ;
65
65
proof = mt . getHexProof ( leaf ) ;
66
66
const validation = await merkleProof . validateProof ( proof , message , rootOnChain ) ;
67
67
expect ( validation ) . equal ( true ) ;
You can’t perform that action at this time.
0 commit comments