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

refactor: DisputeParameters -> ITournamentParametersProvider #106

Merged
merged 3 commits into from
Feb 19, 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
18 changes: 0 additions & 18 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ jobs:
with:
submodules: recursive

- name: Set up cache for Foundry
uses: actions/cache@v3
with:
path: ~/.foundry
key: ${{ runner.os }}-foundry-${{ hashFiles('**/foundry.toml') }}
restore-keys: |
${{ runner.os }}-foundry-

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

Expand All @@ -30,16 +22,6 @@ jobs:
just build-smart-contracts
just test

- name: Set up cache for Cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-

- name: Deps
run: |
export CARTESI_MACHINE_VERSION=0.18.1
Expand Down
22 changes: 6 additions & 16 deletions cartesi-rollups/contracts/script/DaveConsensus.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,21 @@ import {Script} from "forge-std/Script.sol";
import {Machine} from "prt-contracts/Machine.sol";

import "prt-contracts/tournament/factories/MultiLevelTournamentFactory.sol";
import "prt-contracts/CanonicalConstants.sol";
import "prt-contracts/CanonicalTournamentParametersProvider.sol";
import "rollups-contracts/inputs/IInputBox.sol";
import "src/DaveConsensus.sol";

contract DaveConcensusScript is Script {
function run(Machine.Hash initialHash, IInputBox inputBox) external {
DisputeParameters memory disputeParameters = DisputeParameters({
timeConstants: TimeConstants({
matchEffort: ArbitrationConstants.MATCH_EFFORT,
maxAllowance: ArbitrationConstants.MAX_ALLOWANCE
}),
commitmentStructures: new CommitmentStructure[](ArbitrationConstants.LEVELS)
});

for (uint64 i; i < ArbitrationConstants.LEVELS; ++i) {
disputeParameters.commitmentStructures[i] = CommitmentStructure({
log2step: ArbitrationConstants.log2step(i),
height: ArbitrationConstants.height(i)
});
}
vm.startBroadcast(vm.envUint("PRIVATE_KEY"));

MultiLevelTournamentFactory factory = new MultiLevelTournamentFactory(
new TopTournamentFactory(), new MiddleTournamentFactory(), new BottomTournamentFactory(), disputeParameters
new TopTournamentFactory(),
new MiddleTournamentFactory(),
new BottomTournamentFactory(),
new CanonicalTournamentParametersProvider()
);

new DaveConsensus(inputBox, address(0x0), factory, initialHash);

vm.stopBroadcast();
Expand Down
76 changes: 38 additions & 38 deletions cartesi-rollups/contracts/test/Merkle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ import {MerkleConstants} from "src/MerkleConstants.sol";
import {PristineMerkleTree} from "src/PristineMerkleTree.sol";
import {Merkle} from "src/Merkle.sol";

contract PristineMerkleTreeContract {
library PristineMerkleTreeWrapper {
function getNodeAtHeight(uint256 height) external pure returns (bytes32) {
return PristineMerkleTree.getNodeAtHeight(height);
}
}

contract MerkleContract {
library MerkleWrapper {
function join(bytes32 a, bytes32 b) external pure returns (bytes32) {
return Merkle.join(a, b);
}

function getRootAfterReplacementInDrive(
uint256 position,
uint256 log2SizeOfReplacement,
Expand All @@ -42,9 +46,6 @@ contract MerkleContract {
}

contract MerkleTest is Test {
PristineMerkleTreeContract pristineMerkle;
MerkleContract merkle;

uint256 constant LEAF_SIZE = (1 << MerkleConstants.LOG2_LEAF_SIZE);
bytes32 constant WORD_0 = keccak256("foo");
bytes32 constant WORD_1 = keccak256("bar");
Expand All @@ -59,30 +60,25 @@ contract MerkleTest is Test {
bytes32 constant ROOT = keccak256(abi.encode(NODE_01, NODE_23));
uint256 constant MAX_HEIGHT = MerkleConstants.LOG2_MEMORY_SIZE - MerkleConstants.LOG2_LEAF_SIZE;

function setUp() external {
pristineMerkle = new PristineMerkleTreeContract();
merkle = new MerkleContract();
}

function testJoinEquivalence(bytes32 a, bytes32 b) external pure {
assertEq(Merkle.join(a, b), keccak256(abi.encodePacked(a, b)));
assertEq(MerkleWrapper.join(a, b), keccak256(abi.encodePacked(a, b)));
}

function testPristineMerkleTree() external pure {
bytes32 node = keccak256(abi.encode(0));
for (uint256 height; height <= MerkleConstants.TREE_HEIGHT; ++height) {
assertEq(PristineMerkleTree.getNodeAtHeight(height), node);
node = Merkle.join(node, node);
node = MerkleWrapper.join(node, node);
}
}

function testPristineMerkleTreeRevert(uint256 height) external {
height = bound(height, MerkleConstants.TREE_HEIGHT + 1, type(uint256).max);
vm.expectRevert("Height out of bounds");
pristineMerkle.getNodeAtHeight(height);
PristineMerkleTreeWrapper.getNodeAtHeight(height);
}

function testGetRootAfterReplacementInDrive() external view {
function testGetRootAfterReplacementInDrive() external pure {
{
uint256 log2SizeOfReplacement = MerkleConstants.LOG2_LEAF_SIZE;
uint256 position = 0 << log2SizeOfReplacement;
Expand Down Expand Up @@ -110,7 +106,7 @@ contract MerkleTest is Test {

assertEq(
ROOT,
merkle.getRootAfterReplacementInDrive(
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
)
);
Expand Down Expand Up @@ -142,7 +138,7 @@ contract MerkleTest is Test {

assertEq(
ROOT,
merkle.getRootAfterReplacementInDrive(
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
)
);
Expand Down Expand Up @@ -174,7 +170,7 @@ contract MerkleTest is Test {

assertEq(
ROOT,
merkle.getRootAfterReplacementInDrive(
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
)
);
Expand Down Expand Up @@ -206,7 +202,7 @@ contract MerkleTest is Test {

assertEq(
ROOT,
merkle.getRootAfterReplacementInDrive(
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
)
);
Expand All @@ -231,7 +227,7 @@ contract MerkleTest is Test {

assertEq(
ROOT,
merkle.getRootAfterReplacementInDrive(
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
)
);
Expand All @@ -256,7 +252,7 @@ contract MerkleTest is Test {

assertEq(
ROOT,
merkle.getRootAfterReplacementInDrive(
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
)
);
Expand All @@ -273,7 +269,7 @@ contract MerkleTest is Test {
siblings[0] = LEAF_1;
siblings[1] = NODE_23;
vm.expectRevert("Position is not aligned");
merkle.getRootAfterReplacementInDrive(
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
);
}
Expand All @@ -291,71 +287,75 @@ contract MerkleTest is Test {
vm.assume(siblings.length != log2SizeOfDrive - log2SizeOfReplacement);
position = (position >> log2SizeOfReplacement) << log2SizeOfReplacement;
vm.expectRevert("Proof length does not match");
Merkle.getRootAfterReplacementInDrive(position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings);
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
);
}

function testGetRootAfterAnyReplacementInDrive(
uint256 position,
uint256 log2SizeOfReplacement,
uint256 log2SizeOfDrive,
bytes32 replacement
) external view {
) external pure {
log2SizeOfDrive = bound(log2SizeOfDrive, MerkleConstants.LOG2_LEAF_SIZE, MerkleConstants.LOG2_MEMORY_SIZE);
log2SizeOfReplacement = bound(log2SizeOfReplacement, MerkleConstants.LOG2_LEAF_SIZE, log2SizeOfDrive);
bytes32[] memory siblings = new bytes32[](log2SizeOfDrive - log2SizeOfReplacement);
position = (position >> log2SizeOfReplacement) << log2SizeOfReplacement;
merkle.getRootAfterReplacementInDrive(position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings);
MerkleWrapper.getRootAfterReplacementInDrive(
position, log2SizeOfReplacement, log2SizeOfDrive, replacement, siblings
);
}

function testGetMinLog2SizeOfDrive(bytes calldata data) external view {
uint256 log2SizeOfDrive = merkle.getMinLog2SizeOfDrive(data);
function testGetMinLog2SizeOfDrive(bytes calldata data) external pure {
uint256 log2SizeOfDrive = MerkleWrapper.getMinLog2SizeOfDrive(data);
assertLe(data.length, 1 << log2SizeOfDrive);
if (data.length <= LEAF_SIZE) {
assertEq(log2SizeOfDrive, MerkleConstants.LOG2_LEAF_SIZE);
} else {
assertGt(data.length, 1 << (log2SizeOfDrive - 1));
}
merkle.getMerkleRootFromBytes(data, log2SizeOfDrive);
MerkleWrapper.getMerkleRootFromBytes(data, log2SizeOfDrive);
}

function testGetMerkleRootFromBytes() external view {
function testGetMerkleRootFromBytes() external pure {
bytes memory data = _getTestData();
bytes32 root = ROOT;
for (uint256 i; MerkleConstants.LOG2_LEAF_SIZE + HEIGHT + i <= MerkleConstants.LOG2_MEMORY_SIZE; ++i) {
assertEq(merkle.getMerkleRootFromBytes(data, MerkleConstants.LOG2_LEAF_SIZE + HEIGHT + i), root);
root = Merkle.join(root, PristineMerkleTree.getNodeAtHeight(HEIGHT + i));
assertEq(MerkleWrapper.getMerkleRootFromBytes(data, MerkleConstants.LOG2_LEAF_SIZE + HEIGHT + i), root);
root = MerkleWrapper.join(root, PristineMerkleTree.getNodeAtHeight(HEIGHT + i));
}
}

function testGetMerkleRootFromBytesRevertDriveSmallerThanLeaf(uint256 log2SizeOfDrive) external {
log2SizeOfDrive = bound(log2SizeOfDrive, 0, MerkleConstants.LOG2_LEAF_SIZE - 1);
vm.expectRevert("Drive smaller than leaf");
merkle.getMerkleRootFromBytes(_getTestData(), log2SizeOfDrive);
MerkleWrapper.getMerkleRootFromBytes(_getTestData(), log2SizeOfDrive);
}

function testGetMerkleRootFromBytesRevertDataLargerThanDrive(uint256 log2SizeOfDrive) external {
log2SizeOfDrive = MerkleConstants.LOG2_LEAF_SIZE + bound(log2SizeOfDrive, 0, HEIGHT - 1);
vm.expectRevert("Data larger than drive");
merkle.getMerkleRootFromBytes(_getTestData(), log2SizeOfDrive);
MerkleWrapper.getMerkleRootFromBytes(_getTestData(), log2SizeOfDrive);
}

function testGetMerkleRootFromBytesRevertDriveLargerThanMemory(uint256 log2SizeOfDrive) external {
log2SizeOfDrive = bound(log2SizeOfDrive, MerkleConstants.LOG2_MEMORY_SIZE + 1, type(uint256).max);
vm.expectRevert("Drive larger than memory");
merkle.getMerkleRootFromBytes(_getTestData(), log2SizeOfDrive);
MerkleWrapper.getMerkleRootFromBytes(_getTestData(), log2SizeOfDrive);
}

function testGetHashOfLeafAtIndex() external view {
function testGetHashOfLeafAtIndex() external pure {
bytes memory data = _getTestData();
assertEq(merkle.getHashOfLeafAtIndex(data, 0), LEAF_0);
assertEq(merkle.getHashOfLeafAtIndex(data, 1), LEAF_1);
assertEq(merkle.getHashOfLeafAtIndex(data, 2), LEAF_2);
assertEq(MerkleWrapper.getHashOfLeafAtIndex(data, 0), LEAF_0);
assertEq(MerkleWrapper.getHashOfLeafAtIndex(data, 1), LEAF_1);
assertEq(MerkleWrapper.getHashOfLeafAtIndex(data, 2), LEAF_2);
}

function testGetHashOfLeafAtIndex(bytes calldata data, uint256 index) external pure {
index = bound(index, _getNumOfLeaves(data.length), type(uint256).max);
bytes32 leafHash = PristineMerkleTree.getNodeAtHeight(0);
assertEq(Merkle.getHashOfLeafAtIndex(data, index), leafHash);
assertEq(MerkleWrapper.getHashOfLeafAtIndex(data, index), leafHash);
}

function _getTestData() internal pure returns (bytes memory) {
Expand Down
2 changes: 1 addition & 1 deletion cartesi-rollups/node/blockchain-reader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ mod blockchain_reader_tests {
anvil,
provider,
Address::from_hex("0x5fbdb2315678afecb367f032d93f642f64180aa3").unwrap(),
Address::from_hex("0x0165878a594ca255338adfa4d48449f69242eb8f").unwrap(),
Address::from_hex("0xa513e6e4b8f2a923d98304ec87f64353c4d5c853").unwrap(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can eventually make this read from test/programs/echo/addresses

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this would be great.

)
}

Expand Down
21 changes: 2 additions & 19 deletions prt/contracts/script/TopTournament.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,17 @@ import {Machine} from "src/Machine.sol";

import "src/tournament/factories/MultiLevelTournamentFactory.sol";
import "src/IDataProvider.sol";
import "src/CanonicalConstants.sol";
import "src/CanonicalTournamentParametersProvider.sol";

contract TopTournamentScript is Script {
function run(Machine.Hash initialHash) external {
DisputeParameters memory disputeParameters = DisputeParameters({
timeConstants: TimeConstants({
matchEffort: ArbitrationConstants.MATCH_EFFORT,
maxAllowance: ArbitrationConstants.MAX_ALLOWANCE
}),
commitmentStructures: new CommitmentStructure[](
ArbitrationConstants.LEVELS
)
});

for (uint64 i; i < ArbitrationConstants.LEVELS; ++i) {
disputeParameters.commitmentStructures[i] = CommitmentStructure({
log2step: ArbitrationConstants.log2step(i),
height: ArbitrationConstants.height(i)
});
}

vm.startBroadcast(vm.envUint("PRIVATE_KEY"));

MultiLevelTournamentFactory factory = new MultiLevelTournamentFactory(
new TopTournamentFactory(),
new MiddleTournamentFactory(),
new BottomTournamentFactory(),
disputeParameters
new CanonicalTournamentParametersProvider()
);

factory.instantiate(initialHash, IDataProvider(address(0x0)));
Expand Down
27 changes: 27 additions & 0 deletions prt/contracts/src/CanonicalTournamentParametersProvider.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

pragma solidity ^0.8.17;

import "./ITournamentParametersProvider.sol";
import "./CanonicalConstants.sol";

contract CanonicalTournamentParametersProvider is
ITournamentParametersProvider
{
/// @inheritdoc ITournamentParametersProvider
function tournamentParameters(uint64 level)
external
pure
override
returns (TournamentParameters memory)
{
return TournamentParameters({
levels: ArbitrationConstants.LEVELS,
log2step: ArbitrationConstants.log2step(level),
height: ArbitrationConstants.height(level),
matchEffort: ArbitrationConstants.MATCH_EFFORT,
maxAllowance: ArbitrationConstants.MAX_ALLOWANCE
});
}
}
15 changes: 15 additions & 0 deletions prt/contracts/src/ITournamentParametersProvider.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

pragma solidity ^0.8.17;

import {TournamentParameters} from "./TournamentParameters.sol";

interface ITournamentParametersProvider {
/// @notice Get tournament parameters for a given level.
/// @param level The tournament level (0 = top)
function tournamentParameters(uint64 level)
external
view
returns (TournamentParameters memory);
}
Loading
Loading