Commit 9eac826b authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into dependabot/go_modules/gorm.io/gorm-1.25.4

parents c307af69 e9bb919d
......@@ -17,7 +17,6 @@ require (
github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8
github.com/google/uuid v1.3.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v1.0.2
github.com/hashicorp/golang-lru/v2 v2.0.2
github.com/holiman/uint256 v1.2.3
github.com/ipfs/go-datastore v0.6.0
......
......@@ -337,8 +337,6 @@ github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU=
github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
......
......@@ -35,27 +35,19 @@ const (
TraceTypeAlphabet TraceType = "alphabet"
TraceTypeCannon TraceType = "cannon"
// Devnet game IDs
DevnetGameIDAlphabet = uint8(0)
DevnetGameIDCannon = uint8(1)
// Mainnet games
CannonFaultGameID = 0
// Mainnet game IDs
MainnetGameIDFault = uint8(0)
// Devnet games
AlphabetFaultGameID = 255
)
var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon}
// GameIdToString maps game IDs to their string representation on a per-network basis.
var GameIdToString = map[uint64]map[uint8]string{
// Mainnet
1: {
MainnetGameIDFault: "fault-cannon",
},
// Devnet
900: {
DevnetGameIDAlphabet: "fault-alphabet",
DevnetGameIDCannon: "fault-cannon",
},
// GameIdToString maps game IDs to their string representation.
var GameIdToString = map[uint8]string{
CannonFaultGameID: "Cannon",
AlphabetFaultGameID: "Alphabet",
}
func (t TraceType) String() string {
......
......@@ -39,7 +39,6 @@ type Executor struct {
rollupConfig string
l2Genesis string
absolutePreState string
dataDir string
snapshotFreq uint
selectSnapshot snapshotSelect
cmdExecutor cmdExecutor
......@@ -57,7 +56,6 @@ func NewExecutor(logger log.Logger, cfg *config.Config, inputs LocalGameInputs)
rollupConfig: cfg.CannonRollupConfigPath,
l2Genesis: cfg.CannonL2GenesisPath,
absolutePreState: cfg.CannonAbsolutePreState,
dataDir: cfg.CannonDatadir,
snapshotFreq: cfg.CannonSnapshotFreq,
selectSnapshot: findStartingSnapshot,
cmdExecutor: runCmd,
......@@ -71,7 +69,7 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro
return fmt.Errorf("find starting snapshot: %w", err)
}
proofDir := filepath.Join(dir, proofsDir)
dataDir := filepath.Join(e.dataDir, preimagesDir)
dataDir := filepath.Join(dir, preimagesDir)
lastGeneratedState := filepath.Join(dir, finalState)
args := []string{
"run",
......
......@@ -22,7 +22,9 @@ const execTestCannonPrestate = "/foo/pre.json"
func TestGenerateProof(t *testing.T) {
input := "starting.json"
cfg := config.NewConfig(common.Address{0xbb}, "http://localhost:8888", config.TraceTypeCannon, true)
cfg.CannonDatadir = t.TempDir()
tempDir := t.TempDir()
dir := filepath.Join(tempDir, "gameDir")
cfg.CannonDatadir = tempDir
cfg.CannonAbsolutePreState = "pre.json"
cfg.CannonBin = "./bin/cannon"
cfg.CannonServer = "./bin/op-program"
......@@ -58,7 +60,7 @@ func TestGenerateProof(t *testing.T) {
}
return nil
}
err := executor.GenerateProof(context.Background(), cfg.CannonDatadir, proofAt)
err := executor.GenerateProof(context.Background(), dir, proofAt)
require.NoError(t, err)
return binary, subcommand, args
}
......@@ -68,15 +70,15 @@ func TestGenerateProof(t *testing.T) {
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = ""
binary, subcommand, args := captureExec(t, cfg, 150_000_000)
require.DirExists(t, filepath.Join(cfg.CannonDatadir, preimagesDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, proofsDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, snapsDir))
require.DirExists(t, filepath.Join(dir, preimagesDir))
require.DirExists(t, filepath.Join(dir, proofsDir))
require.DirExists(t, filepath.Join(dir, snapsDir))
require.Equal(t, cfg.CannonBin, binary)
require.Equal(t, "run", subcommand)
require.Equal(t, input, args["--input"])
require.Contains(t, args, "--meta")
require.Equal(t, "", args["--meta"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, finalState), args["--output"])
require.Equal(t, filepath.Join(dir, finalState), args["--output"])
require.Equal(t, "=150000000", args["--proof-at"])
require.Equal(t, "=150000001", args["--stop-at"])
require.Equal(t, "%500", args["--snapshot-at"])
......@@ -86,9 +88,9 @@ func TestGenerateProof(t *testing.T) {
require.Equal(t, "--server", args[cfg.CannonServer])
require.Equal(t, cfg.L1EthRpc, args["--l1"])
require.Equal(t, cfg.CannonL2, args["--l2"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, preimagesDir), args["--datadir"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, proofsDir, "%d.json"), args["--proof-fmt"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, snapsDir, "%d.json"), args["--snapshot-fmt"])
require.Equal(t, filepath.Join(dir, preimagesDir), args["--datadir"])
require.Equal(t, filepath.Join(dir, proofsDir, "%d.json"), args["--proof-fmt"])
require.Equal(t, filepath.Join(dir, snapsDir, "%d.json"), args["--snapshot-fmt"])
require.Equal(t, cfg.CannonNetwork, args["--network"])
require.NotContains(t, args, "--rollup.config")
require.NotContains(t, args, "--l2.genesis")
......
......@@ -64,13 +64,14 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, cfg *config.Config
if err != nil {
return nil, fmt.Errorf("fetch local game inputs: %w", err)
}
return NewTraceProviderFromInputs(logger, cfg, localInputs), nil
return NewTraceProviderFromInputs(logger, cfg, gameAddr.Hex(), localInputs), nil
}
func NewTraceProviderFromInputs(logger log.Logger, cfg *config.Config, localInputs LocalGameInputs) *CannonTraceProvider {
func NewTraceProviderFromInputs(logger log.Logger, cfg *config.Config, gameDirName string, localInputs LocalGameInputs) *CannonTraceProvider {
dir := filepath.Join(cfg.CannonDatadir, gameDirName)
return &CannonTraceProvider{
logger: logger,
dir: cfg.CannonDatadir,
dir: dir,
prestate: cfg.CannonAbsolutePreState,
generator: NewExecutor(logger, cfg, localInputs),
}
......
......@@ -11,6 +11,7 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common"
......@@ -149,7 +150,6 @@ func TestGetStepData(t *testing.T) {
func TestAbsolutePreState(t *testing.T) {
dataDir := t.TempDir()
_ = os.Mkdir(dataDir, 0o777)
prestate := "state.json"
......@@ -189,6 +189,21 @@ func TestAbsolutePreState(t *testing.T) {
})
}
func TestUseGameSpecificSubdir(t *testing.T) {
tempDir := t.TempDir()
dataDir := filepath.Join(tempDir, "data")
setupPreState(t, tempDir, "state.json")
logger := testlog.Logger(t, log.LvlInfo)
cfg := &config.Config{
CannonAbsolutePreState: filepath.Join(tempDir, "state.json"),
CannonDatadir: dataDir,
}
gameDirName := "gameSubdir"
localInputs := LocalGameInputs{}
provider := NewTraceProviderFromInputs(logger, cfg, gameDirName, localInputs)
require.Equal(t, filepath.Join(dataDir, gameDirName), provider.dir, "should use game specific subdir")
}
func setupPreState(t *testing.T, dataDir string, filename string) {
srcDir := filepath.Join("test_data")
path := filepath.Join(srcDir, filename)
......
......@@ -78,8 +78,8 @@ cast call $L2_OUTPUT_ORACLE_PROXY "getL2Output(uint256)" $PRIOR_INDEX
echo "Getting the l2 output at index $INDEX"
cast call $L2_OUTPUT_ORACLE_PROXY "getL2Output(uint256)" $INDEX
# (Alphabet) Fault game type = 0
GAME_TYPE=0
# (Alphabet) Fault game type = 255
GAME_TYPE=255
# Root claim commits to the entire trace.
# Alphabet game claim construction: keccak256(abi.encode(trace_index, trace[trace_index]))
......
......@@ -26,8 +26,8 @@ import (
"github.com/stretchr/testify/require"
)
const alphabetGameType uint8 = 0
const cannonGameType uint8 = 1
const alphabetGameType uint8 = 255
const cannonGameType uint8 = 0
const alphabetGameDepth = 4
const lastAlphabetTraceIndex = 1<<alphabetGameDepth - 1
......@@ -170,7 +170,7 @@ func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, roll
L2Claim: challengedOutput.OutputRoot,
L2BlockNumber: challengedOutput.L2BlockNumber,
}
provider := cannon.NewTraceProviderFromInputs(testlog.Logger(h.t, log.LvlInfo).New("role", "CorrectTrace"), cfg, inputs)
provider := cannon.NewTraceProviderFromInputs(testlog.Logger(h.t, log.LvlInfo).New("role", "CorrectTrace"), cfg, "correct", inputs)
rootClaim, err := provider.Get(ctx, math.MaxUint64)
h.require.NoError(err, "Compute correct root hash")
......
......@@ -56,7 +56,8 @@ func (s *jsonRawString) UnmarshalJSON(input []byte) error {
// printDebugTrace logs debug_traceTransaction output to aid in debugging unexpected receipt statuses
func printDebugTrace(ctx context.Context, client *ethclient.Client, txHash common.Hash) {
var trace jsonRawString
options := map[string]string{}
options := map[string]any{}
options["enableReturnData"] = true
err := client.Client().CallContext(ctx, &trace, "debug_traceTransaction", hexutil.Bytes(txHash.Bytes()), options)
if err != nil {
fmt.Printf("TxTrace unavailable: %v\n", err)
......
......@@ -50,7 +50,6 @@ func TestMultipleAlphabetGames(t *testing.T) {
}
func TestMultipleCannonGames(t *testing.T) {
t.Skip("Cannon provider doesn't currently isolate different game traces")
InitParallel(t)
ctx := context.Background()
......
......@@ -6,7 +6,7 @@ import (
"sync/atomic"
"time"
lru "github.com/hashicorp/golang-lru"
lru "github.com/hashicorp/golang-lru/v2"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
......@@ -31,7 +31,7 @@ type metrics struct {
// Groups heartbeats per unique IP, version and chain ID combination.
// string(IP ++ version ++ chainID) -> *heartbeatEntry
heartbeatUsers *lru.Cache
heartbeatUsers *lru.Cache[string, *heartbeatEntry]
}
type heartbeatEntry struct {
......@@ -42,7 +42,7 @@ type heartbeatEntry struct {
}
func NewMetrics(r *prometheus.Registry) Metrics {
lruCache, _ := lru.New(UsersCacheSize)
lruCache, _ := lru.New[string, *heartbeatEntry](UsersCacheSize)
m := &metrics{
heartbeats: promauto.With(r).NewCounterVec(prometheus.CounterOpts{
Namespace: MetricsNamespace,
......@@ -89,7 +89,7 @@ func (m *metrics) RecordHeartbeat(payload heartbeat.Payload, ip string) {
key := fmt.Sprintf("%s;%s;%s", ip, version, chainID)
now := time.Now()
previous, ok, _ := m.heartbeatUsers.PeekOrAdd(key, &heartbeatEntry{Time: now, Count: 1})
entry, ok, _ := m.heartbeatUsers.PeekOrAdd(key, &heartbeatEntry{Time: now, Count: 1})
if !ok {
// if it's a new entry, observe it and exit.
m.sameIP.WithLabelValues(chainID, version).Observe(1)
......@@ -97,7 +97,6 @@ func (m *metrics) RecordHeartbeat(payload heartbeat.Payload, ip string) {
return
}
entry := previous.(*heartbeatEntry)
if now.Sub(entry.Time) < MinHeartbeatInterval {
// if the span is still going, then add it up
atomic.AddUint64(&entry.Count, 1)
......
......@@ -10,7 +10,7 @@ import (
"time"
"github.com/golang/snappy"
lru "github.com/hashicorp/golang-lru"
lru "github.com/hashicorp/golang-lru/v2"
pubsub "github.com/libp2p/go-libp2p-pubsub"
pb "github.com/libp2p/go-libp2p-pubsub/pb"
"github.com/libp2p/go-libp2p/core/host"
......@@ -242,7 +242,7 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config, runCfg GossipRunti
// Seen block hashes per block height
// uint64 -> *seenBlocks
blockHeightLRU, err := lru.New(1000)
blockHeightLRU, err := lru.New[uint64, *seenBlocks](1000)
if err != nil {
panic(fmt.Errorf("failed to set up block height LRU cache: %w", err))
}
......@@ -315,7 +315,7 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config, runCfg GossipRunti
blockHeightLRU.Add(uint64(payload.BlockNumber), seen)
}
if count, hasSeen := seen.(*seenBlocks).hasSeen(payload.BlockHash); count > 5 {
if count, hasSeen := seen.hasSeen(payload.BlockHash); count > 5 {
// [REJECT] if more than 5 blocks have been seen with the same block height
log.Warn("seen too many different blocks at same height", "height", payload.BlockNumber)
return pubsub.ValidationReject
......@@ -327,7 +327,7 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config, runCfg GossipRunti
// mark it as seen. (note: with concurrent validation more than 5 blocks may be marked as seen still,
// but validator concurrency is limited anyway)
seen.(*seenBlocks).markSeen(payload.BlockHash)
seen.markSeen(payload.BlockHash)
// remember the decoded payload for later usage in topic subscriber.
message.ValidatorData = &payload
......
......@@ -186,9 +186,6 @@ func (conf *Config) Host(log log.Logger, reporter metrics.Reporter, metrics Host
tcpTransport := libp2p.Transport(
tcp.NewTCPTransport,
tcp.WithConnectionTimeout(time.Minute*60)) // break unused connections
if err != nil {
return nil, fmt.Errorf("failed to create TCP transport: %w", err)
}
// TODO: technically we can also run the node on websocket and QUIC transports. Maybe in the future?
var nat lconf.NATManagerC // disabled if nil
......
package caching
import lru "github.com/hashicorp/golang-lru"
import lru "github.com/hashicorp/golang-lru/v2"
type Metrics interface {
CacheAdd(label string, cacheSize int, evicted bool)
......@@ -8,13 +8,13 @@ type Metrics interface {
}
// LRUCache wraps hashicorp *lru.Cache and tracks cache metrics
type LRUCache struct {
type LRUCache[K comparable, V any] struct {
m Metrics
label string
inner *lru.Cache
inner *lru.Cache[K, V]
}
func (c *LRUCache) Get(key any) (value any, ok bool) {
func (c *LRUCache[K, V]) Get(key K) (value V, ok bool) {
value, ok = c.inner.Get(key)
if c.m != nil {
c.m.CacheGet(c.label, ok)
......@@ -22,7 +22,7 @@ func (c *LRUCache) Get(key any) (value any, ok bool) {
return value, ok
}
func (c *LRUCache) Add(key, value any) (evicted bool) {
func (c *LRUCache[K, V]) Add(key K, value V) (evicted bool) {
evicted = c.inner.Add(key, value)
if c.m != nil {
c.m.CacheAdd(c.label, c.inner.Len(), evicted)
......@@ -32,10 +32,10 @@ func (c *LRUCache) Add(key, value any) (evicted bool) {
// NewLRUCache creates a LRU cache with the given metrics, labeling the cache adds/gets.
// Metrics are optional: no metrics will be tracked if m == nil.
func NewLRUCache(m Metrics, label string, maxSize int) *LRUCache {
func NewLRUCache[K comparable, V any](m Metrics, label string, maxSize int) *LRUCache[K, V] {
// no errors if the size is positive
cache, _ := lru.New(maxSize)
return &LRUCache{
cache, _ := lru.New[K, V](maxSize)
return &LRUCache[K, V]{
m: m,
label: label,
inner: cache,
......
......@@ -106,19 +106,19 @@ type EthClient struct {
// cache receipts in bundles per block hash
// We cache the receipts fetching job to not lose progress when we have to retry the `Fetch` call
// common.Hash -> *receiptsFetchingJob
receiptsCache *caching.LRUCache
receiptsCache *caching.LRUCache[common.Hash, *receiptsFetchingJob]
// cache transactions in bundles per block hash
// common.Hash -> types.Transactions
transactionsCache *caching.LRUCache
transactionsCache *caching.LRUCache[common.Hash, types.Transactions]
// cache block headers of blocks by hash
// common.Hash -> *HeaderInfo
headersCache *caching.LRUCache
headersCache *caching.LRUCache[common.Hash, eth.BlockInfo]
// cache payloads by hash
// common.Hash -> *eth.ExecutionPayload
payloadsCache *caching.LRUCache
payloadsCache *caching.LRUCache[common.Hash, *eth.ExecutionPayload]
// availableReceiptMethods tracks which receipt methods can be used for fetching receipts
// This may be modified concurrently, but we don't lock since it's a single
......@@ -172,10 +172,10 @@ func NewEthClient(client client.RPC, log log.Logger, metrics caching.Metrics, co
mustBePostMerge: config.MustBePostMerge,
provKind: config.RPCProviderKind,
log: log,
receiptsCache: caching.NewLRUCache(metrics, "receipts", config.ReceiptsCacheSize),
transactionsCache: caching.NewLRUCache(metrics, "txs", config.TransactionsCacheSize),
headersCache: caching.NewLRUCache(metrics, "headers", config.HeadersCacheSize),
payloadsCache: caching.NewLRUCache(metrics, "payloads", config.PayloadsCacheSize),
receiptsCache: caching.NewLRUCache[common.Hash, *receiptsFetchingJob](metrics, "receipts", config.ReceiptsCacheSize),
transactionsCache: caching.NewLRUCache[common.Hash, types.Transactions](metrics, "txs", config.TransactionsCacheSize),
headersCache: caching.NewLRUCache[common.Hash, eth.BlockInfo](metrics, "headers", config.HeadersCacheSize),
payloadsCache: caching.NewLRUCache[common.Hash, *eth.ExecutionPayload](metrics, "payloads", config.PayloadsCacheSize),
availableReceiptMethods: AvailableReceiptsFetchingMethods(config.RPCProviderKind),
lastMethodsReset: time.Now(),
methodResetDuration: config.MethodResetDuration,
......@@ -292,7 +292,7 @@ func (s *EthClient) ChainID(ctx context.Context) (*big.Int, error) {
func (s *EthClient) InfoByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, error) {
if header, ok := s.headersCache.Get(hash); ok {
return header.(eth.BlockInfo), nil
return header, nil
}
return s.headerCall(ctx, "eth_getBlockByHash", hashID(hash))
}
......@@ -310,7 +310,7 @@ func (s *EthClient) InfoByLabel(ctx context.Context, label eth.BlockLabel) (eth.
func (s *EthClient) InfoAndTxsByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, types.Transactions, error) {
if header, ok := s.headersCache.Get(hash); ok {
if txs, ok := s.transactionsCache.Get(hash); ok {
return header.(eth.BlockInfo), txs.(types.Transactions), nil
return header, txs, nil
}
}
return s.blockCall(ctx, "eth_getBlockByHash", hashID(hash))
......@@ -328,7 +328,7 @@ func (s *EthClient) InfoAndTxsByLabel(ctx context.Context, label eth.BlockLabel)
func (s *EthClient) PayloadByHash(ctx context.Context, hash common.Hash) (*eth.ExecutionPayload, error) {
if payload, ok := s.payloadsCache.Get(hash); ok {
return payload.(*eth.ExecutionPayload), nil
return payload, nil
}
return s.payloadCall(ctx, "eth_getBlockByHash", hashID(hash))
}
......@@ -354,7 +354,7 @@ func (s *EthClient) FetchReceipts(ctx context.Context, blockHash common.Hash) (e
// The underlying fetcher uses the receipts hash to verify receipt integrity.
var job *receiptsFetchingJob
if v, ok := s.receiptsCache.Get(blockHash); ok {
job = v.(*receiptsFetchingJob)
job = v
} else {
txHashes := eth.TransactionsToHashes(txs)
job = NewReceiptsFetchingJob(s, s.client, s.maxBatchSize, eth.ToBlockID(info), info.ReceiptHash(), txHashes)
......
......@@ -56,7 +56,7 @@ type L1Client struct {
// cache L1BlockRef by hash
// common.Hash -> eth.L1BlockRef
l1BlockRefsCache *caching.LRUCache
l1BlockRefsCache *caching.LRUCache[common.Hash, eth.L1BlockRef]
}
// NewL1Client wraps a RPC with bindings to fetch L1 data, while logging errors, tracking metrics (optional), and caching.
......@@ -68,7 +68,7 @@ func NewL1Client(client client.RPC, log log.Logger, metrics caching.Metrics, con
return &L1Client{
EthClient: ethClient,
l1BlockRefsCache: caching.NewLRUCache(metrics, "blockrefs", config.L1BlockRefsCacheSize),
l1BlockRefsCache: caching.NewLRUCache[common.Hash, eth.L1BlockRef](metrics, "blockrefs", config.L1BlockRefsCacheSize),
}, nil
}
......@@ -105,7 +105,7 @@ func (s *L1Client) L1BlockRefByNumber(ctx context.Context, num uint64) (eth.L1Bl
// We cache the block reference by hash as it is safe to assume collision will not occur.
func (s *L1Client) L1BlockRefByHash(ctx context.Context, hash common.Hash) (eth.L1BlockRef, error) {
if v, ok := s.l1BlockRefsCache.Get(hash); ok {
return v.(eth.L1BlockRef), nil
return v, nil
}
info, err := s.InfoByHash(ctx, hash)
if err != nil {
......
......@@ -68,11 +68,11 @@ type L2Client struct {
// cache L2BlockRef by hash
// common.Hash -> eth.L2BlockRef
l2BlockRefsCache *caching.LRUCache
l2BlockRefsCache *caching.LRUCache[common.Hash, eth.L2BlockRef]
// cache SystemConfig by L2 hash
// common.Hash -> eth.SystemConfig
systemConfigsCache *caching.LRUCache
systemConfigsCache *caching.LRUCache[common.Hash, eth.SystemConfig]
}
// NewL2Client constructs a new L2Client instance. The L2Client is a thin wrapper around the EthClient with added functions
......@@ -87,8 +87,8 @@ func NewL2Client(client client.RPC, log log.Logger, metrics caching.Metrics, con
return &L2Client{
EthClient: ethClient,
rollupCfg: config.RollupCfg,
l2BlockRefsCache: caching.NewLRUCache(metrics, "blockrefs", config.L2BlockRefsCacheSize),
systemConfigsCache: caching.NewLRUCache(metrics, "systemconfigs", config.L1ConfigsCacheSize),
l2BlockRefsCache: caching.NewLRUCache[common.Hash, eth.L2BlockRef](metrics, "blockrefs", config.L2BlockRefsCacheSize),
systemConfigsCache: caching.NewLRUCache[common.Hash, eth.SystemConfig](metrics, "systemconfigs", config.L1ConfigsCacheSize),
}, nil
}
......@@ -131,7 +131,7 @@ func (s *L2Client) L2BlockRefByNumber(ctx context.Context, num uint64) (eth.L2Bl
// The returned BlockRef may not be in the canonical chain.
func (s *L2Client) L2BlockRefByHash(ctx context.Context, hash common.Hash) (eth.L2BlockRef, error) {
if ref, ok := s.l2BlockRefsCache.Get(hash); ok {
return ref.(eth.L2BlockRef), nil
return ref, nil
}
payload, err := s.PayloadByHash(ctx, hash)
......@@ -151,7 +151,7 @@ func (s *L2Client) L2BlockRefByHash(ctx context.Context, hash common.Hash) (eth.
// The returned [eth.SystemConfig] may not be in the canonical chain when the hash is not canonical.
func (s *L2Client) SystemConfigByL2Hash(ctx context.Context, hash common.Hash) (eth.SystemConfig, error) {
if ref, ok := s.systemConfigsCache.Get(hash); ok {
return ref.(eth.SystemConfig), nil
return ref, nil
}
payload, err := s.PayloadByHash(ctx, hash)
......
......@@ -76,7 +76,8 @@ contract Deploy is Deployer {
initializeL2OutputOracle();
initializeOptimismPortal();
setFaultGameImplementation();
setAlphabetFaultGameImplementation();
setCannonFaultGameImplementation();
transferProxyAdminOwnership();
transferDisputeGameFactoryOwnership();
......@@ -759,10 +760,13 @@ contract Deploy is Deployer {
}
/// @notice Sets the implementation for the `FAULT` game type in the `DisputeGameFactory`
function setFaultGameImplementation() public onlyDevnet broadcast {
// Create the absolute prestate dump
function setCannonFaultGameImplementation() public onlyDevnet broadcast {
DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
Claim mipsAbsolutePrestate;
if (block.chainid == Chains.LocalDevnet || block.chainid == Chains.GethDevnet) {
// Fetch the absolute prestate dump
string memory filePath = string.concat(vm.projectRoot(), "/../../op-program/bin/prestate-proof.json");
bytes32 mipsAbsolutePrestate;
string[] memory commands = new string[](3);
commands[0] = "bash";
commands[1] = "-c";
......@@ -771,35 +775,74 @@ contract Deploy is Deployer {
revert("Cannon prestate dump not found, generate it with `make cannon-prestate` in the monorepo root.");
}
commands[2] = string.concat("cat ", filePath, " | jq -r .pre");
mipsAbsolutePrestate = abi.decode(vm.ffi(commands), (bytes32));
console.log("Absolute prestate: %s", vm.toString(mipsAbsolutePrestate));
mipsAbsolutePrestate = Claim.wrap(abi.decode(vm.ffi(commands), (bytes32)));
console.log(
"[Cannon Dispute Game] Using devnet MIPS Absolute prestate: %s",
vm.toString(Claim.unwrap(mipsAbsolutePrestate))
);
} else {
console.log(
"[Cannon Dispute Game] Using absolute prestate from config: %s", cfg.faultGameAbsolutePrestate()
);
mipsAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate()));
}
// Set the Cannon FaultDisputeGame implementation in the factory.
_setFaultGameImplementation(
factory, GameTypes.FAULT, mipsAbsolutePrestate, IBigStepper(mustGetAddress("Mips")), cfg.faultGameMaxDepth()
);
}
/// @notice Sets the implementation for the alphabet game type in the `DisputeGameFactory`
function setAlphabetFaultGameImplementation() public onlyDevnet broadcast {
DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
for (uint8 i; i < 2; i++) {
Claim absolutePrestate =
Claim.wrap(i == 0 ? bytes32(cfg.faultGameAbsolutePrestate()) : mipsAbsolutePrestate);
IBigStepper faultVm =
IBigStepper(i == 0 ? address(new AlphabetVM(absolutePrestate)) : mustGetAddress("Mips"));
GameType gameType = GameType.wrap(i);
if (address(factory.gameImpls(gameType)) == address(0)) {
factory.setImplementation(
gameType,
// Set the Alphabet FaultDisputeGame implementation in the factory.
Claim alphabetAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate()));
_setFaultGameImplementation(
factory,
GameType.wrap(255),
alphabetAbsolutePrestate,
IBigStepper(new AlphabetVM(alphabetAbsolutePrestate)),
4 // The max game depth of the alphabet game is always 4.
);
}
/// @notice Sets the implementation for the given fault game type in the `DisputeGameFactory`.
function _setFaultGameImplementation(
DisputeGameFactory _factory,
GameType _gameType,
Claim _absolutePrestate,
IBigStepper _faultVm,
uint256 _maxGameDepth
)
internal
{
if (address(_factory.gameImpls(_gameType)) == address(0)) {
_factory.setImplementation(
_gameType,
new FaultDisputeGame({
_gameType: gameType,
_absolutePrestate: absolutePrestate,
_maxGameDepth: i == 0 ? 4 : cfg.faultGameMaxDepth(), // The max depth of the alphabet game is always 4
_gameType: _gameType,
_absolutePrestate: _absolutePrestate,
_maxGameDepth: _maxGameDepth,
_gameDuration: Duration.wrap(uint64(cfg.faultGameMaxDuration())),
_vm: faultVm,
_vm: _faultVm,
_l2oo: L2OutputOracle(mustGetAddress("L2OutputOracleProxy")),
_blockOracle: BlockOracle(mustGetAddress("BlockOracle"))
})
);
uint8 rawGameType = GameType.unwrap(_gameType);
console.log(
"DisputeGameFactoryProxy: set `FaultDisputeGame` implementation (Backend: %s | GameType: %s)",
i == 0 ? "AlphabetVM" : "MIPS",
vm.toString(i)
rawGameType == 0 ? "Cannon" : "Alphabet",
vm.toString(rawGameType)
);
} else {
console.log(
"[WARN] DisputeGameFactoryProxy: `FaultDisputeGame` implementation already set for game type: %s",
vm.toString(GameType.unwrap(_gameType))
);
}
}
}
}
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