diff --git a/.gitignore b/.gitignore index a718c28914..6c624e2e1f 100644 --- a/.gitignore +++ b/.gitignore @@ -109,8 +109,4 @@ dist # vscode .vscode/ -# python -__pycache__/ - -# whitepaper -.pdf +.pdf \ No newline at end of file diff --git a/packages/protocol/contracts/L1/LibData.sol b/packages/protocol/contracts/L1/LibData.sol index 0a191dc77a..c6f2f325c1 100644 --- a/packages/protocol/contracts/L1/LibData.sol +++ b/packages/protocol/contracts/L1/LibData.sol @@ -28,8 +28,6 @@ library LibData { struct ProposedBlock { bytes32 metaHash; - address proposer; - uint64 gasLimit; } struct ForkChoice { @@ -39,7 +37,6 @@ library LibData { address[] provers; } - // This struct takes 9 slots. struct State { // block id => block hash mapping(uint256 => bytes32) l2Hashes; @@ -50,25 +47,11 @@ library LibData { // proposer => commitSlot => hash(commitHash, commitHeight) mapping(address => mapping(uint256 => bytes32)) commits; mapping(address => bool) provers; // Whitelisted provers - // Never or rarely changed + uint64 statusBits; uint64 genesisHeight; - uint64 genesisTimestamp; - uint64 __reservedA1; - uint64 statusBits; // rarely change - // Changed when a block is proposed or proven/finalized - uint256 feeBase; - // Changed when a block is proposed - uint64 nextBlockId; - uint64 lastProposedAt; // Timestamp when the last block is proposed. - uint64 avgBlockTime; // The block time moving average - uint64 __avgGasLimit; // the block gas-limit moving average, not updated. - // Changed when a block is proven/finalized uint64 latestVerifiedHeight; uint64 latestVerifiedId; - uint64 avgProofTime; // the proof time moving average - uint64 __reservedC1; - // Reserved - uint256[41] __gap; + uint64 nextBlockId; } function saveProposedBlock( @@ -76,14 +59,14 @@ library LibData { uint256 id, ProposedBlock memory blk ) internal { - s.proposedBlocks[id % LibConstants.K_MAX_NUM_BLOCKS] = blk; + s.proposedBlocks[id % LibConstants.TAIKO_MAX_PROPOSED_BLOCKS] = blk; } function getProposedBlock( State storage s, uint256 id ) internal view returns (ProposedBlock storage) { - return s.proposedBlocks[id % LibConstants.K_MAX_NUM_BLOCKS]; + return s.proposedBlocks[id % LibConstants.TAIKO_MAX_PROPOSED_BLOCKS]; } function getL2BlockHash( diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index 53c699db5c..45a4586934 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -16,10 +16,10 @@ import "../common/IHeaderSync.sol"; import "../libs/LibAnchorSignature.sol"; import "./LibData.sol"; import "./v1/V1Events.sol"; +import "./v1/V1Finalizing.sol"; import "./v1/V1Proposing.sol"; import "./v1/V1Proving.sol"; import "./v1/V1Utils.sol"; -import "./v1/V1Verifying.sol"; /** * @author dantaik @@ -30,15 +30,14 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { using SafeCastUpgradeable for uint256; LibData.State public state; - uint256[50] private __gap; + uint256[43] private __gap; function init( address _addressManager, - bytes32 _genesisBlockHash, - uint256 _feeBase + bytes32 _genesisBlockHash ) external initializer { EssentialContract._init(_addressManager); - V1Verifying.init(state, _genesisBlockHash, _feeBase); + V1Finalizing.init(state, _genesisBlockHash); } /** @@ -75,11 +74,10 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { * transactions in the L2 block. */ function proposeBlock(bytes[] calldata inputs) external nonReentrant { - V1Proposing.proposeBlock(state, AddressResolver(this), inputs); - V1Verifying.verifyBlocks( + V1Proposing.proposeBlock(state, inputs); + V1Finalizing.verifyBlocks( state, - AddressResolver(this), - LibConstants.K_MAX_VERIFICATIONS_PER_TX, + LibConstants.TAIKO_MAX_VERIFICATIONS_PER_TX, false ); } @@ -104,10 +102,9 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { bytes[] calldata inputs ) external nonReentrant { V1Proving.proveBlock(state, AddressResolver(this), blockIndex, inputs); - V1Verifying.verifyBlocks( + V1Finalizing.verifyBlocks( state, - AddressResolver(this), - LibConstants.K_MAX_VERIFICATIONS_PER_TX, + LibConstants.TAIKO_MAX_VERIFICATIONS_PER_TX, false ); } @@ -136,10 +133,9 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { blockIndex, inputs ); - V1Verifying.verifyBlocks( + V1Finalizing.verifyBlocks( state, - AddressResolver(this), - LibConstants.K_MAX_VERIFICATIONS_PER_TX, + LibConstants.TAIKO_MAX_VERIFICATIONS_PER_TX, false ); } @@ -150,7 +146,7 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { */ function verifyBlocks(uint256 maxBlocks) external nonReentrant { require(maxBlocks > 0, "L1:maxBlocks"); - V1Verifying.verifyBlocks(state, AddressResolver(this), maxBlocks, true); + V1Finalizing.verifyBlocks(state, maxBlocks, true); } /* Add or remove a prover from the whitelist. @@ -183,21 +179,6 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { return V1Proving.isProverWhitelisted(state, prover); } - function getBlockFee() public view returns (uint256 premiumFee) { - (, premiumFee) = V1Proposing.getBlockFee(state); - } - - function getProofReward( - uint64 provenAt, - uint64 proposedAt - ) public view returns (uint256 premiumReward) { - (, premiumReward) = V1Verifying.getProofReward( - state, - provenAt, - proposedAt - ); - } - /** * Check if the L1 is halted. * @return True if halted, false otherwise. @@ -246,35 +227,35 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { public pure returns ( - uint256, // K_CHAIN_ID - uint256, // K_MAX_NUM_BLOCKS - uint256, // K_MAX_VERIFICATIONS_PER_TX - uint256, // K_COMMIT_DELAY_CONFIRMS - uint256, // K_MAX_PROOFS_PER_FORK_CHOICE - uint256, // K_BLOCK_MAX_GAS_LIMIT - uint256, // K_BLOCK_MAX_TXS - bytes32, // K_BLOCK_DEADEND_HASH - uint256, // K_TXLIST_MAX_BYTES - uint256, // K_TX_MIN_GAS_LIMIT - uint256, // K_ANCHOR_TX_GAS_LIMIT - bytes4, // K_ANCHOR_TX_SELECTOR - bytes32 // K_INVALIDATE_BLOCK_LOG_TOPIC + uint256, // TAIKO_CHAIN_ID + uint256, // TAIKO_MAX_PROPOSED_BLOCKS + uint256, // TAIKO_MAX_VERIFICATIONS_PER_TX + uint256, // TAIKO_COMMIT_DELAY_CONFIRMATIONS + uint256, // TAIKO_MAX_PROOFS_PER_FORK_CHOICE + uint256, // TAIKO_BLOCK_MAX_GAS_LIMIT + uint256, // TAIKO_BLOCK_MAX_TXS + bytes32, // TAIKO_BLOCK_DEADEND_HASH + uint256, // TAIKO_TXLIST_MAX_BYTES + uint256, // TAIKO_TX_MIN_GAS_LIMIT + uint256, // V1_ANCHOR_TX_GAS_LIMIT + bytes4, // V1_ANCHOR_TX_SELECTOR + bytes32 // V1_INVALIDATE_BLOCK_LOG_TOPIC ) { return ( - LibConstants.K_CHAIN_ID, - LibConstants.K_MAX_NUM_BLOCKS, - LibConstants.K_MAX_VERIFICATIONS_PER_TX, - LibConstants.K_COMMIT_DELAY_CONFIRMS, - LibConstants.K_MAX_PROOFS_PER_FORK_CHOICE, - LibConstants.K_BLOCK_MAX_GAS_LIMIT, - LibConstants.K_BLOCK_MAX_TXS, - LibConstants.K_BLOCK_DEADEND_HASH, - LibConstants.K_TXLIST_MAX_BYTES, - LibConstants.K_TX_MIN_GAS_LIMIT, - LibConstants.K_ANCHOR_TX_GAS_LIMIT, - LibConstants.K_ANCHOR_TX_SELECTOR, - LibConstants.K_INVALIDATE_BLOCK_LOG_TOPIC + LibConstants.TAIKO_CHAIN_ID, + LibConstants.TAIKO_MAX_PROPOSED_BLOCKS, + LibConstants.TAIKO_MAX_VERIFICATIONS_PER_TX, + LibConstants.TAIKO_COMMIT_DELAY_CONFIRMATIONS, + LibConstants.TAIKO_MAX_PROOFS_PER_FORK_CHOICE, + LibConstants.TAIKO_BLOCK_MAX_GAS_LIMIT, + LibConstants.TAIKO_BLOCK_MAX_TXS, + LibConstants.TAIKO_BLOCK_DEADEND_HASH, + LibConstants.TAIKO_TXLIST_MAX_BYTES, + LibConstants.TAIKO_TX_MIN_GAS_LIMIT, + LibConstants.V1_ANCHOR_TX_GAS_LIMIT, + LibConstants.V1_ANCHOR_TX_SELECTOR, + LibConstants.V1_INVALIDATE_BLOCK_LOG_TOPIC ); } } diff --git a/packages/protocol/contracts/L1/v1/V1Finalizing.sol b/packages/protocol/contracts/L1/v1/V1Finalizing.sol new file mode 100644 index 0000000000..0c2f3b17d6 --- /dev/null +++ b/packages/protocol/contracts/L1/v1/V1Finalizing.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +// +// ╭━━━━╮╱╱╭╮╱╱╱╱╱╭╮╱╱╱╱╱╭╮ +// ┃╭╮╭╮┃╱╱┃┃╱╱╱╱╱┃┃╱╱╱╱╱┃┃ +// ╰╯┃┃┣┻━┳┫┃╭┳━━╮┃┃╱╱╭━━┫╰━┳━━╮ +// ╱╱┃┃┃╭╮┣┫╰╯┫╭╮┃┃┃╱╭┫╭╮┃╭╮┃━━┫ +// ╱╱┃┃┃╭╮┃┃╭╮┫╰╯┃┃╰━╯┃╭╮┃╰╯┣━━┃ +// ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ +pragma solidity ^0.8.9; + +import "./V1Utils.sol"; + +/// @author dantaik +library V1Finalizing { + event BlockVerified(uint256 indexed id, bytes32 blockHash); + + event HeaderSynced( + uint256 indexed height, + uint256 indexed srcHeight, + bytes32 srcHash + ); + + function init(LibData.State storage s, bytes32 _genesisBlockHash) public { + s.l2Hashes[0] = _genesisBlockHash; + s.nextBlockId = 1; + s.genesisHeight = uint64(block.number); + + emit BlockVerified(0, _genesisBlockHash); + emit HeaderSynced(block.number, 0, _genesisBlockHash); + } + + function verifyBlocks( + LibData.State storage s, + uint256 maxBlocks, + bool checkHalt + ) public { + bool halted = V1Utils.isHalted(s); + if (checkHalt) { + require(!halted, "L1:halted"); + } else if (halted) { + // skip finalizing blocks + return; + } + + uint64 latestL2Height = s.latestVerifiedHeight; + bytes32 latestL2Hash = s.l2Hashes[latestL2Height]; + uint64 processed = 0; + + for ( + uint256 i = s.latestVerifiedId + 1; + i < s.nextBlockId && processed <= maxBlocks; + i++ + ) { + LibData.ForkChoice storage fc = s.forkChoices[i][latestL2Hash]; + + // TODO(daniel): use the average proof-time. + if ( + block.timestamp <= + fc.provenAt + LibConstants.K_VERIFICATION_DELAY + ) { + // This block is proven but still needs to wait for verificaiton. + break; + } + + if (fc.blockHash == LibConstants.TAIKO_BLOCK_DEADEND_HASH) { + emit BlockVerified(i, 0); + } else if (fc.blockHash != 0) { + latestL2Height += 1; + latestL2Hash = fc.blockHash; + emit BlockVerified(i, latestL2Hash); + } else { + break; + } + processed += 1; + } + + if (processed > 0) { + s.latestVerifiedId += processed; + + if (latestL2Height > s.latestVerifiedHeight) { + s.latestVerifiedHeight = latestL2Height; + s.l2Hashes[latestL2Height] = latestL2Hash; + emit HeaderSynced(block.number, latestL2Height, latestL2Hash); + } + } + } +} diff --git a/packages/protocol/contracts/L1/v1/V1Proposing.sol b/packages/protocol/contracts/L1/v1/V1Proposing.sol index 30cbc873c8..4663b8b113 100644 --- a/packages/protocol/contracts/L1/v1/V1Proposing.sol +++ b/packages/protocol/contracts/L1/v1/V1Proposing.sol @@ -11,7 +11,6 @@ pragma solidity ^0.8.9; import "../../common/ConfigManager.sol"; import "../../libs/LibConstants.sol"; import "../../libs/LibTxDecoder.sol"; -import "../TkoToken.sol"; import "./V1Utils.sol"; /// @author dantaik @@ -47,7 +46,6 @@ library V1Proposing { function proposeBlock( LibData.State storage s, - AddressResolver resolver, bytes[] calldata inputs ) public { require(!V1Utils.isHalted(s), "L1:halt"); @@ -83,12 +81,13 @@ library V1Proposing { require( txList.length > 0 && - txList.length <= LibConstants.K_TXLIST_MAX_BYTES && + txList.length <= LibConstants.TAIKO_TXLIST_MAX_BYTES && meta.txListHash == txList.hashTxList(), "L1:txList" ); require( - s.nextBlockId < s.latestVerifiedId + LibConstants.K_MAX_NUM_BLOCKS, + s.nextBlockId <= + s.latestVerifiedId + LibConstants.TAIKO_MAX_PROPOSED_BLOCKS, "L1:tooMany" ); @@ -103,51 +102,12 @@ library V1Proposing { s.saveProposedBlock( s.nextBlockId, - LibData.ProposedBlock({ - metaHash: LibData.hashMetadata(meta), - proposer: msg.sender, - gasLimit: meta.gasLimit - }) + LibData.ProposedBlock({metaHash: LibData.hashMetadata(meta)}) ); - if (LibConstants.K_TOKENOMICS_ENABLED) { - uint64 blockTime = meta.timestamp - s.lastProposedAt; - (uint256 fee, uint256 premiumFee) = getBlockFee(s); - s.feeBase = V1Utils.movingAverage(s.feeBase, fee, 1024); - - s.avgBlockTime = V1Utils - .movingAverage(s.avgBlockTime, blockTime, 1024) - .toUint64(); - - // s.avgGasLimit = V1Utils - // .movingAverage(s.avgGasLimit, meta.gasLimit, 1024) - // .toUint64(); - - TkoToken(resolver.resolve("tko_token")).burn( - msg.sender, - premiumFee - ); - } - - s.lastProposedAt = meta.timestamp; emit BlockProposed(s.nextBlockId++, meta); } - function getBlockFee( - LibData.State storage s - ) public view returns (uint256 fee, uint256 premiumFee) { - fee = V1Utils.getTimeAdjustedFee( - s, - true, - uint64(block.timestamp), - s.lastProposedAt, - s.avgBlockTime, - LibConstants.K_BLOCK_TIME_CAP - ); - premiumFee = V1Utils.getSlotsAdjustedFee(s, true, fee); - premiumFee = V1Utils.getBootstrapDiscountedFee(s, premiumFee); - } - function isCommitValid( LibData.State storage s, uint256 commitSlot, @@ -158,7 +118,7 @@ library V1Proposing { return s.commits[msg.sender][commitSlot] == hash && block.number >= - commitHeight + LibConstants.K_COMMIT_DELAY_CONFIRMS; + commitHeight + LibConstants.TAIKO_COMMIT_DELAY_CONFIRMATIONS; } function _validateMetadata(LibData.BlockMetadata memory meta) private pure { @@ -174,7 +134,7 @@ library V1Proposing { ); require( - meta.gasLimit <= LibConstants.K_BLOCK_MAX_GAS_LIMIT, + meta.gasLimit <= LibConstants.TAIKO_BLOCK_MAX_GAS_LIMIT, "L1:gasLimit" ); require(meta.extraData.length <= 32, "L1:extraData"); diff --git a/packages/protocol/contracts/L1/v1/V1Proving.sol b/packages/protocol/contracts/L1/v1/V1Proving.sol index 9fe9c52925..7b3dda8e40 100644 --- a/packages/protocol/contracts/L1/v1/V1Proving.sol +++ b/packages/protocol/contracts/L1/v1/V1Proving.sol @@ -79,11 +79,11 @@ library V1Proving { require(_tx.txType == 0, "L1:anchor:type"); require( _tx.destination == - resolver.resolve(LibConstants.K_CHAIN_ID, "taiko"), + resolver.resolve(LibConstants.TAIKO_CHAIN_ID, "taiko"), "L1:anchor:dest" ); require( - _tx.gasLimit == LibConstants.K_ANCHOR_TX_GAS_LIMIT, + _tx.gasLimit == LibConstants.V1_ANCHOR_TX_GAS_LIMIT, "L1:anchor:gasLimit" ); @@ -95,7 +95,7 @@ library V1Proving { LibBytesUtils.equal( _tx.data, bytes.concat( - LibConstants.K_ANCHOR_TX_SELECTOR, + LibConstants.V1_ANCHOR_TX_SELECTOR, bytes32(evidence.meta.l1Height), evidence.meta.l1Hash ) @@ -167,13 +167,13 @@ library V1Proving { LibReceiptDecoder.Log memory log = receipt.logs[0]; require( log.contractAddress == - resolver.resolve(LibConstants.K_CHAIN_ID, "taiko"), + resolver.resolve(LibConstants.TAIKO_CHAIN_ID, "taiko"), "L1:receipt:addr" ); require(log.data.length == 0, "L1:receipt:data"); require( log.topics.length == 2 && - log.topics[0] == LibConstants.K_INVALIDATE_BLOCK_LOG_TOPIC && + log.topics[0] == LibConstants.V1_INVALIDATE_BLOCK_LOG_TOPIC && log.topics[1] == target.txListHash, "L1:receipt:topics" ); @@ -195,7 +195,7 @@ library V1Proving { resolver, evidence, target, - LibConstants.K_BLOCK_DEADEND_HASH + LibConstants.TAIKO_BLOCK_DEADEND_HASH ); } @@ -285,14 +285,15 @@ library V1Proving { } require( - fc.provers.length < LibConstants.K_MAX_PROOFS_PER_FORK_CHOICE, + fc.provers.length < + LibConstants.TAIKO_MAX_PROOFS_PER_FORK_CHOICE, "L1:proof:tooMany" ); - require( - block.timestamp < V1Utils.uncleProofDeadline(s, fc), - "L1:tooLate" - ); + // No uncle proof can take more than 1.5x time the first proof did. + uint256 delay = fc.provenAt - fc.proposedAt; + uint256 deadline = fc.provenAt + delay / 2; + require(block.timestamp <= deadline, "L1:tooLate"); for (uint256 i = 0; i < fc.provers.length; i++) { require(fc.provers[i] != prover, "L1:prover:dup"); @@ -352,7 +353,7 @@ library V1Proving { header.beneficiary == meta.beneficiary && header.difficulty == 0 && header.gasLimit == - meta.gasLimit + LibConstants.K_ANCHOR_TX_GAS_LIMIT && + meta.gasLimit + LibConstants.V1_ANCHOR_TX_GAS_LIMIT && header.gasUsed > 0 && header.timestamp == meta.timestamp && header.extraData.length == meta.extraData.length && diff --git a/packages/protocol/contracts/L1/v1/V1Utils.sol b/packages/protocol/contracts/L1/v1/V1Utils.sol index d86c98626e..caab538f41 100644 --- a/packages/protocol/contracts/L1/v1/V1Utils.sol +++ b/packages/protocol/contracts/L1/v1/V1Utils.sol @@ -15,8 +15,6 @@ import "../LibData.sol"; /// @author dantaik library V1Utils { - using LibMath for uint256; - uint64 public constant MASK_HALT = 1 << 0; event Halted(bool halted); @@ -31,82 +29,6 @@ library V1Utils { return isBitOne(s, MASK_HALT); } - // Implement "Incentive Multipliers", see the whitepaper. - function getTimeAdjustedFee( - LibData.State storage s, - bool isProposal, - uint64 tNow, - uint64 tLast, - uint64 tAvg, - uint64 tCap - ) internal view returns (uint256) { - if (tAvg == 0) { - return s.feeBase; - } - uint256 _tAvg = tAvg > tCap ? tCap : tAvg; - uint256 tGrace = (LibConstants.K_FEE_GRACE_PERIOD * _tAvg) / 100; - uint256 tMax = (LibConstants.K_FEE_MAX_PERIOD * _tAvg) / 100; - uint256 a = tLast + tGrace; - uint256 b = tNow > a ? tNow - a : 0; - uint256 tRel = (b.min(tMax) * 10000) / tMax; // [0 - 10000] - uint256 alpha = 10000 + - ((LibConstants.K_REWARD_MULTIPLIER - 100) * tRel) / - 100; - if (isProposal) { - return (s.feeBase * 10000) / alpha; // fee - } else { - return (s.feeBase * alpha) / 10000; // reward - } - } - - // Implement "Slot-availability Multipliers", see the whitepaper. - function getSlotsAdjustedFee( - LibData.State storage s, - bool isProposal, - uint256 fee - ) public view returns (uint256) { - // m is the `n'` in the whitepaper - uint256 m = LibConstants.K_MAX_NUM_BLOCKS - - 1 + - LibConstants.K_FEE_PREMIUM_LAMDA; - // n is the number of unverified blocks - uint256 n = s.nextBlockId - s.latestVerifiedId - 1; - // k is `m − n + 1` or `m − n - 1`in the whitepaper - uint256 k = isProposal ? m - n - 1 : m - n + 1; - return (fee * (m - 1) * m) / (m - n) / k; - } - - // Implement "Bootstrap Discount Multipliers", see the whitepaper. - function getBootstrapDiscountedFee( - LibData.State storage s, - uint256 fee - ) internal view returns (uint256) { - uint256 halves = uint256(block.timestamp - s.genesisTimestamp) / - LibConstants.K_HALVING; - uint256 gamma = 1024 - (1024 >> halves); - return (fee * gamma) / 1024; - } - - function movingAverage( - uint256 ma, - uint256 v, - uint256 factor - ) internal pure returns (uint256) { - if (ma == 0) { - return v; - } - uint256 _ma = (ma * (factor - 1) + v) / factor; - return _ma > 0 ? _ma : ma; - } - - // Returns a deterministic deadline for uncle proof submission. - function uncleProofDeadline( - LibData.State storage s, - LibData.ForkChoice storage fc - ) internal view returns (uint64) { - return fc.provenAt + s.avgProofTime; - } - function setBit(LibData.State storage s, uint64 mask, bool one) private { s.statusBits = one ? s.statusBits | mask : s.statusBits & ~mask; } diff --git a/packages/protocol/contracts/L1/v1/V1Verifying.sol b/packages/protocol/contracts/L1/v1/V1Verifying.sol deleted file mode 100644 index 2fb760c870..0000000000 --- a/packages/protocol/contracts/L1/v1/V1Verifying.sol +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// ╭━━━━╮╱╱╭╮╱╱╱╱╱╭╮╱╱╱╱╱╭╮ -// ┃╭╮╭╮┃╱╱┃┃╱╱╱╱╱┃┃╱╱╱╱╱┃┃ -// ╰╯┃┃┣┻━┳┫┃╭┳━━╮┃┃╱╱╭━━┫╰━┳━━╮ -// ╱╱┃┃┃╭╮┣┫╰╯┫╭╮┃┃┃╱╭┫╭╮┃╭╮┃━━┫ -// ╱╱┃┃┃╭╮┃┃╭╮┫╰╯┃┃╰━╯┃╭╮┃╰╯┣━━┃ -// ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ -pragma solidity ^0.8.9; - -import "../../common/AddressResolver.sol"; -import "../TkoToken.sol"; -import "./V1Utils.sol"; - -/// @author dantaik -library V1Verifying { - using SafeCastUpgradeable for uint256; - event BlockVerified(uint256 indexed id, bytes32 blockHash); - - event HeaderSynced( - uint256 indexed height, - uint256 indexed srcHeight, - bytes32 srcHash - ); - - function init( - LibData.State storage s, - bytes32 _genesisBlockHash, - uint256 _feeBase - ) public { - require(_feeBase > 0, "L1:feeBase"); - - s.genesisHeight = uint64(block.number); - s.genesisTimestamp = uint64(block.timestamp); - s.feeBase = _feeBase; - s.nextBlockId = 1; - s.lastProposedAt = uint64(block.timestamp); - s.l2Hashes[0] = _genesisBlockHash; - - emit BlockVerified(0, _genesisBlockHash); - emit HeaderSynced(block.number, 0, _genesisBlockHash); - } - - function verifyBlocks( - LibData.State storage s, - AddressResolver resolver, - uint256 maxBlocks, - bool checkHalt - ) public { - bool halted = V1Utils.isHalted(s); - if (checkHalt) { - require(!halted, "L1:halted"); - } else if (halted) { - // skip finalizing blocks - return; - } - - uint64 latestL2Height = s.latestVerifiedHeight; - bytes32 latestL2Hash = s.l2Hashes[latestL2Height]; - uint64 processed = 0; - TkoToken tkoToken; - - for ( - uint256 i = s.latestVerifiedId + 1; - i < s.nextBlockId && processed <= maxBlocks; - i++ - ) { - LibData.ForkChoice storage fc = s.forkChoices[i][latestL2Hash]; - - // Uncle proof can not take more than 2x time the first proof did. - if ( - fc.blockHash == 0 || - block.timestamp <= V1Utils.uncleProofDeadline(s, fc) - ) { - break; - } else { - if (fc.blockHash != LibConstants.K_BLOCK_DEADEND_HASH) { - latestL2Height += 1; - latestL2Hash = fc.blockHash; - } - - if (LibConstants.K_TOKENOMICS_ENABLED) { - (uint256 reward, uint256 premiumReward) = getProofReward( - s, - fc.provenAt, - fc.proposedAt - ); - - s.feeBase = V1Utils.movingAverage(s.feeBase, reward, 1024); - - s.avgProofTime = V1Utils - .movingAverage( - s.avgProofTime, - fc.provenAt - fc.proposedAt, - 1024 - ) - .toUint64(); - - if (address(tkoToken) == address(0)) { - tkoToken = TkoToken(resolver.resolve("tko_token")); - } - - // Reward multiple provers - uint sum = 2 ** fc.provers.length - 1; - for (uint k = 0; k < fc.provers.length; k++) { - uint weight = (1 << (fc.provers.length - k - 1)); - uint proverReward = (premiumReward * weight) / sum; - - if (tkoToken.balanceOf(fc.provers[k]) == 0) { - // reduce reward if the prover has 0 TKO balance. - proverReward /= 2; - } - tkoToken.mint(fc.provers[k], proverReward); - } - } - - emit BlockVerified(i, fc.blockHash); - } - - processed += 1; - } - - if (processed > 0) { - s.latestVerifiedId += processed; - - if (latestL2Height > s.latestVerifiedHeight) { - s.latestVerifiedHeight = latestL2Height; - s.l2Hashes[latestL2Height] = latestL2Hash; - emit HeaderSynced(block.number, latestL2Height, latestL2Hash); - } - } - } - - function getProofReward( - LibData.State storage s, - uint64 provenAt, - uint64 proposedAt - ) public view returns (uint256 reward, uint256 premiumReward) { - reward = V1Utils.getTimeAdjustedFee( - s, - false, - provenAt, - proposedAt, - s.avgProofTime, - LibConstants.K_PROOF_TIME_CAP - ); - premiumReward = V1Utils.getSlotsAdjustedFee(s, false, reward); - premiumReward = - (premiumReward * (10000 - LibConstants.K_REWARD_BURN_POINTS)) / - 10000; - } -} diff --git a/packages/protocol/contracts/L2/V1TaikoL2.sol b/packages/protocol/contracts/L2/V1TaikoL2.sol index 1e101fa9d3..b087bd9d01 100644 --- a/packages/protocol/contracts/L2/V1TaikoL2.sol +++ b/packages/protocol/contracts/L2/V1TaikoL2.sol @@ -134,42 +134,39 @@ contract V1TaikoL2 is AddressResolver, ReentrancyGuard, IHeaderSync { * Private Functions * **********************/ - // NOTE: If the order of the return values of this function changes, then - // some test cases that using this function in generate_genesis.test.ts - // may also needs to be modified accordingly. function getConstants() public pure returns ( - uint256, // K_CHAIN_ID - uint256, // K_MAX_NUM_BLOCKS - uint256, // K_MAX_VERIFICATIONS_PER_TX - uint256, // K_COMMIT_DELAY_CONFIRMS - uint256, // K_MAX_PROOFS_PER_FORK_CHOICE - uint256, // K_BLOCK_MAX_GAS_LIMIT - uint256, // K_BLOCK_MAX_TXS - bytes32, // K_BLOCK_DEADEND_HASH - uint256, // K_TXLIST_MAX_BYTES - uint256, // K_TX_MIN_GAS_LIMIT - uint256, // K_ANCHOR_TX_GAS_LIMIT - bytes4, // K_ANCHOR_TX_SELECTOR - bytes32 // K_INVALIDATE_BLOCK_LOG_TOPIC + uint256, // TAIKO_CHAIN_ID + uint256, // TAIKO_MAX_PROPOSED_BLOCKS + uint256, // TAIKO_MAX_VERIFICATIONS_PER_TX + uint256, // TAIKO_COMMIT_DELAY_CONFIRMATIONS + uint256, // TAIKO_MAX_PROOFS_PER_FORK_CHOICE + uint256, // TAIKO_BLOCK_MAX_GAS_LIMIT + uint256, // TAIKO_BLOCK_MAX_TXS + bytes32, // TAIKO_BLOCK_DEADEND_HASH + uint256, // TAIKO_TXLIST_MAX_BYTES + uint256, // TAIKO_TX_MIN_GAS_LIMIT + uint256, // V1_ANCHOR_TX_GAS_LIMIT + bytes4, // V1_ANCHOR_TX_SELECTOR + bytes32 // V1_INVALIDATE_BLOCK_LOG_TOPIC ) { return ( - LibConstants.K_CHAIN_ID, - LibConstants.K_MAX_NUM_BLOCKS, - LibConstants.K_MAX_VERIFICATIONS_PER_TX, - LibConstants.K_COMMIT_DELAY_CONFIRMS, - LibConstants.K_MAX_PROOFS_PER_FORK_CHOICE, - LibConstants.K_BLOCK_MAX_GAS_LIMIT, - LibConstants.K_BLOCK_MAX_TXS, - LibConstants.K_BLOCK_DEADEND_HASH, - LibConstants.K_TXLIST_MAX_BYTES, - LibConstants.K_TX_MIN_GAS_LIMIT, - LibConstants.K_ANCHOR_TX_GAS_LIMIT, - LibConstants.K_ANCHOR_TX_SELECTOR, - LibConstants.K_INVALIDATE_BLOCK_LOG_TOPIC + LibConstants.TAIKO_CHAIN_ID, + LibConstants.TAIKO_MAX_PROPOSED_BLOCKS, + LibConstants.TAIKO_MAX_VERIFICATIONS_PER_TX, + LibConstants.TAIKO_COMMIT_DELAY_CONFIRMATIONS, + LibConstants.TAIKO_MAX_PROOFS_PER_FORK_CHOICE, + LibConstants.TAIKO_BLOCK_MAX_GAS_LIMIT, + LibConstants.TAIKO_BLOCK_MAX_TXS, + LibConstants.TAIKO_BLOCK_DEADEND_HASH, + LibConstants.TAIKO_TXLIST_MAX_BYTES, + LibConstants.TAIKO_TX_MIN_GAS_LIMIT, + LibConstants.V1_ANCHOR_TX_GAS_LIMIT, + LibConstants.V1_ANCHOR_TX_SELECTOR, + LibConstants.V1_INVALIDATE_BLOCK_LOG_TOPIC ); } @@ -201,9 +198,9 @@ contract V1TaikoL2 is AddressResolver, ReentrancyGuard, IHeaderSync { function _hashPublicInputs( uint256 chainId, uint256 number, - uint256 feeBase, + uint256 baseFee, bytes32[255] memory ancestors ) private pure returns (bytes32) { - return keccak256(abi.encodePacked(chainId, number, feeBase, ancestors)); + return keccak256(abi.encodePacked(chainId, number, baseFee, ancestors)); } } diff --git a/packages/protocol/contracts/bridge/BridgedERC20.sol b/packages/protocol/contracts/bridge/BridgedERC20.sol index 4df80c3466..bb1ef4268e 100644 --- a/packages/protocol/contracts/bridge/BridgedERC20.sol +++ b/packages/protocol/contracts/bridge/BridgedERC20.sol @@ -8,12 +8,10 @@ // ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ pragma solidity ^0.8.9; -import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; -// solhint-disable-next-line max-line-length -import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; - import "../common/EssentialContract.sol"; import "../thirdparty/ERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; /** * @author dantaik diff --git a/packages/protocol/contracts/bridge/EtherVault.sol b/packages/protocol/contracts/bridge/EtherVault.sol index 310b2360b2..cc874dbb9f 100644 --- a/packages/protocol/contracts/bridge/EtherVault.sol +++ b/packages/protocol/contracts/bridge/EtherVault.sol @@ -8,12 +8,10 @@ // ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ pragma solidity ^0.8.9; -// solhint-disable-next-line max-line-length -import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol"; - import "../common/EssentialContract.sol"; import "../libs/LibAddress.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol"; /** * Vault that holds Ether. diff --git a/packages/protocol/contracts/bridge/TokenVault.sol b/packages/protocol/contracts/bridge/TokenVault.sol index 7753ad9551..86e189fa87 100644 --- a/packages/protocol/contracts/bridge/TokenVault.sol +++ b/packages/protocol/contracts/bridge/TokenVault.sol @@ -8,7 +8,6 @@ // ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ pragma solidity ^0.8.9; -// solhint-disable-next-line max-line-length import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol"; diff --git a/packages/protocol/contracts/common/AddressResolver.sol b/packages/protocol/contracts/common/AddressResolver.sol index 24a6d01e92..0d4050ac6f 100644 --- a/packages/protocol/contracts/common/AddressResolver.sol +++ b/packages/protocol/contracts/common/AddressResolver.sol @@ -8,9 +8,8 @@ // ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ pragma solidity ^0.8.9; -import "@openzeppelin/contracts/utils/Strings.sol"; - import "./IAddressManager.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; /** * This abstract contract provides a name-to-address lookup. Under the hood, diff --git a/packages/protocol/contracts/common/EssentialContract.sol b/packages/protocol/contracts/common/EssentialContract.sol index 3c6b086d38..15efe953bd 100644 --- a/packages/protocol/contracts/common/EssentialContract.sol +++ b/packages/protocol/contracts/common/EssentialContract.sol @@ -9,7 +9,6 @@ pragma solidity ^0.8.9; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -// solhint-disable-next-line max-line-length import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "./AddressResolver.sol"; diff --git a/packages/protocol/contracts/libs/LibAnchorSignature.sol b/packages/protocol/contracts/libs/LibAnchorSignature.sol index 607f8fb5af..7256fd3241 100644 --- a/packages/protocol/contracts/libs/LibAnchorSignature.sol +++ b/packages/protocol/contracts/libs/LibAnchorSignature.sol @@ -11,9 +11,9 @@ import "../thirdparty/LibUint512.sol"; /// @author david library LibAnchorSignature { - address public constant K_GOLDEN_TOUCH_ADDRESS = + address public constant TAIKO_GOLDEN_TOUCH_ADDRESS = 0x0000777735367b36bC9B61C50022d9D0700dB4Ec; - uint256 public constant K_GOLDEN_TOUCH_PRIVATEKEY = + uint256 public constant TAIKO_GOLDEN_TOUCH_PRIVATEKEY = 0x92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce38; uint256 public constant GX = @@ -32,7 +32,7 @@ library LibAnchorSignature { // ( // uint256 GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW, // uint256 GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH - // ) = Uint512.mul256x256(GX, K_GOLDEN_TOUCH_PRIVATEKEY); + // ) = Uint512.mul256x256(GX, TAIKO_GOLDEN_TOUCH_PRIVATEKEY); uint256 public constant GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW = 0xb4a95509ce05fe8d45987859a067780d16a367c0e2cacf79cd301b93fb717940; uint256 public constant GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH = @@ -41,7 +41,7 @@ library LibAnchorSignature { // ( // uint256 GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW, // uint256 GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH - // ) = Uint512.mul256x256(GX2, K_GOLDEN_TOUCH_PRIVATEKEY); + // ) = Uint512.mul256x256(GX2, TAIKO_GOLDEN_TOUCH_PRIVATEKEY); uint256 public constant GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW = 0xad77eceea844778cb4376153fc8f06f12f1695df4585bf75bfb17ec19ce90818; uint256 public constant GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH = diff --git a/packages/protocol/contracts/libs/LibBlockHeader.sol b/packages/protocol/contracts/libs/LibBlockHeader.sol index a312d31484..37f7808753 100644 --- a/packages/protocol/contracts/libs/LibBlockHeader.sol +++ b/packages/protocol/contracts/libs/LibBlockHeader.sol @@ -78,7 +78,7 @@ library LibBlockHeader { return header.parentHash != 0 && header.ommersHash == EMPTY_OMMERS_HASH && - header.gasLimit <= LibConstants.K_BLOCK_MAX_GAS_LIMIT && + header.gasLimit <= LibConstants.TAIKO_BLOCK_MAX_GAS_LIMIT && header.extraData.length <= 32 && header.difficulty == 0 && header.nonce == 0; diff --git a/packages/protocol/contracts/libs/LibConstants.sol b/packages/protocol/contracts/libs/LibConstants.sol index 0f661cca73..f1beabd67a 100644 --- a/packages/protocol/contracts/libs/LibConstants.sol +++ b/packages/protocol/contracts/libs/LibConstants.sol @@ -11,37 +11,28 @@ pragma solidity ^0.8.9; /// @author dantaik library LibConstants { // https://github.com/ethereum-lists/chains/pull/1611 - uint256 public constant K_CHAIN_ID = 167; - uint256 public constant K_MAX_NUM_BLOCKS = 2049; // up to 2048 pending blocks - // This number is calculated from K_MAX_NUM_BLOCKS to make - // the 'the maximum value of the multiplier' close to 20.0 - uint256 public constant K_FEE_PREMIUM_LAMDA = 590; uint256 public constant K_ZKPROOFS_PER_BLOCK = 1; + uint256 public constant TAIKO_CHAIN_ID = 167; uint256 public constant K_VERIFICATION_DELAY = 60 minutes; - uint256 public constant K_MAX_VERIFICATIONS_PER_TX = 20; - uint256 public constant K_COMMIT_DELAY_CONFIRMS = 4; - uint256 public constant K_MAX_PROOFS_PER_FORK_CHOICE = 5; - uint256 public constant K_BLOCK_MAX_GAS_LIMIT = 5000000; // TODO - uint256 public constant K_BLOCK_MAX_TXS = 20; // TODO - uint256 public constant K_TXLIST_MAX_BYTES = 10240; // TODO - uint256 public constant K_TX_MIN_GAS_LIMIT = 21000; // TODO - uint256 public constant K_REWARD_BURN_POINTS = 100; // 1% - uint256 public constant K_ANCHOR_TX_GAS_LIMIT = 250000; + uint256 public constant TAIKO_MAX_PROPOSED_BLOCKS = 2048; + uint256 public constant TAIKO_MAX_VERIFICATIONS_PER_TX = 20; + uint256 public constant TAIKO_COMMIT_DELAY_CONFIRMATIONS = 4; + uint256 public constant TAIKO_MAX_PROOFS_PER_FORK_CHOICE = 5; + uint256 public constant TAIKO_BLOCK_MAX_GAS_LIMIT = 5000000; // TODO + uint256 public constant TAIKO_BLOCK_MAX_TXS = 20; // TODO + bytes32 public constant TAIKO_BLOCK_DEADEND_HASH = bytes32(uint256(1)); - uint64 public constant K_REWARD_MULTIPLIER = 400; // 400% - uint64 public constant K_FEE_GRACE_PERIOD = 125; // 125% - uint64 public constant K_FEE_MAX_PERIOD = 375; // 375% - uint64 public constant K_BLOCK_TIME_CAP = 48 seconds; - uint64 public constant K_PROOF_TIME_CAP = 60 minutes; - uint64 public constant K_HALVING = 180 days; + uint256 public constant TAIKO_TXLIST_MAX_BYTES = 10240; // TODO + uint256 public constant TAIKO_TX_MIN_GAS_LIMIT = 21000; // TODO - bytes4 public constant K_ANCHOR_TX_SELECTOR = + // Taiko L2 releated constants + uint256 public constant V1_ANCHOR_TX_GAS_LIMIT = 250000; + + bytes4 public constant V1_ANCHOR_TX_SELECTOR = bytes4(keccak256("anchor(uint256,bytes32)")); - bytes32 public constant K_BLOCK_DEADEND_HASH = bytes32(uint256(1)); - bytes32 public constant K_INVALIDATE_BLOCK_LOG_TOPIC = + bytes32 public constant V1_INVALIDATE_BLOCK_LOG_TOPIC = keccak256("BlockInvalidated(bytes32)"); bool public constant K_WHITELIST_PROVERS = false; - bool public constant K_TOKENOMICS_ENABLED = true; } diff --git a/packages/protocol/contracts/libs/LibInvalidTxList.sol b/packages/protocol/contracts/libs/LibInvalidTxList.sol index 40d3105129..5231a8167f 100644 --- a/packages/protocol/contracts/libs/LibInvalidTxList.sol +++ b/packages/protocol/contracts/libs/LibInvalidTxList.sol @@ -18,26 +18,23 @@ import "../thirdparty/LibRLPWriter.sol"; * A library to invalidate a txList using the following rules: * * A txList is valid if and only if: - * 1. The txList's length is no more than `K_TXLIST_MAX_BYTES`. + * 1. The txList's length is no more than `TAIKO_TXLIST_MAX_BYTES`. * 2. The txList is well-formed RLP, with no additional trailing bytes. - * 3. The total number of transactions is no more than `K_BLOCK_MAX_TXS`. + * 3. The total number of transactions is no more than `TAIKO_BLOCK_MAX_TXS`. * 4. The sum of all transaction gas limit is no more than - * `K_BLOCK_MAX_GAS_LIMIT`. + * `TAIKO_BLOCK_MAX_GAS_LIMIT`. * * A transaction is valid if and only if: * 1. The transaction is well-formed RLP, with no additional trailing bytes * (rule #1 in Ethereum yellow paper). * 2. The transaction's signature is valid (rule #2 in Ethereum yellow paper). * 3. The transaction's the gas limit is no smaller than the intrinsic gas - * `K_TX_MIN_GAS_LIMIT` (rule #5 in Ethereum yellow paper). + * `TAIKO_TX_MIN_GAS_LIMIT` (rule #5 in Ethereum yellow paper). * * @title LibInvalidTxList * @author david */ library LibInvalidTxList { - // NOTE: If the order of this enum changes, then some test cases that using - // this enum in generate_genesis.test.ts may also needs to be - // modified accordingly. enum Reason { OK, BINARY_TOO_LARGE, @@ -53,20 +50,20 @@ library LibInvalidTxList { Reason hint, uint256 txIdx ) internal pure returns (Reason) { - if (encoded.length > LibConstants.K_TXLIST_MAX_BYTES) { + if (encoded.length > LibConstants.TAIKO_TXLIST_MAX_BYTES) { return Reason.BINARY_TOO_LARGE; } try LibTxDecoder.decodeTxList(encoded) returns ( LibTxDecoder.TxList memory txList ) { - if (txList.items.length > LibConstants.K_BLOCK_MAX_TXS) { + if (txList.items.length > LibConstants.TAIKO_BLOCK_MAX_TXS) { return Reason.BLOCK_TOO_MANY_TXS; } if ( LibTxDecoder.sumGasLimit(txList) > - LibConstants.K_BLOCK_MAX_GAS_LIMIT + LibConstants.TAIKO_BLOCK_MAX_GAS_LIMIT ) { return Reason.BLOCK_GAS_LIMIT_TOO_LARGE; } @@ -84,7 +81,7 @@ library LibInvalidTxList { if (hint == Reason.TX_GAS_LIMIT_TOO_SMALL) { require( - _tx.gasLimit >= LibConstants.K_TX_MIN_GAS_LIMIT, + _tx.gasLimit >= LibConstants.TAIKO_TX_MIN_GAS_LIMIT, "bad hint" ); return Reason.TX_GAS_LIMIT_TOO_SMALL; diff --git a/packages/protocol/contracts/libs/LibTxDecoder.sol b/packages/protocol/contracts/libs/LibTxDecoder.sol index 9c10316f7d..c7aa4c2895 100644 --- a/packages/protocol/contracts/libs/LibTxDecoder.sol +++ b/packages/protocol/contracts/libs/LibTxDecoder.sol @@ -162,7 +162,10 @@ library LibTxDecoder { txLegacy.data = LibRLPReader.readBytes(body[5]); // EIP-155 is enabled on L2 txLegacy.v = uint8( - LibRLPReader.readUint256(body[6]) - LibConstants.K_CHAIN_ID * 2 + 35 + LibRLPReader.readUint256(body[6]) - + LibConstants.TAIKO_CHAIN_ID * + 2 + + 35 ); txLegacy.r = LibRLPReader.readUint256(body[7]); txLegacy.s = LibRLPReader.readUint256(body[8]); diff --git a/packages/protocol/contracts/libs/LibTxUtils.sol b/packages/protocol/contracts/libs/LibTxUtils.sol index d68edfbbdc..2faa63eb51 100644 --- a/packages/protocol/contracts/libs/LibTxUtils.sol +++ b/packages/protocol/contracts/libs/LibTxUtils.sol @@ -72,7 +72,9 @@ library LibTxUtils { // For legacy transactions, there are three more RLP items to // encode defined in EIP-155. if (transaction.txType == 0 && i == list.length - 4) { - list[i + 1] = LibRLPWriter.writeUint(LibConstants.K_CHAIN_ID); + list[i + 1] = LibRLPWriter.writeUint( + LibConstants.TAIKO_CHAIN_ID + ); list[i + 2] = LibRLPWriter.writeUint64(0); list[i + 3] = LibRLPWriter.writeUint64(0); break; diff --git a/packages/protocol/contracts/test/libs/TestLibAnchorSignature.sol b/packages/protocol/contracts/test/libs/TestLibAnchorSignature.sol index 3a80e2d2d1..2f1d0bcdc8 100644 --- a/packages/protocol/contracts/test/libs/TestLibAnchorSignature.sol +++ b/packages/protocol/contracts/test/libs/TestLibAnchorSignature.sol @@ -29,8 +29,8 @@ library TestLibAnchorSignature { function goldenTouchAddress() public pure returns (address, uint256) { return ( - LibAnchorSignature.K_GOLDEN_TOUCH_ADDRESS, - LibAnchorSignature.K_GOLDEN_TOUCH_PRIVATEKEY + LibAnchorSignature.TAIKO_GOLDEN_TOUCH_ADDRESS, + LibAnchorSignature.TAIKO_GOLDEN_TOUCH_PRIVATEKEY ); } } diff --git a/packages/protocol/docs/L1/LibData.md b/packages/protocol/docs/L1/LibData.md index 21c79e4035..63f11bb57d 100644 --- a/packages/protocol/docs/L1/LibData.md +++ b/packages/protocol/docs/L1/LibData.md @@ -22,8 +22,6 @@ struct BlockMetadata { ```solidity struct ProposedBlock { bytes32 metaHash; - address proposer; - uint64 gasLimit; } ``` @@ -49,18 +47,9 @@ struct State { mapping(uint256 => mapping(bytes32 => struct LibData.ForkChoice)) forkChoices; mapping(bytes32 => uint256) commits; uint64 genesisHeight; - uint64 genesisTimestamp; - uint64 reservedA1; - uint64 reservedA2; - uint256 feeBase; - uint64 nextBlockId; - uint64 lastProposedAt; - uint64 avgBlockTime; - uint64 avgGasLimit; uint64 latestVerifiedHeight; uint64 latestVerifiedId; - uint64 avgProofTime; - uint64 reservedC1; + uint64 nextBlockId; } ``` diff --git a/packages/protocol/docs/L1/TaikoL1.md b/packages/protocol/docs/L1/TaikoL1.md index 00fc777c97..7e18387f85 100644 --- a/packages/protocol/docs/L1/TaikoL1.md +++ b/packages/protocol/docs/L1/TaikoL1.md @@ -9,13 +9,13 @@ struct LibData.State state ### \_\_gap ```solidity -uint256[42] __gap +uint256[45] __gap ``` ### init ```solidity -function init(address _addressManager, bytes32 _genesisBlockHash, uint256 _feeBase) external +function init(address _addressManager, bytes32 _genesisBlockHash) external ``` ### commitBlock @@ -94,18 +94,6 @@ Verify up to N blocks. | --------- | ------- | ------------------------------- | | maxBlocks | uint256 | Max number of blocks to verify. | -### getBlockFee - -```solidity -function getBlockFee() public view returns (uint256 premiumFee) -``` - -### getProofReward - -```solidity -function getProofReward(uint64 provenAt, uint64 proposedAt) public view returns (uint256 premiumReward) -``` - ### isCommitValid ```solidity diff --git a/packages/protocol/docs/L1/v1/V1Finalizing.md b/packages/protocol/docs/L1/v1/V1Finalizing.md index 23129248ef..1dcf04bbe0 100644 --- a/packages/protocol/docs/L1/v1/V1Finalizing.md +++ b/packages/protocol/docs/L1/v1/V1Finalizing.md @@ -1,4 +1,4 @@ -## V1Verifying +## V1Finalizing ### BlockVerified @@ -15,11 +15,11 @@ event HeaderSynced(uint256 height, uint256 srcHeight, bytes32 srcHash) ### init ```solidity -function init(struct LibData.State s, bytes32 _genesisBlockHash, uint256 _feeBase) public +function init(struct LibData.State s, bytes32 _genesisBlockHash) public ``` ### verifyBlocks -``` - +```solidity +function verifyBlocks(struct LibData.State s, uint256 maxBlocks) public ``` diff --git a/packages/protocol/docs/L1/v1/V1Proposing.md b/packages/protocol/docs/L1/v1/V1Proposing.md index 01dce60bd9..2f2ce24c40 100644 --- a/packages/protocol/docs/L1/v1/V1Proposing.md +++ b/packages/protocol/docs/L1/v1/V1Proposing.md @@ -21,13 +21,7 @@ function commitBlock(struct LibData.State s, bytes32 commitHash) public ### proposeBlock ```solidity -function proposeBlock(struct LibData.State s, contract AddressResolver resolver, bytes[] inputs) public -``` - -### getBlockFee - -```solidity -function getBlockFee(struct LibData.State s) public view returns (uint256 fee, uint256 premiumFee) +function proposeBlock(struct LibData.State s, bytes[] inputs) public ``` ### isCommitValid @@ -36,12 +30,6 @@ function getBlockFee(struct LibData.State s) public view returns (uint256 fee, u function isCommitValid(struct LibData.State s, bytes32 hash) public view returns (bool) ``` -### \_calcProposerBootstrapReward - -```solidity -function _calcProposerBootstrapReward(struct LibData.State s) private view returns (uint256 proposerReward) -``` - ### \_validateMetadata ```solidity diff --git a/packages/protocol/docs/L1/v1/V1Utils.md b/packages/protocol/docs/L1/v1/V1Utils.md deleted file mode 100644 index b6aad8d139..0000000000 --- a/packages/protocol/docs/L1/v1/V1Utils.md +++ /dev/null @@ -1,19 +0,0 @@ -## V1Utils - -### feeScaleBeta - -```solidity -function feeScaleBeta(struct LibData.State s, uint256 fee, bool releaseOneSlot) public view returns (uint256) -``` - -### movingAverage - -```solidity -function movingAverage(uint256 ma, uint256 v, uint256 factor) internal pure returns (uint256) -``` - -### feeScaleAlpha - -```solidity -function feeScaleAlpha(uint64 tNow, uint64 tLast, uint64 tAvg) internal pure returns (uint256) -``` diff --git a/packages/protocol/docs/L2/V1TaikoL2.md b/packages/protocol/docs/L2/V1TaikoL2.md index 7cd8b1594f..643da92147 100644 --- a/packages/protocol/docs/L2/V1TaikoL2.md +++ b/packages/protocol/docs/L2/V1TaikoL2.md @@ -109,5 +109,5 @@ function _checkPublicInputs() private ### \_hashPublicInputs ```solidity -function _hashPublicInputs(uint256 chainId, uint256 number, uint256 feeBase, bytes32[255] ancestors) private pure returns (bytes32) +function _hashPublicInputs(uint256 chainId, uint256 number, uint256 baseFee, bytes32[255] ancestors) private pure returns (bytes32) ``` diff --git a/packages/protocol/docs/libs/LibAnchorSignature.md b/packages/protocol/docs/libs/LibAnchorSignature.md index 3d7fe857a4..ac0531d134 100644 --- a/packages/protocol/docs/libs/LibAnchorSignature.md +++ b/packages/protocol/docs/libs/LibAnchorSignature.md @@ -1,15 +1,15 @@ ## LibAnchorSignature -### K_GOLDEN_TOUCH_ADDRESS +### TAIKO_GOLDEN_TOUCH_ADDRESS ```solidity -address K_GOLDEN_TOUCH_ADDRESS +address TAIKO_GOLDEN_TOUCH_ADDRESS ``` -### K_GOLDEN_TOUCH_PRIVATEKEY +### TAIKO_GOLDEN_TOUCH_PRIVATEKEY ```solidity -uint256 K_GOLDEN_TOUCH_PRIVATEKEY +uint256 TAIKO_GOLDEN_TOUCH_PRIVATEKEY ``` ### GX diff --git a/packages/protocol/docs/libs/LibConstants.md b/packages/protocol/docs/libs/LibConstants.md index 59cfbfa1fe..812205af2d 100644 --- a/packages/protocol/docs/libs/LibConstants.md +++ b/packages/protocol/docs/libs/LibConstants.md @@ -1,109 +1,79 @@ ## LibConstants -### K_CHAIN_ID +### TAIKO_CHAIN_ID ```solidity -uint256 K_CHAIN_ID +uint256 TAIKO_CHAIN_ID ``` -### K_MAX_NUM_BLOCKS +### TAIKO_MAX_PROPOSED_BLOCKS ```solidity -uint256 K_MAX_NUM_BLOCKS +uint256 TAIKO_MAX_PROPOSED_BLOCKS ``` -### K_FEE_PREMIUM_PHI +### TAIKO_MAX_VERIFICATIONS_PER_TX ```solidity -uint256 K_FEE_PREMIUM_PHI +uint256 TAIKO_MAX_VERIFICATIONS_PER_TX ``` -### K_REWARD_MULTIPLIER +### TAIKO_COMMIT_DELAY_CONFIRMATIONS ```solidity -uint64 K_REWARD_MULTIPLIER +uint256 TAIKO_COMMIT_DELAY_CONFIRMATIONS ``` -### K_FEE_GRACE_PERIOD +### TAIKO_MAX_PROOFS_PER_FORK_CHOICE ```solidity -uint64 K_FEE_GRACE_PERIOD +uint256 TAIKO_MAX_PROOFS_PER_FORK_CHOICE ``` -### K_FEE_MAX_PERIOD +### TAIKO_BLOCK_MAX_GAS_LIMIT ```solidity -uint64 K_FEE_MAX_PERIOD +uint256 TAIKO_BLOCK_MAX_GAS_LIMIT ``` -### K_MAX_FINALIZATIONS_PER_TX +### TAIKO_BLOCK_MAX_TXS ```solidity -uint256 K_MAX_FINALIZATIONS_PER_TX +uint256 TAIKO_BLOCK_MAX_TXS ``` -### K_COMMIT_DELAY_CONFIRMS +### TAIKO_BLOCK_DEADEND_HASH ```solidity -uint256 K_COMMIT_DELAY_CONFIRMS +bytes32 TAIKO_BLOCK_DEADEND_HASH ``` -### K_MAX_PROOFS_PER_FORK_CHOICE +### TAIKO_TXLIST_MAX_BYTES ```solidity -uint256 K_MAX_PROOFS_PER_FORK_CHOICE +uint256 TAIKO_TXLIST_MAX_BYTES ``` -### K_BLOCK_MAX_GAS_LIMIT +### TAIKO_TX_MIN_GAS_LIMIT ```solidity -uint256 K_BLOCK_MAX_GAS_LIMIT +uint256 TAIKO_TX_MIN_GAS_LIMIT ``` -### K_BLOCK_MAX_TXS +### V1_ANCHOR_TX_GAS_LIMIT ```solidity -uint256 K_BLOCK_MAX_TXS +uint256 V1_ANCHOR_TX_GAS_LIMIT ``` -### K_BLOCK_DEADEND_HASH +### V1_ANCHOR_TX_SELECTOR ```solidity -bytes32 K_BLOCK_DEADEND_HASH +bytes4 V1_ANCHOR_TX_SELECTOR ``` -### K_TXLIST_MAX_BYTES +### V1_INVALIDATE_BLOCK_LOG_TOPIC ```solidity -uint256 K_TXLIST_MAX_BYTES -``` - -### K_TX_MIN_GAS_LIMIT - -```solidity -uint256 K_TX_MIN_GAS_LIMIT -``` - -### K_REWARD_BURN_POINTS - -```solidity -uint256 K_REWARD_BURN_POINTS -``` - -### K_ANCHOR_TX_GAS_LIMIT - -```solidity -uint256 K_ANCHOR_TX_GAS_LIMIT -``` - -### K_ANCHOR_TX_SELECTOR - -```solidity -bytes4 K_ANCHOR_TX_SELECTOR -``` - -### K_INVALIDATE_BLOCK_LOG_TOPIC - -```solidity -bytes32 K_INVALIDATE_BLOCK_LOG_TOPIC +bytes32 V1_INVALIDATE_BLOCK_LOG_TOPIC ``` diff --git a/packages/protocol/docs/libs/LibInvalidTxList.md b/packages/protocol/docs/libs/LibInvalidTxList.md index 15ff494ca5..2a2c134cc9 100644 --- a/packages/protocol/docs/libs/LibInvalidTxList.md +++ b/packages/protocol/docs/libs/LibInvalidTxList.md @@ -4,11 +4,11 @@ A library to invalidate a txList using the following rules: A txList is valid if and only if: -1. The txList's length is no more than `K_TXLIST_MAX_BYTES`. +1. The txList's length is no more than `TAIKO_TXLIST_MAX_BYTES`. 2. The txList is well-formed RLP, with no additional trailing bytes. -3. The total number of transactions is no more than `K_BLOCK_MAX_TXS`. +3. The total number of transactions is no more than `TAIKO_BLOCK_MAX_TXS`. 4. The sum of all transaction gas limit is no more than - `K_BLOCK_MAX_GAS_LIMIT`. + `TAIKO_BLOCK_MAX_GAS_LIMIT`. A transaction is valid if and only if: @@ -16,7 +16,7 @@ A transaction is valid if and only if: (rule #1 in Ethereum yellow paper). 2. The transaction's signature is valid (rule #2 in Ethereum yellow paper). 3. The transaction's the gas limit is no smaller than the intrinsic gas - `K_TX_MIN_GAS_LIMIT` (rule #5 in Ethereum yellow paper). + `TAIKO_TX_MIN_GAS_LIMIT` (rule #5 in Ethereum yellow paper). ### Reason diff --git a/packages/protocol/hardhat.config.ts b/packages/protocol/hardhat.config.ts index 5bf1779d6b..10d30879ea 100644 --- a/packages/protocol/hardhat.config.ts +++ b/packages/protocol/hardhat.config.ts @@ -93,7 +93,7 @@ const config: HardhatUserConfig = { transform: (line) => { if ( process.env.CHAIN_ID && - line.includes("uint256 public constant K_CHAIN_ID") + line.includes("uint256 public constant TAIKO_CHAIN_ID") ) { return `${line.slice(0, line.indexOf(" ="))} = ${ process.env.CHAIN_ID @@ -103,7 +103,7 @@ const config: HardhatUserConfig = { if ( process.env.COMMIT_DELAY_CONFIRMATIONS && line.includes( - "uint256 public constant K_COMMIT_DELAY_CONFIRMS" + "uint256 public constant TAIKO_COMMIT_DELAY_CONFIRMATIONS" ) ) { return `${line.slice(0, line.indexOf(" ="))} = ${ diff --git a/packages/protocol/tasks/config.ts b/packages/protocol/tasks/config.ts index de7f7afc3b..22ae3d79c9 100644 --- a/packages/protocol/tasks/config.ts +++ b/packages/protocol/tasks/config.ts @@ -1,3 +1,3 @@ // https://github.com/ethereum-lists/chains/pull/1611 -export const K_CHAIN_ID = 167 -export const K_DEPLOY_CONFIRMATIONS = 12 +export const TAIKO_CHAINID = 167 +export const DEFAULT_DEPLOY_CONFIRMATIONS = 12 diff --git a/packages/protocol/tasks/deploy_L1.ts b/packages/protocol/tasks/deploy_L1.ts index dfc3d445a3..da0787961c 100644 --- a/packages/protocol/tasks/deploy_L1.ts +++ b/packages/protocol/tasks/deploy_L1.ts @@ -18,11 +18,16 @@ task("deploy_L1") "L2 genesis block hash", ethers.constants.HashZero ) - .addOptionalParam("l2ChainId", "L2 chain id", config.K_CHAIN_ID, types.int) + .addOptionalParam( + "l2ChainId", + "L2 chain id", + config.TAIKO_CHAINID, + types.int + ) .addOptionalParam( "confirmations", "Number of confirmations to wait for deploy transaction.", - config.K_DEPLOY_CONFIRMATIONS, + config.DEFAULT_DEPLOY_CONFIRMATIONS, types.int ) .setAction(async (args, hre: any) => { @@ -107,11 +112,9 @@ export async function deployContracts(hre: any) { "TaikoL1", await deployBaseLibs(hre) ) - const feeBase = hre.ethers.BigNumber.from(10).pow(18) - await utils.waitTx( hre, - await TaikoL1.init(AddressManager.address, l2GenesisBlockHash, feeBase) + await TaikoL1.init(AddressManager.address, l2GenesisBlockHash) ) // Used by LibBridgeRead @@ -162,7 +165,7 @@ async function deployBaseLibs(hre: any) { const libUint512 = await utils.deployContract(hre, "Uint512") const v1Utils = await utils.deployContract(hre, "V1Utils") - const v1Verifying = await utils.deployContract(hre, "V1Verifying", { + const v1Finalizing = await utils.deployContract(hre, "V1Finalizing", { V1Utils: v1Utils.address, }) const v1Proposing = await utils.deployContract(hre, "V1Proposing", { @@ -178,7 +181,7 @@ async function deployBaseLibs(hre: any) { }) return { - V1Verifying: v1Verifying.address, + V1Finalizing: v1Finalizing.address, V1Proposing: v1Proposing.address, V1Proving: v1Proving.address, V1Utils: v1Utils.address, diff --git a/packages/protocol/test/L1/TaikoL1.test.ts b/packages/protocol/test/L1/TaikoL1.test.ts index bbd21f3f36..652618b3e7 100644 --- a/packages/protocol/test/L1/TaikoL1.test.ts +++ b/packages/protocol/test/L1/TaikoL1.test.ts @@ -1,6 +1,5 @@ import { expect } from "chai" import { ethers } from "hardhat" -import { BigNumber } from "ethers" describe("TaikoL1", function () { async function deployTaikoL1Fixture() { @@ -50,8 +49,8 @@ describe("TaikoL1", function () { }) ).deploy() - const v1Verifying = await ( - await ethers.getContractFactory("V1Verifying", { + const v1Finalizing = await ( + await ethers.getContractFactory("V1Finalizing", { libraries: { V1Utils: v1Utils.address, }, @@ -60,7 +59,7 @@ describe("TaikoL1", function () { const TaikoL1Factory = await ethers.getContractFactory("TaikoL1", { libraries: { - V1Verifying: v1Verifying.address, + V1Finalizing: v1Finalizing.address, V1Proposing: v1Proposing.address, V1Proving: v1Proving.address, Uint512: uint512.address, @@ -70,8 +69,7 @@ describe("TaikoL1", function () { const genesisHash = randomBytes32() const taikoL1 = await TaikoL1Factory.deploy() - const feeBase = BigNumber.from(10).pow(18) - await taikoL1.init(addressManager.address, genesisHash, feeBase) + await taikoL1.init(addressManager.address, genesisHash) return { taikoL1, genesisHash } } diff --git a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts index d16915c711..4409a8dcae 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts @@ -1,6 +1,6 @@ import { expect } from "chai" import { ethers } from "hardhat" -import { K_BRIDGE_MESSAGE } from "../../constants/messages" +import { TAIKO_BRIDGE_MESSAGE } from "../../constants/messages" describe("LibBridgeData", function () { async function deployLibBridgeDataFixture() { @@ -31,7 +31,7 @@ describe("LibBridgeData", function () { "tuple(uint256 id, address sender, uint256 srcChainId, uint256 destChainId, address owner, address to, address refundAddress, uint256 depositValue, uint256 callValue, uint256 processingFee, uint256 gasLimit, bytes data, string memo)", ] - const testVar = [K_BRIDGE_MESSAGE, testMessage] + const testVar = [TAIKO_BRIDGE_MESSAGE, testMessage] const MessageStatus = { NEW: 0, @@ -56,7 +56,7 @@ describe("LibBridgeData", function () { await deployLibBridgeDataFixture() // dummy struct to test with - const testVar = [K_BRIDGE_MESSAGE, testMessage] + const testVar = [TAIKO_BRIDGE_MESSAGE, testMessage] const hashed = await libData.hashMessage(testMessage) const expectedEncoded = ethers.utils.defaultAbiCoder.encode( testTypes, diff --git a/packages/protocol/test/constants/messages.ts b/packages/protocol/test/constants/messages.ts index c6880c6fd0..212301c9f8 100644 --- a/packages/protocol/test/constants/messages.ts +++ b/packages/protocol/test/constants/messages.ts @@ -1,3 +1,3 @@ -const K_BRIDGE_MESSAGE = "TAIKO_BRIDGE_MESSAGE" +const TAIKO_BRIDGE_MESSAGE = "TAIKO_BRIDGE_MESSAGE" -export { K_BRIDGE_MESSAGE } +export { TAIKO_BRIDGE_MESSAGE } diff --git a/packages/protocol/test/genesis/generate_genesis.test.ts b/packages/protocol/test/genesis/generate_genesis.test.ts index 76ec24ef35..d14d4ed9f7 100644 --- a/packages/protocol/test/genesis/generate_genesis.test.ts +++ b/packages/protocol/test/genesis/generate_genesis.test.ts @@ -177,7 +177,7 @@ action("Generate Genesis", function () { const tx = await V1TaikoL2.invalidateBlock( bytes, - 6, // hint: TX_INVALID_SIG + 5, // hint: TX_INVALID_SIG 0 ) @@ -331,9 +331,9 @@ action("Generate Genesis", function () { async function generateMaxSizeInvalidTxList(V1TaikoL2: any) { const constants = await V1TaikoL2.getConstants() - const chainId = constants[0].toNumber() // K_CHAIN_ID - const blockMaxTxNums = constants[6].toNumber() // K_BLOCK_MAX_TXS - const txListMaxBytes = constants[8].toNumber() // K_TXLIST_MAX_BYTES + const chainId = constants[0].toNumber() + const blockMaxTxNums = constants[6].toNumber() + const txListMaxBytes = constants[8].toNumber() const tx = { type: 2, diff --git a/packages/protocol/test/libs/LibTxUtils.test.ts b/packages/protocol/test/libs/LibTxUtils.test.ts index ae92f04db9..4dc9a82a84 100644 --- a/packages/protocol/test/libs/LibTxUtils.test.ts +++ b/packages/protocol/test/libs/LibTxUtils.test.ts @@ -30,7 +30,7 @@ describe("LibTxUtils", function () { await ethers.getContractFactory("TestLibRLPWriter") ).deploy() - chainId = (await libConstants.K_CHAIN_ID()).toNumber() + chainId = (await libConstants.TAIKO_CHAIN_ID()).toNumber() const unsignedLegacyTx: UnsignedTransaction = { type: 0, diff --git a/packages/whitepaper/main.tex b/packages/whitepaper/main.tex index f367542112..0b8224c83d 100644 --- a/packages/whitepaper/main.tex +++ b/packages/whitepaper/main.tex @@ -373,7 +373,7 @@ \subsubsection{Invalid Blocks} \label{sec:proving-invalid} It's important to note that these throw-away blocks are never a part of the Taiko chain. The only purpose of the block is to be able reuse the EVM proving subsystem so that we can create proofs for blocks with unexpected transaction data. -\subsection{Verification of Blocks}\label{sec:verifying} +\subsection{On-chain Finalization of Blocks}\label{sec:verifying} Assuming the $j$-th block is the last verified valid block. The $i$-th block ($i > j$) can be verified if 1) the $(i-1)$-th block has been verified, and 2) the $i$-th block has a Fork Choice $E$ whose parent block hash $E(H_p)$ equals the $j$-th block's hash.