Skip to content

Commit

Permalink
feat: proofClaim in Rollup (#8636)
Browse files Browse the repository at this point in the history
Fix #8608 

Add the proofClaim to the rollup.

Update the `canPrune` logic to account for it.
  • Loading branch information
just-mitch committed Sep 20, 2024
1 parent 9d09b1d commit 6b1a7ba
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 12 deletions.
93 changes: 89 additions & 4 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
// @todo #8018
uint256 public constant TIMELINESS_PROVING_IN_SLOTS = 100;

uint256 public constant CLAIM_DURATION_IN_L2_SLOTS = 13;
uint256 public constant PROOF_COMMITMENT_MIN_BOND_AMOUNT_IN_TST = 1000;

uint256 public immutable L1_BLOCK_AT_GENESIS;
IRegistry public immutable REGISTRY;
IInbox public immutable INBOX;
Expand All @@ -63,6 +66,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
IVerifier public verifier;

ChainTips public tips;
DataStructures.EpochProofClaim public proofClaim;

// @todo Validate assumption:
// Currently we assume that the archive root following a block is specific to the block
Expand Down Expand Up @@ -177,6 +181,60 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
vkTreeRoot = _vkTreeRoot;
}

function claimEpochProofRight(DataStructures.EpochProofQuote calldata _quote)
external
override(IRollup)
{
uint256 currentSlot = getCurrentSlot();
address currentProposer = getCurrentProposer();
uint256 epochToProve = getEpochToProve();

if (currentProposer != address(0) && currentProposer != msg.sender) {
revert Errors.Leonidas__InvalidProposer(currentProposer, msg.sender);
}

if (_quote.epochToProve != epochToProve) {
revert Errors.Rollup__NotClaimingCorrectEpoch(epochToProve, _quote.epochToProve);
}

if (currentSlot % Constants.AZTEC_EPOCH_DURATION >= CLAIM_DURATION_IN_L2_SLOTS) {
revert Errors.Rollup__NotInClaimPhase(
currentSlot % Constants.AZTEC_EPOCH_DURATION, CLAIM_DURATION_IN_L2_SLOTS
);
}

// if the epoch to prove is not the one that has been claimed,
// then whatever is in the proofClaim is stale
if (proofClaim.epochToProve == epochToProve && proofClaim.proposerClaimant != address(0)) {
revert Errors.Rollup__ProofRightAlreadyClaimed();
}

if (_quote.bondAmount < PROOF_COMMITMENT_MIN_BOND_AMOUNT_IN_TST) {
revert Errors.Rollup__InsufficientBondAmount(
PROOF_COMMITMENT_MIN_BOND_AMOUNT_IN_TST, _quote.bondAmount
);
}

if (_quote.validUntilSlot < currentSlot) {
revert Errors.Rollup__QuoteExpired(currentSlot, _quote.validUntilSlot);
}

// We don't currently unstake,
// but we will as part of https://github.com/AztecProtocol/aztec-packages/issues/8652.
// Blocked on submitting epoch proofs to this contract.
address bondProvider = PROOF_COMMITMENT_ESCROW.stakeBond(_quote);

proofClaim = DataStructures.EpochProofClaim({
epochToProve: epochToProve,
basisPointFee: _quote.basisPointFee,
bondAmount: _quote.bondAmount,
bondProvider: bondProvider,
proposerClaimant: msg.sender
});

emit ProofRightClaimed(epochToProve, bondProvider, msg.sender, _quote.bondAmount, currentSlot);
}

/**
* @notice Publishes the body and propose the block
* @dev `eth_log_handlers` rely on this function
Expand Down Expand Up @@ -480,7 +538,26 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
return tips.pendingBlockNumber;
}

/**
* @notice Get the epoch that should be proven
*
* @dev This is the epoch that should be proven. It does so by getting the epoch of the block
* following the last proven block. If there is no such block (i.e. the pending chain is
* the same as the proven chain), then revert.
*
* @return uint256 - The epoch to prove
*/
function getEpochToProve() public view override(IRollup) returns (uint256) {
if (tips.provenBlockNumber == tips.pendingBlockNumber) {
revert Errors.Rollup__NoEpochToProve();
} else {
return getEpochAt(blocks[getProvenBlockNumber() + 1].slotNumber);
}
}

