Skip to content

Commit e1d6bd5

Browse files
authored
Merge pull request #7 from distributed-lab/optimizations
Add storage optimizations
2 parents b354b53 + 0f17350 commit e1d6bd5

File tree

8 files changed

+186
-160
lines changed

8 files changed

+186
-160
lines changed

contracts/SPVContract.sol

Lines changed: 74 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)