From 3681483efe97c38a488563594c003dabfa23b2de Mon Sep 17 00:00:00 2001 From: Daniel Wang <99078276+dantaik@users.noreply.github.com> Date: Fri, 9 Dec 2022 16:24:51 +0800 Subject: [PATCH] fix(protocol): update avg proof time and avg block time (#391) --- packages/protocol/contracts/L1/LibData.sol | 4 +++- .../protocol/contracts/L1/v1/V1Proposing.sol | 8 +++++++ .../protocol/contracts/L1/v1/V1Proving.sol | 3 ++- packages/protocol/contracts/L1/v1/V1Utils.sol | 21 +++++++++++++++++-- .../protocol/contracts/L1/v1/V1Verifying.sol | 20 +++++++++++++++--- .../protocol/contracts/libs/LibConstants.sol | 5 +++++ 6 files changed, 54 insertions(+), 7 deletions(-) diff --git a/packages/protocol/contracts/L1/LibData.sol b/packages/protocol/contracts/L1/LibData.sol index d753a798a83..d7d7f884fcc 100644 --- a/packages/protocol/contracts/L1/LibData.sol +++ b/packages/protocol/contracts/L1/LibData.sol @@ -63,7 +63,9 @@ library LibData { // Changed when a block is proven/finalized uint64 latestVerifiedHeight; uint64 latestVerifiedId; - uint64 avgProofTime; // the proof time moving average + // the proof time moving average, note that for each block, only the + // first proof's time is considered. + uint64 avgProofTime; uint64 __reservedC1; // Reserved uint256[42] __gap; diff --git a/packages/protocol/contracts/L1/v1/V1Proposing.sol b/packages/protocol/contracts/L1/v1/V1Proposing.sol index bdd7ed9b1f5..6add00c3b10 100644 --- a/packages/protocol/contracts/L1/v1/V1Proposing.sol +++ b/packages/protocol/contracts/L1/v1/V1Proposing.sol @@ -98,6 +98,14 @@ library V1Proposing { meta.mixHash = bytes32(block.difficulty); } + state.avgBlockTime = V1Utils + .movingAverage({ + maValue: state.avgBlockTime, + newValue: meta.timestamp - state.lastProposedAt, + maf: LibConstants.K_BLOCK_TIME_MAF + }) + .toUint64(); + state.saveProposedBlock( state.nextBlockId, LibData.ProposedBlock({ diff --git a/packages/protocol/contracts/L1/v1/V1Proving.sol b/packages/protocol/contracts/L1/v1/V1Proving.sol index 4182c022a51..0c0158e4e5f 100644 --- a/packages/protocol/contracts/L1/v1/V1Proving.sol +++ b/packages/protocol/contracts/L1/v1/V1Proving.sol @@ -269,7 +269,8 @@ library V1Proving { ); require( - block.timestamp < V1Utils.uncleProofDeadline(state, fc), + block.timestamp < + V1Utils.uncleProofDeadline(state, fc, target.id), "L1:tooLate" ); diff --git a/packages/protocol/contracts/L1/v1/V1Utils.sol b/packages/protocol/contracts/L1/v1/V1Utils.sol index b339b911899..5b1921ea073 100644 --- a/packages/protocol/contracts/L1/v1/V1Utils.sol +++ b/packages/protocol/contracts/L1/v1/V1Utils.sol @@ -96,9 +96,26 @@ library V1Utils { // Returns a deterministic deadline for uncle proof submission. function uncleProofDeadline( LibData.State storage state, - LibData.ForkChoice storage fc + LibData.ForkChoice storage fc, + uint256 blockId ) internal view returns (uint64) { - return fc.provenAt + state.avgProofTime; + if (blockId <= 2 * LibConstants.K_MAX_NUM_BLOCKS) { + return fc.provenAt + LibConstants.K_INITIAL_UNCLE_DELAY; + } else { + return fc.provenAt + state.avgProofTime; + } + } + + function movingAverage( + uint256 maValue, + uint256 newValue, + uint256 maf + ) internal pure returns (uint256) { + if (maValue == 0) { + return newValue; + } + uint256 _ma = (maValue * (maf - 1) + newValue) / maf; + return _ma > 0 ? _ma : maValue; } function setBit( diff --git a/packages/protocol/contracts/L1/v1/V1Verifying.sol b/packages/protocol/contracts/L1/v1/V1Verifying.sol index c57776928f6..9f33dcc1356 100644 --- a/packages/protocol/contracts/L1/v1/V1Verifying.sol +++ b/packages/protocol/contracts/L1/v1/V1Verifying.sol @@ -61,15 +61,28 @@ library V1Verifying { i++ ) { LibData.ForkChoice storage fc = state.forkChoices[i][latestL2Hash]; + LibData.ProposedBlock storage target = LibData.getProposedBlock( + state, + i + ); // Uncle proof can not take more than 2x time the first proof did. - if (!_isVerifiable(state, fc)) { + if (!_isVerifiable(state, fc, i)) { break; } else { if (fc.blockHash != LibConstants.K_BLOCK_DEADEND_HASH) { latestL2Height += 1; latestL2Hash = fc.blockHash; } + + state.avgProofTime = V1Utils + .movingAverage({ + maValue: state.avgProofTime, + newValue: fc.provenAt - target.proposedAt, + maf: LibConstants.K_PROOF_TIME_MAF + }) + .toUint64(); + processed += 1; emit BlockVerified(i, fc.blockHash); _cleanUp(fc); @@ -98,10 +111,11 @@ library V1Verifying { function _isVerifiable( LibData.State storage state, - LibData.ForkChoice storage fc + LibData.ForkChoice storage fc, + uint256 blockId ) private view returns (bool) { return fc.blockHash != 0 && - block.timestamp > V1Utils.uncleProofDeadline(state, fc); + block.timestamp > V1Utils.uncleProofDeadline(state, fc, blockId); } } diff --git a/packages/protocol/contracts/libs/LibConstants.sol b/packages/protocol/contracts/libs/LibConstants.sol index a5782a01250..4804c038d8f 100644 --- a/packages/protocol/contracts/libs/LibConstants.sol +++ b/packages/protocol/contracts/libs/LibConstants.sol @@ -26,6 +26,11 @@ library LibConstants { uint256 public constant K_TX_MIN_GAS_LIMIT = 21000; // TODO uint256 public constant K_ANCHOR_TX_GAS_LIMIT = 250000; + uint256 public constant K_BLOCK_TIME_MAF = 1024; + uint256 public constant K_PROOF_TIME_MAF = 1024; + + uint64 public constant K_INITIAL_UNCLE_DELAY = 60 minutes; + bytes4 public constant K_ANCHOR_TX_SELECTOR = bytes4(keccak256("anchor(uint256,bytes32)"));