Commit abaa065b authored by Joshua Gutow's avatar Joshua Gutow Committed by GitHub

Properly wrap errors (#3366)

* op-node: Properly wrap errors

* op-proposer: Properly wrap errors

* Update linters to use errorlint

This includes a hack with golangci-lint to disable the assertion
and comparison check in errorlint but to retain the errorf lint.

In the the future the assertion lint could probably be fixed, but
the comparison lint may be overactive with certain cases.
parent c564e4e4
...@@ -410,7 +410,7 @@ jobs: ...@@ -410,7 +410,7 @@ jobs:
fi fi
- run: - run:
name: Lint name: Lint
command: golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell ./... command: golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" ./...
working_directory: <<parameters.working_directory>> working_directory: <<parameters.working_directory>>
- store_test_results: - store_test_results:
path: /test-results path: /test-results
......
...@@ -17,7 +17,7 @@ test: ...@@ -17,7 +17,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E asciicheck,goimports,misspell ./... golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is"
.PHONY: \ .PHONY: \
op-batcher \ op-batcher \
......
...@@ -2,7 +2,7 @@ test: ...@@ -2,7 +2,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E asciicheck,goimports,misspell ./... golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is"
.PHONY: \ .PHONY: \
test \ test \
......
...@@ -18,7 +18,7 @@ test: ...@@ -18,7 +18,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E asciicheck,goimports,misspell ./... golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is"
fuzz: fuzz:
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzExecutionPayloadUnmarshal ./eth go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzExecutionPayloadUnmarshal ./eth
......
...@@ -30,7 +30,7 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error { ...@@ -30,7 +30,7 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error {
accountClaimed := []interface{}{uint64(res.Nonce), (*big.Int)(res.Balance).Bytes(), res.StorageHash, res.CodeHash} accountClaimed := []interface{}{uint64(res.Nonce), (*big.Int)(res.Balance).Bytes(), res.StorageHash, res.CodeHash}
accountClaimedValue, err := rlp.EncodeToBytes(accountClaimed) accountClaimedValue, err := rlp.EncodeToBytes(accountClaimed)
if err != nil { if err != nil {
return fmt.Errorf("failed to encode account from retrieved values: %v", err) return fmt.Errorf("failed to encode account from retrieved values: %w", err)
} }
// create a db with all trie nodes // create a db with all trie nodes
...@@ -38,7 +38,7 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error { ...@@ -38,7 +38,7 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error {
for i, encodedNode := range res.AccountProof { for i, encodedNode := range res.AccountProof {
nodeKey := crypto.Keccak256(encodedNode) nodeKey := crypto.Keccak256(encodedNode)
if err := db.Put(nodeKey, encodedNode); err != nil { if err := db.Put(nodeKey, encodedNode); err != nil {
return fmt.Errorf("failed to load proof value %d into mem db: %v", i, err) return fmt.Errorf("failed to load proof value %d into mem db: %w", i, err)
} }
} }
...@@ -54,7 +54,7 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error { ...@@ -54,7 +54,7 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error {
// now get the full value from the account proof, and check that it matches the JSON contents // now get the full value from the account proof, and check that it matches the JSON contents
accountProofValue, err := proofTrie.TryGet(key[:]) accountProofValue, err := proofTrie.TryGet(key[:])
if err != nil { if err != nil {
return fmt.Errorf("failed to retrieve account value: %v", err) return fmt.Errorf("failed to retrieve account value: %w", err)
} }
if !bytes.Equal(accountClaimedValue, accountProofValue) { if !bytes.Equal(accountClaimedValue, accountProofValue) {
......
...@@ -184,7 +184,7 @@ func (payload *ExecutionPayload) UnmarshalSSZ(scope uint32, r io.Reader) error { ...@@ -184,7 +184,7 @@ func (payload *ExecutionPayload) UnmarshalSSZ(scope uint32, r io.Reader) error {
copy(payload.ExtraData, buf[extraDataOffset:transactionsOffset]) copy(payload.ExtraData, buf[extraDataOffset:transactionsOffset])
txs, err := unmarshalTransactions(buf[transactionsOffset:]) txs, err := unmarshalTransactions(buf[transactionsOffset:])
if err != nil { if err != nil {
return fmt.Errorf("failed to unmarshal transactions list: %v", err) return fmt.Errorf("failed to unmarshal transactions list: %w", err)
} }
payload.Transactions = txs payload.Transactions = txs
return nil return nil
......
...@@ -201,7 +201,7 @@ func BlockAsPayload(bl *types.Block) (*ExecutionPayload, error) { ...@@ -201,7 +201,7 @@ func BlockAsPayload(bl *types.Block) (*ExecutionPayload, error) {
for i, tx := range bl.Transactions() { for i, tx := range bl.Transactions() {
otx, err := tx.MarshalBinary() otx, err := tx.MarshalBinary()
if err != nil { if err != nil {
return nil, fmt.Errorf("tx %d failed to marshal: %v", i, err) return nil, fmt.Errorf("tx %d failed to marshal: %w", i, err)
} }
opaqueTxs[i] = otx opaqueTxs[i] = otx
} }
......
...@@ -116,7 +116,7 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error { ...@@ -116,7 +116,7 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
client.NewInstrumentedRPC(l1Node, n.metrics), n.log, n.metrics.L1SourceCache, client.NewInstrumentedRPC(l1Node, n.metrics), n.log, n.metrics.L1SourceCache,
sources.L1ClientDefaultConfig(&cfg.Rollup, trustRPC)) sources.L1ClientDefaultConfig(&cfg.Rollup, trustRPC))
if err != nil { if err != nil {
return fmt.Errorf("failed to create L1 source: %v", err) return fmt.Errorf("failed to create L1 source: %w", err)
} }
// Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync
......
...@@ -152,20 +152,20 @@ func NewConfig(ctx *cli.Context) (*Config, error) { ...@@ -152,20 +152,20 @@ func NewConfig(ctx *cli.Context) (*Config, error) {
p, err := loadNetworkPrivKey(ctx) p, err := loadNetworkPrivKey(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load p2p priv key: %v", err) return nil, fmt.Errorf("failed to load p2p priv key: %w", err)
} }
conf.Priv = p conf.Priv = p
if err := conf.loadListenOpts(ctx); err != nil { if err := conf.loadListenOpts(ctx); err != nil {
return nil, fmt.Errorf("failed to load p2p listen options: %v", err) return nil, fmt.Errorf("failed to load p2p listen options: %w", err)
} }
if err := conf.loadDiscoveryOpts(ctx); err != nil { if err := conf.loadDiscoveryOpts(ctx); err != nil {
return nil, fmt.Errorf("failed to load p2p discovery options: %v", err) return nil, fmt.Errorf("failed to load p2p discovery options: %w", err)
} }
if err := conf.loadLibp2pOpts(ctx); err != nil { if err := conf.loadLibp2pOpts(ctx); err != nil {
return nil, fmt.Errorf("failed to load p2p options: %v", err) return nil, fmt.Errorf("failed to load p2p options: %w", err)
} }
conf.ConnGater = DefaultConnGater conf.ConnGater = DefaultConnGater
...@@ -189,11 +189,11 @@ func (conf *Config) loadListenOpts(ctx *cli.Context) error { ...@@ -189,11 +189,11 @@ func (conf *Config) loadListenOpts(ctx *cli.Context) error {
var err error var err error
conf.ListenTCPPort, err = validatePort(ctx.GlobalUint(flags.ListenTCPPort.Name)) conf.ListenTCPPort, err = validatePort(ctx.GlobalUint(flags.ListenTCPPort.Name))
if err != nil { if err != nil {
return fmt.Errorf("bad listen TCP port: %v", err) return fmt.Errorf("bad listen TCP port: %w", err)
} }
conf.ListenUDPPort, err = validatePort(ctx.GlobalUint(flags.ListenUDPPort.Name)) conf.ListenUDPPort, err = validatePort(ctx.GlobalUint(flags.ListenUDPPort.Name))
if err != nil { if err != nil {
return fmt.Errorf("bad listen UDP port: %v", err) return fmt.Errorf("bad listen UDP port: %w", err)
} }
return nil return nil
} }
...@@ -206,17 +206,17 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error { ...@@ -206,17 +206,17 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error {
var err error var err error
conf.AdvertiseTCPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseTCPPort.Name)) conf.AdvertiseTCPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseTCPPort.Name))
if err != nil { if err != nil {
return fmt.Errorf("bad advertised TCP port: %v", err) return fmt.Errorf("bad advertised TCP port: %w", err)
} }
conf.AdvertiseUDPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseUDPPort.Name)) conf.AdvertiseUDPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseUDPPort.Name))
if err != nil { if err != nil {
return fmt.Errorf("bad advertised UDP port: %v", err) return fmt.Errorf("bad advertised UDP port: %w", err)
} }
adIP := ctx.GlobalString(flags.AdvertiseIP.Name) adIP := ctx.GlobalString(flags.AdvertiseIP.Name)
if adIP != "" { // optional if adIP != "" { // optional
ips, err := net.LookupIP(adIP) ips, err := net.LookupIP(adIP)
if err != nil { if err != nil {
return fmt.Errorf("failed to lookup IP of %q to advertise in ENR: %v", adIP, err) return fmt.Errorf("failed to lookup IP of %q to advertise in ENR: %w", adIP, err)
} }
// Find the first v4 IP it resolves to // Find the first v4 IP it resolves to
for _, ip := range ips { for _, ip := range ips {
...@@ -239,7 +239,7 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error { ...@@ -239,7 +239,7 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error {
} }
conf.DiscoveryDB, err = enode.OpenDB(dbPath) conf.DiscoveryDB, err = enode.OpenDB(dbPath)
if err != nil { if err != nil {
return fmt.Errorf("failed to open discovery db: %v", err) return fmt.Errorf("failed to open discovery db: %w", err)
} }
records := strings.Split(ctx.GlobalString(flags.Bootnodes.Name), ",") records := strings.Split(ctx.GlobalString(flags.Bootnodes.Name), ",")
...@@ -250,7 +250,7 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error { ...@@ -250,7 +250,7 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error {
} }
nodeRecord, err := enode.Parse(enode.ValidSchemes, recordB64) nodeRecord, err := enode.Parse(enode.ValidSchemes, recordB64)
if err != nil { if err != nil {
return fmt.Errorf("bootnode record %d (of %d) is invalid: %q err: %v", i, len(records), recordB64, err) return fmt.Errorf("bootnode record %d (of %d) is invalid: %q err: %w", i, len(records), recordB64, err)
} }
conf.Bootnodes = append(conf.Bootnodes, nodeRecord) conf.Bootnodes = append(conf.Bootnodes, nodeRecord)
} }
...@@ -300,7 +300,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { ...@@ -300,7 +300,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error {
} }
a, err := multiaddr.NewMultiaddr(addr) a, err := multiaddr.NewMultiaddr(addr)
if err != nil { if err != nil {
return fmt.Errorf("failed to parse multi addr of static peer %d (out of %d): %q err: %v", i, len(addrs), addr, err) return fmt.Errorf("failed to parse multi addr of static peer %d (out of %d): %q err: %w", i, len(addrs), addr, err)
} }
conf.StaticPeers = append(conf.StaticPeers, a) conf.StaticPeers = append(conf.StaticPeers, a)
} }
...@@ -318,7 +318,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { ...@@ -318,7 +318,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error {
return fmt.Errorf("could not recognize mux %s", v) return fmt.Errorf("could not recognize mux %s", v)
} }
if err != nil { if err != nil {
return fmt.Errorf("failed to make %s constructor: %v", v, err) return fmt.Errorf("failed to make %s constructor: %w", v, err)
} }
conf.HostMux = append(conf.HostMux, mc) conf.HostMux = append(conf.HostMux, mc)
} }
...@@ -342,7 +342,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { ...@@ -342,7 +342,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error {
return fmt.Errorf("could not recognize security %s", v) return fmt.Errorf("could not recognize security %s", v)
} }
if err != nil { if err != nil {
return fmt.Errorf("failed to make %s constructor: %v", v, err) return fmt.Errorf("failed to make %s constructor: %w", v, err)
} }
conf.HostSecurity = append(conf.HostSecurity, sc) conf.HostSecurity = append(conf.HostSecurity, sc)
} }
...@@ -368,7 +368,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { ...@@ -368,7 +368,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error {
} else { } else {
store, err = leveldb.NewDatastore(peerstorePath, nil) // default leveldb options are fine store, err = leveldb.NewDatastore(peerstorePath, nil) // default leveldb options are fine
if err != nil { if err != nil {
return fmt.Errorf("failed to open leveldb db for peerstore: %v", err) return fmt.Errorf("failed to open leveldb db for peerstore: %w", err)
} }
} }
conf.Store = store conf.Store = store
...@@ -386,26 +386,26 @@ func loadNetworkPrivKey(ctx *cli.Context) (*crypto.Secp256k1PrivateKey, error) { ...@@ -386,26 +386,26 @@ func loadNetworkPrivKey(ctx *cli.Context) (*crypto.Secp256k1PrivateKey, error) {
if os.IsNotExist(err) { if os.IsNotExist(err) {
p, _, err := crypto.GenerateSecp256k1Key(rand.Reader) p, _, err := crypto.GenerateSecp256k1Key(rand.Reader)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to generate new p2p priv key: %v", err) return nil, fmt.Errorf("failed to generate new p2p priv key: %w", err)
} }
b, err := p.Raw() b, err := p.Raw()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode new p2p priv key: %v", err) return nil, fmt.Errorf("failed to encode new p2p priv key: %w", err)
} }
f, err := os.OpenFile(keyPath, os.O_CREATE|os.O_WRONLY, 0600) f, err := os.OpenFile(keyPath, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to store new p2p priv key: %v", err) return nil, fmt.Errorf("failed to store new p2p priv key: %w", err)
} }
defer f.Close() defer f.Close()
if _, err := f.WriteString(hex.EncodeToString(b)); err != nil { if _, err := f.WriteString(hex.EncodeToString(b)); err != nil {
return nil, fmt.Errorf("failed to write new p2p priv key: %v", err) return nil, fmt.Errorf("failed to write new p2p priv key: %w", err)
} }
return (p).(*crypto.Secp256k1PrivateKey), nil return (p).(*crypto.Secp256k1PrivateKey), nil
} else { } else {
defer f.Close() defer f.Close()
data, err := io.ReadAll(f) data, err := io.ReadAll(f)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read priv key file: %v", err) return nil, fmt.Errorf("failed to read priv key file: %w", err)
} }
return parsePriv(strings.TrimSpace(string(data))) return parsePriv(strings.TrimSpace(string(data)))
} }
......
...@@ -137,7 +137,7 @@ func enrToAddrInfo(r *enode.Node) (*peer.AddrInfo, *crypto.Secp256k1PublicKey, e ...@@ -137,7 +137,7 @@ func enrToAddrInfo(r *enode.Node) (*peer.AddrInfo, *crypto.Secp256k1PublicKey, e
} }
mAddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/%s/%s/tcp/%d", ipScheme, ip.String(), r.TCP())) mAddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/%s/%s/tcp/%d", ipScheme, ip.String(), r.TCP()))
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("could not construct multi addr: %v", err) return nil, nil, fmt.Errorf("could not construct multi addr: %w", err)
} }
var enrPub Secp256k1 var enrPub Secp256k1
if err := r.Load(&enrPub); err != nil { if err := r.Load(&enrPub); err != nil {
...@@ -146,7 +146,7 @@ func enrToAddrInfo(r *enode.Node) (*peer.AddrInfo, *crypto.Secp256k1PublicKey, e ...@@ -146,7 +146,7 @@ func enrToAddrInfo(r *enode.Node) (*peer.AddrInfo, *crypto.Secp256k1PublicKey, e
pub := (*crypto.Secp256k1PublicKey)(&enrPub) pub := (*crypto.Secp256k1PublicKey)(&enrPub)
peerID, err := peer.IDFromPublicKey(pub) peerID, err := peer.IDFromPublicKey(pub)
if err != nil { if err != nil {
return nil, pub, fmt.Errorf("could not compute peer ID from pubkey for multi-addr: %v", err) return nil, pub, fmt.Errorf("could not compute peer ID from pubkey for multi-addr: %w", err)
} }
return &peer.AddrInfo{ return &peer.AddrInfo{
ID: peerID, ID: peerID,
...@@ -177,18 +177,18 @@ func (o *OptimismENRData) EncodeRLP(w io.Writer) error { ...@@ -177,18 +177,18 @@ func (o *OptimismENRData) EncodeRLP(w io.Writer) error {
func (o *OptimismENRData) DecodeRLP(s *rlp.Stream) error { func (o *OptimismENRData) DecodeRLP(s *rlp.Stream) error {
b, err := s.Bytes() b, err := s.Bytes()
if err != nil { if err != nil {
return fmt.Errorf("failed to decode outer ENR entry: %v", err) return fmt.Errorf("failed to decode outer ENR entry: %w", err)
} }
// We don't check the byte length: the below readers are limited, and the ENR itself has size limits. // We don't check the byte length: the below readers are limited, and the ENR itself has size limits.
// Future "optimism" entries may contain additional data, and will be tagged with a newer version etc. // Future "optimism" entries may contain additional data, and will be tagged with a newer version etc.
r := bytes.NewReader(b) r := bytes.NewReader(b)
chainID, err := binary.ReadUvarint(r) chainID, err := binary.ReadUvarint(r)
if err != nil { if err != nil {
return fmt.Errorf("failed to read chain ID var int: %v", err) return fmt.Errorf("failed to read chain ID var int: %w", err)
} }
version, err := binary.ReadUvarint(r) version, err := binary.ReadUvarint(r)
if err != nil { if err != nil {
return fmt.Errorf("failed to read version var int: %v", err) return fmt.Errorf("failed to read version var int: %w", err)
} }
o.chainID = chainID o.chainID = chainID
o.version = version o.version = version
......
...@@ -193,7 +193,7 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx ...@@ -193,7 +193,7 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx
// uint64 -> *seenBlocks // uint64 -> *seenBlocks
blockHeightLRU, err := lru.New(100) blockHeightLRU, err := lru.New(100)
if err != nil { if err != nil {
panic(fmt.Errorf("failed to set up block height LRU cache: %v", err)) panic(fmt.Errorf("failed to set up block height LRU cache: %w", err))
} }
return func(ctx context.Context, id peer.ID, message *pubsub.Message) pubsub.ValidationResult { return func(ctx context.Context, id peer.ID, message *pubsub.Message) pubsub.ValidationResult {
...@@ -330,13 +330,13 @@ func (p *publisher) PublishL2Payload(ctx context.Context, payload *eth.Execution ...@@ -330,13 +330,13 @@ func (p *publisher) PublishL2Payload(ctx context.Context, payload *eth.Execution
buf.Write(make([]byte, 65)) buf.Write(make([]byte, 65))
if _, err := payload.MarshalSSZ(buf); err != nil { if _, err := payload.MarshalSSZ(buf); err != nil {
return fmt.Errorf("failed to encoded execution payload to publish: %v", err) return fmt.Errorf("failed to encoded execution payload to publish: %w", err)
} }
data := buf.Bytes() data := buf.Bytes()
payloadData := data[65:] payloadData := data[65:]
sig, err := signer.Sign(ctx, SigningDomainBlocksV1, p.cfg.L2ChainID, payloadData) sig, err := signer.Sign(ctx, SigningDomainBlocksV1, p.cfg.L2ChainID, payloadData)
if err != nil { if err != nil {
return fmt.Errorf("failed to sign execution payload with signer: %v", err) return fmt.Errorf("failed to sign execution payload with signer: %w", err)
} }
copy(data[:65], sig[:]) copy(data[:65], sig[:])
...@@ -359,15 +359,15 @@ func JoinGossip(p2pCtx context.Context, self peer.ID, ps *pubsub.PubSub, log log ...@@ -359,15 +359,15 @@ func JoinGossip(p2pCtx context.Context, self peer.ID, ps *pubsub.PubSub, log log
pubsub.WithValidatorTimeout(3*time.Second), pubsub.WithValidatorTimeout(3*time.Second),
pubsub.WithValidatorConcurrency(4)) pubsub.WithValidatorConcurrency(4))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to register blocks gossip topic: %v", err) return nil, fmt.Errorf("failed to register blocks gossip topic: %w", err)
} }
blocksTopic, err := ps.Join(blocksTopicName) blocksTopic, err := ps.Join(blocksTopicName)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to join blocks gossip topic: %v", err) return nil, fmt.Errorf("failed to join blocks gossip topic: %w", err)
} }
blocksTopicEvents, err := blocksTopic.EventHandler() blocksTopicEvents, err := blocksTopic.EventHandler()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create blocks gossip topic handler: %v", err) return nil, fmt.Errorf("failed to create blocks gossip topic handler: %w", err)
} }
go LogTopicEvents(p2pCtx, log.New("topic", "blocks"), blocksTopicEvents) go LogTopicEvents(p2pCtx, log.New("topic", "blocks"), blocksTopicEvents)
...@@ -379,7 +379,7 @@ func JoinGossip(p2pCtx context.Context, self peer.ID, ps *pubsub.PubSub, log log ...@@ -379,7 +379,7 @@ func JoinGossip(p2pCtx context.Context, self peer.ID, ps *pubsub.PubSub, log log
subscription, err := blocksTopic.Subscribe() subscription, err := blocksTopic.Subscribe()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to subscribe to blocks gossip topic: %v", err) return nil, fmt.Errorf("failed to subscribe to blocks gossip topic: %w", err)
} }
subscriber := MakeSubscriber(log, BlocksHandler(gossipIn.OnUnsafeL2Payload)) subscriber := MakeSubscriber(log, BlocksHandler(gossipIn.OnUnsafeL2Payload))
......
...@@ -48,40 +48,40 @@ func (conf *Config) Host(log log.Logger) (host.Host, error) { ...@@ -48,40 +48,40 @@ func (conf *Config) Host(log log.Logger) (host.Host, error) {
pub := conf.Priv.GetPublic() pub := conf.Priv.GetPublic()
pid, err := peer.IDFromPublicKey(pub) pid, err := peer.IDFromPublicKey(pub)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to derive pubkey from network priv key: %v", err) return nil, fmt.Errorf("failed to derive pubkey from network priv key: %w", err)
} }
ps, err := pstoreds.NewPeerstore(context.Background(), conf.Store, pstoreds.DefaultOpts()) ps, err := pstoreds.NewPeerstore(context.Background(), conf.Store, pstoreds.DefaultOpts())
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open peerstore: %v", err) return nil, fmt.Errorf("failed to open peerstore: %w", err)
} }
if err := ps.AddPrivKey(pid, conf.Priv); err != nil { if err := ps.AddPrivKey(pid, conf.Priv); err != nil {
return nil, fmt.Errorf("failed to set up peerstore with priv key: %v", err) return nil, fmt.Errorf("failed to set up peerstore with priv key: %w", err)
} }
if err := ps.AddPubKey(pid, pub); err != nil { if err := ps.AddPubKey(pid, pub); err != nil {
return nil, fmt.Errorf("failed to set up peerstore with pub key: %v", err) return nil, fmt.Errorf("failed to set up peerstore with pub key: %w", err)
} }
connGtr, err := conf.ConnGater(conf) connGtr, err := conf.ConnGater(conf)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open connection gater: %v", err) return nil, fmt.Errorf("failed to open connection gater: %w", err)
} }
connMngr, err := conf.ConnMngr(conf) connMngr, err := conf.ConnMngr(conf)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open connection manager: %v", err) return nil, fmt.Errorf("failed to open connection manager: %w", err)
} }
listenAddr, err := addrFromIPAndPort(conf.ListenIP, conf.ListenTCPPort) listenAddr, err := addrFromIPAndPort(conf.ListenIP, conf.ListenTCPPort)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to make listen addr: %v", err) return nil, fmt.Errorf("failed to make listen addr: %w", err)
} }
tcpTransport, err := lconf.TransportConstructor( tcpTransport, err := lconf.TransportConstructor(
tcp.NewTCPTransport, tcp.NewTCPTransport,
tcp.WithConnectionTimeout(time.Minute*60)) // break unused connections tcp.WithConnectionTimeout(time.Minute*60)) // break unused connections
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create TCP transport: %v", err) 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? // TODO: technically we can also run the node on websocket and QUIC transports. Maybe in the future?
...@@ -140,7 +140,7 @@ func (conf *Config) Host(log log.Logger) (host.Host, error) { ...@@ -140,7 +140,7 @@ func (conf *Config) Host(log log.Logger) (host.Host, error) {
for _, peerAddr := range conf.StaticPeers { for _, peerAddr := range conf.StaticPeers {
addr, err := peer.AddrInfoFromP2pAddr(peerAddr) addr, err := peer.AddrInfoFromP2pAddr(peerAddr)
if err != nil { if err != nil {
return nil, fmt.Errorf("bad peer address: %v", err) return nil, fmt.Errorf("bad peer address: %w", err)
} }
h.Peerstore().AddAddrs(addr.ID, addr.Addrs, time.Hour*24*7) h.Peerstore().AddAddrs(addr.ID, addr.Addrs, time.Hour*24*7)
// We protect the peer, so the connection manager doesn't decide to prune it. // We protect the peer, so the connection manager doesn't decide to prune it.
......
...@@ -56,7 +56,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l ...@@ -56,7 +56,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l
if n.dv5Udp != nil { if n.dv5Udp != nil {
n.dv5Udp.Close() n.dv5Udp.Close()
} }
return fmt.Errorf("failed to start p2p host: %v", err) return fmt.Errorf("failed to start p2p host: %w", err)
} }
if n.host != nil { if n.host != nil {
...@@ -71,12 +71,12 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l ...@@ -71,12 +71,12 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l
n.host.RemoveStreamHandler(identify.IDDelta) n.host.RemoveStreamHandler(identify.IDDelta)
n.gs, err = NewGossipSub(resourcesCtx, n.host, rollupCfg) n.gs, err = NewGossipSub(resourcesCtx, n.host, rollupCfg)
if err != nil { if err != nil {
return fmt.Errorf("failed to start gossipsub router: %v", err) return fmt.Errorf("failed to start gossipsub router: %w", err)
} }
n.gsOut, err = JoinGossip(resourcesCtx, n.host.ID(), n.gs, log, rollupCfg, gossipIn) n.gsOut, err = JoinGossip(resourcesCtx, n.host.ID(), n.gs, log, rollupCfg, gossipIn)
if err != nil { if err != nil {
return fmt.Errorf("failed to join blocks gossip topic: %v", err) return fmt.Errorf("failed to join blocks gossip topic: %w", err)
} }
log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().Pretty()) log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().Pretty())
...@@ -88,7 +88,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l ...@@ -88,7 +88,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l
// All nil if disabled. // All nil if disabled.
n.dv5Local, n.dv5Udp, err = setup.Discovery(log.New("p2p", "discv5"), rollupCfg, tcpPort) n.dv5Local, n.dv5Udp, err = setup.Discovery(log.New("p2p", "discv5"), rollupCfg, tcpPort)
if err != nil { if err != nil {
return fmt.Errorf("failed to start discv5: %v", err) return fmt.Errorf("failed to start discv5: %w", err)
} }
} }
return nil return nil
...@@ -129,12 +129,12 @@ func (n *NodeP2P) Close() error { ...@@ -129,12 +129,12 @@ func (n *NodeP2P) Close() error {
} }
if n.gsOut != nil { if n.gsOut != nil {
if err := n.gsOut.Close(); err != nil { if err := n.gsOut.Close(); err != nil {
result = multierror.Append(result, fmt.Errorf("failed to close gossip cleanly: %v", err)) result = multierror.Append(result, fmt.Errorf("failed to close gossip cleanly: %w", err))
} }
} }
if n.host != nil { if n.host != nil {
if err := n.host.Close(); err != nil { if err := n.host.Close(); err != nil {
result = multierror.Append(result, fmt.Errorf("failed to close p2p host cleanly: %v", err)) result = multierror.Append(result, fmt.Errorf("failed to close p2p host cleanly: %w", err))
} }
} }
return result.ErrorOrNil() return result.ErrorOrNil()
......
...@@ -356,7 +356,7 @@ func (s *APIBackend) ConnectPeer(ctx context.Context, addr string) error { ...@@ -356,7 +356,7 @@ func (s *APIBackend) ConnectPeer(ctx context.Context, addr string) error {
h := s.node.Host() h := s.node.Host()
addrInfo, err := peer.AddrInfoFromString(addr) addrInfo, err := peer.AddrInfoFromString(addr)
if err != nil { if err != nil {
return fmt.Errorf("bad peer address: %v", err) return fmt.Errorf("bad peer address: %w", err)
} }
// Put a sanity limit on the connection time // Put a sanity limit on the connection time
ctx, cancel := context.WithTimeout(ctx, time.Second*30) ctx, cancel := context.WithTimeout(ctx, time.Second*30)
......
...@@ -88,7 +88,7 @@ func LoadSignerSetup(ctx *cli.Context) (SignerSetup, error) { ...@@ -88,7 +88,7 @@ func LoadSignerSetup(ctx *cli.Context) (SignerSetup, error) {
// TODO: load from encrypted keystore // TODO: load from encrypted keystore
priv, err := crypto.LoadECDSA(keyFile) priv, err := crypto.LoadECDSA(keyFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read batch submitter key: %v", err) return nil, fmt.Errorf("failed to read batch submitter key: %w", err)
} }
return &PreparedSigner{Signer: NewLocalSigner(priv)}, nil return &PreparedSigner{Signer: NewLocalSigner(priv)}, nil
......
...@@ -172,7 +172,7 @@ func encodeDeposits(deposits []*types.DepositTx) (out []eth.Data, err error) { ...@@ -172,7 +172,7 @@ func encodeDeposits(deposits []*types.DepositTx) (out []eth.Data, err error) {
for i, tx := range deposits { for i, tx := range deposits {
opaqueTx, err := types.NewTx(tx).MarshalBinary() opaqueTx, err := types.NewTx(tx).MarshalBinary()
if err != nil { if err != nil {
return nil, fmt.Errorf("bad deposit %d: %v", i, err) return nil, fmt.Errorf("bad deposit %d: %w", i, err)
} }
out = append(out, opaqueTx) out = append(out, opaqueTx)
} }
......
...@@ -258,16 +258,16 @@ func (eq *EngineQueue) tryNextUnsafePayload(ctx context.Context) error { ...@@ -258,16 +258,16 @@ func (eq *EngineQueue) tryNextUnsafePayload(ctx context.Context) error {
} }
if fcRes.PayloadStatus.Status != eth.ExecutionValid { if fcRes.PayloadStatus.Status != eth.ExecutionValid {
eq.unsafePayloads.Pop() eq.unsafePayloads.Pop()
return NewTemporaryError(fmt.Errorf("cannot prepare unsafe chain for new payload: new - %v; parent: %v; err: %v", return NewTemporaryError(fmt.Errorf("cannot prepare unsafe chain for new payload: new - %v; parent: %v; err: %w",
first.ID(), first.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))) first.ID(), first.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus)))
} }
status, err := eq.engine.NewPayload(ctx, first) status, err := eq.engine.NewPayload(ctx, first)
if err != nil { if err != nil {
return NewTemporaryError(fmt.Errorf("failed to update insert payload: %v", err)) return NewTemporaryError(fmt.Errorf("failed to update insert payload: %w", err))
} }
if status.Status != eth.ExecutionValid { if status.Status != eth.ExecutionValid {
eq.unsafePayloads.Pop() eq.unsafePayloads.Pop()
return NewTemporaryError(fmt.Errorf("cannot process unsafe payload: new - %v; parent: %v; err: %v", return NewTemporaryError(fmt.Errorf("cannot process unsafe payload: new - %v; parent: %v; err: %w",
first.ID(), first.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))) first.ID(), first.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus)))
} }
eq.unsafeHead = ref eq.unsafeHead = ref
...@@ -302,7 +302,7 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error ...@@ -302,7 +302,7 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error
payload, err := eq.engine.PayloadByNumber(ctx, eq.safeHead.Number+1) payload, err := eq.engine.PayloadByNumber(ctx, eq.safeHead.Number+1)
if err != nil { if err != nil {
return NewTemporaryError(fmt.Errorf("failed to get existing unsafe payload to compare against derived attributes from L1: %v", err)) return NewTemporaryError(fmt.Errorf("failed to get existing unsafe payload to compare against derived attributes from L1: %w", err))
} }
if err := AttributesMatchBlock(eq.safeAttributes[0], eq.safeHead.Hash, payload); err != nil { if err := AttributesMatchBlock(eq.safeAttributes[0], eq.safeHead.Hash, payload); err != nil {
eq.log.Warn("L2 reorg: existing unsafe block does not match derived attributes from L1", "err", err) eq.log.Warn("L2 reorg: existing unsafe block does not match derived attributes from L1", "err", err)
...@@ -311,7 +311,7 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error ...@@ -311,7 +311,7 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error
} }
ref, err := PayloadToBlockRef(payload, &eq.cfg.Genesis) ref, err := PayloadToBlockRef(payload, &eq.cfg.Genesis)
if err != nil { if err != nil {
return NewResetError(fmt.Errorf("failed to decode L2 block ref from payload: %v", err)) return NewResetError(fmt.Errorf("failed to decode L2 block ref from payload: %w", err))
} }
eq.safeHead = ref eq.safeHead = ref
eq.metrics.RecordL2Ref("l2_safe", ref) eq.metrics.RecordL2Ref("l2_safe", ref)
...@@ -364,7 +364,7 @@ func (eq *EngineQueue) forceNextSafeAttributes(ctx context.Context) error { ...@@ -364,7 +364,7 @@ func (eq *EngineQueue) forceNextSafeAttributes(ctx context.Context) error {
} }
ref, err := PayloadToBlockRef(payload, &eq.cfg.Genesis) ref, err := PayloadToBlockRef(payload, &eq.cfg.Genesis)
if err != nil { if err != nil {
return NewTemporaryError(fmt.Errorf("failed to decode L2 block ref from payload: %v", err)) return NewTemporaryError(fmt.Errorf("failed to decode L2 block ref from payload: %w", err))
} }
eq.safeHead = ref eq.safeHead = ref
eq.unsafeHead = ref eq.unsafeHead = ref
...@@ -399,7 +399,7 @@ func (eq *EngineQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error ...@@ -399,7 +399,7 @@ func (eq *EngineQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error
} }
l1Origin, err := l1Fetcher.L1BlockRefByHash(ctx, safe.L1Origin.Hash) l1Origin, err := l1Fetcher.L1BlockRefByHash(ctx, safe.L1Origin.Hash)
if err != nil { if err != nil {
return NewTemporaryError(fmt.Errorf("failed to fetch the new L1 progress: origin: %v; err: %v", safe.L1Origin, err)) return NewTemporaryError(fmt.Errorf("failed to fetch the new L1 progress: origin: %v; err: %w", safe.L1Origin, err))
} }
if safe.Time < l1Origin.Time { if safe.Time < l1Origin.Time {
return NewResetError(fmt.Errorf("cannot reset block derivation to start at L2 block %s with time %d older than its L1 origin %s with time %d, time invariant is broken", return NewResetError(fmt.Errorf("cannot reset block derivation to start at L2 block %s with time %d older than its L1 origin %s with time %d, time invariant is broken",
......
...@@ -120,12 +120,12 @@ func L1InfoDeposit(seqNumber uint64, block eth.BlockInfo) (*types.DepositTx, err ...@@ -120,12 +120,12 @@ func L1InfoDeposit(seqNumber uint64, block eth.BlockInfo) (*types.DepositTx, err
func L1InfoDepositBytes(seqNumber uint64, l1Info eth.BlockInfo) ([]byte, error) { func L1InfoDepositBytes(seqNumber uint64, l1Info eth.BlockInfo) ([]byte, error) {
dep, err := L1InfoDeposit(seqNumber, l1Info) dep, err := L1InfoDeposit(seqNumber, l1Info)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create L1 info tx: %v", err) return nil, fmt.Errorf("failed to create L1 info tx: %w", err)
} }
l1Tx := types.NewTx(dep) l1Tx := types.NewTx(dep)
opaqueL1Tx, err := l1Tx.MarshalBinary() opaqueL1Tx, err := l1Tx.MarshalBinary()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode L1 info tx: %v", err) return nil, fmt.Errorf("failed to encode L1 info tx: %w", err)
} }
return opaqueL1Tx, nil return opaqueL1Tx, nil
} }
...@@ -25,14 +25,14 @@ func PayloadToBlockRef(payload *eth.ExecutionPayload, genesis *rollup.Genesis) ( ...@@ -25,14 +25,14 @@ func PayloadToBlockRef(payload *eth.ExecutionPayload, genesis *rollup.Genesis) (
} }
var tx types.Transaction var tx types.Transaction
if err := tx.UnmarshalBinary(payload.Transactions[0]); err != nil { if err := tx.UnmarshalBinary(payload.Transactions[0]); err != nil {
return eth.L2BlockRef{}, fmt.Errorf("failed to decode first tx to read l1 info from: %v", err) return eth.L2BlockRef{}, fmt.Errorf("failed to decode first tx to read l1 info from: %w", err)
} }
if tx.Type() != types.DepositTxType { if tx.Type() != types.DepositTxType {
return eth.L2BlockRef{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type()) return eth.L2BlockRef{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type())
} }
info, err := L1InfoDepositTxData(tx.Data()) info, err := L1InfoDepositTxData(tx.Data())
if err != nil { if err != nil {
return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %w", err)
} }
l1Origin = eth.BlockID{Hash: info.BlockHash, Number: info.Number} l1Origin = eth.BlockID{Hash: info.BlockHash, Number: info.Number}
sequenceNumber = info.SequenceNumber sequenceNumber = info.SequenceNumber
......
...@@ -40,22 +40,22 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { ...@@ -40,22 +40,22 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
p2pSignerSetup, err := p2p.LoadSignerSetup(ctx) p2pSignerSetup, err := p2p.LoadSignerSetup(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load p2p signer: %v", err) return nil, fmt.Errorf("failed to load p2p signer: %w", err)
} }
p2pConfig, err := p2p.NewConfig(ctx) p2pConfig, err := p2p.NewConfig(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load p2p config: %v", err) return nil, fmt.Errorf("failed to load p2p config: %w", err)
} }
l1Endpoint, err := NewL1EndpointConfig(ctx) l1Endpoint, err := NewL1EndpointConfig(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load l1 endpoint info: %v", err) return nil, fmt.Errorf("failed to load l1 endpoint info: %w", err)
} }
l2Endpoint, err := NewL2EndpointConfig(ctx, log) l2Endpoint, err := NewL2EndpointConfig(ctx, log)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load l2 endpoints info: %v", err) return nil, fmt.Errorf("failed to load l2 endpoints info: %w", err)
} }
cfg := &node.Config{ cfg := &node.Config{
...@@ -112,7 +112,7 @@ func NewL2EndpointConfig(ctx *cli.Context, log log.Logger) (*node.L2EndpointConf ...@@ -112,7 +112,7 @@ func NewL2EndpointConfig(ctx *cli.Context, log log.Logger) (*node.L2EndpointConf
} else { } else {
log.Warn("Failed to read JWT secret from file, generating a new one now. Configure L2 geth with --authrpc.jwt-secret=" + fmt.Sprintf("%q", fileName)) log.Warn("Failed to read JWT secret from file, generating a new one now. Configure L2 geth with --authrpc.jwt-secret=" + fmt.Sprintf("%q", fileName))
if _, err := io.ReadFull(rand.Reader, secret[:]); err != nil { if _, err := io.ReadFull(rand.Reader, secret[:]); err != nil {
return nil, fmt.Errorf("failed to generate jwt secret: %v", err) return nil, fmt.Errorf("failed to generate jwt secret: %w", err)
} }
if err := os.WriteFile(fileName, []byte(hexutil.Encode(secret[:])), 0600); err != nil { if err := os.WriteFile(fileName, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
return nil, err return nil, err
...@@ -137,13 +137,13 @@ func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) { ...@@ -137,13 +137,13 @@ func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) {
rollupConfigPath := ctx.GlobalString(flags.RollupConfig.Name) rollupConfigPath := ctx.GlobalString(flags.RollupConfig.Name)
file, err := os.Open(rollupConfigPath) file, err := os.Open(rollupConfigPath)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read rollup config: %v", err) return nil, fmt.Errorf("failed to read rollup config: %w", err)
} }
defer file.Close() defer file.Close()
var rollupConfig rollup.Config var rollupConfig rollup.Config
if err := json.NewDecoder(file).Decode(&rollupConfig); err != nil { if err := json.NewDecoder(file).Decode(&rollupConfig); err != nil {
return nil, fmt.Errorf("failed to decode rollup config: %v", err) return nil, fmt.Errorf("failed to decode rollup config: %w", err)
} }
return &rollupConfig, nil return &rollupConfig, nil
} }
......
...@@ -17,7 +17,7 @@ test: ...@@ -17,7 +17,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E asciicheck,goimports,misspell ./... golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is"
.PHONY: \ .PHONY: \
clean \ clean \
......
...@@ -168,12 +168,12 @@ func (d *Driver) CraftTx( ...@@ -168,12 +168,12 @@ func (d *Driver) CraftTx(
l1Header, err := d.cfg.L1Client.HeaderByNumber(ctx, nil) l1Header, err := d.cfg.L1Client.HeaderByNumber(ctx, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("error resolving checkpoint block: %v", err) return nil, fmt.Errorf("error resolving checkpoint block: %w", err)
} }
l2Header, err := d.cfg.L2Client.HeaderByNumber(ctx, nextCheckpointBlock) l2Header, err := d.cfg.L2Client.HeaderByNumber(ctx, nextCheckpointBlock)
if err != nil { if err != nil {
return nil, fmt.Errorf("error resolving checkpoint block: %v", err) return nil, fmt.Errorf("error resolving checkpoint block: %w", err)
} }
if l2Header.Number.Cmp(nextCheckpointBlock) != 0 { if l2Header.Number.Cmp(nextCheckpointBlock) != 0 {
......
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