Commit 8d7584ee authored by Adrian Sutton's avatar Adrian Sutton

Add hook for executing cannon into trace provider.

Currently just errors with information on what to manually generate.
parent e7a25442
...@@ -9,9 +9,12 @@ import ( ...@@ -9,9 +9,12 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
) )
const proofsDir = "proofs" const (
proofsDir = "proofs"
)
type proofData struct { type proofData struct {
ClaimValue hexutil.Bytes `json:"post"` ClaimValue hexutil.Bytes `json:"post"`
...@@ -19,13 +22,20 @@ type proofData struct { ...@@ -19,13 +22,20 @@ type proofData struct {
ProofData hexutil.Bytes `json:"proof-data"` ProofData hexutil.Bytes `json:"proof-data"`
} }
type Executor interface {
// GenerateProof executes cannon to generate a proof at the specified trace index in dataDir.
GenerateProof(dataDir string, proofAt uint64) error
}
type CannonTraceProvider struct { type CannonTraceProvider struct {
dir string dir string
executor Executor
} }
func NewCannonTraceProvider(dataDir string) *CannonTraceProvider { func NewCannonTraceProvider(logger log.Logger, dataDir string) *CannonTraceProvider {
return &CannonTraceProvider{ return &CannonTraceProvider{
dir: dataDir, dir: dataDir,
executor: newExecutor(logger),
} }
} }
...@@ -65,6 +75,13 @@ func (p *CannonTraceProvider) AbsolutePreState() []byte { ...@@ -65,6 +75,13 @@ func (p *CannonTraceProvider) AbsolutePreState() []byte {
func (p *CannonTraceProvider) loadProof(i uint64) (*proofData, error) { func (p *CannonTraceProvider) loadProof(i uint64) (*proofData, error) {
path := filepath.Join(p.dir, proofsDir, fmt.Sprintf("%d.json", i)) path := filepath.Join(p.dir, proofsDir, fmt.Sprintf("%d.json", i))
file, err := os.Open(path) file, err := os.Open(path)
if errors.Is(err, os.ErrNotExist) {
if err := p.executor.GenerateProof(p.dir, i); err != nil {
return nil, fmt.Errorf("generate cannon trace with proof at %v: %w", i, err)
}
// Try opening the file again now and it should exist.
file, err = os.Open(path)
}
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot open proof file (%v): %w", path, err) return nil, fmt.Errorf("cannot open proof file (%v): %w", path, err)
} }
......
...@@ -15,63 +15,79 @@ import ( ...@@ -15,63 +15,79 @@ import (
var testData embed.FS var testData embed.FS
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
provider := setupWithTestData(t) dataDir := setupTestData(t)
t.Run("ExistingProof", func(t *testing.T) { t.Run("ExistingProof", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
value, err := provider.Get(0) value, err := provider.Get(0)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, common.HexToHash("0x45fd9aa59768331c726e719e76aa343e73123af888804604785ae19506e65e87"), value) require.Equal(t, common.HexToHash("0x45fd9aa59768331c726e719e76aa343e73123af888804604785ae19506e65e87"), value)
require.Empty(t, executor.generated)
}) })
t.Run("ProofUnavailable", func(t *testing.T) { t.Run("ProofUnavailable", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
_, err := provider.Get(7) _, err := provider.Get(7)
require.ErrorIs(t, err, os.ErrNotExist) require.ErrorIs(t, err, os.ErrNotExist)
require.Contains(t, executor.generated, 7, "should have tried to generate the proof")
}) })
t.Run("MissingPostHash", func(t *testing.T) { t.Run("MissingPostHash", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
_, err := provider.Get(1) _, err := provider.Get(1)
require.ErrorContains(t, err, "missing post hash") require.ErrorContains(t, err, "missing post hash")
require.Empty(t, executor.generated)
}) })
t.Run("IgnoreUnknownFields", func(t *testing.T) { t.Run("IgnoreUnknownFields", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
value, err := provider.Get(2) value, err := provider.Get(2)
require.NoError(t, err) require.NoError(t, err)
expected := common.HexToHash("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") expected := common.HexToHash("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
require.Equal(t, expected, value) require.Equal(t, expected, value)
require.Empty(t, executor.generated)
}) })
} }
func TestGetPreimage(t *testing.T) { func TestGetPreimage(t *testing.T) {
provider := setupWithTestData(t) dataDir := setupTestData(t)
t.Run("ExistingProof", func(t *testing.T) { t.Run("ExistingProof", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
value, proof, err := provider.GetPreimage(0) value, proof, err := provider.GetPreimage(0)
require.NoError(t, err) require.NoError(t, err)
expected := common.Hex2Bytes("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000") expected := common.Hex2Bytes("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000")
require.Equal(t, expected, value) require.Equal(t, expected, value)
expectedProof := common.Hex2Bytes("08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004") expectedProof := common.Hex2Bytes("08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004")
require.Equal(t, expectedProof, proof) require.Equal(t, expectedProof, proof)
require.Empty(t, executor.generated)
}) })
t.Run("ProofUnavailable", func(t *testing.T) { t.Run("ProofUnavailable", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
_, _, err := provider.GetPreimage(7) _, _, err := provider.GetPreimage(7)
require.ErrorIs(t, err, os.ErrNotExist) require.ErrorIs(t, err, os.ErrNotExist)
require.Contains(t, executor.generated, 7, "should have tried to generate the proof")
}) })
t.Run("MissingStateData", func(t *testing.T) { t.Run("MissingStateData", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
_, _, err := provider.GetPreimage(1) _, _, err := provider.GetPreimage(1)
require.ErrorContains(t, err, "missing state data") require.ErrorContains(t, err, "missing state data")
require.Empty(t, executor.generated)
}) })
t.Run("IgnoreUnknownFields", func(t *testing.T) { t.Run("IgnoreUnknownFields", func(t *testing.T) {
provider, executor := setupWithTestData(dataDir)
value, proof, err := provider.GetPreimage(2) value, proof, err := provider.GetPreimage(2)
require.NoError(t, err) require.NoError(t, err)
expected := common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc") expected := common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")
require.Equal(t, expected, value) require.Equal(t, expected, value)
expectedProof := common.Hex2Bytes("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd") expectedProof := common.Hex2Bytes("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd")
require.Equal(t, expectedProof, proof) require.Equal(t, expectedProof, proof)
require.Empty(t, executor.generated)
}) })
} }
func setupWithTestData(t *testing.T) *CannonTraceProvider { func setupTestData(t *testing.T) string {
srcDir := filepath.Join("test_data", "proofs") srcDir := filepath.Join("test_data", "proofs")
entries, err := testData.ReadDir(srcDir) entries, err := testData.ReadDir(srcDir)
require.NoError(t, err) require.NoError(t, err)
...@@ -84,5 +100,22 @@ func setupWithTestData(t *testing.T) *CannonTraceProvider { ...@@ -84,5 +100,22 @@ func setupWithTestData(t *testing.T) *CannonTraceProvider {
err = os.WriteFile(filepath.Join(dataDir, "proofs", entry.Name()), file, 0o644) err = os.WriteFile(filepath.Join(dataDir, "proofs", entry.Name()), file, 0o644)
require.NoErrorf(t, err, "writing %v", path) require.NoErrorf(t, err, "writing %v", path)
} }
return NewCannonTraceProvider(dataDir) return dataDir
}
func setupWithTestData(dataDir string) (*CannonTraceProvider, *stubExecutor) {
executor := &stubExecutor{}
return &CannonTraceProvider{
dir: dataDir,
executor: executor,
}, executor
}
type stubExecutor struct {
generated []int // Using int makes assertions easier
}
func (e *stubExecutor) GenerateProof(dir string, i uint64) error {
e.generated = append(e.generated, int(i))
return nil
} }
package cannon
import (
"fmt"
"github.com/ethereum/go-ethereum/log"
)
type executor struct {
logger log.Logger
}
func newExecutor(logger log.Logger) Executor {
return &executor{
logger: logger,
}
}
func (e *executor) GenerateProof(dir string, i uint64) error {
return fmt.Errorf("please execute cannon with --proof-at %v --proof-fmt %v/%v/%%d.json", i, dir, proofsDir)
}
...@@ -55,7 +55,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se ...@@ -55,7 +55,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
var trace TraceProvider var trace TraceProvider
switch cfg.TraceType { switch cfg.TraceType {
case flags.TraceTypeCannon: case flags.TraceTypeCannon:
trace = cannon.NewCannonTraceProvider(cfg.CannonDatadir) trace = cannon.NewCannonTraceProvider(logger, cfg.CannonDatadir)
case flags.TraceTypeAlphabet: case flags.TraceTypeAlphabet:
trace = NewAlphabetProvider(cfg.AlphabetTrace, uint64(cfg.GameDepth)) trace = NewAlphabetProvider(cfg.AlphabetTrace, uint64(cfg.GameDepth))
default: default:
......
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