Skip to content

Commit b4c6a99

Browse files
committed
Merge branch 'master' into dev
2 parents 920684d + 3ef7407 commit b4c6a99

20 files changed

+27610
-3788
lines changed

src/core-contracts/package-lock.json renamed to package-lock.json

Lines changed: 163 additions & 119 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core-contracts/contracts/HistoricalSPVGateway.sol

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ import {SPVGateway} from "./SPVGateway.sol";
1414

1515
contract HistoricalSPVGateway is IHistoricalSPVGateway, SPVGateway {
1616
using BlockHeader for bytes;
17-
using TargetsHelper for bytes32;
1817
using EndianConverter for bytes32;
1918
using BlockHistory for bytes32[];
2019

2120
bytes32 public constant HISTORICAL_SPV_GATEWAY_STORAGE_SLOT =
2221
keccak256("spv.gateway.historical.spv.gateway.storage");
2322

2423
struct HistoricalSPVGatewayStorage {
24+
uint32 lastHistoryEpochStartTime;
2525
uint256 historyBlocksCount;
2626
bytes32 historyBlocksTreeRoot;
2727
}
@@ -41,6 +41,7 @@ contract HistoricalSPVGateway is IHistoricalSPVGateway, SPVGateway {
4141
function __HistoricalSPVGateway_init(
4242
bytes calldata blockHeaderRaw_,
4343
uint64 blockHeight_,
44+
uint32 lastHistoryEpochStartTime_,
4445
uint256 cumulativeWork_,
4546
bytes32 historyBlocksTreeRoot_,
4647
BlockHistory.HistoryProofData calldata proofData_
@@ -53,12 +54,14 @@ contract HistoricalSPVGateway is IHistoricalSPVGateway, SPVGateway {
5354
historyBlocksTreeRoot_,
5455
blockHash_,
5556
blockHeight_,
57+
lastHistoryEpochStartTime_,
5658
cumulativeWork_,
5759
proofData_
5860
);
5961

6062
_initialize(blockHeader_, blockHash_, blockHeight_, cumulativeWork_);
6163

64+
_getHistoricalSPVGatewayStorage().lastHistoryEpochStartTime = lastHistoryEpochStartTime_;
6265
_getHistoricalSPVGatewayStorage().historyBlocksCount = blockHeight_;
6366
_getHistoricalSPVGatewayStorage().historyBlocksTreeRoot = historyBlocksTreeRoot_;
6467
}
@@ -107,6 +110,11 @@ contract HistoricalSPVGateway is IHistoricalSPVGateway, SPVGateway {
107110
);
108111
}
109112

113+
/// @inheritdoc IHistoricalSPVGateway
114+
function getLastHistoryEpochStartTime() public view returns (uint32) {
115+
return _getHistoricalSPVGatewayStorage().lastHistoryEpochStartTime;
116+
}
117+
110118
/// @inheritdoc IHistoricalSPVGateway
111119
function getHistoryBlocksCount() public view returns (uint256) {
112120
return _getHistoricalSPVGatewayStorage().historyBlocksCount;
@@ -116,4 +124,17 @@ contract HistoricalSPVGateway is IHistoricalSPVGateway, SPVGateway {
116124
function getHistoryBlocksTreeRoot() public view returns (bytes32) {
117125
return _getHistoricalSPVGatewayStorage().historyBlocksTreeRoot;
118126
}
127+
128+
function _getEpochPassedTime(uint64 blockHeight_) internal view override returns (uint32) {
129+
uint64 startEpochBlockHeight_ = blockHeight_ -
130+
TargetsHelper.DIFFICULTY_ADJUSTMENT_INTERVAL;
131+
132+
if (startEpochBlockHeight_ > getHistoryBlocksCount()) {
133+
return super._getEpochPassedTime(blockHeight_);
134+
}
135+
136+
uint32 epochEndTime_ = _getBlockHeaderTime(getBlockHash(blockHeight_ - 1));
137+
138+
return epochEndTime_ - getLastHistoryEpochStartTime();
139+
}
119140
}

src/core-contracts/contracts/SPVGateway.sol

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,13 +335,10 @@ contract SPVGateway is ISPVGateway, Initializable {
335335
if (TargetsHelper.isTargetAdjustmentBlock(blockHeight_)) {
336336
$.lastEpochCumulativeWork += TargetsHelper.countEpochCumulativeWork(currentTarget_);
337337

338-
uint32 epochStartTime_ = _getBlockHeaderTime(
339-
getBlockHash(blockHeight_ - TargetsHelper.DIFFICULTY_ADJUSTMENT_INTERVAL)
338+
currentTarget_ = TargetsHelper.countNewRoundedTarget(
339+
currentTarget_,
340+
_getEpochPassedTime(blockHeight_)
340341
);
341-
uint32 epochEndTime_ = _getBlockHeaderTime(getBlockHash(blockHeight_ - 1));
342-
uint32 passedTime_ = epochEndTime_ - epochStartTime_;
343-
344-
currentTarget_ = TargetsHelper.countNewRoundedTarget(currentTarget_, passedTime_);
345342
}
346343

347344
return currentTarget_;
@@ -439,6 +436,15 @@ contract SPVGateway is ISPVGateway, Initializable {
439436
return _getMedianTime(blocksTime_, needsSort_);
440437
}
441438

439+
function _getEpochPassedTime(uint64 blockHeight_) internal view virtual returns (uint32) {
440+
uint32 epochStartTime_ = _getBlockHeaderTime(
441+
getBlockHash(blockHeight_ - TargetsHelper.DIFFICULTY_ADJUSTMENT_INTERVAL)
442+
);
443+
uint32 epochEndTime_ = _getBlockHeaderTime(getBlockHash(blockHeight_ - 1));
444+
445+
return epochEndTime_ - epochStartTime_;
446+
}
447+
442448
function _getBlockCumulativeWork(
443449
uint64 blockHeight_,
444450
bytes32 blockHash_

src/core-contracts/contracts/interfaces/IHistoricalSPVGateway.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ interface IHistoricalSPVGateway is ISPVGateway {
6464
HistoryBlockInclusionProofData calldata inclusionProofData_
6565
) external view returns (bool);
6666

67+
/**
68+
* @notice Gets the last history epoch start time.
69+
* @return Returns the start time of the last history epoch.
70+
*/
71+
function getLastHistoryEpochStartTime() external view returns (uint32);
72+
6773
/**
6874
* @notice Gets the total number of historical blocks stored.
6975
* @return Returns the number of historical blocks.

src/core-contracts/contracts/libs/BlockHistory.sol

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ library BlockHistory {
3939
error InvalidProofBlockHash();
4040
error InvalidProofBlockHeight();
4141
error InvalidProofCumulativeWork();
42-
error InvalidProof();
42+
error InvalidProofEpochStartTime();
4343
error InvalidHistoryBlocksTreeRoot();
44+
error InvalidProof();
4445

4546
/**
4647
* @notice Verifies a ZK-SNARK proof for the Bitcoin history.
@@ -55,6 +56,7 @@ library BlockHistory {
5556
bytes32 historyBlocksTreeRoot_,
5657
bytes32 blockHash_,
5758
uint64 blockHeight_,
59+
uint32 currentEpochStartTime_,
5860
uint256 cumulativeWork_,
5961
HistoryProofData calldata proofData_
6062
) internal view returns (bool) {
@@ -64,6 +66,10 @@ library BlockHistory {
6466
cumulativeWork_ == getProofCumulativeWork(proofData_),
6567
InvalidProofCumulativeWork()
6668
);
69+
require(
70+
currentEpochStartTime_ == getProofEpochStartTime(blockHeight_ + 1, proofData_),
71+
InvalidProofEpochStartTime()
72+
);
6773
require(
6874
historyBlocksTreeRoot_ == getHistoryBlocksTreeRoot(blockHeight_ + 1, proofData_),
6975
InvalidHistoryBlocksTreeRoot()
@@ -180,11 +186,9 @@ library BlockHistory {
180186
uint64 provedBlocksCount_,
181187
HistoryProofData calldata proofData_
182188
) internal pure returns (bytes32 parsedBlocksTreeRoot_) {
183-
uint256 frontierLength_ = Math.log2(provedBlocksCount_ / CHUNK_SIZE) + 1;
184-
185-
bool isPowOf2_ = provedBlocksCount_ & (provedBlocksCount_ - 1) == 0;
189+
uint256 frontierLength_ = _countFrontierLength(provedBlocksCount_);
186190

187-
if (isPowOf2_) {
191+
if (LibBit.isPo2(provedBlocksCount_)) {
188192
parsedBlocksTreeRoot_ = _getBytes32FromInputs(
189193
proofData_,
190194
PROOF_FRONTIER_OFFSET + 32 * (frontierLength_ - 1)
@@ -227,6 +231,26 @@ library BlockHistory {
227231
return uint256(proofData_.publicInputs[PROOF_CUMULATIVE_WORK_OFFSET]);
228232
}
229233

234+
/**
235+
* @notice Retrieves the last proved epoch start time from the ZK proof's public inputs.
236+
* @param provedBlocksCount_ The total number of blocks included in the proof.
237+
* @param proofData_ The struct containing the proof and public inputs.
238+
* @return The epoch start time.
239+
*/
240+
function getProofEpochStartTime(
241+
uint64 provedBlocksCount_,
242+
HistoryProofData calldata proofData_
243+
) internal pure returns (uint32) {
244+
return
245+
uint32(
246+
uint256(
247+
proofData_.publicInputs[
248+
PROOF_FRONTIER_OFFSET + 32 * _countFrontierLength(provedBlocksCount_)
249+
]
250+
)
251+
);
252+
}
253+
230254
/**
231255
* @notice Calculates the chunk number for a given block height.
232256
* @param blockHeight_ The height of the block.
@@ -322,7 +346,7 @@ library BlockHistory {
322346
uint256 frontierLength_,
323347
HistoryProofData calldata proofData_
324348
) internal pure returns (bytes32 computedRoot_) {
325-
for (uint256 i = 0; i < frontierLength_; ++i) {
349+
for (uint256 i = 0; i < frontierLength_ - 1; ++i) {
326350
bytes32 currentNode_ = _getBytes32FromInputs(
327351
proofData_,
328352
PROOF_FRONTIER_OFFSET + 32 * i
@@ -348,6 +372,10 @@ library BlockHistory {
348372
}
349373
}
350374

375+
function _countFrontierLength(uint64 provedBlocksCount_) private pure returns (uint256) {
376+
return Math.log2(provedBlocksCount_ / CHUNK_SIZE, Math.Rounding.Ceil) + 1;
377+
}
378+
351379
function _processProof(
352380
bytes32[] calldata merkleProof_,
353381
bytes32 value_,

0 commit comments

Comments
 (0)