@@ -23,7 +23,7 @@ contract SPVContract is ISPVContract, Initializable {
2323
2424 struct SPVContractStorage {
2525 mapping (bytes32 => BlockData) blocksData;
26- mapping (uint256 => bytes32 ) blocksHeightToBlockHash;
26+ mapping (uint64 => bytes32 ) blocksHeightToBlockHash;
2727 bytes32 mainchainHead;
2828 uint256 lastEpochCumulativeWork;
2929 }
@@ -56,7 +56,7 @@ contract SPVContract is ISPVContract, Initializable {
5656
5757 function __SPVContract_init (
5858 bytes calldata blockHeaderRaw_ ,
59- uint256 blockHeight_ ,
59+ uint64 blockHeight_ ,
6060 uint256 cumulativeWork_
6161 ) external initializer {
6262 (BlockHeaderData memory blockHeader_ , bytes32 blockHash_ ) = _parseBlockHeaderRaw (
@@ -91,11 +91,11 @@ contract SPVContract is ISPVContract, Initializable {
9191 bytes32 [] memory blockHashes_
9292 ) = _parseBlockHeadersRaw (blockHeaderRawArray_);
9393
94- uint256 firstBlockHeight_ = getBlockHeight (blockHeaders_[0 ].prevBlockHash) + 1 ;
94+ uint64 firstBlockHeight_ = getBlockHeight (blockHeaders_[0 ].prevBlockHash) + 1 ;
9595 bytes32 currentTarget_ = getBlockTarget (blockHeaders_[0 ].prevBlockHash);
9696
97- for (uint256 i = 0 ; i < blockHeaderRawArray_.length ; ++ i) {
98- uint256 currentBlockHeight_ = firstBlockHeight_ + i;
97+ for (uint64 i = 0 ; i < blockHeaderRawArray_.length ; ++ i) {
98+ uint64 currentBlockHeight_ = firstBlockHeight_ + i;
9999
100100 currentTarget_ = _updateLastEpochCumulativeWork (currentTarget_, currentBlockHeight_);
101101
@@ -126,7 +126,7 @@ contract SPVContract is ISPVContract, Initializable {
126126 PrevBlockDoesNotExist (blockHeader_.prevBlockHash)
127127 );
128128
129- uint256 blockHeight_ = getBlockHeight (blockHeader_.prevBlockHash) + 1 ;
129+ uint64 blockHeight_ = getBlockHeight (blockHeader_.prevBlockHash) + 1 ;
130130 bytes32 currentTarget_ = getBlockTarget (blockHeader_.prevBlockHash);
131131
132132 currentTarget_ = _updateLastEpochCumulativeWork (currentTarget_, blockHeight_);
@@ -142,16 +142,7 @@ contract SPVContract is ISPVContract, Initializable {
142142 }
143143
144144 /// @inheritdoc ISPVContract
145- function validateBlockHash (bytes32 blockHash_ ) external view returns (bool , uint256 ) {
146- if (! isInMainchain (blockHash_)) {
147- return (false , 0 );
148- }
149-
150- return (true , getMainchainBlockHeight () - getBlockHeight (blockHash_));
151- }
152-
153- /// @inheritdoc ISPVContract
154- function verifyTx (
145+ function checkTxInclusion (
155146 bytes32 blockHash_ ,
156147 bytes32 txid_ ,
157148 bytes32 [] calldata merkleProof_ ,
@@ -164,13 +155,23 @@ contract SPVContract is ISPVContract, Initializable {
164155 return TxMerkleProof.verify (merkleProof_, directions_, reversedRoot_, txid_);
165156 }
166157
158+ /// @inheritdoc ISPVContract
159+ function getMainchainHead () public view returns (bytes32 ) {
160+ return _getSPVContractStorage ().mainchainHead;
161+ }
162+
163+ /// @inheritdoc ISPVContract
164+ function getMainchainHeight () public view returns (uint64 ) {
165+ return getBlockHeight (_getSPVContractStorage ().mainchainHead);
166+ }
167+
167168 /// @inheritdoc ISPVContract
168169 function getBlockInfo (bytes32 blockHash_ ) external view returns (BlockInfo memory blockInfo_ ) {
169170 if (! blockExists (blockHash_)) {
170171 return blockInfo_;
171172 }
172173
173- BlockData memory blockData_ = getBlockData (blockHash_) ;
174+ BlockData memory blockData_ = _getSPVContractStorage ().blocksData[blockHash_] ;
174175
175176 blockInfo_ = BlockInfo ({
176177 mainBlockData: blockData_,
@@ -180,48 +181,57 @@ contract SPVContract is ISPVContract, Initializable {
180181 }
181182
182183 /// @inheritdoc ISPVContract
183- function getLastEpochCumulativeWork () external view returns (uint256 ) {
184- return _getSPVContractStorage ().lastEpochCumulativeWork;
185- }
184+ function getBlockHeader (bytes32 blockHash_ ) public view returns (BlockHeaderData memory ) {
185+ BlockData storage blockData = _getSPVContractStorage ().blocksData[blockHash_];
186186
187- /// @inheritdoc ISPVContract
188- function getBlockMerkleRoot (bytes32 blockHash_ ) public view returns (bytes32 ) {
189- return _getBlockHeader (blockHash_).merkleRoot;
187+ return
188+ BlockHeaderData ({
189+ version: blockData.version,
190+ prevBlockHash: blockData.prevBlockHash,
191+ merkleRoot: blockData.merkleRoot,
192+ time: blockData.time,
193+ bits: blockData.bits,
194+ nonce: blockData.nonce
195+ });
190196 }
191197
192198 /// @inheritdoc ISPVContract
193- function getMainchainHead () public view returns (bytes32 ) {
194- return _getSPVContractStorage ().mainchainHead;
199+ function getBlockStatus (bytes32 blockHash_ ) external view returns (bool , uint64 ) {
200+ if (! isInMainchain (blockHash_)) {
201+ return (false , 0 );
202+ }
203+
204+ return (true , getMainchainHeight () - getBlockHeight (blockHash_));
195205 }
196206
197207 /// @inheritdoc ISPVContract
198- function getBlockData (bytes32 blockHash_ ) public view returns (BlockData memory ) {
199- return _getSPVContractStorage ().blocksData[blockHash_];
208+ function getBlockMerkleRoot (bytes32 blockHash_ ) public view returns (bytes32 ) {
209+ return _getSPVContractStorage ().blocksData[blockHash_].merkleRoot ;
200210 }
201211
202212 /// @inheritdoc ISPVContract
203- function getBlockHeight (bytes32 blockHash_ ) public view returns (uint256 ) {
213+ function getBlockHeight (bytes32 blockHash_ ) public view returns (uint64 ) {
204214 return _getSPVContractStorage ().blocksData[blockHash_].blockHeight;
205215 }
206216
207217 /// @inheritdoc ISPVContract
208- function getBlockHash (uint256 blockHeight_ ) public view returns (bytes32 ) {
218+ function getBlockHash (uint64 blockHeight_ ) public view returns (bytes32 ) {
209219 return _getSPVContractStorage ().blocksHeightToBlockHash[blockHeight_];
210220 }
211221
212222 /// @inheritdoc ISPVContract
213223 function getBlockTarget (bytes32 blockHash_ ) public view returns (bytes32 ) {
214- return TargetsHelper.bitsToTarget (_getBlockHeader (blockHash_) .bits);
224+ return TargetsHelper.bitsToTarget (_getSPVContractStorage ().blocksData[blockHash_] .bits);
215225 }
216226
217227 /// @inheritdoc ISPVContract
218- function blockExists ( bytes32 blockHash_ ) public view returns (bool ) {
219- return _getBlockHeader (blockHash_).time > 0 ;
228+ function getLastEpochCumulativeWork ( ) public view returns (uint256 ) {
229+ return _getSPVContractStorage ().lastEpochCumulativeWork ;
220230 }
221231
222232 /// @inheritdoc ISPVContract
223- function getMainchainBlockHeight ( ) public view returns (uint256 ) {
224- return getBlockHeight ( _getSPVContractStorage ().mainchainHead) ;
233+ function blockExists ( bytes32 blockHash_ ) public view returns (bool ) {
234+ return _getBlockHeaderTime (blockHash_) > 0 ;
225235 }
226236
227237 /// @inheritdoc ISPVContract
@@ -232,11 +242,19 @@ contract SPVContract is ISPVContract, Initializable {
232242 function _addBlock (
233243 BlockHeaderData memory blockHeader_ ,
234244 bytes32 blockHash_ ,
235- uint256 blockHeight_
245+ uint64 blockHeight_
236246 ) internal {
237247 SPVContractStorage storage $ = _getSPVContractStorage ();
238248
239- $.blocksData[blockHash_] = BlockData ({header: blockHeader_, blockHeight: blockHeight_});
249+ $.blocksData[blockHash_] = BlockData ({
250+ prevBlockHash: blockHeader_.prevBlockHash,
251+ merkleRoot: blockHeader_.merkleRoot,
252+ version: blockHeader_.version,
253+ time: blockHeader_.time,
254+ nonce: blockHeader_.nonce,
255+ bits: blockHeader_.bits,
256+ blockHeight: blockHeight_
257+ });
240258
241259 _updateMainchainHead (blockHeader_, blockHash_, blockHeight_);
242260
@@ -246,7 +264,7 @@ contract SPVContract is ISPVContract, Initializable {
246264 function _updateMainchainHead (
247265 BlockHeaderData memory blockHeader_ ,
248266 bytes32 blockHash_ ,
249- uint256 blockHeight_
267+ uint64 blockHeight_
250268 ) internal {
251269 SPVContractStorage storage $ = _getSPVContractStorage ();
252270
@@ -270,31 +288,34 @@ contract SPVContract is ISPVContract, Initializable {
270288 $.blocksHeightToBlockHash[blockHeight_] = blockHash_;
271289
272290 bytes32 prevBlockHash_ = blockHeader_.prevBlockHash;
273- uint256 prevBlockHeight_ = blockHeight_ - 1 ;
291+ uint64 prevBlockHeight_ = blockHeight_ - 1 ;
274292
275293 do {
276294 $.blocksHeightToBlockHash[prevBlockHeight_] = prevBlockHash_;
277295
278- prevBlockHash_ = _getBlockHeader (prevBlockHash_).prevBlockHash;
279- -- prevBlockHeight_;
296+ prevBlockHash_ = _getSPVContractStorage ().blocksData[prevBlockHash_].prevBlockHash;
297+
298+ unchecked {
299+ -- prevBlockHeight_;
300+ }
280301 } while (getBlockHash (prevBlockHeight_) != prevBlockHash_ && prevBlockHash_ != 0 );
281302 }
282303 }
283304
284305 function _updateLastEpochCumulativeWork (
285306 bytes32 currentTarget_ ,
286- uint256 blockHeight_
307+ uint64 blockHeight_
287308 ) internal returns (bytes32 ) {
288309 SPVContractStorage storage $ = _getSPVContractStorage ();
289310
290311 if (TargetsHelper.isTargetAdjustmentBlock (blockHeight_)) {
291312 $.lastEpochCumulativeWork += TargetsHelper.countEpochCumulativeWork (currentTarget_);
292313
293- uint256 epochStartTime_ = _getBlockHeader (
314+ uint32 epochStartTime_ = _getBlockHeaderTime (
294315 getBlockHash (blockHeight_ - TargetsHelper.DIFFICULTY_ADJUSTMENT_INTERVAL)
295- ).time ;
296- uint256 epochEndTime_ = _getBlockHeader (getBlockHash (blockHeight_ - 1 )).time ;
297- uint256 passedTime_ = epochEndTime_ - epochStartTime_;
316+ );
317+ uint32 epochEndTime_ = _getBlockHeaderTime (getBlockHash (blockHeight_ - 1 ));
318+ uint32 passedTime_ = epochEndTime_ - epochStartTime_;
298319
299320 currentTarget_ = TargetsHelper.countNewRoundedTarget (currentTarget_, passedTime_);
300321 }
@@ -341,7 +362,7 @@ contract SPVContract is ISPVContract, Initializable {
341362
342363 function _getStorageMedianTime (
343364 BlockHeaderData memory blockHeader_ ,
344- uint256 blockHeight_
365+ uint64 blockHeight_
345366 ) internal view returns (uint32 ) {
346367 if (blockHeight_ == 1 ) {
347368 return blockHeader_.time;
@@ -350,17 +371,17 @@ contract SPVContract is ISPVContract, Initializable {
350371 bytes32 toBlockHash_ = blockHeader_.prevBlockHash;
351372
352373 if (blockHeight_ - 1 < MEDIAN_PAST_BLOCKS) {
353- return _getBlockHeader (toBlockHash_).time ;
374+ return _getBlockHeaderTime (toBlockHash_);
354375 }
355376
356377 uint256 [] memory blocksTime_ = new uint256 [](MEDIAN_PAST_BLOCKS);
357378 bool needsSort_;
358379
359380 for (uint256 i = MEDIAN_PAST_BLOCKS; i > 0 ; -- i) {
360- uint32 currentTime_ = _getBlockHeader (toBlockHash_).time ;
381+ uint32 currentTime_ = _getBlockHeaderTime (toBlockHash_);
361382
362383 blocksTime_[i - 1 ] = currentTime_;
363- toBlockHash_ = _getBlockHeader (toBlockHash_) .prevBlockHash;
384+ toBlockHash_ = _getSPVContractStorage ().blocksData[toBlockHash_] .prevBlockHash;
364385
365386 if (i < MEDIAN_PAST_BLOCKS && currentTime_ > blocksTime_[i]) {
366387 needsSort_ = true ;
@@ -372,7 +393,7 @@ contract SPVContract is ISPVContract, Initializable {
372393
373394 function _getMemoryMedianTime (
374395 BlockHeaderData[] memory blockHeaders_ ,
375- uint256 to_
396+ uint64 to_
376397 ) internal pure returns (uint32 ) {
377398 if (blockHeaders_.length < MEDIAN_PAST_BLOCKS) {
378399 return 0 ;
@@ -395,7 +416,7 @@ contract SPVContract is ISPVContract, Initializable {
395416 }
396417
397418 function _getBlockCumulativeWork (
398- uint256 blockHeight_ ,
419+ uint64 blockHeight_ ,
399420 bytes32 blockHash_
400421 ) internal view returns (uint256 ) {
401422 uint256 currentEpochCumulativeWork_ = getBlockTarget (blockHash_).countCumulativeWork (
@@ -405,8 +426,8 @@ contract SPVContract is ISPVContract, Initializable {
405426 return _getSPVContractStorage ().lastEpochCumulativeWork + currentEpochCumulativeWork_;
406427 }
407428
408- function _getBlockHeader (bytes32 blockHash_ ) internal view returns (BlockHeaderData storage ) {
409- return _getSPVContractStorage ().blocksData[blockHash_].header ;
429+ function _getBlockHeaderTime (bytes32 blockHash_ ) internal view returns (uint32 ) {
430+ return _getSPVContractStorage ().blocksData[blockHash_].time ;
410431 }
411432
412433 function _onlyNonExistingBlock (bytes32 blockHash_ ) internal view {
0 commit comments