Skip to content

Commit ce1c5b8

Browse files
committed
switched from bytes to HashDirection array;
refactored parse-proof-helpers
1 parent ba795ea commit ce1c5b8

File tree

5 files changed

+361
-161
lines changed

5 files changed

+361
-161
lines changed

contracts/SPVContract.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ contract SPVContract is ISPVContract, Initializable {
155155
bytes32 blockHash_,
156156
bytes32 txid_,
157157
bytes32[] calldata merkleProof_,
158-
bytes calldata directions_
158+
TxMerkleProof.HashDirection[] calldata directions_
159159
) external view returns (bool) {
160160
bytes32 blockMerkleRoot_ = getBlockMerkleRoot(blockHash_);
161161

contracts/interfaces/ISPVContract.sol

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pragma solidity ^0.8.28;
33

44
import {BlockHeaderData} from "../libs/BlockHeader.sol";
5+
import {TxMerkleProof} from "../libs/TxMerkleProof.sol";
56

67
/**
78
* @notice Interface for an SPV (Simplified Payment Verification) contract.
@@ -125,13 +126,13 @@ interface ISPVContract {
125126
* @param blockHash_ The hash of the block in which to verify the transaction
126127
* @param txid_ The transaction id to verify
127128
* @param merkleProof_ The array of hashes used to build the Merkle root
128-
* @param directions_ The string indicating the hashing directions for the Merkle proof
129+
* @param directions_ The array indicating the hashing directions for the Merkle proof
129130
*/
130131
function verifyTx(
131132
bytes32 blockHash_,
132133
bytes32 txid_,
133134
bytes32[] memory merkleProof_,
134-
bytes calldata directions_
135+
TxMerkleProof.HashDirection[] calldata directions_
135136
) external view returns (bool);
136137

137138
/**

contracts/libs/TxMerkleProof.sol

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ pragma solidity ^0.8.28;
66
* Provides functions for processing and verifying Merkle tree proofs
77
*/
88
library TxMerkleProof {
9+
/**
10+
* @notice Possible directions for hashing:
11+
* - Left: computed hash is on the left, sibling hash is on the right.
12+
* - Right: computed hash is on the right, sibling hash is on the left.
13+
* - Self: node has no sibling and is hashed with itself.
14+
* */
15+
enum HashDirection {
16+
Left,
17+
Right,
18+
Self
19+
}
20+
921
/**
1022
* @notice Emitted when the proof and directions array are of different length.
1123
* This error ensures that only correctly sized proofs are processed
@@ -15,13 +27,13 @@ library TxMerkleProof {
1527
/**
1628
* @notice Returns true if `leaf_` can be proven to be part of a Merkle tree
1729
* defined by `root_`. Requires a `proof_` containing the sibling hashes along
18-
* the path from the leaf to the root. Each byte of `directions_` indicates
30+
* the path from the leaf to the root. Each element of `directions_` indicates
1931
* the hashing order for each pair.
2032
* Uses double SHA-256 hashing.
2133
*/
2234
function verify(
23-
bytes32[] memory proof_,
24-
bytes calldata directions_,
35+
bytes32[] calldata proof_,
36+
HashDirection[] calldata directions_,
2537
bytes32 root_,
2638
bytes32 leaf_
2739
) internal pure returns (bool) {
@@ -34,31 +46,31 @@ library TxMerkleProof {
3446
* @notice Returns the rebuilt hash obtained by traversing the Merkle tree
3547
* from `leaf_` using `proof_`. A `proof_` is valid if and only if the rebuilt
3648
* hash matches the given tree root. The pre-images are hashed in the order
37-
* specified by the `directions_` bytes.
49+
* specified by the `directions_` elements.
3850
* Uses double SHA-256 hashing.
3951
*/
4052
function processProof(
41-
bytes32[] memory proof_,
42-
bytes calldata directions_,
53+
bytes32[] calldata proof_,
54+
HashDirection[] calldata directions_,
4355
bytes32 leaf_
4456
) internal pure returns (bytes32) {
4557
bytes32 computedHash_ = leaf_;
4658
uint256 proofLength_ = proof_.length;
4759

4860
for (uint256 i = 0; i < proofLength_; ++i) {
49-
if (directions_[i] == hex"00") {
50-
computedHash_ = _sha256(computedHash_, proof_[i]);
51-
} else if (directions_[i] == hex"01") {
52-
computedHash_ = _sha256(proof_[i], computedHash_);
61+
if (directions_[i] == HashDirection.Left) {
62+
computedHash_ = _doubleSHA256(computedHash_, proof_[i]);
63+
} else if (directions_[i] == HashDirection.Right) {
64+
computedHash_ = _doubleSHA256(proof_[i], computedHash_);
5365
} else {
54-
computedHash_ = _sha256(computedHash_, computedHash_);
66+
computedHash_ = _doubleSHA256(computedHash_, computedHash_);
5567
}
5668
}
5769

5870
return computedHash_;
5971
}
6072

61-
function _sha256(bytes32 left_, bytes32 right_) private pure returns (bytes32) {
73+
function _doubleSHA256(bytes32 left_, bytes32 right_) private pure returns (bytes32) {
6274
return sha256(abi.encodePacked(sha256(abi.encodePacked(left_, right_))));
6375
}
6476
}

0 commit comments

Comments
 (0)