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

Optimism Dispute Game Support #45

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

Chomtana
Copy link

An improved approach to #36

In this version, there's no need to split the code into two different files. We first try to find the index using the dispute game. If the dispute game is unavailable, we will fall back to using L2OutputOracle.

The function that needs L2OutputOracle has been replaced with OptimismPortalProxy, which is the core of the OP Stack. OptimismPortalProxy can derive both L2OutputOracle and DisputeGameFactory.

This implementation has been tested and works well.

image

The deployed gateway implementation differs slightly from the one in the repository, with the ENS Tracker part removed and the app variable moved into a local variable that reinitializes on every request.

return l2out.outputRoot;
}

function getDisputeGameOutput(
Copy link
Member

Choose a reason for hiding this comment

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

Are there any reference you used so that I can verify?

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

How did you manage to test each failure scenario like GameChallenged, GameTooEarly, DeprecatedProof or are they even possible to test?

Copy link
Member

@Arachnid Arachnid left a comment

Choose a reason for hiding this comment

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

Thanks again for writing this!

op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-verifier/contracts/OPVerifier.sol Outdated Show resolved Hide resolved
revert GameTypeMismatch(index, respectedGameType, gameType);
}

// Revert if the game is challenged
Copy link
Member

Choose a reason for hiding this comment

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

Can we revert even if there's a challenge initiated? Eg, only allow unchallenged or finalized games?

Copy link
Author

Choose a reason for hiding this comment

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

That will make it vulnerable to malicious challengers that try to challenge random game?

op-verifier/contracts/interfaces/IDisputeGame.sol Outdated Show resolved Hide resolved
op-verifier/contracts/interfaces/IDisputeGameFactory.sol Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
op-gateway/src/OPProofService.ts Outdated Show resolved Hide resolved
@Chomtana
Copy link
Author

Chomtana commented Jun 7, 2024

Merged and pushed the new version

Using OPOutputLookup contract I have built at https://github.com/Opti-domains/dispute-game-lookup/blob/main/src/OPOutputLookup.sol to do the calculation and advanced search in a single call. So, the lowest latency one can achieve.

Pending unit test on https://github.com/Opti-domains/dispute-game-lookup

However, it works manual testing: https://app.ens.domains/disputegame.eth?tab=records (On Sepolia testnet)

Copy link
Member

@Arachnid Arachnid left a comment

Choose a reason for hiding this comment

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

Thanks! Can you include the source for the helper contract in this repo, and deploy it as part of the tests?

op-gateway/src/OPProofService.ts Show resolved Hide resolved
@Chomtana
Copy link
Author

Chomtana commented Jul 16, 2024

Hi @Arachnid @makoto

Sorry for the delay, I have been busy for these weeks!

Helper contracts and libraries have been merged into the repo and a deployment script to deterministically deploy OPOutputLookup have been added.

Some trick has been implemented to be able to import @eth-optimism/contracts-bedrock into the contracts rather than copying the code.

Current contract and gateway (with app variable moved into a local variable) has been successfully tested on current implementation.

https://app.ens.domains/disputegame.eth?tab=records (Sepolia)

image

@mdtanrikulu mdtanrikulu self-requested a review July 23, 2024 14:43
Copy link
Member

@Arachnid Arachnid left a comment

Choose a reason for hiding this comment

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

Thank you for your persistent hard work on this! I'd say it's very close to done.

I left a couple of comments; aside from them are you able to write some tests using a mock for the Optimism contracts so that we can verify the binary search works as expected?

const block = await this.opOutputLookup.getOPProvableBlock(
await this.optimismPortal.getAddress(),
this.minAge,
1000000000
Copy link
Member

Choose a reason for hiding this comment

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

What parameter is this? Can you leave a comment on it?

Copy link
Author

Choose a reason for hiding this comment

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

It's Unlimited maximum age to have the gateway fetch output root regardless of maximum age parameter as it will be verified on the contract anyway. Commented

);
}

// Revert if the game is challenged
Copy link
Member

Choose a reason for hiding this comment

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

We should also reject games that have an open challenge, not just games that have already been successfully challenged. Otherwise an attacker can keep using an invalid state during the whole challenge process.

Copy link
Author

Choose a reason for hiding this comment

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

That would make it delay a few days at least if we check for the IN_PROGRESS status. I haven't seen a function to directly check for an open challenge.

Copy link
Author

Choose a reason for hiding this comment

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

Can be seen at https://sepolia.etherscan.io/address/0x99b0e2a750Cd985A3707a8C792BB0ADb28d148b4#readContract

That try to implement this one

image

image

It go back 4 days in OP sepolia testnet

Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit confused by this. Reading the OP code, it looks like the assumption is that every dispute game in fact corresponds to an active dispute. Are dispute games automatically created for each new block committed, or are they only created when someone challenges a block?

Copy link
Contributor

Choose a reason for hiding this comment

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

Dispute games are created for every state root proposal and the successful resolution of a game is what updates the anchor state in the AnchorStateRegistry.

In principle anyone can create a game (and Optimism do have confirmed production test canaries trying to break things with invalid root claims) but the game has to resolve in favour of the proposed state for the anchor to be updated.

https://github.com/ethereum-optimism/optimism/blob/c2f290d479f7319776205c2640f140a8423cb987/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol#L59

Copy link
Author

Choose a reason for hiding this comment

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

It may be possible to detect that the length of claimData is greater than 1, which means someone has tried to challenge, but I'm not 100% sure.

Copy link
Author

@Chomtana Chomtana Aug 2, 2024

Choose a reason for hiding this comment

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

Implemented open challenge detection with these checks

    function _isGameChallenging(
        IChallengingDisputeGame proxy
    ) internal view returns (bool) {
        // If the game is finalized, we ignore the challenging status
        if (proxy.status() == GameStatus.DEFENDER_WINS) return false;

        // If claimData length is greater than 1, the game is challenging
        if (proxy.claimDataLen() > 1) {
            return true;
        }

        // If root claim is countered by someone then the game is challenging
        (, address counteredBy, , , , , ) = proxy.claimData(0);
        if (counteredBy != address(0)) return true;

        return false;
    }

And fixed interpolation search revert on case that lower bound has moved beyond the max timestamp

Copy link
Member

Choose a reason for hiding this comment

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

Looks good! Is interpolation search working fine now then? Some tests (and benchmarks) are all that's missing to merge this, I think.

Thank you again for all your hard work on this PR.

Copy link
Author

@Chomtana Chomtana Aug 16, 2024

Choose a reason for hiding this comment

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

Test cases have been implemented in my dispute-game-lookup repository. I am using Foundry's fuzz testing combined with mainnet forking to identify and fix edge cases, including integer underflow and rounding errors.

The test cases can be found at the following links:

The files in the dispute-game-lookup repo and this repo differ only in the import section, as shown in these diffs:

Copy link
Author

Choose a reason for hiding this comment

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

For benchmarking, it take about 3.3s for each record processed in parallel on chrome network profiling

image

https://app.ens.domains/disputegame.eth (On Sepolia)

op-verifier/contracts/lib/DisputeGameLookup.sol Outdated Show resolved Hide resolved
op-verifier/README.md Show resolved Hide resolved
op-verifier/contracts/lib/DisputeGameLookup.sol Outdated Show resolved Hide resolved
);
}

// Revert if the game is challenged
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit confused by this. Reading the OP code, it looks like the assumption is that every dispute game in fact corresponds to an active dispute. Are dispute games automatically created for each new block committed, or are they only created when someone challenges a block?

@GavinPacini
Copy link

Hey, just wondering what's required here to get this into main? It seems to be working but I'm happy to pick it up if you have more change requests @Arachnid.

@Chomtana
Copy link
Author

Chomtana commented Oct 1, 2024

This version is working, but there is still room for improvement, such as adding an anchor or backup feature for dispute game types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants