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 {
func (a *Agent) PerformActions() {
a.mu.Lock()
defer a.mu.Unlock()
for _, pair := range a.game.ClaimPairs() {
_ = a.move(pair.claim, pair.parent)
for _, claim := range a.game.Claims() {
_ = a.move(claim)
}
}
// 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)
if err != nil {
a.log.Warn("Failed to execute the next move", "err", err)
......
......@@ -25,14 +25,7 @@ func FullGame() {
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()
}
......@@ -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))
disputedProvider := fault.NewAlphabetProvider(disputed, uint64(maxDepth))
......@@ -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()
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 {
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 {
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 {
// Put adds a claim into the game state.
Put(claim Claim) error
// ClaimPairs returns a list of claim pairs.
ClaimPairs() []struct {
claim Claim
parent Claim
}
// Claims returns all of the claims in the game.
Claims() []Claim
IsDuplicate(claim Claim) bool
}
......@@ -93,8 +90,8 @@ func (g *gameState) recurseTree(treeNode *Node, claim ClaimData) (*Node, error)
// Put adds a claim into the game state.
func (g *gameState) Put(claim Claim) error {
// If the claim is the root node and the node is set, return an error.
if claim.IsRoot() && g.root.self != (Claim{}) {
// The game is always initialized with a root claim. Cannot add a second.
if claim.IsRoot() {
return ErrClaimExists
}
......@@ -132,40 +129,15 @@ func (g *gameState) IsDuplicate(claim Claim) bool {
return ok
}
// recurseTreePairs recursively walks down the tree from the root node
// returning a list of claim and parent pairs.
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
func (g *gameState) Claims() []Claim {
return g.root.claims()
}
// ClaimPairs returns a list of claim pairs.
func (g *gameState) ClaimPairs() []struct {
claim Claim
parent Claim
} {
return g.recurseTreePairs(&g.root)
func (n *Node) claims() []Claim {
var out []Claim
out = append(out, n.self)
for _, c := range n.children {
out = append(out, c.claims()...)
}
return out
}
......@@ -121,10 +121,7 @@ func TestGame_ClaimPairs(t *testing.T) {
require.NoError(t, err)
// Validate claim pairs.
expected := []struct{ claim, parent Claim }{
{middle, top},
{bottom, middle},
}
pairs := g.ClaimPairs()
require.ElementsMatch(t, expected, pairs)
expected := []Claim{top, middle, bottom}
claims := g.Claims()
require.ElementsMatch(t, expected, claims)
}
......@@ -2,7 +2,6 @@ package fault
import (
"context"
"fmt"
"os"
"time"
......@@ -15,17 +14,15 @@ type Orchestrator struct {
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{
responses: make(chan Claim, 100),
outputChs: make([]chan Claim, len(traces)),
agents: make([]Agent, len(traces)),
}
PrettyPrintAlphabetClaim("init", root)
PrettyPrintAlphabetClaim("init", counter)
log.Info("Starting game", "root_letter", string(root.Value[31:]))
for i, trace := range traces {
game := NewGameState(root)
_ = game.Put(counter)
o.agents[i] = NewAgent(game, int(maxDepth), trace, &o, log.New("role", names[i]))
o.outputChs[i] = make(chan Claim)
}
......@@ -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 {
// NextMove returns the next move to make given the current state of the game.
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)
if err != nil {
return nil, err
......
......@@ -22,6 +22,20 @@ func TestSolver_NextMove_Opponent(t *testing.T) {
claim Claim
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,
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