Skip to content

Commit

Permalink
Adap multi-block proposals to gwyneth
Browse files Browse the repository at this point in the history
  • Loading branch information
Keszey Dániel authored and Keszey Dániel committed Jul 15, 2024
1 parent 8d6c287 commit 81d2882
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 36 deletions.
34 changes: 24 additions & 10 deletions packages/protocol/contracts/L1/BasedOperator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,27 +64,41 @@ contract BasedOperator is EssentialContract, TaikoErrors {

/// @dev Proposes a Taiko L2 block.
function proposeBlock(
bytes calldata params,
bytes calldata txList,
bytes[] calldata data,
bytes[] calldata txLists,
address prover
)
external
payable
nonReentrant
whenNotPaused
returns (TaikoData.BlockMetadata memory _block)
returns (TaikoData.BlockMetadata[] memory _blocks)
{
if(txLists.length != 0) {
require(data.length == txLists.length, "mismatched params length");
}

require(msg.value == PROVER_BOND, "Prover bond not expected");

_block = TaikoL1(resolve("taiko", false)).proposeBlock(params, txList);
_blocks = new TaikoData.BlockMetadata[](data.length);
for (uint i = 0; i < data.length; i++) {
if(txLists.length != 0) {
// If calldata, then pass forward the calldata
_blocks[i] = TaikoL1(resolve("taiko", false)).proposeBlock(data[i], txLists[i]);
}
else {
// Blob otherwise
_blocks[i] = TaikoL1(resolve("taiko", false)).proposeBlock(data[i], "");
}

// Check if we have whitelisted proposers
if (!_isProposerPermitted(_block)) {
revert L1_INVALID_PROPOSER();
}
// Check if we have whitelisted proposers
if (!_isProposerPermitted(_blocks[i])) {
revert L1_INVALID_PROPOSER();
}

// Store who paid for proving the block
blocks[_block.l2BlockNumber] = Block({ assignedProver: prover, bond: uint96(PROVER_BOND) });
// Store who paid for proving the block
blocks[_blocks[i].l2BlockNumber] = Block({ assignedProver: prover, bond: uint96(PROVER_BOND) });
}

// Verify some blocks
_verifyBlocks(MAX_BLOCKS_TO_VERIFY);
Expand Down
2 changes: 2 additions & 0 deletions packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ library TaikoData {
uint64 timestamp;
uint24 txListByteOffset;
uint24 txListByteSize;
// todo: Do we need this below ?
// bytes32 blobId OR blobHash; ? as per in current taiko-mono's preconfirmation branch ?
bool blobUsed;
}

Expand Down
11 changes: 7 additions & 4 deletions packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ contract TaikoL1 is EssentialContract, TaikoEvents, TaikoErrors {
}

/// Proposes a Taiko L2 block.
/// @param data Block parameters, currently an encoded BlockParams object.
/// @param data Block parameters, currently an encoded BlockMetadata object.
/// @param txList txList data if calldata is used for DA.
/// @return _block The metadata of the proposed L2 block.
function proposeBlock(
Expand All @@ -64,8 +64,8 @@ contract TaikoL1 is EssentialContract, TaikoEvents, TaikoErrors {
payable
nonReentrant
whenNotPaused
onlyFromNamed("operator")
returns (
//onlyFromNamed("operator")
TaikoData.BlockMetadata memory _block
)
{
Expand All @@ -85,7 +85,9 @@ contract TaikoL1 is EssentialContract, TaikoEvents, TaikoErrors {
require(_block.blobUsed == (txList.length == 0), "INVALID_BLOB_USED");
// Verify DA data
if (_block.blobUsed) {
//require(_block.blobHash == blobhash(0), "invalid data blob");
// Todo: Is blobHash posisble to be checked and pre-calculated in input metadata off-chain ?
// or shall we do something with it to cross check ?
// require(_block.blobHash == blobhash(0), "invalid data blob");
require(
uint256(_block.txListByteOffset) + _block.txListByteSize <= MAX_BYTES_PER_BLOB,
"invalid blob size"
Expand All @@ -104,7 +106,8 @@ contract TaikoL1 is EssentialContract, TaikoEvents, TaikoErrors {

TaikoData.Block storage parentBlock = state.blocks[(state.numBlocks - 1)];

require(_block.parentMetaHash == parentBlock.metaHash, "invalid parentHash");
require(_block.parentMetaHash == parentBlock.metaHash, "invalid parentMetaHash");
require(_block.parentBlockHash == parentBlock.blockHash, "invalid parentHash");

// Verify the passed in L1 state block number.
// We only allow the L1 block to be 4 epochs old.
Expand Down
11 changes: 3 additions & 8 deletions packages/protocol/contracts/L1/actors/PBSActor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,16 @@ contract PBSActor {

/// @dev Proposes a Taiko L2 block.
function proposeBlock(
bytes calldata params,
bytes calldata txList,
bytes[] calldata data,
bytes[] calldata txLists,
bytes memory proverPaymentData,
bytes32 parentHash,
uint256 tip
)
external
payable
{
// TODO(Brecht): just pass in opaque data to make it general, though kind of doesn't matter
TaikoData.BlockMetadata memory _block =
operator.proposeBlock{ value: msg.value - tip }(params, txList, proverPaymentData);

// Check if parent block has the right meta hash
require(keccak256(abi.encode(_block)) == parentHash, "unexpected parent");
operator.proposeBlock{ value: msg.value - tip }(data, txLists, proverPaymentData);

// Do conditional payment
address(block.coinbase).sendEtherAndVerify(tip);
Expand Down
17 changes: 10 additions & 7 deletions packages/protocol/contracts/L1/actors/ProverPayment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ contract ProverPayment {

/// @dev Proposes a Taiko L2 block.
function proposeBlock(
bytes calldata params,
bytes calldata txList,
bytes[] calldata data,
bytes[] calldata txLists,
bytes calldata proverAssignment
)
external
payable
returns (TaikoData.BlockMetadata memory _block)
returns (TaikoData.BlockMetadata[] memory _blocks)
{
// Decode the assignment data
ProverAssignment memory assignment = abi.decode(proverAssignment, (ProverAssignment));
Expand All @@ -51,19 +51,22 @@ contract ProverPayment {
balances[assignment.prover] -= operator.PROVER_BOND();

// Propose the block
_block = operator.proposeBlock{ value: operator.PROVER_BOND() }(
params, txList, assignment.prover
_blocks = operator.proposeBlock{ value: operator.PROVER_BOND() }(
data, txLists, assignment.prover
);

uint64 highestl2BlockNumber = _blocks[_blocks.length-1].l2BlockNumber;

// Hash the assignment with the blobHash, this hash will be signed by
// the prover, therefore, we add a string as a prefix.
// IMPORTANT!! Assignment now multi-block assignment!!
bytes32 hash = hashAssignment(assignment);
require(assignment.prover.isValidSignature(hash, assignment.signature), "invalid signature");

// Check assignment validity
require(
(assignment.metaHash != 0 || keccak256(abi.encode(_block)) != assignment.metaHash)
&& (assignment.maxBlockId != 0 || _block.l2BlockNumber > assignment.maxBlockId)
(assignment.metaHash != 0 || keccak256(abi.encode(_blocks)) != assignment.metaHash)
&& (assignment.maxBlockId != 0 || highestl2BlockNumber > assignment.maxBlockId)
&& (assignment.maxProposedIn != 0 || block.number > assignment.maxProposedIn),
"unexpected block"
);
Expand Down
24 changes: 17 additions & 7 deletions packages/protocol/test/L1/TaikoL1TestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -303,24 +303,34 @@ abstract contract TaikoL1TestBase is TaikoTest {

// hookcalls[0] = TaikoData.HookCall(address(assignmentHook), abi.encode(assignment));

bytes memory dummyTxList =
bytes[] memory dummyTxList = new bytes[](1);
dummyTxList[0] =
hex"0000000000000000000000000000000000000000000000000000000000000001";
bytes memory emptyTxList;

// If blob is used, empty tx list
bytes[] memory emptyTxList;

// Input metadata sturct can now support multiple block proposals per L1 TXN

Check failure on line 313 in packages/protocol/test/L1/TaikoL1TestBase.sol

View workflow job for this annotation

GitHub Actions / codespell

sturct ==> struct
bytes[] memory metasEncoded = new bytes[](1);
metasEncoded[0] = abi.encode(meta);

TaikoData.BlockMetadata[] memory _returnedBlocks = new TaikoData.BlockMetadata[](1);

if (revertReason == "") {
vm.prank(proposer, proposer);
meta = basedOperator.proposeBlock{ value: 1 ether / 10 }(
abi.encode(meta), meta.blobUsed == true ? emptyTxList : dummyTxList, prover
_returnedBlocks = basedOperator.proposeBlock{ value: 1 ether / 10 }(
metasEncoded, meta.blobUsed == true ? emptyTxList : dummyTxList, prover
);
} else {
vm.prank(proposer, proposer);
vm.expectRevert(revertReason);
meta = basedOperator.proposeBlock{ value: 1 ether / 10 }(
abi.encode(meta), meta.blobUsed == true ? emptyTxList : dummyTxList, prover
_returnedBlocks = basedOperator.proposeBlock{ value: 1 ether / 10 }(
metasEncoded, meta.blobUsed == true ? emptyTxList : dummyTxList, prover
);
return meta;
}

return meta;
return _returnedBlocks[0];
}

function proveBlock(address prover, bytes memory blockProof) internal {
Expand Down

0 comments on commit 81d2882

Please sign in to comment.