Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
80fb940c
Unverified
Commit
80fb940c
authored
Jun 27, 2023
by
refcell.eth
Committed by
GitHub
Jun 27, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Game state implementation with root node and sequential state (#6161)
construction.
parent
6fbbb7b7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
263 additions
and
2 deletions
+263
-2
game.go
op-challenger/fault/game.go
+148
-2
game_test.go
op-challenger/fault/game_test.go
+115
-0
No files found.
op-challenger/fault/game.go
View file @
80fb940c
package
fault
package
fault
import
(
"errors"
)
var
(
// ErrClaimExists is returned when a claim already exists in the game state.
ErrClaimExists
=
errors
.
New
(
"claim exists in game state"
)
// ErrClaimNotFound is returned when a claim does not exist in the game state.
ErrClaimNotFound
=
errors
.
New
(
"claim not found in game state"
)
)
// Game is an interface that represents the state of a dispute game.
// Game is an interface that represents the state of a dispute game.
type
Game
interface
{
type
Game
interface
{
// Put adds a claim into the game state
and returns its parent claim
.
// Put adds a claim into the game state.
Put
(
claim
Claim
)
(
Claim
,
error
)
Put
(
claim
Claim
)
error
// ClaimPairs returns a list of claim pairs.
// ClaimPairs returns a list of claim pairs.
ClaimPairs
()
[]
struct
{
ClaimPairs
()
[]
struct
{
...
@@ -11,3 +23,137 @@ type Game interface {
...
@@ -11,3 +23,137 @@ type Game interface {
parent
Claim
parent
Claim
}
}
}
}
// Node is a node in the game state tree.
type
Node
struct
{
self
Claim
children
[]
*
Node
}
// gameState is a struct that represents the state of a dispute game.
// The game state implements the [Game] interface.
type
gameState
struct
{
root
Node
}
// NewGameState returns a new game state.
// The provided [Claim] is used as the root node.
func
NewGameState
(
root
Claim
)
*
gameState
{
return
&
gameState
{
root
:
Node
{
self
:
root
,
children
:
make
([]
*
Node
,
0
),
},
}
}
// getParent returns the parent of the provided [Claim].
func
(
g
*
gameState
)
getParent
(
claim
Claim
)
(
Claim
,
error
)
{
// If the claim is the root node, return an error.
if
claim
.
IsRoot
()
{
return
Claim
{},
ErrClaimNotFound
}
// Walk down the tree from the root node to find the parent.
found
,
err
:=
g
.
recurseTree
(
&
g
.
root
,
claim
.
Parent
)
if
err
!=
nil
{
return
Claim
{},
err
}
// Return the parent of the found node.
return
found
.
self
,
nil
}
// recurseTree recursively walks down the tree from the root node to find the
// node with the provided [Claim].
func
(
g
*
gameState
)
recurseTree
(
treeNode
*
Node
,
claim
ClaimData
)
(
*
Node
,
error
)
{
// Check if the current node is the claim.
if
treeNode
.
self
.
ClaimData
==
claim
{
return
treeNode
,
nil
}
// Check all children of the current node.
for
_
,
child
:=
range
treeNode
.
children
{
// Recurse and drop errors.
n
,
_
:=
g
.
recurseTree
(
child
,
claim
)
if
n
!=
nil
{
return
n
,
nil
}
}
// If we reach this point, the claim was not found.
return
nil
,
ErrClaimNotFound
}
// 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
{})
{
return
ErrClaimExists
}
// Grab the claim's parent.
parent
:=
claim
.
Parent
// Walk down the tree from the root node to find the parent.
found
,
err
:=
g
.
recurseTree
(
&
g
.
root
,
parent
)
if
err
!=
nil
{
return
err
}
// Check that the node is not already in the tree.
for
_
,
child
:=
range
found
.
children
{
if
child
.
self
==
claim
{
return
ErrClaimExists
}
}
// Create a new node.
node
:=
Node
{
self
:
claim
,
children
:
make
([]
*
Node
,
0
),
}
// Add the node to the tree.
found
.
children
=
append
(
found
.
children
,
&
node
)
return
nil
}
// 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
}
// ClaimPairs returns a list of claim pairs.
func
(
g
*
gameState
)
ClaimPairs
()
[]
struct
{
claim
Claim
parent
Claim
}
{
return
g
.
recurseTreePairs
(
&
g
.
root
)
}
op-challenger/fault/game_test.go
0 → 100644
View file @
80fb940c
package
fault
import
(
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func
createTestClaims
()
(
Claim
,
Claim
,
Claim
)
{
top
:=
Claim
{
ClaimData
:
ClaimData
{
Value
:
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000768"
),
Position
:
NewPosition
(
0
,
0
),
},
Parent
:
ClaimData
{},
}
middle
:=
Claim
{
ClaimData
:
ClaimData
{
Value
:
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000364"
),
Position
:
NewPosition
(
1
,
1
),
},
Parent
:
top
.
ClaimData
,
}
bottom
:=
Claim
{
ClaimData
:
ClaimData
{
Value
:
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000465"
),
Position
:
NewPosition
(
2
,
2
),
},
Parent
:
middle
.
ClaimData
,
}
return
top
,
middle
,
bottom
}
// TestGame_Put_RootAlreadyExists tests the [Game.Put] method using a [gameState]
// instance errors when the root claim already exists in state.
func
TestGame_Put_RootAlreadyExists
(
t
*
testing
.
T
)
{
// Setup the game state.
top
,
_
,
_
:=
createTestClaims
()
g
:=
NewGameState
(
top
)
// Try to put the root claim into the game state again.
err
:=
g
.
Put
(
top
)
require
.
ErrorIs
(
t
,
err
,
ErrClaimExists
)
}
// TestGame_Put_AlreadyExists tests the [Game.Put] method using a [gameState]
// instance errors when the given claim already exists in state.
func
TestGame_Put_AlreadyExists
(
t
*
testing
.
T
)
{
// Setup the game state.
top
,
middle
,
_
:=
createTestClaims
()
g
:=
NewGameState
(
top
)
// Put the next claim into state.
err
:=
g
.
Put
(
middle
)
require
.
NoError
(
t
,
err
)
// Put the claim into the game state again.
err
=
g
.
Put
(
middle
)
require
.
ErrorIs
(
t
,
err
,
ErrClaimExists
)
}
// TestGame_Put_ParentsAndChildren tests the [Game.Put] method using a [gameState] instance.
func
TestGame_Put_ParentsAndChildren
(
t
*
testing
.
T
)
{
// Setup the game state.
top
,
middle
,
bottom
:=
createTestClaims
()
g
:=
NewGameState
(
top
)
// We should not be able to get the parent of the root claim.
parent
,
err
:=
g
.
getParent
(
top
)
require
.
ErrorIs
(
t
,
err
,
ErrClaimNotFound
)
require
.
Equal
(
t
,
parent
,
Claim
{})
// Put the middle claim into the game state.
// We should expect no parent to exist, yet.
err
=
g
.
Put
(
middle
)
require
.
NoError
(
t
,
err
)
parent
,
err
=
g
.
getParent
(
middle
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
parent
,
top
)
// Put the bottom claim into the game state.
// We should expect the parent to be the claim we just added.
err
=
g
.
Put
(
bottom
)
require
.
NoError
(
t
,
err
)
parent
,
err
=
g
.
getParent
(
bottom
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
parent
,
middle
)
}
// TestGame_ClaimPairs tests the [Game.ClaimPairs] method using a [gameState] instance.
func
TestGame_ClaimPairs
(
t
*
testing
.
T
)
{
// Setup the game state.
top
,
middle
,
bottom
:=
createTestClaims
()
g
:=
NewGameState
(
top
)
// Add middle claim to the game state.
err
:=
g
.
Put
(
middle
)
require
.
NoError
(
t
,
err
)
// Add the bottom claim to the game state.
err
=
g
.
Put
(
bottom
)
require
.
NoError
(
t
,
err
)
// Validate claim pairs.
expected
:=
[]
struct
{
claim
,
parent
Claim
}{
{
middle
,
top
},
{
bottom
,
middle
},
}
pairs
:=
g
.
ClaimPairs
()
require
.
ElementsMatch
(
t
,
expected
,
pairs
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment