Commit a0089f58 authored by Adrian Sutton's avatar Adrian Sutton

op-challenger: Provide proof data when calling step

parent 818bc9f4
......@@ -135,6 +135,7 @@ func (a *Agent) step(claim Claim, game Game) error {
ClaimIndex: uint64(step.LeafClaim.ContractIndex),
IsAttack: step.IsAttack,
StateData: step.PreState,
Proof: step.ProofData,
}
return a.responder.Step(context.TODO(), callData)
}
......@@ -26,21 +26,21 @@ func NewAlphabetProvider(state string, depth uint64) *AlphabetProvider {
}
// GetPreimage returns the preimage for the given hash.
func (ap *AlphabetProvider) GetPreimage(i uint64) ([]byte, error) {
func (ap *AlphabetProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
// The index cannot be larger than the maximum index as computed by the depth.
if i >= ap.maxLen {
return []byte{}, ErrIndexTooLarge
return nil, nil, ErrIndexTooLarge
}
// We extend the deepest hash to the maximum depth if the trace is not expansive.
if i >= uint64(len(ap.state)) {
return ap.GetPreimage(uint64(len(ap.state)) - 1)
}
return BuildAlphabetPreimage(i, ap.state[i]), nil
return BuildAlphabetPreimage(i, ap.state[i]), []byte{}, nil
}
// Get returns the claim value at the given index in the trace.
func (ap *AlphabetProvider) Get(i uint64) (common.Hash, error) {
claimBytes, err := ap.GetPreimage(i)
claimBytes, _, err := ap.GetPreimage(i)
if err != nil {
return common.Hash{}, err
}
......
......@@ -55,16 +55,17 @@ func FuzzIndexToBytes(f *testing.F) {
func TestGetPreimage_Succeeds(t *testing.T) {
ap := NewAlphabetProvider("abc", 2)
expected := BuildAlphabetPreimage(0, "a'")
retrieved, err := ap.GetPreimage(uint64(0))
retrieved, proof, err := ap.GetPreimage(uint64(0))
require.NoError(t, err)
require.Equal(t, expected, retrieved)
require.Empty(t, proof)
}
// TestGetPreimage_TooLargeIndex_Fails tests the GetPreimage
// function errors if the index is too large.
func TestGetPreimage_TooLargeIndex_Fails(t *testing.T) {
ap := NewAlphabetProvider("abc", 2)
_, err := ap.GetPreimage(4)
_, _, err := ap.GetPreimage(4)
require.ErrorIs(t, err, ErrIndexTooLarge)
}
......
......@@ -43,16 +43,20 @@ func (p *CannonTraceProvider) Get(i uint64) (common.Hash, error) {
return value, nil
}
func (p *CannonTraceProvider) GetPreimage(i uint64) ([]byte, error) {
func (p *CannonTraceProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
proof, err := p.loadProof(i)
if err != nil {
return nil, err
return nil, nil, err
}
value := ([]byte)(proof.StateData)
if len(value) == 0 {
return nil, errors.New("proof missing state data")
return nil, nil, errors.New("proof missing state data")
}
return value, nil
data := ([]byte)(proof.ProofData)
if len(data) == 0 {
return nil, nil, errors.New("proof missing proof data")
}
return value, data, nil
}
func (p *CannonTraceProvider) AbsolutePreState() []byte {
......
......@@ -43,27 +43,31 @@ func TestGet(t *testing.T) {
func TestGetPreimage(t *testing.T) {
provider := setupWithTestData(t)
t.Run("ExistingProof", func(t *testing.T) {
value, err := provider.GetPreimage(0)
value, proof, err := provider.GetPreimage(0)
require.NoError(t, err)
expected := common.Hex2Bytes("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000")
require.Equal(t, expected, value)
expectedProof := common.Hex2Bytes("08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004")
require.Equal(t, expectedProof, proof)
})
t.Run("ProofUnavailable", func(t *testing.T) {
_, err := provider.GetPreimage(7)
_, _, err := provider.GetPreimage(7)
require.ErrorIs(t, err, os.ErrNotExist)
})
t.Run("MissingStateData", func(t *testing.T) {
_, err := provider.GetPreimage(1)
_, _, err := provider.GetPreimage(1)
require.ErrorContains(t, err, "missing state data")
})
t.Run("IgnoreUnknownFields", func(t *testing.T) {
value, err := provider.GetPreimage(2)
value, proof, err := provider.GetPreimage(2)
require.NoError(t, err)
expected := common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")
require.Equal(t, expected, value)
expectedProof := common.Hex2Bytes("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd")
require.Equal(t, expectedProof, proof)
})
}
......
......@@ -67,6 +67,7 @@ type StepData struct {
LeafClaim Claim
IsAttack bool
PreState []byte
ProofData []byte
}
// AttemptStep determines what step should occur for a given leaf claim.
......@@ -84,6 +85,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e
}
index := claim.TraceIndex(s.gameDepth)
var preState []byte
var proofData []byte
// If we are attacking index 0, we provide the absolute pre-state, not an intermediate state
if index == 0 && !claimCorrect {
preState = s.AbsolutePreState()
......@@ -92,7 +94,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e
if !claimCorrect {
index = index - 1
}
preState, err = s.GetPreimage(index)
preState, proofData, err = s.GetPreimage(index)
if err != nil {
return StepData{}, err
}
......@@ -102,6 +104,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e
LeafClaim: claim,
IsAttack: !claimCorrect,
PreState: preState,
ProofData: proofData,
}, nil
}
......
......@@ -100,7 +100,7 @@ func TestNoMoveAgainstOwnLevel(t *testing.T) {
func TestAttemptStep(t *testing.T) {
maxDepth := 3
canonicalProvider := NewAlphabetProvider("abcdefgh", uint64(maxDepth))
canonicalProvider := &alphabetWithProofProvider{NewAlphabetProvider("abcdefgh", uint64(maxDepth))}
solver := NewSolver(maxDepth, canonicalProvider)
_, _, middle, bottom := createTestClaims()
......@@ -116,6 +116,7 @@ func TestAttemptStep(t *testing.T) {
require.Equal(t, bottom, step.LeafClaim)
require.True(t, step.IsAttack)
require.Equal(t, step.PreState, BuildAlphabetPreimage(3, "d"))
require.Equal(t, step.ProofData, []byte{3})
_, err = solver.AttemptStep(middle, false)
require.Error(t, err)
......@@ -137,3 +138,15 @@ func TestAttempStep_AgreeWithClaimLevel_Fails(t *testing.T) {
require.Error(t, err)
require.Equal(t, StepData{}, step)
}
type alphabetWithProofProvider struct {
*AlphabetProvider
}
func (a *alphabetWithProofProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
preimage, _, err := a.AlphabetProvider.GetPreimage(i)
if err != nil {
return nil, nil, err
}
return preimage, []byte{byte(i)}, nil
}
......@@ -8,7 +8,6 @@ import (
)
var (
ErrNegativeIndex = errors.New("index cannot be negative")
ErrIndexTooLarge = errors.New("index is larger than the maximum index")
)
......@@ -20,13 +19,17 @@ type StepCallData struct {
Proof []byte
}
// TraceProvider is a generic way to get a claim value at a specific
// step in the trace.
// Get(i) = Keccak256(GetPreimage(i))
// AbsolutePreState is the value of the trace that transitions to the trace value at index 0
// TraceProvider is a generic way to get a claim value at a specific step in the trace.
type TraceProvider interface {
// Get returns the claim value at the requested index.
// Get(i) = Keccak256(GetPreimage(i))
Get(i uint64) (common.Hash, error)
GetPreimage(i uint64) ([]byte, error)
// GetPreimage returns the pre-image for a claim at the specified trace index, along
// with any associated proof data to assist in its verification.
GetPreimage(i uint64) (preimage []byte, proofData []byte, err error)
// AbsolutePreState is the pre-image value of the trace that transitions to the trace value at index 0
AbsolutePreState() []byte
}
......
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