Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c49bd33
feat: first run at nr changes for batch rollup
MirandaWood Jul 30, 2024
358c7b3
feat: add ts types, structs, tests (not yet impl in orch)
MirandaWood Jul 31, 2024
9b288e3
feat: handle vks for block root and block merge circuits
MirandaWood Aug 1, 2024
c740c10
chore: small fixes, cleanup, inject prev block hash
MirandaWood Aug 1, 2024
8859550
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 2, 2024
c031a20
chore: fmt, cleanup after adding prover_id via merge
MirandaWood Aug 2, 2024
6b97c3a
chore: better comments, more root -> block_root renaming, add new cir…
MirandaWood Aug 2, 2024
56c01ac
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 5, 2024
df113ce
feat: clean fee throw, add prev_block_hash to root pub inputs
MirandaWood Aug 5, 2024
b064be0
chore: fix for tests, more root -> block root renaming, comments
MirandaWood Aug 7, 2024
951981f
feat: accumulate fees, test, add more clarity comments
MirandaWood Aug 8, 2024
d84984e
feat: verify block root proofs on L1, add prover id to PIs
MirandaWood Aug 9, 2024
381da05
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 9, 2024
930ebea
feat: add vk root to final root rollup inputs, fix typo
MirandaWood Aug 12, 2024
82aa39a
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 12, 2024
abfca2b
feat: L1 process stores block hash, remove unused code
MirandaWood Aug 12, 2024
b23e646
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 12, 2024
605e192
fix: update eth log handlers, revert fee acc, some comments
MirandaWood Aug 13, 2024
644173b
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 13, 2024
eb3e283
fix: add epoch to block root/merge methods post merge
MirandaWood Aug 13, 2024
bb4815d
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 13, 2024
1f114aa
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 13, 2024
6d37433
feat: fixes after merge, use blockroot artifact, add proving todos
MirandaWood Aug 19, 2024
117d9d3
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 19, 2024
ef2a883
fix: post merge fixes
MirandaWood Aug 19, 2024
3127243
chore: forge fmt
MirandaWood Aug 19, 2024
3e2f55f
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 19, 2024
a657e05
fix: post merge fixes to publisher
MirandaWood Aug 19, 2024
bc17e45
chore: cleanup opt chaining in orchestrator
MirandaWood Aug 22, 2024
99064a1
Merge remote-tracking branch 'origin' into mw/batch-rollup
MirandaWood Aug 22, 2024
388bce3
chore: fmt + fix post merge
MirandaWood Aug 22, 2024
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
99 changes: 76 additions & 23 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {Leonidas} from "./sequencer_selection/Leonidas.sol";
contract Rollup is Leonidas, IRollup, ITestRollup {
struct BlockLog {
bytes32 archive;
bytes32 blockHash;
uint128 slotNumber;
bool isProven;
}
Expand Down Expand Up @@ -88,7 +89,8 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
VERSION = 1;

// Genesis block
blocks[0] = BlockLog({archive: bytes32(0), slotNumber: 0, isProven: true});
blocks[0] =
BlockLog({archive: bytes32(0), blockHash: bytes32(0), slotNumber: 0, isProven: true});
pendingBlockCount = 1;
provenBlockCount = 1;
}
Expand Down Expand Up @@ -181,17 +183,19 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
*
* @param _header - The L2 block header
* @param _archive - A root of the archive tree after the L2 block is applied
* @param _blockHash - The poseidon2 hash of the header added to the archive tree in the rollup circuit
* @param _signatures - Signatures from the validators
* @param _body - The body of the L2 block
*/
function publishAndProcess(
bytes calldata _header,
bytes32 _archive,
bytes32 _blockHash,
SignatureLib.Signature[] memory _signatures,
bytes calldata _body
) external override(IRollup) {
AVAILABILITY_ORACLE.publish(_body);
process(_header, _archive, _signatures);
process(_header, _archive, _blockHash, _signatures);
}
Comment on lines 190 to 199
Copy link
Contributor

Choose a reason for hiding this comment

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

