Skip to content

Removes start publication from checkpoint #111

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

Merged
merged 3 commits into from
May 8, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
19 changes: 9 additions & 10 deletions src/protocol/CheckpointTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ contract CheckpointTracker is ICheckpointTracker {
}

/// @inheritdoc ICheckpointTracker
/// @dev This function does not use the `start` checkpoint since we don't support parallel transitions.
function proveTransition(
Checkpoint calldata start,
Checkpoint calldata,
Checkpoint calldata end,
uint256 numPublications,
bytes calldata proof
Expand All @@ -47,19 +48,17 @@ contract CheckpointTracker is ICheckpointTracker {

require(end.commitment != 0, "Checkpoint commitment cannot be 0");

require(
start.publicationId == _provenCheckpoint.publicationId && start.commitment == _provenCheckpoint.commitment,
"Start checkpoint must be the latest proven checkpoint"
);

require(start.publicationId < end.publicationId, "End publication must be after the last proven publication");

bytes32 startPublicationHash = publicationFeed.getPublicationHash(start.publicationId);
bytes32 startPublicationHash = publicationFeed.getPublicationHash(_provenCheckpoint.publicationId);
bytes32 endPublicationHash = publicationFeed.getPublicationHash(end.publicationId);
require(endPublicationHash != 0, "End publication does not exist");

verifier.verifyProof(
startPublicationHash, endPublicationHash, start.commitment, end.commitment, numPublications, proof
startPublicationHash,
endPublicationHash,
_provenCheckpoint.commitment,
end.commitment,
numPublications,
proof
);

_provenCheckpoint = end;
Expand Down
39 changes: 9 additions & 30 deletions test/CheckpointTracker.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,54 +59,33 @@ contract CheckpointTrackerTest is Test {
}

function test_proveTransition_SuccessfulTransition() public {
ICheckpointTracker.Checkpoint memory start =
ICheckpointTracker.Checkpoint({publicationId: 0, commitment: keccak256(abi.encode("genesis"))});
ICheckpointTracker.Checkpoint memory end =
ICheckpointTracker.Checkpoint({publicationId: 3, commitment: keccak256(abi.encode("end"))});
uint256 numRelevantPublications = 2;

vm.expectEmit();
emit ICheckpointTracker.CheckpointUpdated(end);
tracker.proveTransition(start, end, numRelevantPublications, proof);

// Empty checkpoint needed to comply with the interface, but not used in `CheckpointTracker`
ICheckpointTracker.Checkpoint memory emptyCheckpoint =
ICheckpointTracker.Checkpoint({publicationId: 0, commitment: bytes32(0)});
tracker.proveTransition(emptyCheckpoint, end, numRelevantPublications, proof);

ICheckpointTracker.Checkpoint memory provenCheckpoint = tracker.getProvenCheckpoint();
assertEq(provenCheckpoint.publicationId, end.publicationId);
assertEq(provenCheckpoint.commitment, end.commitment);
}

function test_proveTransition_RevertWhenEndCommitmentIsZero() public {
ICheckpointTracker.Checkpoint memory start =
ICheckpointTracker.Checkpoint({publicationId: 0, commitment: keccak256(abi.encode("genesis"))});
ICheckpointTracker.Checkpoint memory end =
ICheckpointTracker.Checkpoint({publicationId: 3, commitment: bytes32(0)});
uint256 numRelevantPublications = 2;

vm.expectRevert("Checkpoint commitment cannot be 0");
tracker.proveTransition(start, end, numRelevantPublications, proof);
}

function test_proveTransition_RevertWhenStartCheckpointNotLatestProven() public {
ICheckpointTracker.Checkpoint memory start =
ICheckpointTracker.Checkpoint({publicationId: 1, commitment: keccak256(abi.encode("wrong"))});
ICheckpointTracker.Checkpoint memory end =
ICheckpointTracker.Checkpoint({publicationId: 3, commitment: keccak256(abi.encode("end"))});
uint256 numRelevantPublications = 2;

vm.expectRevert("Start checkpoint must be the latest proven checkpoint");
tracker.proveTransition(start, end, numRelevantPublications, proof);
}

function test_proveTransition_RevertWhenEndPublicationNotAfterStart() public {
ICheckpointTracker.Checkpoint memory start =
ICheckpointTracker.Checkpoint({publicationId: 0, commitment: keccak256(abi.encode("genesis"))});
ICheckpointTracker.Checkpoint memory end =
ICheckpointTracker.Checkpoint({publicationId: 0, commitment: keccak256(abi.encode("end"))});
// this is nonsensical, but we're testing the publicationId check so I think it makes sense for the other
// parameters to match previous tests.
uint256 numRelevantPublications = 2;

vm.expectRevert("End publication must be after the last proven publication");
tracker.proveTransition(start, end, numRelevantPublications, proof);
// Empty checkpoint needed to comply with the interface, but not used in `CheckpointTracker`
ICheckpointTracker.Checkpoint memory emptyCheckpoint =
ICheckpointTracker.Checkpoint({publicationId: 0, commitment: bytes32(0)});
tracker.proveTransition(emptyCheckpoint, end, numRelevantPublications, proof);
}

function createSampleFeed() private {
Expand Down
2 changes: 1 addition & 1 deletion test/mocks/MockCheckpointTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ contract MockCheckpointTracker is ICheckpointTracker {

/// @notice Do nothing. All checkpoints and proofs are accepted.
function proveTransition(
Checkpoint calldata start,
Checkpoint calldata,
Checkpoint calldata end,
uint256 numPublications,
bytes calldata proof
Expand Down