@@ -3,18 +3,20 @@ pragma solidity ^0.8.28;
33
44import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol " ;
55
6+ import {BlockHeader} from "@solarity/solidity-lib/libs/bitcoin/BlockHeader.sol " ;
7+ import {TxMerkleProof} from "@solarity/solidity-lib/libs/bitcoin/TxMerkleProof.sol " ;
8+ import {EndianConverter} from "@solarity/solidity-lib/libs/utils/EndianConverter.sol " ;
9+
610import {LibSort} from "solady/src/utils/LibSort.sol " ;
7- import {LibBit} from "solady/src/utils/LibBit.sol " ;
811
9- import {BlockHeader, BlockHeaderData} from "./libs/BlockHeader.sol " ;
1012import {TargetsHelper} from "./libs/TargetsHelper.sol " ;
11- import {TxMerkleProof} from "./libs/TxMerkleProof.sol " ;
1213
1314import {ISPVContract} from "./interfaces/ISPVContract.sol " ;
1415
1516contract SPVContract is ISPVContract , Initializable {
1617 using BlockHeader for bytes ;
1718 using TargetsHelper for bytes32 ;
19+ using EndianConverter for bytes32 ;
1820
1921 uint8 public constant MEDIAN_PAST_BLOCKS = 11 ;
2022
@@ -39,7 +41,7 @@ contract SPVContract is ISPVContract, Initializable {
3941 }
4042
4143 function __SPVContract_init () external initializer {
42- BlockHeaderData memory genesisBlockHeader_ = BlockHeaderData ({
44+ BlockHeader.HeaderData memory genesisBlockHeader_ = BlockHeader. HeaderData ({
4345 version: 1 ,
4446 prevBlockHash: bytes32 (0 ),
4547 merkleRoot: 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b ,
@@ -59,7 +61,7 @@ contract SPVContract is ISPVContract, Initializable {
5961 uint64 blockHeight_ ,
6062 uint256 cumulativeWork_
6163 ) external initializer {
62- (BlockHeaderData memory blockHeader_ , bytes32 blockHash_ ) = _parseBlockHeaderRaw (
64+ (BlockHeader.HeaderData memory blockHeader_ , bytes32 blockHash_ ) = _parseBlockHeaderRaw (
6365 blockHeaderRaw_
6466 );
6567
@@ -87,7 +89,7 @@ contract SPVContract is ISPVContract, Initializable {
8789 bytes [] calldata blockHeaderRawArray_
8890 ) external broadcastMainchainUpdateEvent {
8991 (
90- BlockHeaderData [] memory blockHeaders_ ,
92+ BlockHeader.HeaderData [] memory blockHeaders_ ,
9193 bytes32 [] memory blockHashes_
9294 ) = _parseBlockHeadersRaw (blockHeaderRawArray_);
9395
@@ -117,7 +119,7 @@ contract SPVContract is ISPVContract, Initializable {
117119 function addBlockHeader (
118120 bytes calldata blockHeaderRaw_
119121 ) external broadcastMainchainUpdateEvent {
120- (BlockHeaderData memory blockHeader_ , bytes32 blockHash_ ) = _parseBlockHeaderRaw (
122+ (BlockHeader.HeaderData memory blockHeader_ , bytes32 blockHash_ ) = _parseBlockHeaderRaw (
121123 blockHeaderRaw_
122124 );
123125
@@ -143,16 +145,21 @@ contract SPVContract is ISPVContract, Initializable {
143145
144146 /// @inheritdoc ISPVContract
145147 function checkTxInclusion (
146- bytes32 blockHash_ ,
147- bytes32 txid_ ,
148148 bytes32 [] calldata merkleProof_ ,
149- TxMerkleProof.HashDirection[] calldata directions_
149+ bytes32 blockHash_ ,
150+ bytes32 txId_ ,
151+ uint256 txIndex_ ,
152+ uint256 minConfirmationsCount_
150153 ) external view returns (bool ) {
151- bytes32 blockMerkleRoot_ = getBlockMerkleRoot (blockHash_);
154+ ( bool isInMainchain_ , uint256 confirmationsCount_ ) = getBlockStatus (blockHash_);
152155
153- bytes32 reversedRoot_ = bytes32 (LibBit.reverseBytes (uint256 (blockMerkleRoot_)));
156+ if (! isInMainchain_ || confirmationsCount_ < minConfirmationsCount_) {
157+ return false ;
158+ }
159+
160+ bytes32 leRoot_ = getBlockMerkleRoot (blockHash_).bytes32BEtoLE ();
154161
155- return TxMerkleProof.verify (merkleProof_, directions_, reversedRoot_, txid_ );
162+ return TxMerkleProof.verify (merkleProof_, leRoot_, txId_, txIndex_ );
156163 }
157164
158165 /// @inheritdoc ISPVContract
@@ -181,11 +188,13 @@ contract SPVContract is ISPVContract, Initializable {
181188 }
182189
183190 /// @inheritdoc ISPVContract
184- function getBlockHeader (bytes32 blockHash_ ) public view returns (BlockHeaderData memory ) {
191+ function getBlockHeader (
192+ bytes32 blockHash_
193+ ) public view returns (BlockHeader.HeaderData memory ) {
185194 BlockData storage blockData = _getSPVContractStorage ().blocksData[blockHash_];
186195
187196 return
188- BlockHeaderData ({
197+ BlockHeader. HeaderData ({
189198 version: blockData.version,
190199 prevBlockHash: blockData.prevBlockHash,
191200 merkleRoot: blockData.merkleRoot,
@@ -196,7 +205,7 @@ contract SPVContract is ISPVContract, Initializable {
196205 }
197206
198207 /// @inheritdoc ISPVContract
199- function getBlockStatus (bytes32 blockHash_ ) external view returns (bool , uint64 ) {
208+ function getBlockStatus (bytes32 blockHash_ ) public view returns (bool , uint64 ) {
200209 if (! isInMainchain (blockHash_)) {
201210 return (false , 0 );
202211 }
@@ -240,7 +249,7 @@ contract SPVContract is ISPVContract, Initializable {
240249 }
241250
242251 function _addBlock (
243- BlockHeaderData memory blockHeader_ ,
252+ BlockHeader.HeaderData memory blockHeader_ ,
244253 bytes32 blockHash_ ,
245254 uint64 blockHeight_
246255 ) internal {
@@ -262,7 +271,7 @@ contract SPVContract is ISPVContract, Initializable {
262271 }
263272
264273 function _updateMainchainHead (
265- BlockHeaderData memory blockHeader_ ,
274+ BlockHeader.HeaderData memory blockHeader_ ,
266275 bytes32 blockHash_ ,
267276 uint64 blockHeight_
268277 ) internal {
@@ -328,11 +337,11 @@ contract SPVContract is ISPVContract, Initializable {
328337 )
329338 internal
330339 view
331- returns (BlockHeaderData [] memory blockHeaders_ , bytes32 [] memory blockHashes_ )
340+ returns (BlockHeader.HeaderData [] memory blockHeaders_ , bytes32 [] memory blockHashes_ )
332341 {
333342 require (blockHeaderRawArray_.length > 0 , EmptyBlockHeaderArray ());
334343
335- blockHeaders_ = new BlockHeaderData [](blockHeaderRawArray_.length );
344+ blockHeaders_ = new BlockHeader. HeaderData [](blockHeaderRawArray_.length );
336345 blockHashes_ = new bytes32 [](blockHeaderRawArray_.length );
337346
338347 for (uint256 i = 0 ; i < blockHeaderRawArray_.length ; ++ i) {
@@ -354,14 +363,14 @@ contract SPVContract is ISPVContract, Initializable {
354363
355364 function _parseBlockHeaderRaw (
356365 bytes calldata blockHeaderRaw_
357- ) internal view returns (BlockHeaderData memory blockHeader_ , bytes32 blockHash_ ) {
358- (blockHeader_, blockHash_) = blockHeaderRaw_.parseBlockHeaderData ( );
366+ ) internal view returns (BlockHeader.HeaderData memory blockHeader_ , bytes32 blockHash_ ) {
367+ (blockHeader_, blockHash_) = blockHeaderRaw_.parseBlockHeader ( true );
359368
360369 _onlyNonExistingBlock (blockHash_);
361370 }
362371
363372 function _getStorageMedianTime (
364- BlockHeaderData memory blockHeader_ ,
373+ BlockHeader.HeaderData memory blockHeader_ ,
365374 uint64 blockHeight_
366375 ) internal view returns (uint32 ) {
367376 if (blockHeight_ == 1 ) {
@@ -392,7 +401,7 @@ contract SPVContract is ISPVContract, Initializable {
392401 }
393402
394403 function _getMemoryMedianTime (
395- BlockHeaderData [] memory blockHeaders_ ,
404+ BlockHeader.HeaderData [] memory blockHeaders_ ,
396405 uint64 to_
397406 ) internal pure returns (uint32 ) {
398407 if (blockHeaders_.length < MEDIAN_PAST_BLOCKS) {
@@ -435,7 +444,7 @@ contract SPVContract is ISPVContract, Initializable {
435444 }
436445
437446 function _validateBlockRules (
438- BlockHeaderData memory blockHeader_ ,
447+ BlockHeader.HeaderData memory blockHeader_ ,
439448 bytes32 blockHash_ ,
440449 bytes32 target_ ,
441450 uint32 medianTime_
0 commit comments