Heads up you'll need to tweak the SUPPORTED_SIGS in eth_log_handlers if you change this. We should derive those dynamically from the abi instead of hardcoding them, so we don't forget to update them whenever we change the Rollup.sol interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, saved me lots of debugging time!


/**
Expand All @@ -200,19 +204,24 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
* @dev `eth_log_handlers` rely on this function
* @param _header - The L2 block header
* @param _archive - A root of the archive tree after the L2 block is applied
* @param _blockHash - The poseidon2 hash of the header added to the archive tree in the rollup circuit
* @param _body - The body of the L2 block
*/
function publishAndProcess(bytes calldata _header, bytes32 _archive, bytes calldata _body)
external
override(IRollup)
{
function publishAndProcess(
bytes calldata _header,
bytes32 _archive,
bytes32 _blockHash,
bytes calldata _body
) external override(IRollup) {
AVAILABILITY_ORACLE.publish(_body);
process(_header, _archive);
process(_header, _archive, _blockHash);
}

/**
* @notice Submit a proof for a block in the pending chain
*
* @dev TODO(#7346): Verify root proofs rather than block root when batch rollups are integrated.
*
* @dev Will call `_progressState` to update the proven chain. Notice this have potentially
* unbounded gas consumption.
*
Expand All @@ -231,10 +240,11 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
*
* @param _header - The header of the block (should match the block in the pending chain)
* @param _archive - The archive root of the block (should match the block in the pending chain)
* @param _proverId - The id of this block's prover
* @param _aggregationObject - The aggregation object for the proof
* @param _proof - The proof to verify
*/
function submitProof(
function submitBlockRootProof(
bytes calldata _header,
bytes32 _archive,
bytes32 _proverId,
Expand All @@ -259,23 +269,59 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
revert Errors.Rollup__InvalidProposedArchive(expectedArchive, _archive);
}

bytes32[] memory publicInputs =
new bytes32[](4 + Constants.HEADER_LENGTH + Constants.AGGREGATION_OBJECT_LENGTH);
// the archive tree root
publicInputs[0] = _archive;
// TODO(#7346): Currently verifying block root proofs until batch rollups fully integrated.
// Hence the below pub inputs are BlockRootOrBlockMergePublicInputs, which are larger than
// the planned set (RootRollupPublicInputs), for the interim.
// Public inputs are not fully verified (TODO(#7373))

bytes32[] memory publicInputs = new bytes32[](
Constants.BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH + Constants.AGGREGATION_OBJECT_LENGTH
);

// From block_root_or_block_merge_public_inputs.nr: BlockRootOrBlockMergePublicInputs.
// previous_archive.root: the previous archive tree root
publicInputs[0] = expectedLastArchive;
// previous_archive.next_available_leaf_index: the previous archive next available index
publicInputs[1] = bytes32(header.globalVariables.blockNumber);

// new_archive.root: the new archive tree root
publicInputs[2] = expectedArchive;
// this is the _next_ available leaf in the archive tree
// normally this should be equal to the block number (since leaves are 0-indexed and blocks 1-indexed)
// but in yarn-project/merkle-tree/src/new_tree.ts we prefill the tree so that block N is in leaf N
publicInputs[1] = bytes32(header.globalVariables.blockNumber + 1);

publicInputs[2] = vkTreeRoot;

bytes32[] memory headerFields = HeaderLib.toFields(header);
for (uint256 i = 0; i < headerFields.length; i++) {
publicInputs[i + 3] = headerFields[i];
// new_archive.next_available_leaf_index: the new archive next available index
publicInputs[3] = bytes32(header.globalVariables.blockNumber + 1);

// TODO(#7346): Currently previous block hash is unchecked, but will be checked in batch rollup (block merge -> root).
// block-building-helpers.ts is injecting as 0 for now, replicating here.
// previous_block_hash: the block hash just preceding this block (will eventually become the end_block_hash of the prev batch)
publicInputs[4] = bytes32(0);

// end_block_hash: the current block hash (will eventually become the hash of the final block proven in a batch)
publicInputs[5] = blocks[header.globalVariables.blockNumber].blockHash;

// For block root proof outputs, we have a block 'range' of just 1 block => start and end globals are the same
bytes32[] memory globalVariablesFields = HeaderLib.toFields(header.globalVariables);
for (uint256 i = 0; i < globalVariablesFields.length; i++) {
// start_global_variables
publicInputs[i + 6] = globalVariablesFields[i];
// end_global_variables
publicInputs[globalVariablesFields.length + i + 6] = globalVariablesFields[i];
Comment on lines +306 to +309
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd try to get this 6 into constants.sol, or at least into a constant in HeaderLib

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, shouldn't it be 9?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It starts at 6 because:

  • PIs 0-5 are are the old archive, new archive, and block hash
  • PIs 6-14 are the 'start global variables' (filled by publicInputs[i + 6] above)
  • PIs 15-23 are the 'end global variables' (filled by publicInputs[globalVariablesFields.length +i+ 6] above)

Basically, we have one block rather than a range so the pair of global variables are the same. I'm just using one loop to append them both.
I was thinking rather than hardcode indices I could just use some offset and increment it with each push, to avoid any errors if anything changes?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah got it, my bad!

}
// out_hash: root of this block's l2 to l1 message tree (will eventually be root of roots)
publicInputs[24] = header.contentCommitment.outHash;

// For block root proof outputs, we have a single recipient-value fee payment pair,
// but the struct contains space for the max (32) => we keep 31*2=62 fields blank to represent it.
// fees: array of recipient-value pairs, for a single block just one entry (will eventually be filled and paid out here)
publicInputs[25] = bytes32(uint256(uint160(header.globalVariables.coinbase)));
publicInputs[26] = bytes32(header.totalFees);
// publicInputs[27] -> publicInputs[88] left blank for empty fee array entries

publicInputs[headerFields.length + 3] = _proverId;
// vk_tree_root
publicInputs[89] = vkTreeRoot;
// prover_id: id of current block range's prover
publicInputs[90] = _proverId;

// the block proof is recursive, which means it comes with an aggregation object
// this snippet copies it into the public inputs needed for verification
Expand All @@ -286,7 +332,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
assembly {
part := calldataload(add(_aggregationObject.offset, mul(i, 32)))
}
publicInputs[i + 4 + Constants.HEADER_LENGTH] = part;
publicInputs[i + 91] = part;
}

if (!verifier.verify(_proof, publicInputs)) {
Expand Down Expand Up @@ -327,11 +373,13 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
*
* @param _header - The L2 block header
* @param _archive - A root of the archive tree after the L2 block is applied
* @param _blockHash - The poseidon2 hash of the header added to the archive tree in the rollup circuit
* @param _signatures - Signatures from the validators
*/
function process(
bytes calldata _header,
bytes32 _archive,
bytes32 _blockHash,
SignatureLib.Signature[] memory _signatures
) public override(IRollup) {
// Decode and validate header
Expand All @@ -343,6 +391,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
// the slot number to uint128
blocks[pendingBlockCount++] = BlockLog({
archive: _archive,
blockHash: _blockHash,
slotNumber: uint128(header.globalVariables.slotNumber),
isProven: false
});
Expand Down Expand Up @@ -385,10 +434,14 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
*
* @param _header - The L2 block header
* @param _archive - A root of the archive tree after the L2 block is applied
* @param _blockHash - The poseidon2 hash of the header added to the archive tree in the rollup circuit
*/
function process(bytes calldata _header, bytes32 _archive) public override(IRollup) {
function process(bytes calldata _header, bytes32 _archive, bytes32 _blockHash)
public
override(IRollup)
{
SignatureLib.Signature[] memory emptySignatures = new SignatureLib.Signature[](0);
process(_header, _archive, emptySignatures);
process(_header, _archive, _blockHash, emptySignatures);
}

/**
Expand Down
26 changes: 22 additions & 4 deletions l1-contracts/src/core/interfaces/IRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,44 @@ interface IRollup {
function publishAndProcess(
bytes calldata _header,
bytes32 _archive,
bytes32 _blockHash,
SignatureLib.Signature[] memory _signatures,
bytes calldata _body
) external;
function publishAndProcess(bytes calldata _header, bytes32 _archive, bytes calldata _body)
external;
function process(bytes calldata _header, bytes32 _archive) external;
function publishAndProcess(
bytes calldata _header,
bytes32 _archive,
bytes32 _blockHash,
bytes calldata _body
) external;
function process(bytes calldata _header, bytes32 _archive, bytes32 _blockHash) external;
function process(
bytes calldata _header,
bytes32 _archive,
bytes32 _blockHash,
SignatureLib.Signature[] memory _signatures
) external;

function submitProof(
function submitBlockRootProof(
bytes calldata _header,
bytes32 _archive,
bytes32 _proverId,
bytes calldata _aggregationObject,
bytes calldata _proof
) external;

// TODO(#7346): Integrate batch rollups
// function submitRootProof(
// bytes32 _previousArchive,
// bytes32 _archive,
// bytes32 outHash,
// address[32] calldata coinbases,
// uint256[32] calldata fees,
// bytes32 _proverId,
// bytes calldata _aggregationObject,
// bytes calldata _proof
// ) external;

function archive() external view returns (bytes32);
function isBlockProven(uint256 _blockNumber) external view returns (bool);
function archiveAt(uint256 _blockNumber) external view returns (bytes32);
Expand Down
5 changes: 4 additions & 1 deletion l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ library Constants {
uint256 internal constant ROOT_PARITY_INDEX = 19;
uint256 internal constant BASE_ROLLUP_INDEX = 20;
uint256 internal constant MERGE_ROLLUP_INDEX = 21;
uint256 internal constant ROOT_ROLLUP_INDEX = 22;
uint256 internal constant BLOCK_ROOT_ROLLUP_INDEX = 22;
uint256 internal constant BLOCK_MERGE_ROLLUP_INDEX = 23;
uint256 internal constant ROOT_ROLLUP_INDEX = 24;
uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4;
uint256 internal constant ARGS_HASH_CHUNK_LENGTH = 16;
uint256 internal constant ARGS_HASH_CHUNK_COUNT = 16;
Expand Down Expand Up @@ -197,6 +199,7 @@ library Constants {
uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 663;
uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 12;
uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 29;
uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 91;
uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674;
uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048;
uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048;
Expand Down
29 changes: 29 additions & 0 deletions l1-contracts/src/core/libraries/HeaderLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,33 @@ library HeaderLib {

return fields;
}

// TODO(#7346): Currently using the below to verify block root proofs until batch rollups fully integrated.
// Once integrated, remove the below fn (not used anywhere else).
function toFields(GlobalVariables memory _globalVariables)
internal
pure
returns (bytes32[] memory)
{
bytes32[] memory fields = new bytes32[](Constants.GLOBAL_VARIABLES_LENGTH);

fields[0] = bytes32(_globalVariables.chainId);
fields[1] = bytes32(_globalVariables.version);
fields[2] = bytes32(_globalVariables.blockNumber);
fields[3] = bytes32(_globalVariables.slotNumber);
fields[4] = bytes32(_globalVariables.timestamp);
fields[5] = bytes32(uint256(uint160(_globalVariables.coinbase)));
fields[6] = bytes32(_globalVariables.feeRecipient);
fields[7] = bytes32(_globalVariables.gasFees.feePerDaGas);
fields[8] = bytes32(_globalVariables.gasFees.feePerL2Gas);

// fail if the header structure has changed without updating this function
if (fields.length != Constants.GLOBAL_VARIABLES_LENGTH) {
// TODO(Miranda): Temporarily using this method and below error while block-root proofs are verified
// When we verify root proofs, this method can be removed => no need for separate named error
revert Errors.HeaderLib__InvalidHeaderSize(Constants.HEADER_LENGTH, fields.length);
}

return fields;
}
}
Loading