Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol): remove gas limit check #14087

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/protocol/contracts/L1/TaikoConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ library TaikoConfig {
blockMaxVerificationsPerTx: 10,
// Set it to 6M, since its the upper limit of the Alpha-2
// testnet's circuits.
blockMaxGasLimit: 6_000_000,
blockMaxGasUsed: 6_000_000,
blockFeeBaseGas: 20_000,
// Set it to 79 (+1 TaikoL2.anchor transaction = 80),
// and 80 is the upper limit of the Alpha-2 testnet's circuits.
Expand Down
6 changes: 2 additions & 4 deletions packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ library TaikoData {
// This number is calculated from blockMaxProposals to make
// the 'the maximum value of the multiplier' close to 20.0
uint256 blockMaxVerificationsPerTx;
uint32 blockMaxGasLimit;
// The max gas used per block, including anchor.
uint32 blockMaxGasUsed;
uint32 blockFeeBaseGas;
uint64 blockMaxTransactions;
uint64 blockMaxTxListBytes;
Expand Down Expand Up @@ -55,7 +56,6 @@ library TaikoData {
struct BlockMetadataInput {
bytes32 txListHash;
address beneficiary;
uint32 gasLimit;
davidtaikocha marked this conversation as resolved.
Show resolved Hide resolved
uint24 txListByteStart; // byte-wise start index (inclusive)
uint24 txListByteEnd; // byte-wise end index (exclusive)
bool cacheTxListInfo;
Expand All @@ -71,7 +71,6 @@ library TaikoData {
bytes32 txListHash;
uint24 txListByteStart;
uint24 txListByteEnd;
uint32 gasLimit;
address beneficiary;
address treasury;
TaikoData.EthDeposit[] depositsProcessed;
Expand Down Expand Up @@ -109,7 +108,6 @@ library TaikoData {
bytes32 metaHash;
// slot 3: (13 bytes available)
uint64 blockId;
uint32 gasLimit;
uint24 nextForkChoiceId;
uint24 verifiedForkChoiceId;
bool proverReleased;
Expand Down
10 changes: 2 additions & 8 deletions packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,8 @@ contract TaikoL1 is
});
}

function getBlockFee(uint32 gasLimit) public view returns (uint64) {
return LibProposing.getBlockFee({
state: state,
config: getConfig(),
gasLimit: gasLimit
});
function getBlockFee() public view returns (uint64) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we also change the calculation of L2 EIP-1559? since its "purchasing" the block.gaslimit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If block.gaslimit is set to blockMaxGasUsed I think it's fine.

return LibProposing.getBlockFee({ state: state, config: getConfig() });
}

function getTaikoTokenBalance(address addr) public view returns (uint256) {
Expand All @@ -193,7 +189,6 @@ contract TaikoL1 is
view
returns (
bytes32 _metaHash,
uint32 _gasLimit,
uint24 _nextForkChoiceId,
uint24 _verifiedForkChoiceId,
bool _proverReleased,
Expand All @@ -211,7 +206,6 @@ contract TaikoL1 is
blockId: blockId
});
_metaHash = blk.metaHash;
_gasLimit = blk.gasLimit;
_nextForkChoiceId = blk.nextForkChoiceId;
_verifiedForkChoiceId = blk.verifiedForkChoiceId;
_proverReleased = blk.proverReleased;
Expand Down
21 changes: 6 additions & 15 deletions packages/protocol/contracts/L1/libs/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,12 @@ library LibProposing {
// from the beacon chain. Since multiple Taiko blocks
// can be proposed in one Ethereum block, we need to
// add salt to this random number as L2 mixHash
meta.mixHash = bytes32(block.difficulty * state.numBlocks);
meta.mixHash = bytes32(block.prevrandao * state.numBlocks);
}

meta.txListHash = input.txListHash;
meta.txListByteStart = input.txListByteStart;
meta.txListByteEnd = input.txListByteEnd;
meta.gasLimit = input.gasLimit;
meta.beneficiary = input.beneficiary;
meta.treasury = resolver.resolve(config.chainId, "treasury", false);
meta.depositsProcessed =
Expand All @@ -105,7 +104,6 @@ library LibProposing {

blk.metaHash = LibUtils.hashMetadata(meta);
blk.blockId = state.numBlocks;
blk.gasLimit = meta.gasLimit;
blk.nextForkChoiceId = 1;
blk.verifiedForkChoiceId = 0;
blk.proverReleased = false;
Expand Down Expand Up @@ -139,7 +137,7 @@ library LibProposing {
);
}

uint64 blockFee = getBlockFee(state, config, meta.gasLimit);
uint64 blockFee = getBlockFee(state, config);

if (state.taikoTokenBalances[msg.sender] < blockFee) {
revert L1_INSUFFICIENT_TOKEN();
Expand Down Expand Up @@ -171,17 +169,16 @@ library LibProposing {
// in case of differences refund after verification
function getBlockFee(
TaikoData.State storage state,
TaikoData.Config memory config,
uint32 gasLimit
TaikoData.Config memory config
)
internal
view
returns (uint64)
{
// The diff between gasLimit and gasUsed will be redistributed back to
// the balance of proposer
return state.feePerGas
* (gasLimit + LibL2Consts.ANCHOR_GAS_COST + config.blockFeeBaseGas);
return
state.feePerGas * (config.blockMaxGasUsed + config.blockFeeBaseGas);
}

function _validateBlock(
Expand All @@ -194,13 +191,7 @@ library LibProposing {
view
returns (bool cacheTxListInfo)
{
if (
input.beneficiary == address(0)
//
|| input.gasLimit == 0
//
|| input.gasLimit > config.blockMaxGasLimit
) revert L1_INVALID_METADATA();
if (input.beneficiary == address(0)) revert L1_INVALID_METADATA();

if (
state.numBlocks
Expand Down
4 changes: 3 additions & 1 deletion packages/protocol/contracts/L1/libs/LibProving.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ library LibProving {
|| evidence.signalRoot == 0
//
|| evidence.gasUsed == 0
//
|| evidence.gasUsed > config.blockMaxGasUsed
) revert L1_INVALID_EVIDENCE();

if (blockId <= state.lastVerifiedBlockId || blockId >= state.numBlocks)
Expand Down Expand Up @@ -191,7 +193,7 @@ library LibProving {
| (uint256(evidence.gasUsed) << 32);

// Also hash configs that will be used by circuits
inputs[9] = uint256(config.blockMaxGasLimit) << 192
inputs[9] = uint256(config.blockMaxGasUsed) << 192
| uint256(config.blockMaxTransactions) << 128
| uint256(config.blockMaxTxListBytes) << 64;

Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts/L1/libs/LibUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ library LibUtils {

inputs[5] = (uint256(meta.txListByteStart) << 232)
| (uint256(meta.txListByteEnd) << 208) //
| (uint256(meta.gasLimit) << 176)
// | (uint256(meta.gasLimit) << 176) // Room for a uint32
| (uint256(uint160(meta.beneficiary)) << 16);

inputs[6] = (uint256(uint160(meta.treasury)) << 96);
Expand Down
11 changes: 3 additions & 8 deletions packages/protocol/contracts/L1/libs/LibVerifying.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ library LibVerifying {
config.chainId <= 1 //
|| config.blockMaxProposals == 1
|| config.blockRingBufferSize <= config.blockMaxProposals + 1
|| config.blockMaxGasLimit == 0 || config.blockMaxTransactions == 0
|| config.blockMaxGasUsed <= LibL2Consts.ANCHOR_GAS_COST
|| config.blockMaxTransactions == 0
|| config.blockMaxTxListBytes == 0
|| config.blockTxListExpiry > 30 * 24 hours
|| config.blockMaxTxListBytes > 128 * 1024 //blob up to 128K
Expand Down Expand Up @@ -182,12 +183,6 @@ library LibVerifying {
)
private
{
// the actually mined L2 block's gasLimit is blk.gasLimit +
// LibL2Consts.ANCHOR_GAS_COST, so fc.gasUsed may greater than
// blk.gasLimit here.
uint32 _gasLimit = blk.gasLimit + LibL2Consts.ANCHOR_GAS_COST;
assert(fc.gasUsed <= _gasLimit);

IProverPool proverPool =
IProverPool(resolver.resolve("prover_pool", false));

Expand Down Expand Up @@ -240,7 +235,7 @@ library LibVerifying {
state.taikoTokenBalances[fc.prover] += proofReward;

state.taikoTokenBalances[blk.proposer] +=
(_gasLimit - fc.gasUsed) * blk.feePerGas;
(config.blockMaxGasUsed - fc.gasUsed) * blk.feePerGas;

emit BlockVerified(blk.blockId, fc.blockHash, proofReward);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts/L2/TaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
gaslimit: uint64(block.gaslimit),
timestamp: uint64(block.timestamp),
parentHash: parentHash,
prevrandao: block.difficulty,
prevrandao: block.prevrandao,
coinbase: block.coinbase,
chainid: uint32(block.chainid)
});
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts/test/L1/TestTaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ contract TestTaikoL1 is TaikoL1 {
// This number is calculated from blockMaxProposals to make
// the 'the maximum value of the multiplier' close to 20.0
config.blockMaxVerificationsPerTx = 0;
config.blockMaxGasLimit = 30_000_000;
config.blockMaxGasUsed = 30_000_000;
config.blockMaxTransactions = 20;
config.blockMaxTxListBytes = 120_000;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract TestTaikoL1EnableTokenomics is TaikoL1 {
// the 'the maximum value of the multiplier' close to 20.0
config.blockMaxVerificationsPerTx = 0; // dont verify blocks
// automatically
config.blockMaxGasLimit = 30_000_000;
config.blockMaxGasUsed = 30_000_000;
config.blockMaxTransactions = 20;
config.blockMaxTxListBytes = 120_000;
}
Expand Down
26 changes: 14 additions & 12 deletions packages/protocol/docs/how_taiko_proves_blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ The ZKP must prove that _TaikoL2.anchor(...)_ is the first transaction in the bl

- The anchor transaction's `to` address must be the registered `taiko_l2` address, which is hashed into the ZKP `instance`. And the `tx.origin` must be the golden touch address.
- The anchor transaction's ABI must be:
```solidity
function anchor(
bytes32 l1Hash,
bytes32 l1SignalRoot,
uint64 l1Height,
uint64 parentGasUsed
) external;
```

```solidity
function anchor(
bytes32 l1Hash,
bytes32 l1SignalRoot,
uint64 l1Height,
uint64 parentGasUsed
) external;
```

- A circuit will verify the integrity among: `l1Hash`, `l1SignalRoot`, and `l1SignalServiceAddress`
- `l1SignalServiceAddress`, `l2SignalServiceAddress` and `parentGasUsed` are directly hashed into the ZKP's instance
- `l1Height` and `l1Hash` are both part of the block metadata (`meta.l1Height` and `meta.l1Hash`), the `metaHash` is used to calculate the ZKP instance.
Expand Down Expand Up @@ -107,7 +109,7 @@ The following [**block level variables**](https://docs.soliditylang.org/en/v0.8.
- `block.basefee` (`uint`): current block's base fee ([EIP-3198](https://eips.ethereum.org/EIPS/eip-3198) and [modified EIP-1559](./L2EIP1559.md))
- `block.chainid` (`uint`): current chain id
- `block.coinbase` (`address payable`): current block miner's address
- `block.difficulty` (`uint`): alias for `block.prevrandao` ([EIP-4399](https://eips.ethereum.org/EIPS/eip-4399))
- `block.prevrandao` (`uint`): alias for `block.prevrandao` ([EIP-4399](https://eips.ethereum.org/EIPS/eip-4399))
- `block.gaslimit` (`uint`): current block gaslimit
- `block.number` (`uint`): current block number
- `block.prevrandao` (`uint`): random number provided by the beacon chain
Expand All @@ -116,12 +118,12 @@ The following [**block level variables**](https://docs.soliditylang.org/en/v0.8.
We need to verify when these variables are accessed within the EVM, their values are consistent with the current world state, the block's metadata and the actual L2 block's block header:

- `blockhash`: EVM allows access to the most recent 256 block hashes. All these hashes are available inside the plonk lookup table. ZKP must prove that the lookup table is consistent with L2's historical values.
- `blockhash(block.number - 1)`, has the same value as in the block header and is also the same value as the parent block's hash on L2.
- The other 255 hashes, `blockhash(block.number - 256)` to `blockhash(block.number - 2)` are checked in the anchor transaction to simplify circuits. Therefore, as long as the anchor transaction is zk-proven, these 255 ancestor hashes are proven indirectly.
- `blockhash(block.number - 1)`, has the same value as in the block header and is also the same value as the parent block's hash on L2.
- The other 255 hashes, `blockhash(block.number - 256)` to `blockhash(block.number - 2)` are checked in the anchor transaction to simplify circuits. Therefore, as long as the anchor transaction is zk-proven, these 255 ancestor hashes are proven indirectly.
- `block.basefee`: verified to be the correct value in the anchor transaction.
- `block.chainid`: this field is also checked by the anchor transaction, so no extra ZKP circuits are required.
- `block.coinbase`: ZKP must verify the value must be the same as `meta.beneficiary`. Again, the metadata hash is part of the ZK instance.
- `block.difficulty`: this is now the same as `block.prevrandao`, so we only check `block.prevrandao`.
- `block.prevrandao`: this is now the same as `block.prevrandao`, so we only check `block.prevrandao`.
- `block.gaslimit`: ZKP must verify this value must equal `meta.gasLimit`.
- `block.number`: this must be checked against the block header and `meta.id`.
- `block.prevrandao`: this must be checked against the `mixHash` field in the L2 block header and `meta.mixHash`.
Expand Down
2 changes: 0 additions & 2 deletions packages/protocol/test/GasComparison.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ contract FooBar {
txListHash: bytes32(uint256(1)),
txListByteStart: 0,
txListByteEnd: 1000,
gasLimit: 1,
mixHash: bytes32(uint256(1)),
timestamp: 1,
depositsProcessed: new TaikoData.EthDeposit[](0)
Expand All @@ -102,7 +101,6 @@ contract FooBar {
txListHash: bytes32(uint256(1)),
txListByteStart: 0,
txListByteEnd: 1000,
gasLimit: 1,
mixHash: bytes32(uint256(1)),
timestamp: 1,
depositsProcessed: new TaikoData.EthDeposit[](0)
Expand Down
35 changes: 14 additions & 21 deletions packages/protocol/test/ProverPool_Protocol_Interactions.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,11 @@ contract TaikoL1ProverPool is TaikoL1TestBase {
uint256 blockId = 1; blockId < conf.blockMaxProposals * 9; blockId++
) {
printVariables("before propose");
TaikoData.BlockMetadata memory meta =
proposeBlock(Alice, 1_000_000, 1024);
TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1024);
//printVariables("after propose");
mine(1);

(,,,,,,,, address prover,,) = L1.getBlock(blockId);
(,,,,,,, address prover,,) = L1.getBlock(blockId);
console2.log("Prover address:", getNameFromAddress(prover));

bytes32 blockHash = bytes32(1e10 + blockId);
Expand Down Expand Up @@ -283,12 +282,11 @@ contract TaikoL1ProverPool is TaikoL1TestBase {
uint256 blockId = 1; blockId < conf.blockMaxProposals * 9; blockId++
) {
printVariables("before propose");
TaikoData.BlockMetadata memory meta =
proposeBlock(Alice, 1_000_000, 1024);
TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1024);
//printVariables("after propose");
mine(1);

(,,,,,,,, address prover,,) = L1.getBlock(blockId);
(,,,,,,, address prover,,) = L1.getBlock(blockId);
console2.log("Prover address:", getNameFromAddress(prover));

bytes32 blockHash = bytes32(1e10 + blockId);
Expand Down Expand Up @@ -331,12 +329,11 @@ contract TaikoL1ProverPool is TaikoL1TestBase {
uint256 blockId = 1; blockId < conf.blockMaxProposals * 9; blockId++
) {
printVariables("before propose");
TaikoData.BlockMetadata memory meta =
proposeBlock(Alice, 1_000_000, 1024);
TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1024);
//printVariables("after propose");
mine(1);

(,,,,,,,, address prover,,) = L1.getBlock(blockId);
(,,,,,,, address prover,,) = L1.getBlock(blockId);
console2.log("Prover address:", getNameFromAddress(prover));

bytes32 blockHash = bytes32(1e10 + blockId);
Expand Down Expand Up @@ -396,12 +393,11 @@ contract TaikoL1ProverPool is TaikoL1TestBase {
uint256 blockId = 1; blockId < conf.blockMaxProposals * 9; blockId++
) {
printVariables("before propose");
TaikoData.BlockMetadata memory meta =
proposeBlock(Alice, 1_000_000, 1024);
TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1024);
//printVariables("after propose");
mine(1);

(,,,,,,,, address prover,,) = L1.getBlock(blockId);
(,,,,,,, address prover,,) = L1.getBlock(blockId);
console2.log("Prover address:", getNameFromAddress(prover));

bytes32 blockHash = bytes32(1e10 + blockId);
Expand Down Expand Up @@ -460,12 +456,11 @@ contract TaikoL1ProverPool is TaikoL1TestBase {
// was 5 * 1e8
}
printVariables("before propose");
TaikoData.BlockMetadata memory meta =
proposeBlock(Alice, 1_000_000, 1024);
TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1024);
//printVariables("after propose");
mine(1);

(,,,,,,,, address prover,,) = L1.getBlock(blockId);
(,,,,,,, address prover,,) = L1.getBlock(blockId);
console2.log("Prover address:", getNameFromAddress(prover));

bytes32 blockHash = bytes32(1e10 + blockId);
Expand Down Expand Up @@ -510,12 +505,11 @@ contract TaikoL1ProverPool is TaikoL1TestBase {
uint256 blockId = 1; blockId < conf.blockMaxProposals * 1; blockId++
) {
printVariables("before propose");
TaikoData.BlockMetadata memory meta =
proposeBlock(Alice, 1_000_000, 1024);
TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1024);
//printVariables("after propose");
mine(1);

(,,,,,,,, address prover,,) = L1.getBlock(blockId);
(,,,,,,, address prover,,) = L1.getBlock(blockId);
console2.log("Prover address:", getNameFromAddress(prover));

bytes32 blockHash = bytes32(1e10 + blockId);
Expand Down Expand Up @@ -573,12 +567,11 @@ contract TaikoL1ProverPool is TaikoL1TestBase {
uint256 blockId = 1; blockId < conf.blockMaxProposals * 1; blockId++
) {
printVariables("before propose");
TaikoData.BlockMetadata memory meta =
proposeBlock(Alice, 1_000_000, 1024);
TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1024);
//printVariables("after propose");
mine(1);

(,,,,,,,, address prover,,) = L1.getBlock(blockId);
(,,,,,,, address prover,,) = L1.getBlock(blockId);
console2.log("Prover address:", getNameFromAddress(prover));

bytes32 blockHash = bytes32(1e10 + blockId);
Expand Down
Loading