function _prune() internal {
delete proofClaim;

uint256 pending = tips.pendingBlockNumber;

// @note We are not deleting the blocks, but we are "winding back" the pendingTip to the last block that was proven.
Expand All @@ -501,12 +578,20 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
uint256 oldestPendingEpoch = getEpochAt(blocks[tips.provenBlockNumber + 1].slotNumber);
uint256 startSlotOfPendingEpoch = oldestPendingEpoch * Constants.AZTEC_EPOCH_DURATION;

// TODO: #8608 adds a proof claim, which will allow us to prune the chain more aggressively.
// That is what will add a `CLAIM_DURATION` to the pruning logic.
if (currentSlot < startSlotOfPendingEpoch + 2 * Constants.AZTEC_EPOCH_DURATION) {
// suppose epoch 1 is proven, epoch 2 is pending, epoch 3 is the current epoch.
// we prune the pending chain back to the end of epoch 1 if:
// - the proof claim phase of epoch 3 has ended without a claim to prove epoch 2 (or proof of epoch 2)
// - we reach epoch 4 without a proof of epoch 2 (regardless of whether a proof claim was submitted)
bool inClaimPhase = currentSlot
< startSlotOfPendingEpoch + Constants.AZTEC_EPOCH_DURATION + CLAIM_DURATION_IN_L2_SLOTS;

bool claimExists = currentSlot < startSlotOfPendingEpoch + 2 * Constants.AZTEC_EPOCH_DURATION
&& proofClaim.epochToProve == oldestPendingEpoch && proofClaim.proposerClaimant != address(0);

if (inClaimPhase || claimExists) {
// If we are in the claim phase, do not prune
return false;
}

return true;
}

Expand Down
13 changes: 13 additions & 0 deletions l1-contracts/src/core/interfaces/IRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,18 @@ interface IRollup {
event L2BlockProposed(uint256 indexed blockNumber, bytes32 indexed archive);
event L2ProofVerified(uint256 indexed blockNumber, bytes32 indexed proverId);
event PrunedPending(uint256 provenBlockNumber, uint256 pendingBlockNumber);
event ProofRightClaimed(
uint256 indexed epoch,
address indexed bondProvider,
address indexed proposer,
uint256 bondAmount,
uint256 currentSlot
);

function prune() external;

function claimEpochProofRight(DataStructures.EpochProofQuote calldata _quote) external;

function propose(
bytes calldata _header,
bytes32 _archive,
Expand Down Expand Up @@ -48,10 +57,13 @@ interface IRollup {
DataStructures.ExecutionFlags memory _flags
) external view;

// solhint-disable-next-line func-name-mixedcase
function INBOX() external view returns (IInbox);

// solhint-disable-next-line func-name-mixedcase
function OUTBOX() external view returns (IOutbox);

// solhint-disable-next-line func-name-mixedcase
function L1_BLOCK_AT_GENESIS() external view returns (uint256);

function status(uint256 myHeaderBlockNumber)
Expand Down Expand Up @@ -81,5 +93,6 @@ interface IRollup {
function archiveAt(uint256 _blockNumber) external view returns (bytes32);
function getProvenBlockNumber() external view returns (uint256);
function getPendingBlockNumber() external view returns (uint256);
function getEpochToProve() external view returns (uint256);
function computeTxsEffectsHash(bytes calldata _body) external pure returns (bytes32);
}
8 changes: 8 additions & 0 deletions l1-contracts/src/core/libraries/DataStructures.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,12 @@ library DataStructures {
address rollup;
uint32 basisPointFee;
}

struct EpochProofClaim {
uint256 epochToProve; // the epoch that the bond provider is claiming to prove
uint256 basisPointFee; // the fee that the bond provider will receive as a percentage of the block rewards
uint256 bondAmount; // the amount of escrowed funds that the bond provider will stake. Must be at least PROOF_COMMITMENT_BOND_AMOUNT
address bondProvider; // the address that has deposited funds in the escrow contract
address proposerClaimant; // the address of the proposer that submitted the claim
}
}
22 changes: 14 additions & 8 deletions l1-contracts/src/core/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,29 @@ library Errors {
error Outbox__BlockNotProven(uint256 l2BlockNumber); // 0x0e194a6d

// Rollup
error Rollup__InsufficientBondAmount(uint256 minimum, uint256 provided); // 0xa165f276
error Rollup__InvalidArchive(bytes32 expected, bytes32 actual); // 0xb682a40e
error Rollup__InvalidProposedArchive(bytes32 expected, bytes32 actual); // 0x32532e73
error Rollup__InvalidBlockNumber(uint256 expected, uint256 actual); // 0xe5edf847
error Rollup__SlotValueTooLarge(uint256 slot); // 0x7234f4fe
error Rollup__SlotAlreadyInChain(uint256 lastSlot, uint256 proposedSlot); // 0x83510bd0
error Rollup__InvalidChainId(uint256 expected, uint256 actual); // 0x37b5bc12
error Rollup__InvalidEpoch(uint256 expected, uint256 actual); // 0x3c6d65e6
error Rollup__TryingToProveNonExistingBlock(); // 0x34ef4954
error Rollup__InvalidInHash(bytes32 expected, bytes32 actual); // 0xcd6f4233
error Rollup__InvalidProof(); // 0xa5b2ba17
error Rollup__InvalidChainId(uint256 expected, uint256 actual); // 0x37b5bc12
error Rollup__InvalidVersion(uint256 expected, uint256 actual); // 0x9ef30794
error Rollup__InvalidProposedArchive(bytes32 expected, bytes32 actual); // 0x32532e73
error Rollup__InvalidTimestamp(uint256 expected, uint256 actual); // 0x3132e895
error Rollup__InvalidVersion(uint256 expected, uint256 actual); // 0x9ef30794
error Rollup__NoEpochToProve(); // 0xcbaa3951
error Rollup__NonSequentialProving(); // 0x1e5be132
error Rollup__NotClaimingCorrectEpoch(uint256 expected, uint256 actual); // 0xf0e0744d
error Rollup__NothingToPrune(); // 0x850defd3
error Rollup__NotInClaimPhase(uint256 currentSlotInEpoch, uint256 claimDuration); // 0xe6969f11
error Rollup__ProofRightAlreadyClaimed(); // 0x2cac5f0a
error Rollup__QuoteExpired(uint256 currentSlot, uint256 quoteSlot); // 0x20a001eb
error Rollup__SlotAlreadyInChain(uint256 lastSlot, uint256 proposedSlot); // 0x83510bd0
error Rollup__SlotValueTooLarge(uint256 slot); // 0x7234f4fe
error Rollup__TimestampInFuture(uint256 max, uint256 actual); // 0x89f30690
error Rollup__TimestampTooOld(); // 0x72ed9c81
error Rollup__TryingToProveNonExistingBlock(); // 0x34ef4954
error Rollup__UnavailableTxs(bytes32 txsHash); // 0x414906c3
error Rollup__NothingToPrune(); // 0x850defd3
error Rollup__NonSequentialProving(); // 0x1e5be132

// Registry
error Registry__RollupNotRegistered(address rollup); // 0xa1fee4cf
Expand Down
Loading

0 comments on commit 6b1a7ba

Please sign in to comment.