diff --git a/fraud-proofs/fraud-proof-basics/bonds.md b/fraud-proofs/fraud-proof-basics/bonds.md index 51a4a797..562286b0 100644 --- a/fraud-proofs/fraud-proof-basics/bonds.md +++ b/fraud-proofs/fraud-proof-basics/bonds.md @@ -1,6 +1,35 @@ # Bonds -:::warning Work in progress -Bonds mechanism is not yet implemented in the Cartesi's fraud proof system. To get the latest updates, get in touch with the core contributors on Cartesi [Discord](https://discord.gg/cartesi). -::: +## What is a bond mechanism? +A bond mechanism in the fraud-proof system is an economic security system that requires any participant to post a collateral when submitting a claim in the dispute-resolution process. + +The goal is to introduce a modest economic cost to submitting claims, thereby mitigating the impact of Sybil attacks. Bonds provide a means to reimburse dispute-related expenses, ensuring that honest participants are not financially penalized for engaging in validation. + +The mechanism is not intended to create participation incentives, rather, its design objective is to keep honest, altruistic validation as close to costless as possible, irrespective of the number or behavior of Sybil identities. + +## Why do we need bonds? A Case without Bonds +In a dispute process, each transaction made on Ethereum would incur gas costs for the proposer and the challenger. This cost does not include the bond amount. In this setup, a malicious proposer who can spend a relatively large amount of gas fees has an advantage to repeatedly post claims until the honest challenger exhausts their funds or computational resources. + +This is infamously known as the resource-exhaustion attack or [proof-of-whale attack](https://ethresear.ch/t/fraud-proofs-are-broken/19234). It is a type of Sybil attack. To deter such an attack, we introduce a bond system in the fraud-proof system. + +Naively introducing a high bond amount will impact decentralisation. Liveness and security may depend on preventing the adversary from creating too many Sybils. Increasing bonds in such a scenario harms decentralization by restricting the number of players that can afford to participate. + +## Implementation in PRT v2 +Cartesi’s _Permissionless Refereed Tournament (PRT) v2_ features a bond system. Each tournament level requires a bond to be posted in order for a commitment to be submitted. + +A defender gets the gas fees as a refund with an optional incentive to be an active defender of the system. In a single dispute process (a tournament system), the fraud-proof design asks participants to stake a bond at each level of the game. + +In the worst-case scenario, an honest validator will have one bond for each tournament level. Currently, PRT v2 features three levels: top, middle, and bottom, which correspond to three bonds. Bond values differ at each level. + +When joining a tournament, participants must send the bond value in Ether. The contract enforces this requirement and reverts with an `InsufficientBond` error if the payment is insufficient. + +The **refund calculation** is capped by three values: the contract balance, a weighted fraction of the bond value, and the actual gas used plus a profit margin. The profit margin incentivizes honest participants to perform necessary operations. + +The submitter of the winning commitment receives any remaining bonds after tournament completion, recovering their costs plus rewards from eliminated participants. + +However, in practice, issuing refunds introduces an additional challenge. During dispute actions such as bisections and steps, multiple honest validators may attempt the same operation simultaneously. Only the first transaction succeeds, while any following ones revert, creating a race condition that leads to unnecessary gas losses and complicates proper refunds. + +To address this, PRT can leverage a targeted technique based on **MEV-Share’s** `mev_sendBundle` RPC. Although MEV-Share is a general MEV redistribution protocol, we rely on it only for its ability to relay transactions predictably through searcher relays. By submitting dispute actions via `mev_sendBundle`, validators avoid public mempool races and ensure that the intended action is included without incurring failed-transaction costs. + +This approach preserves the goal of making honest validation effectively costless, even when many validators attempt the same operation. diff --git a/fraud-proofs/honeypot/introduction.md b/fraud-proofs/honeypot/introduction.md index 9710e0a0..3d5ba2cd 100644 --- a/fraud-proofs/honeypot/introduction.md +++ b/fraud-proofs/honeypot/introduction.md @@ -1,9 +1,5 @@ # Introduction -:::caution - Honeypot app is being updated. We recently found a bug in the application that has led to a fail-stop state. This means the current deployment is permanently frozen, and the bounty funds within it are no longer recoverable. Get in touch with us on [Discord](https://discord.gg/cWGbyFkQ2W) for more details. -::: - This section focuses on the Cartesi application - the Honeypot - its introduction, application logic and how it demonstrates the PRT fraud-proof system's capabilities in a real-world scenario. diff --git a/fraud-proofs/references/daveconsensus.md b/fraud-proofs/references/daveconsensus.md index 0883b56f..debbc5b6 100644 --- a/fraud-proofs/references/daveconsensus.md +++ b/fraud-proofs/references/daveconsensus.md @@ -3,6 +3,17 @@ ## DaveConsensus Contract --- +DaveConsensus (also referred to as PRT-Rollups Consensus) is the consensus contract for applications that use Dave-style tournaments (such as PRT) for verification. +This contract is responsible for validating a single application, whose inputs must originate from a pre-configured InputBox contract. + +DaveConsensus manages epochs, which are defined as half-open block-number intervals of the form [a, b). +Epochs are numbered sequentially starting from 0. + +Off-chain nodes can track progress by subscribing to the _EpochSealed_ event. This event indicates which epochs have been sealed, which ones are fully settled, and which epoch is currently open for challenges. +Anyone may settle an epoch by calling _settle()_, and an epoch’s eligibility for settlement can be checked via _canSettle()_. Learn more about epochs [here](../../../fraud-proofs/fraud-proof-basics/epochs). + +This contract links input ingestion, epoch progression, and Dave tournament-based verification under a single consensus interface. + ### `canSettle()` ```solidity @@ -15,9 +26,9 @@ Check if the current epoch can be settled by querying the tournament's arbitrati | Name | Type | Description | |------|------|-------------| -| `isFinished` | `bool` | Whether tournament is finished | -| `epochNumber` | `uint256` | Current epoch number | -| `winnerCommitment` | `Tree.Node` | Winner's commitment from tournament | +| `isFinished` | `bool` | Whether the current sealed epoch tournament has finished | +| `epochNumber` | `uint256` | Current sealed epoch number | +| `winnerCommitment` | `Tree.Node` | Winner's commitment in case the tournament has finished | ### `settle()` @@ -25,15 +36,15 @@ Check if the current epoch can be settled by querying the tournament's arbitrati function settle(uint256 epochNumber, bytes32 outputsMerkleRoot, bytes32[] calldata proof) external ``` -Settle an epoch using tournament results and create a new tournament for the next epoch. +Settle the current sealed epoch. On success, it emits an [`EpochSealed`](#epochsealed) event. **Parameters:** | Name | Type | Description | |------|------|-------------| -| `epochNumber` | `uint256` | The epoch number to settle | -| `outputsMerkleRoot` | `bytes32` | Root hash of the outputs Merkle tree | -| `proof` | `bytes32[]` | Merkle proof array for validation | +| `epochNumber` | `uint256` | The current sealed epoch number (used to avoid race conditions) | +| `outputsMerkleRoot` | `bytes32` | The post-epoch outputs Merkle root (used to validate outputs) | +| `proof` | `bytes32[]` | The bottom-up Merkle proof of the outputs Merkle root in the final machine state | ### `getCurrentSealedEpoch()` @@ -50,7 +61,7 @@ Get information about the current sealed epoch including bounds and tournament. | `epochNumber` | `uint256` | Current epoch number | | `inputIndexLowerBound` | `uint256` | Lower bound of input indices (inclusive) | | `inputIndexUpperBound` | `uint256` | Upper bound of input indices (exclusive) | -| `tournament` | `ITournament` | Current tournament contract | +| `tournament` | `ITournament` | The tournament that will decide the post-epoch state | ### `isOutputsMerkleRootValid()` @@ -69,9 +80,9 @@ Validate whether a given outputs Merkle root is valid for the specified applicat **Returns:** -| Name | Type | Description | +| Index | Type | Description | |------|------|-------------| -| `valid` | `bool` | Whether the outputs Merkle root is valid | +| [0] | `bool` | Whether the outputs Merkle root is valid | ### `provideMerkleRootOfInput()` @@ -90,63 +101,76 @@ Get the Merkle root for input data at a specific index within the current epoch. **Returns:** -| Name | Type | Description | +| Index | Type | Description | |------|------|-------------| -| `merkleRoot` | `bytes32` | Merkle root of the input data | - -## DaveConsensusFactory Contract ---- - -### `newDaveConsensus()` +| [0] | `bytes32` | Merkle root of the input data | +### `ConsensusCreation` ```solidity -function newDaveConsensus(address appContract, Machine.Hash initialMachineStateHash) external returns (DaveConsensus) +event ConsensusCreation(IInputBox inputBox, address appContract, ITournamentFactory tournamentFactory) ``` -Deploy a new DaveConsensus contract instance for an application. +An event emitted when a new DaveConsensus contract is deployed. **Parameters:** - | Name | Type | Description | |------|------|-------------| -| `appContract` | `address` | Application contract address | -| `initialMachineStateHash` | `Machine.Hash` | Initial state hash of the Cartesi machine | +| `inputBox` | `IInputBox` | The input box contract | +| `appContract` | `address` | The application contract | +| `tournamentFactory` | `ITournamentFactory` | The tournament factory contract | -**Returns:** +### `EpochSealed` +```solidity +event EpochSealed(uint256 epochNumber, uint256 inputIndexLowerBound, uint256 inputIndexUpperBound, Machine.Hash initialMachineStateHash, bytes32 outputsMerkleRoot, ITournament tournament) +``` +An event emitted when a new epoch is sealed. + +**Parameters:** | Name | Type | Description | |------|------|-------------| -| `daveConsensus` | `DaveConsensus` | Deployed DaveConsensus contract instance | +| `epochNumber` | `uint256` | The epoch number | +| `inputIndexLowerBound` | `uint256` | The lower bound of the input index (inclusive) | +| `inputIndexUpperBound` | `uint256` | The upper bound of the input index (exclusive) | +| `initialMachineStateHash` | `Machine.Hash` | The initial machine state hash | +| `outputsMerkleRoot` | `bytes32` | The Merkle root hash of the outputs tree | +| `tournament` | `ITournament` | The sealed epoch tournament contract| + +## DaveAppFactory Contract +--- + +Dave-Application Factory contract allows anyone to reliably deploy an application validated with its corresponding Consensus contract. -### `newDaveConsensus()` (with salt) +### `newDaveApp()` ```solidity -function newDaveConsensus(address appContract, Machine.Hash initialMachineStateHash, bytes32 salt) external returns (DaveConsensus) +function newDaveApp(bytes32 templateHash, bytes32 salt) external returns (IApplication appContract, IDaveConsensus daveConsensus) ``` -Deploy a new DaveConsensus contract with deterministic address using CREATE2. +Deploy a new Dave-Application pair deterministically. **Parameters:** | Name | Type | Description | |------|------|-------------| -| `appContract` | `address` | Application contract address | -| `initialMachineStateHash` | `Machine.Hash` | Initial state hash of the Cartesi machine | -| `salt` | `bytes32` | Salt for CREATE2 deterministic deployment | +| `templateHash` | `bytes32` | Template hash of the application | +| `salt` | `bytes32` | A 32-byte value used to add entropy to the addresses | **Returns:** | Name | Type | Description | |------|------|-------------| -| `daveConsensus` | `DaveConsensus` | Deployed DaveConsensus contract instance | +| `appContract` | `IApplication` | Deployed application contract | +| `daveConsensus` | `IDaveConsensus` | Deployed DaveConsensus contract | -### `calculateDaveConsensusAddress()` + +### `calculateDaveAppAddress()` ```solidity -function calculateDaveConsensusAddress(address appContract, Machine.Hash initialMachineStateHash, bytes32 salt) external view returns (address) +function calculateDaveAppAddress(bytes32 templateHash, bytes32 salt) external view returns (address appContractAddress, address daveConsensusAddress) ``` -Calculate the deployment address for a DaveConsensus contract before deployment. +Calculate the deployment address for a Dave-App pair before deployment. **Parameters:** @@ -160,4 +184,18 @@ Calculate the deployment address for a DaveConsensus contract before deployment. | Name | Type | Description | |------|------|-------------| -| `address` | `address` | Calculated deployment address | +| `appContractAddress` | `address` | Calculated deployment address for the application contract | +| `daveConsensusAddress` | `address` | Calculated deployment address for the DaveConsensus contract | + +### `DaveAppCreated` +```solidity +event DaveAppCreated(IApplication appContract, IDaveConsensus daveConsensus) +``` + +An event emitted when a new Dave-App pair is deployed. + +**Parameters:** +| Name | Type | Description | +|------|------|-------------| +| `appContract` | `IApplication` | The deployed application contract | +| `daveConsensus` | `IDaveConsensus` | The deployed DaveConsensus contract | \ No newline at end of file diff --git a/fraud-proofs/references/deployments.md b/fraud-proofs/references/deployments.md index addd19aa..7bc1d396 100644 --- a/fraud-proofs/references/deployments.md +++ b/fraud-proofs/references/deployments.md @@ -6,25 +6,25 @@ This page covers the PRT and Honeypot v2 deployed contracts and their addresses. | Component | Mainnet Address | |-----------|-----------------| -| **Top Tournament** | [`0x09114973AE4bf3Af3896E4e541082C73f224F8Aa`](https://etherscan.io/address/0x09114973AE4bf3Af3896E4e541082C73f224F8Aa) | -| **Middle Tournament** | [`0xe49E4CB0Ab5c0E5792E762807329B420Cc4FF1AE`](https://etherscan.io/address/0xe49E4CB0Ab5c0E5792E762807329B420Cc4FF1AE) | -| **Bottom Tournament** | [`0x18256941eC7B661F9F46C228b74e775b581e63f8`](https://etherscan.io/address/0x18256941eC7B661F9F46C228b74e775b581e63f8) | -| **Cartesi State Transition** | [`0x772732EFbDE6559B2960327276ed33d707fF057f`](https://etherscan.io/address/0x772732EFbDE6559B2960327276ed33d707fF057f) | -| **MultiLevel Tournament Factory** | [`0xA31C2aCfF3464658866960c0fBD3d798310272D7`](https://etherscan.io/address/0xA31C2aCfF3464658866960c0fBD3d798310272D7) | -| **CanonicalTournamentParametersProvider** | [`0xcC0a49320891Bf35bca834aF1045ab89Ecd44c0c`](https://etherscan.io/address/0xcC0a49320891Bf35bca834aF1045ab89Ecd44c0c) | +| **Top-Tournament Factory** | [`0xfdF16a7D9143f5E3B7B056b761a7eF8Ce18dc6eF`](https://etherscan.io/address/0xfdF16a7D9143f5E3B7B056b761a7eF8Ce18dc6eF) | +| **Middle-Tournament Factory** | [`0x47c7f40841F842f7691cB9Fd6Cd63673B79dCe79`](https://etherscan.io/address/0x47c7f40841F842f7691cB9Fd6Cd63673B79dCe79) | +| **Bottom-Tournament Factory** | [`0x6ccb8955afFA2aE4A88a4fC30916b41074d1F2B6`](https://etherscan.io/address/0x6ccb8955afFA2aE4A88a4fC30916b41074d1F2B6) | +| **Cartesi State Transition** | [`0x31EEaeC2A8d855B13B376b72C172F0c20A2910F6`](https://etherscan.io/address/0x31EEaeC2A8d855B13B376b72C172F0c20A2910F6) | +| **Cartesi Machine I/O State Transition** | [`0x6288F737D7B18594b3092aEF13aB47071281A8b0`](https://etherscan.io/address/0x6288F737D7B18594b3092aEF13aB47071281A8b0) | +| **RISC-V State Transition** | [`0x31a7AE6095516f78a30a8991aee2881D429AfECF`](https://etherscan.io/address/0x31a7AE6095516f78a30a8991aee2881D429AfECF) | +| **Multi-Level Tournament Factory** | [`0x74A82BAeD499a19e007243b86830e0A86154E816`](https://etherscan.io/address/0x74A82BAeD499a19e007243b86830e0A86154E816) | +| **Canonical Tournament Parameters Provider** | [`0xEf77920dA48Ed9b16Bee85291A9B29C74d0e32eb`](https://etherscan.io/address/0xEf77920dA48Ed9b16Bee85291A9B29C74d0e32eb) | -## Honeypot v2 Deployments -:::caution - Honeypot app is being updated. We recently found a bug in the application that has led to a fail-stop state. This means the current deployment is permanently frozen, and the bounty funds within it are no longer recoverable. Get in touch with us on [Discord](https://discord.gg/cWGbyFkQ2W) for more details. -::: + +## Honeypot v3 Deployments | Component | Mainnet Address | |-----------|-----------------| -| **Machine Hash** | `0x615acc9fb8ae058d0e45c0d12fa10e1a6c9e645222c6fd94dfeda194ee427c14` | -| **Application Contract** | [`0x4c1e74ef88a75c24e49eddd9f70d82a94d19251c`](https://etherscan.io/address/0x4c1e74ef88a75c24e49eddd9f70d82a94d19251c) | -| **Dave PRT Consensus Contract** | [`0x6CE590b9F0697327f18c601DF6f0baE4a0801B68`](https://etherscan.io/address/0x6CE590b9F0697327f18c601DF6f0baE4a0801B68) | -| **Input Box Contract** | [`0xc70074BDD26d8cF983Ca6A5b89b8db52D5850051`](https://etherscan.io/address/0xc70074BDD26d8cF983Ca6A5b89b8db52D5850051) | -| **ERC-20 Portal** | [`0xc700D6aDd016eECd59d989C028214Eaa0fCC0051`](https://etherscan.io/address/0xc700D6aDd016eECd59d989C028214Eaa0fCC0051) | +| **Machine Hash** | `0x144d45af1181b35f2b11c4b1150d6cb16934c28093707fb97c911ff16b3fe609` | +| **Application Contract** | [`0xfddf68726a28e418fa0c2a52c3134904a8c3e998`](https://etherscan.io/address/0xfddf68726a28e418fa0c2a52c3134904a8c3e998) | +| **Dave PRT Consensus Contract** | [`0xF0D8374F8446E87e013Ec1435C7245E05f439259`](https://etherscan.io/address/0xF0D8374F8446E87e013Ec1435C7245E05f439259) | +| **Input Box Contract** | [`0x1b51e2992A2755Ba4D6F7094032DF91991a0Cfac`](https://etherscan.io/address/0x1b51e2992A2755Ba4D6F7094032DF91991a0Cfac) | +| **ERC-20 Portal** | [`0xACA6586A0Cf05bD831f2501E7B4aea550dA6562D`](https://etherscan.io/address/0xACA6586A0Cf05bD831f2501E7B4aea550dA6562D) | | **ERC-20 Token** | CTSI @ [`0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D`](https://etherscan.io/address/0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D) | | **ERC-20 Wallet** | Cartesi Multisig @ [`0x60247492F1538Ed4520e61aE41ca2A8447592Ff5`](https://etherscan.io/address/0x60247492F1538Ed4520e61aE41ca2A8447592Ff5) | diff --git a/fraud-proofs/references/prt-v1-deployments.md b/fraud-proofs/references/prt-v1-deployments.md new file mode 100644 index 00000000..ea0019dd --- /dev/null +++ b/fraud-proofs/references/prt-v1-deployments.md @@ -0,0 +1,30 @@ +# Deployments + +This page covers the PRT and Honeypot v2 deployed contracts and their addresses. + +## PRT Deployments + +| Component | Mainnet Address | +|-----------|-----------------| +| **Top-Tournament Factory** | [`0x71C6A5fF7f4f31451CcB5bE312Fa1C5F2a060d5c`](https://etherscan.io/address/0x71C6A5fF7f4f31451CcB5bE312Fa1C5F2a060d5c) | +| **Middle-Tournament Factory** | [`0x2B3272E7Bcf06d36b9A902dfc0dD0d9384F2A4c4`](https://etherscan.io/address/0x2B3272E7Bcf06d36b9A902dfc0dD0d9384F2A4c4) | +| **Bottom-Tournament Factory** | [`0x4C7ab101e9B114A253475485b301E0D0c9e20647`](https://etherscan.io/address/0x4C7ab101e9B114A253475485b301E0D0c9e20647) | +| **Cartesi State Transition** | [`0x772732EFbDE6559B2960327276ed33d707fF057f`](https://etherscan.io/address/0x772732EFbDE6559B2960327276ed33d707fF057f) | +| **Multi-Level Tournament Factory** | [`0xA31C2aCfF3464658866960c0fBD3d798310272D7`](https://etherscan.io/address/0xA31C2aCfF3464658866960c0fBD3d798310272D7) | +| **Canonical Tournament Parameters Provider** | [`0xcC0a49320891Bf35bca834aF1045ab89Ecd44c0c`](https://etherscan.io/address/0xcC0a49320891Bf35bca834aF1045ab89Ecd44c0c) | + +## Honeypot v2 Deployments +:::caution +The Honeypot app has been updated. We recently found a bug in the application that has led to a fail-stop state. This means the current deployment is permanently frozen, and the bounty funds within it are no longer recoverable. Read the [post-mortem](https://cartesi.io/blog/prt_honeypot_postmortem/) for more details. +::: + +| Component | Mainnet Address | +|-----------|-----------------| +| **Machine Hash** | `0x615acc9fb8ae058d0e45c0d12fa10e1a6c9e645222c6fd94dfeda194ee427c14` | +| **Application Contract** | [`0x4c1e74ef88a75c24e49eddd9f70d82a94d19251c`](https://etherscan.io/address/0x4c1e74ef88a75c24e49eddd9f70d82a94d19251c) | +| **Dave PRT Consensus Contract** | [`0x6CE590b9F0697327f18c601DF6f0baE4a0801B68`](https://etherscan.io/address/0x6CE590b9F0697327f18c601DF6f0baE4a0801B68) | +| **Input Box Contract** | [`0xc70074BDD26d8cF983Ca6A5b89b8db52D5850051`](https://etherscan.io/address/0xc70074BDD26d8cF983Ca6A5b89b8db52D5850051) | +| **ERC-20 Portal** | [`0xc700D6aDd016eECd59d989C028214Eaa0fCC0051`](https://etherscan.io/address/0xc700D6aDd016eECd59d989C028214Eaa0fCC0051) | +| **ERC-20 Token** | CTSI @ [`0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D`](https://etherscan.io/address/0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D) | +| **ERC-20 Wallet** | Cartesi Multisig @ [`0x60247492F1538Ed4520e61aE41ca2A8447592Ff5`](https://etherscan.io/address/0x60247492F1538Ed4520e61aE41ca2A8447592Ff5) | + diff --git a/fraud-proofs/references/tournament.md b/fraud-proofs/references/tournament.md index b0086876..b0442b54 100644 --- a/fraud-proofs/references/tournament.md +++ b/fraud-proofs/references/tournament.md @@ -1,30 +1,150 @@ # PRT Core Contracts -## Tournament Base Contract +## Tournament Factory Functions +--- +Tournament factory contracts are responsible for instantiating and deploying tournaments. They handle the initialization of tournament parameters including initial machine state, data providers, and timing configurations. There are two main factory types: `SingleLevelTournamentFactory` for simple disputes and `MultiLevelTournamentFactory` for complex multi-level dispute resolution, which coordinates the creation of Top, Middle, and Bottom tournament instances. + +### `instantiate()` + +```solidity +function instantiate(Machine.Hash initialState, IDataProvider provider) external returns (ITournament) +``` + +Create a new single-level tournament instance. + +**Event Emitted:** `TournamentCreated(ITournament tournament)` when tournament is created + +**Parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `initialState` | `Machine.Hash` | Initial machine state hash | +| `provider` | `IDataProvider` | Data provider for input validation | + +**Return Values:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `ITournament` | Created tournament instance | + +### `instantiateTop()` (MultiLevelTournamentFactory) + +```solidity +function instantiateTop(Machine.Hash _initialHash, IDataProvider _provider) external returns (ITournament) +``` + +Create a new top-level tournament in the multi-level hierarchy. + +**Parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `initialHash` | `Machine.Hash` | Initial machine state hash | +| `provider` | `IDataProvider` | Data provider for input validation | + +**Returns:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `Tournament` | Created top tournament instance | + +### `instantiateMiddle()` + +```solidity +function instantiateMiddle(Machine.Hash initialHash, Tree.Node contestedCommitmentOne, Machine.Hash contestedFinalStateOne, Tree.Node contestedCommitmentTwo, Machine.Hash contestedFinalStateTwo, Time.Duration allowance, uint256 startCycle, uint64 level, IDataProvider provider) external returns (ITournament) +``` + +Create a new middle-level tournament for dispute resolution. + +**Parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `initialHash` | `Machine.Hash` | Initial machine state hash | +| `contestedCommitmentOne` | `Tree.Node` | First contested commitment | +| `contestedFinalStateOne` | `Machine.Hash` | First contested final state | +| `contestedCommitmentTwo` | `Tree.Node` | Second contested commitment | +| `contestedFinalStateTwo` | `Machine.Hash` | Second contested final state | +| `allowance` | `Time.Duration` | Time allowance for participants | +| `startCycle` | `uint256` | Starting cycle for the tournament | +| `level` | `uint64` | Tournament level in hierarchy | +| `provider` | `IDataProvider` | Data provider for input validation | + +**Returns:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `ITournament` | Created middle tournament instance | + +### `instantiateBottom()` + +```solidity +function instantiateBottom(Machine.Hash initialHash, Tree.Node contestedCommitmentOne, Machine.Hash contestedFinalStateOne, Tree.Node contestedCommitmentTwo, Machine.Hash contestedFinalStateTwo, Time.Duration allowance, uint256 startCycle, uint64 level, IDataProvider provider) external returns (ITournament) +``` + +Create a new bottom-level tournament for leaf dispute resolution. + +**Parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `initialHash` | `Machine.Hash` | Initial machine state hash | +| `contestedCommitmentOne` | `Tree.Node` | First contested commitment | +| `contestedFinalStateOne` | `Machine.Hash` | First contested final state | +| `contestedCommitmentTwo` | `Tree.Node` | Second contested commitment | +| `contestedFinalStateTwo` | `Machine.Hash` | Second contested final state | +| `allowance` | `Time.Duration` | Time allowance for participants | +| `startCycle` | `uint256` | Starting cycle for the tournament | +| `level` | `uint64` | Tournament level in hierarchy | +| `provider` | `IDataProvider` | Data provider for input validation | + +**Returns:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `ITournament` | Created bottom tournament instance | + +## Tournament Core Functions --- +Core tournament contracts implement the asynchronous PRT-style dispute resolution mechanism. The abstract Tournament contract provides the foundational skeleton that resolves disputes among N parties in O(log N) depth under chess-clock timing, with asynchronous pairing where claims are matched as they arrive without requiring a prebuilt bracket. Concrete implementations include `SingleLevelTournament` for single-level disputes, `TopTournament` for the root of multi-level instances, `MiddleTournament` for intermediate levels, and `BottomTournament` for the leaf level that performs actual state transitions. + ### `joinTournament()` ```solidity -function joinTournament(Tree.Node finalState, bytes32[] calldata proof, Tree.Node leftChild, Tree.Node rightChild) external tournamentOpen tournamentNotFinished +function joinTournament(Machine.Hash finalState, bytes32[] calldata proof, Tree.Node leftNode, Tree.Node rightNode) external payable ``` Join a tournament by submitting a final computation hash with Merkle proof. Creates a match if another participant is waiting. -**Event Emitted:** `commitmentJoined(Tree.Node root)` when commitment is successfully added - **Parameters:** | Name | Type | Description | |------|------|-------------| | `finalState` | `Tree.Node` | Final computational hash | | `proof` | `bytes32[]` | Merkle proof for the final state | -| `leftChild` | `Tree.Node` | Left child of the commitment node | -| `rightChild` | `Tree.Node` | Right child of the commitment node | +| `leftNode` | `Tree.Node` | Left node of the commitment | +| `rightNode` | `Tree.Node` | Right node of the commitment | + +### `arbitrationResult()` + +```solidity +function arbitrationResult() external view returns (bool finished, Tree.Node winnerCommitment, Machine.Hash finalState) +``` + +Get the final arbitration result from the root tournament. + +**Return Values:** + +| Name | Type | Description | +|------|------|-------------| +| `finished` | `bool` | Whether the tournament is finished | +| `winnerCommitment` | `Tree.Node` | The winning commitment | +| `finalState` | `Machine.Hash` | Final machine state hash of winner | ### `advanceMatch()` ```solidity -function advanceMatch(Match.Id calldata matchId, Tree.Node leftNode, Tree.Node rightNode, Tree.Node newLeftNode, Tree.Node newRightNode) external tournamentNotFinished +function advanceMatch(Match.Id calldata matchId, Tree.Node leftNode, Tree.Node rightNode, Tree.Node newLeftNode, Tree.Node newRightNode) external ``` Advance a match by providing new intermediate nodes in the binary search process. @@ -42,7 +162,7 @@ Advance a match by providing new intermediate nodes in the binary search process ### `winMatchByTimeout()` ```solidity -function winMatchByTimeout(Match.Id calldata matchId) external tournamentNotFinished +function winMatchByTimeout(Match.Id calldata matchId, Tree.Node leftNode, Tree.Node rightNode) external ``` Win a match when the opponent has run out of time allowance. @@ -56,7 +176,7 @@ Win a match when the opponent has run out of time allowance. ### `eliminateMatchByTimeout()` ```solidity -function eliminateMatchByTimeout(Match.Id calldata matchId) external tournamentNotFinished +function eliminateMatchByTimeout(Match.Id calldata matchId) external ``` Eliminate a match when both participants have run out of time. @@ -70,43 +190,55 @@ Eliminate a match when both participants have run out of time. ### `isFinished()` ```solidity -function isFinished() public view returns (bool) +function isFinished() external view returns (bool) ``` Check if the tournament has finished (has a winner or is eliminated). -**Returns:** - -| Name | Type | Description | -|------|------|-------------| -| `finished` | `bool` | Whether the tournament is finished | - ### `isClosed()` ```solidity -function isClosed() public view returns (bool) +function isClosed() external view returns (bool) ``` Check if the tournament is closed to new participants. -**Returns:** +### `bondValue()` +```solidity +function bondValue() external view returns (uint256) +``` -| Name | Type | Description | +Get the amount of Wei necessary to call `joinTournament()`. + +**Return Values:** + +| Index | Type | Description | |------|------|-------------| -| `closed` | `bool` | Whether the tournament is closed | +| [0] | `uint256` | The tournament bond value | -## NonLeafTournament Contract Functions ---- +### `tryRecoveringBond()` + +```solidity +function tryRecoveringBond() external returns (bool) +``` + +Try recovering the bond of the winner commitment submitter. + +**Return Values:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `bool` | Whether the recovery was successful | ### `sealInnerMatchAndCreateInnerTournament()` ```solidity -function sealInnerMatchAndCreateInnerTournament(Match.Id calldata matchId, Tree.Node leftLeaf, Tree.Node rightLeaf, Machine.Hash agreeHash, bytes32[] calldata agreeHashProof) external tournamentNotFinished +function sealInnerMatchAndCreateInnerTournament(Match.Id calldata matchId, Tree.Node leftLeaf, Tree.Node rightLeaf, Machine.Hash agreeHash, bytes32[] calldata agreeHashProof) external ``` Seal an inner match and create a new inner tournament to resolve the dispute at a finer granularity. -**Event Emitted:** `newInnerTournament(Match.IdHash indexed, NonRootTournament)` when inner tournament is created +**Event Emitted:** `NewInnerTournament(Match.IdHash indexed matchIdHash, ITournament indexed childTournament)` when inner tournament is created **Parameters:** @@ -121,7 +253,7 @@ Seal an inner match and create a new inner tournament to resolve the dispute at ### `winInnerTournament()` ```solidity -function winInnerTournament(NonRootTournament innerTournament) external tournamentNotFinished +function winInnerTournament(ITournament childTournament, Tree.Node leftNode, Tree.Node rightNode) external ``` Process the result of a finished inner tournament and advance the parent match. @@ -130,12 +262,14 @@ Process the result of a finished inner tournament and advance the parent match. | Name | Type | Description | |------|------|-------------| -| `innerTournament` | `NonRootTournament` | Address of the finished inner tournament | +| `childTournament` | `ITournament` | The inner/child tournament | +| `leftNode` | `Tree.Node` | Left child of the winning commitment | +| `rightNode` | `Tree.Node` | Right child of the winning commitment | ### `eliminateInnerTournament()` ```solidity -function eliminateInnerTournament(NonRootTournament innerTournament) external tournamentNotFinished +function eliminateInnerTournament(ITournament childTournament) external ``` Eliminate an inner tournament that has no winner and advance the parent match. @@ -144,10 +278,7 @@ Eliminate an inner tournament that has no winner and advance the parent match. | Name | Type | Description | |------|------|-------------| -| `innerTournament` | `NonRootTournament` | Address of the inner tournament to eliminate | - -## NonRootTournament Contract Functions ---- +| `childTournament` | `ITournament` | The inner/child tournament to eliminate | ### `innerTournamentWinner()` @@ -159,168 +290,254 @@ Get the winner information from a finished inner tournament for parent tournamen **Returns:** -| Name | Type | Description | +| Index | Type | Description | |------|------|-------------| -| `isFinished` | `bool` | Whether the tournament is finished | -| `contestedCommitment` | `Tree.Node` | The contested parent commitment | -| `winnerCommitment` | `Tree.Node` | The winning inner commitment | -| `clock` | `Clock.State` | Paused clock state of the winner | +| [0] | `bool` | Whether the tournament is finished | +| [1] | `Tree.Node` | The contested parent commitment | +| [2] | `Tree.Node` | The winning inner commitment | +| [3] | `Clock.State` | Paused clock state of the winning inner commitment | ### `canBeEliminated()` ```solidity -function canBeEliminated() public view returns (bool) +function canBeEliminated() external view returns (bool) ``` Check if the tournament can be safely eliminated by its parent. **Returns:** -| Name | Type | Description | +| Index | Type | Description | |------|------|-------------| -| `eliminatable` | `bool` | Whether the tournament can be eliminated | +| [0] | `bool` | Whether the tournament can be eliminated | -## RootTournament Contract Functions +## Other View Functions --- -### `arbitrationResult()` +### `tournamentArguments()` +```solidity +function tournamentArguments() external view returns (TournamentArguments memory) +``` + +Get the tournament arguments. + +**Return Values:** +| Index | Type | Description | +|------|------|-------------| +| [0] | `TournamentArguments` | The tournament arguments | + +### `canWinMatchByTimeout()` ```solidity -function arbitrationResult() external view returns (bool isFinished, Tree.Node winnerCommitment, Machine.Hash finalMachineStateHash) +function canWinMatchByTimeout(Match.Id calldata matchId) external view returns (bool) ``` -Get the final arbitration result from the root tournament. +Check if a match can be won by timeout. -**Returns:** +**Parameters:** | Name | Type | Description | |------|------|-------------| -| `isFinished` | `bool` | Whether the tournament is finished | -| `winnerCommitment` | `Tree.Node` | The winning commitment | -| `finalMachineStateHash` | `Machine.Hash` | Final machine state hash of winner | +| `matchId` | `Match.Id` | The identifier of the match | -## Tournament Factory Functions ---- +**Return Values:** -### `instantiate()` (SingleLevelTournamentFactory) +| Index | Type | Description | +|------|------|-------------| +| [0] | `bool` | Whether the match can be won by timeout | +### `getCommitment()` ```solidity -function instantiate(Machine.Hash initialHash, IDataProvider provider) external returns (ITournament) +function getCommitment(Tree.Node commitmentRoot) external view returns (Clock.State memory clock, Machine.Hash finalState) ``` +Get the clock and final state of a commitment. -Create a new single-level tournament instance. +**Parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `commitmentRoot` | `Tree.Node` | The root of the commitment | + +**Return Values:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `Clock.State` | The clock state of the commitment | +| [1] | `Machine.Hash` | The final state of the commitment | -**Event Emitted:** `tournamentCreated(ITournament)` when tournament is created +### `getMatch()` +```solidity +function getMatch(Match.IdHash matchIdHash) external view returns (Match.State memory) +``` + +Get the match state for a given match identifier. **Parameters:** | Name | Type | Description | |------|------|-------------| -| `initialHash` | `Machine.Hash` | Initial machine state hash | -| `provider` | `IDataProvider` | Data provider for input validation | +| `matchIdHash` | `Match.IdHash` | The identifier of the match | -**Returns:** +**Return Values:** -| Name | Type | Description | +| Index | Type | Description | |------|------|-------------| -| `tournament` | `ITournament` | Created tournament instance | +| [0] | `Match.State` | The state of the match | -### `instantiate()` (MultiLevelTournamentFactory) +### `getMatchCycle()` ```solidity -function instantiate(Machine.Hash initialHash, IDataProvider provider) external returns (ITournament) +function getMatchCycle(Match.IdHash matchIdHash) external view returns (uint256) ``` -Create a new multi-level tournament hierarchy starting with a top tournament. - -**Event Emitted:** `tournamentCreated(ITournament)` when tournament is created +Get the running machine cycle of a match by its ID hash. **Parameters:** | Name | Type | Description | |------|------|-------------| -| `initialHash` | `Machine.Hash` | Initial machine state hash | -| `provider` | `IDataProvider` | Data provider for input validation | +| `matchIdHash` | `Match.IdHash` | The identifier of the match | + +**Return Values:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `uint256` | The cycle of the match | -**Returns:** + +### `tournamentLevelConstants()` +```solidity +function tournamentLevelConstants() external view returns (uint64 maxLevel, uint64 level, uint64 log2step, uint64 height) +``` +Get the level constants of a tournament. + +**Return Values:** | Name | Type | Description | |------|------|-------------| -| `tournament` | `ITournament` | Created top tournament instance | +| `maxLevel` | `uint64` | The maximum number of levels in the tournament | +| `level` | `uint64` | The current level of the tournament | +| `log2step` | `uint64` | The log2 number of steps between commitment leaves | +| `height` | `uint64` | The height of the commitment tree | + +### `timeFinished()` +```solidity +function timeFinished() external view returns (bool, Time.Instant) +``` + +Get the confirmation and time when the tournament finished. + +**Return Values:** + +| Index | Type | Description | +|------|------|-------------| +| [0] | `bool` | Whether the tournament has finished | +| [1] | `Time.Instant` | The time when the tournament finished | -### `instantiateTop()` +## Events Emitted +--- +### `TournamentCreated()` ```solidity -function instantiateTop(Machine.Hash initialHash, IDataProvider provider) external returns (Tournament) +event TournamentCreated(ITournament tournament) ``` -Create a new top-level tournament in the multi-level hierarchy. +An event emitted when a new tournament is instantiated. **Parameters:** | Name | Type | Description | |------|------|-------------| -| `initialHash` | `Machine.Hash` | Initial machine state hash | -| `provider` | `IDataProvider` | Data provider for input validation | +| `tournament` | `ITournament` | The tournament with its arguments | -**Returns:** +### `CommitmentJoined()` +```solidity +event CommitmentJoined(Tree.Node commitmentRoot, Machine.Hash finalState, address claimer) +``` + +An event emitted when a commitment is successfully added. + +**Parameters:** | Name | Type | Description | |------|------|-------------| -| `tournament` | `Tournament` | Created top tournament instance | +| `commitmentRoot` | `Tree.Node` | The root of the commitment | +| `finalState` | `Machine.Hash` | The final computational hash | +| `claimer` | `address` | The address of the claimer | -### `instantiateMiddle()` +### `PartialBondRefund()` +```solidity +event PartialBondRefund(address indexed recipient, uint256 value, bool indexed success, bytes ret) +``` + +An event emitted when a partial bond refund is successful. + +**Parameters:** +| Name | Type | Description | +|------|------|-------------| +| `recipient` | `address` | The address of the recipient | +| `value` | `uint256` | The amount of the refund | +| `success` | `bool` | Whether the refund was successful | +| `ret` | `bytes` | The return data of the refund | +### `NewInnerTournament()` ```solidity -function instantiateMiddle(Machine.Hash initialHash, Tree.Node contestedCommitmentOne, Machine.Hash contestedFinalStateOne, Tree.Node contestedCommitmentTwo, Machine.Hash contestedFinalStateTwo, Time.Duration allowance, uint256 startCycle, uint64 level, IDataProvider provider) external returns (Tournament) +event NewInnerTournament(Match.IdHash indexed matchIdHash, ITournament indexed childTournament) ``` -Create a new middle-level tournament for dispute resolution. +An event emitted when a new inner tournament is created. **Parameters:** | Name | Type | Description | |------|------|-------------| -| `initialHash` | `Machine.Hash` | Initial machine state hash | -| `contestedCommitmentOne` | `Tree.Node` | First contested commitment | -| `contestedFinalStateOne` | `Machine.Hash` | First contested final state | -| `contestedCommitmentTwo` | `Tree.Node` | Second contested commitment | -| `contestedFinalStateTwo` | `Machine.Hash` | Second contested final state | -| `allowance` | `Time.Duration` | Time allowance for participants | -| `startCycle` | `uint256` | Starting cycle for the tournament | -| `level` | `uint64` | Tournament level in hierarchy | -| `provider` | `IDataProvider` | Data provider for input validation | +| `matchIdHash` | `Match.IdHash` | Hashed Identifier of the match | +| `childTournament` | `ITournament` | The inner/child tournament | -**Returns:** +### `MatchCreated()` +```solidity +event MatchCreated(Match.IdHash indexed matchIdHash, Tree.Node indexed one, Tree.Node indexed two, Tree.Node leftOfTwo) +``` + +An event emitted when a new match is created. + +**Parameters:** | Name | Type | Description | |------|------|-------------| -| `tournament` | `Tournament` | Created middle tournament instance | - -### `instantiateBottom()` +| `matchIdHash` | `Match.IdHash` | Identifier of the match | +| `one` | `Tree.Node` | One of the participants | +| `two` | `Tree.Node` | Two of the participants | +| `leftOfTwo` | `Tree.Node` | Left node of the two | +### `MatchAdvanced()` ```solidity -function instantiateBottom(Machine.Hash initialHash, Tree.Node contestedCommitmentOne, Machine.Hash contestedFinalStateOne, Tree.Node contestedCommitmentTwo, Machine.Hash contestedFinalStateTwo, Time.Duration allowance, uint256 startCycle, uint64 level, IDataProvider provider) external returns (Tournament) +event MatchAdvanced(Match.IdHash indexed matchIdHash, Tree.Node otherParent, Tree.Node leftNode) ``` -Create a new bottom-level tournament for leaf dispute resolution. +An event emitted when a match is advanced. **Parameters:** | Name | Type | Description | |------|------|-------------| -| `initialHash` | `Machine.Hash` | Initial machine state hash | -| `contestedCommitmentOne` | `Tree.Node` | First contested commitment | -| `contestedFinalStateOne` | `Machine.Hash` | First contested final state | -| `contestedCommitmentTwo` | `Tree.Node` | Second contested commitment | -| `contestedFinalStateTwo` | `Machine.Hash` | Second contested final state | -| `allowance` | `Time.Duration` | Time allowance for participants | -| `startCycle` | `uint256` | Starting cycle for the tournament | -| `level` | `uint64` | Tournament level in hierarchy | -| `provider` | `IDataProvider` | Data provider for input validation | +| `matchIdHash` | `Match.IdHash` | Hashed Identifier of the match | +| `otherParent` | `Tree.Node` | The new `otherParent` value | +| `leftNode` | `Tree.Node` | The new `leftNode` value | -**Returns:** +### `MatchDeleted()` +```solidity +event MatchDeleted(Match.IdHash indexed matchIdHash, Tree.Node indexed one, Tree.Node indexed two, MatchDeletionReason reason, WinnerCommitment winnerCommitment) +``` + +An event emitted when a match is deleted. + +**Parameters:** | Name | Type | Description | |------|------|-------------| -| `tournament` | `Tournament` | Created bottom tournament instance | +| `matchIdHash` | `Match.IdHash` | Hashed Identifier of the match | +| `one` | `Tree.Node` | Commitment of the 1st participant | +| `two` | `Tree.Node` | Commitment of the 2nd participant | +| `reason` | `MatchDeletionReason` | The reason for the deletion | +| `winnerCommitment` | `WinnerCommitment` | The winner commitment | \ No newline at end of file diff --git a/sidebarsFraudProofs.js b/sidebarsFraudProofs.js index 2118f5f9..b47743ae 100644 --- a/sidebarsFraudProofs.js +++ b/sidebarsFraudProofs.js @@ -89,7 +89,7 @@ module.exports = { { type: 'doc', id: 'references/tournament', - label: 'Tournament Core Contracts', + label: 'Tournament Contracts', }, { type: 'doc',