Commit 52e2088b authored by Joshua Gutow's avatar Joshua Gutow

op-challenger: Counter the root claim

parent 4acb210e
...@@ -42,13 +42,13 @@ func (a *Agent) AddClaim(claim Claim) error { ...@@ -42,13 +42,13 @@ func (a *Agent) AddClaim(claim Claim) error {
func (a *Agent) PerformActions() { func (a *Agent) PerformActions() {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
for _, pair := range a.game.ClaimPairs() { for _, claim := range a.game.Claims() {
_ = a.move(pair.claim, pair.parent) _ = a.move(claim)
} }
} }
// move determines & executes the next move given a claim pair // move determines & executes the next move given a claim pair
func (a *Agent) move(claim, parent Claim) error { func (a *Agent) move(claim Claim) error {
nextMove, err := a.solver.NextMove(claim) nextMove, err := a.solver.NextMove(claim)
if err != nil { if err != nil {
a.log.Warn("Failed to execute the next move", "err", err) a.log.Warn("Failed to execute the next move", "err", err)
......
...@@ -25,14 +25,7 @@ func FullGame() { ...@@ -25,14 +25,7 @@ func FullGame() {
Position: fault.NewPosition(0, 0), Position: fault.NewPosition(0, 0),
}, },
} }
counter := fault.Claim{
ClaimData: fault.ClaimData{
Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000364"),
Position: fault.NewPosition(1, 0),
},
Parent: root.ClaimData,
}
o := fault.NewOrchestrator(maxDepth, []fault.TraceProvider{canonicalProvider, disputedProvider}, []string{"charlie", "mallory"}, root, counter) o := fault.NewOrchestrator(maxDepth, []fault.TraceProvider{canonicalProvider, disputedProvider}, []string{"charlie", "mallory"}, root)
o.Start() o.Start()
} }
...@@ -37,17 +37,6 @@ func SolverExampleOne() { ...@@ -37,17 +37,6 @@ func SolverExampleOne() {
}, },
} }
// Note: We have to create the first counter claim seperately because next move does not know how to counter
// the root claim at this time.
// Counter claim is d at trace index 3 from the canonical provider
counter := fault.Claim{
ClaimData: fault.ClaimData{
Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000364"),
Position: fault.NewPosition(1, 0),
},
Parent: root.ClaimData,
}
canonicalProvider := fault.NewAlphabetProvider(canonical, uint64(maxDepth)) canonicalProvider := fault.NewAlphabetProvider(canonical, uint64(maxDepth))
disputedProvider := fault.NewAlphabetProvider(disputed, uint64(maxDepth)) disputedProvider := fault.NewAlphabetProvider(disputed, uint64(maxDepth))
...@@ -63,17 +52,22 @@ func SolverExampleOne() { ...@@ -63,17 +52,22 @@ func SolverExampleOne() {
fmt.Println("go left to d, then right to x (cannonical is f), then left to e") fmt.Println("go left to d, then right to x (cannonical is f), then left to e")
fmt.Println() fmt.Println()
PrettyPrintAlphabetClaim("Root claim", root) PrettyPrintAlphabetClaim("Root claim", root)
PrettyPrintAlphabetClaim("Counter claim", counter)
claim1, err := disputedSolver.NextMove(counter) claim1, err := cannonicalSolver.NextMove(root)
if err != nil {
fmt.Printf("error getting claim from provider: %v", err)
}
PrettyPrintAlphabetClaim("Cannonical move", *claim1)
claim2, err := disputedSolver.NextMove(*claim1)
if err != nil { if err != nil {
fmt.Printf("error getting claim from disputed provider: %v", err) fmt.Printf("error getting claim from provider: %v", err)
} }
PrettyPrintAlphabetClaim("Disputed moved", *claim1) PrettyPrintAlphabetClaim("Disputed moved", *claim2)
claim2, err := cannonicalSolver.NextMove(*claim1) claim3, err := cannonicalSolver.NextMove(*claim2)
if err != nil { if err != nil {
fmt.Printf("error getting claim from disputed provider: %v", err) fmt.Printf("error getting claim from provider: %v", err)
} }
PrettyPrintAlphabetClaim("Cannonical move", *claim2) PrettyPrintAlphabetClaim("Cannonical move", *claim3)
} }
...@@ -17,11 +17,8 @@ type Game interface { ...@@ -17,11 +17,8 @@ type Game interface {
// Put adds a claim into the game state. // Put adds a claim into the game state.
Put(claim Claim) error Put(claim Claim) error
// ClaimPairs returns a list of claim pairs. // Claims returns all of the claims in the game.
ClaimPairs() []struct { Claims() []Claim
claim Claim
parent Claim
}
IsDuplicate(claim Claim) bool IsDuplicate(claim Claim) bool
} }
...@@ -93,8 +90,8 @@ func (g *gameState) recurseTree(treeNode *Node, claim ClaimData) (*Node, error) ...@@ -93,8 +90,8 @@ func (g *gameState) recurseTree(treeNode *Node, claim ClaimData) (*Node, error)
// Put adds a claim into the game state. // Put adds a claim into the game state.
func (g *gameState) Put(claim Claim) error { func (g *gameState) Put(claim Claim) error {
// If the claim is the root node and the node is set, return an error. // The game is always initialized with a root claim. Cannot add a second.
if claim.IsRoot() && g.root.self != (Claim{}) { if claim.IsRoot() {
return ErrClaimExists return ErrClaimExists
} }
...@@ -132,40 +129,15 @@ func (g *gameState) IsDuplicate(claim Claim) bool { ...@@ -132,40 +129,15 @@ func (g *gameState) IsDuplicate(claim Claim) bool {
return ok return ok
} }
// recurseTreePairs recursively walks down the tree from the root node func (g *gameState) Claims() []Claim {
// returning a list of claim and parent pairs. return g.root.claims()
func (g *gameState) recurseTreePairs(current *Node) []struct {
claim Claim
parent Claim
} {
// Create a list of claim pairs.
pairs := make([]struct {
claim Claim
parent Claim
}, 0)
// Iterate over all children of the current node.
for _, child := range current.children {
// Add the current node to the list of pairs.
pairs = append(pairs, struct {
claim Claim
parent Claim
}{
claim: child.self,
parent: current.self,
})
// Recurse down the tree.
pairs = append(pairs, g.recurseTreePairs(child)...)
}
return pairs
} }
// ClaimPairs returns a list of claim pairs. func (n *Node) claims() []Claim {
func (g *gameState) ClaimPairs() []struct { var out []Claim
claim Claim out = append(out, n.self)
parent Claim for _, c := range n.children {
} { out = append(out, c.claims()...)
return g.recurseTreePairs(&g.root) }
return out
} }
...@@ -121,10 +121,7 @@ func TestGame_ClaimPairs(t *testing.T) { ...@@ -121,10 +121,7 @@ func TestGame_ClaimPairs(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Validate claim pairs. // Validate claim pairs.
expected := []struct{ claim, parent Claim }{ expected := []Claim{top, middle, bottom}
{middle, top}, claims := g.Claims()
{bottom, middle}, require.ElementsMatch(t, expected, claims)
}
pairs := g.ClaimPairs()
require.ElementsMatch(t, expected, pairs)
} }
...@@ -2,7 +2,6 @@ package fault ...@@ -2,7 +2,6 @@ package fault
import ( import (
"context" "context"
"fmt"
"os" "os"
"time" "time"
...@@ -15,17 +14,15 @@ type Orchestrator struct { ...@@ -15,17 +14,15 @@ type Orchestrator struct {
responses chan Claim responses chan Claim
} }
func NewOrchestrator(maxDepth uint64, traces []TraceProvider, names []string, root, counter Claim) Orchestrator { func NewOrchestrator(maxDepth uint64, traces []TraceProvider, names []string, root Claim) Orchestrator {
o := Orchestrator{ o := Orchestrator{
responses: make(chan Claim, 100), responses: make(chan Claim, 100),
outputChs: make([]chan Claim, len(traces)), outputChs: make([]chan Claim, len(traces)),
agents: make([]Agent, len(traces)), agents: make([]Agent, len(traces)),
} }
PrettyPrintAlphabetClaim("init", root) log.Info("Starting game", "root_letter", string(root.Value[31:]))
PrettyPrintAlphabetClaim("init", counter)
for i, trace := range traces { for i, trace := range traces {
game := NewGameState(root) game := NewGameState(root)
_ = game.Put(counter)
o.agents[i] = NewAgent(game, int(maxDepth), trace, &o, log.New("role", names[i])) o.agents[i] = NewAgent(game, int(maxDepth), trace, &o, log.New("role", names[i]))
o.outputChs[i] = make(chan Claim) o.outputChs[i] = make(chan Claim)
} }
...@@ -72,16 +69,3 @@ func (o *Orchestrator) responderThread() { ...@@ -72,16 +69,3 @@ func (o *Orchestrator) responderThread() {
} }
} }
func PrettyPrintAlphabetClaim(name string, claim Claim) {
value := claim.Value
idx := value[30]
letter := value[31]
par_letter := claim.Parent.Value[31]
if claim.IsRoot() {
fmt.Printf("%s\ttrace %v letter %c\n", name, idx, letter)
} else {
fmt.Printf("%s\ttrace %v letter %c is attack %v parent letter %c\n", name, idx, letter, !claim.DefendsParent(), par_letter)
}
}
...@@ -23,6 +23,21 @@ func NewSolver(gameDepth int, traceProvider TraceProvider) *Solver { ...@@ -23,6 +23,21 @@ func NewSolver(gameDepth int, traceProvider TraceProvider) *Solver {
// NextMove returns the next move to make given the current state of the game. // 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) (*Claim, error) {
// Special case of the root claim
if claim.IsRoot() {
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
}
}
parentCorrect, err := s.agreeWithClaim(claim.Parent) parentCorrect, err := s.agreeWithClaim(claim.Parent)
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -22,6 +22,20 @@ func TestSolver_NextMove_Opponent(t *testing.T) { ...@@ -22,6 +22,20 @@ func TestSolver_NextMove_Opponent(t *testing.T) {
claim Claim claim Claim
response ClaimData response ClaimData
}{ }{
{
7,
Claim{
ClaimData: ClaimData{
Value: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000077a"),
Position: NewPosition(0, 0),
},
// Root claim has no parent
},
ClaimData{
Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000364"),
Position: NewPosition(1, 0),
},
},
{ {
3, 3,
Claim{ Claim{
......
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