Commit 139acfbf authored by Joshua Gutow's avatar Joshua Gutow

op-challenger: Only respond to claims at levels we disagree with

This is important to ensure that the challenger would not counter claims
that itself made. This also appears to fix the step transaction revert
issue.
parent 051aa24d
......@@ -14,4 +14,4 @@ MALLORY_KEY="28d7045146193f5f4eeb151c4843544b1b0d30a7ac1680c845a416fac65a7715"
FAULT_GAME_ADDRESS="0x8daf17a20c9dba35f005b6324f493785d239719d"
./bin/op-challenger --l1-eth-rpc http://localhost:8545 --alphabet "abcdefgh" --game-address $FAULT_GAME_ADDRESS --private-key $CHARLIE_KEY --num-confirmations 1
./bin/op-challenger --l1-eth-rpc http://localhost:8545 --alphabet "abcdefgh" --game-address $FAULT_GAME_ADDRESS --private-key $CHARLIE_KEY --num-confirmations 1 --agree-with-proposed-output=true
......@@ -70,7 +70,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) {
// move determines & executes the next move given a claim
func (a *Agent) move(claim Claim, game Game) error {
nextMove, err := a.solver.NextMove(claim)
nextMove, err := a.solver.NextMove(claim, game.AgreeWithClaimLevel(claim))
if err != nil {
a.log.Warn("Failed to execute the next move", "err", err)
return err
......
......@@ -53,19 +53,19 @@ func SolverExampleOne() {
fmt.Println()
PrettyPrintAlphabetClaim("Root claim", root)
claim1, err := cannonicalSolver.NextMove(root)
claim1, err := cannonicalSolver.NextMove(root, false)
if err != nil {
fmt.Printf("error getting claim from provider: %v", err)
}
PrettyPrintAlphabetClaim("Cannonical move", *claim1)
claim2, err := disputedSolver.NextMove(*claim1)
claim2, err := disputedSolver.NextMove(*claim1, false)
if err != nil {
fmt.Printf("error getting claim from provider: %v", err)
}
PrettyPrintAlphabetClaim("Disputed moved", *claim2)
claim3, err := cannonicalSolver.NextMove(*claim2)
claim3, err := cannonicalSolver.NextMove(*claim2, false)
if err != nil {
fmt.Printf("error getting claim from provider: %v", err)
}
......
......@@ -33,6 +33,9 @@ type Game interface {
// PostStateClaim gets the claim which commits to the post-state of this specific claim.
// This will return an error if it is called with a non-leaf claim.
PostStateClaim(claim Claim) (Claim, error)
// AgreeWithLevel returns if the game state agrees with the provided claim level.
AgreeWithClaimLevel(claim Claim) bool
}
type extendedClaim struct {
......
......@@ -21,7 +21,11 @@ func NewSolver(gameDepth int, traceProvider TraceProvider) *Solver {
}
// NextMove returns the next move to make given the current state of the game.
func (s *Solver) NextMove(claim Claim) (*Claim, error) {
func (s *Solver) NextMove(claim Claim, agreeWithClaimLevel bool) (*Claim, error) {
if agreeWithClaimLevel {
return nil, nil
}
// Special case of the root claim
if claim.IsRoot() {
return s.handleRoot(claim)
......@@ -29,6 +33,36 @@ func (s *Solver) NextMove(claim Claim) (*Claim, error) {
return s.handleMiddle(claim)
}
func (s *Solver) handleRoot(claim Claim) (*Claim, error) {
agree, err := s.agreeWithClaim(claim.ClaimData)
if err != nil {
return nil, err
}
// Attack the root claim if we do not agree with it
// Note: We always disagree with the claim level at this point,
// so if we agree with claim maybe we should also attack?
if !agree {
return s.attack(claim)
} else {
return nil, nil
}
}
func (s *Solver) handleMiddle(claim Claim) (*Claim, error) {
claimCorrect, err := s.agreeWithClaim(claim.ClaimData)
if err != nil {
return nil, err
}
if claim.Depth() == s.gameDepth {
return nil, errors.New("game depth reached")
}
if claimCorrect {
return s.defend(claim)
} else {
return s.attack(claim)
}
}
type StepData struct {
LeafClaim Claim
IsAttack bool
......@@ -57,52 +91,6 @@ func (s *Solver) AttemptStep(claim Claim) (StepData, error) {
}, nil
}
func (s *Solver) handleRoot(claim Claim) (*Claim, error) {
agree, err := s.agreeWithClaim(claim.ClaimData)
if err != nil {
return nil, err
}
// Attack the root claim if we do not agree with it
if !agree {
return s.attack(claim)
} else {
return nil, nil
}
}
func (s *Solver) handleMiddle(claim Claim) (*Claim, error) {
parentCorrect, err := s.agreeWithClaim(claim.Parent)
if err != nil {
return nil, err
}
claimCorrect, err := s.agreeWithClaim(claim.ClaimData)
if err != nil {
return nil, err
}
if claim.Depth() == s.gameDepth {
return nil, errors.New("game depth reached")
}
if parentCorrect && claimCorrect {
// We agree with the parent, but the claim is disagreeing with it.
// Since we agree with the claim, the difference must be to the right of the claim
return s.defend(claim)
} else if parentCorrect && !claimCorrect {
// We agree with the parent, but the claim disagrees with it.
// Since we disagree with the claim, the difference must be to the left of the claim
return s.attack(claim)
} else if !parentCorrect && claimCorrect {
// Do nothing, we disagree with the parent, but this claim has correctly countered it
return nil, nil
} else if !parentCorrect && !claimCorrect {
// We disagree with the parent so want to counter it (which the claim is doing)
// but we also disagree with the claim so there must be a difference to the left of claim
// Note that we will create the correct counter-claim for parent when it is evaluated, no need to do it here
return s.attack(claim)
}
// This should not be reached
return nil, errors.New("no next move")
}
// attack returns a response that attacks the claim.
func (s *Solver) attack(claim Claim) (*Claim, error) {
position := claim.Attack()
......
......@@ -74,12 +74,30 @@ func TestSolver_NextMove_Opponent(t *testing.T) {
}
for _, test := range indices {
res, err := solver.NextMove(test.claim)
res, err := solver.NextMove(test.claim, false)
require.NoError(t, err)
require.Equal(t, test.response, res.ClaimData)
}
}
func TestNoMoveAgainstOwnLevel(t *testing.T) {
maxDepth := 3
mallory := NewAlphabetProvider("abcdepqr", uint64(maxDepth))
solver := NewSolver(maxDepth, mallory)
claim := Claim{
ClaimData: ClaimData{
Value: alphabetClaim(7, "z"),
Position: NewPosition(0, 0),
},
// Root claim has no parent
}
move, err := solver.NextMove(claim, true)
require.Nil(t, move)
require.Nil(t, err)
}
func TestAttemptStep(t *testing.T) {
maxDepth := 3
canonicalProvider := NewAlphabetProvider("abcdefgh", uint64(maxDepth))
......
......@@ -15,4 +15,4 @@ MALLORY_KEY="28d7045146193f5f4eeb151c4843544b1b0d30a7ac1680c845a416fac65a7715"
FAULT_GAME_ADDRESS="0x8daf17a20c9dba35f005b6324f493785d239719d"
./bin/op-challenger --l1-eth-rpc http://localhost:8545 --alphabet "abcdexyz" --game-address $FAULT_GAME_ADDRESS --private-key $MALLORY_KEY --num-confirmations 1
./bin/op-challenger --l1-eth-rpc http://localhost:8545 --alphabet "abcdexyz" --game-address $FAULT_GAME_ADDRESS --private-key $MALLORY_KEY --num-confirmations 1 --agree-with-proposed-output=false
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment