Skip to content

Commit

Permalink
feat: validate chain id
Browse files Browse the repository at this point in the history
  • Loading branch information
torives committed Mar 12, 2024
1 parent a18e8f0 commit f5c29bc
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- Added verification to ensure CARTESI_BLOCKCHAIN_ID matches the id returned from the Ethereum node

## Changed

- Changed CARTESI_BLOCKCHAIN_ID type from int to uint

## [1.3.0] 2024-02-09

### Added
Expand Down
46 changes: 46 additions & 0 deletions cmd/cartesi-rollups-node/chainid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package main

import (
"context"
"fmt"
"time"

"github.com/cartesi/rollups-node/internal/config"
"github.com/ethereum/go-ethereum/ethclient"
)

const defaultTimeout = 3 * time.Second

// Checks if the chain id from the configuration matches the chain id reported
// by the Ethereum node. If they don't, it returns an error.
func validateChainId(ctx context.Context, chainId uint64, ethereumNodeAddr string) error {
remoteChainId, err := getChainId(ctx, ethereumNodeAddr)
if err != nil {
config.ErrorLogger.Printf("Couldn't validate chainId: %v\n", err)
} else if chainId != remoteChainId {
return fmt.Errorf(
"chainId mismatch. Expected %v but Ethereum node returned %v",
chainId,
remoteChainId,
)
}
return nil
}

func getChainId(ctx context.Context, ethereumNodeAddr string) (uint64, error) {
ctx, cancel := context.WithTimeout(ctx, defaultTimeout)
defer cancel()

client, err := ethclient.Dial(ethereumNodeAddr)
if err != nil {
return 0, fmt.Errorf("Failed to create RPC client: %v", err)
}
chainId, err := client.ChainID(ctx)
if err != nil {
return 0, fmt.Errorf("Failed to get chain id: %v", err)
}
return chainId.Uint64(), nil
}
48 changes: 48 additions & 0 deletions cmd/cartesi-rollups-node/chainid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package main

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/suite"
)

type ValidateChainIdSuite struct {
suite.Suite
}

func TestValidateChainId(t *testing.T) {
suite.Run(t, new(ValidateChainIdSuite))
}

func (s *ValidateChainIdSuite) TestItFailsIfChainIdsDoNotMatch() {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintln(w, `{"jsonrpc":"2.0","id":67,"result":"0x7a69"}`)
}))
defer ts.Close()
localChainId := uint64(11111)

err := validateChainId(context.Background(), localChainId, ts.URL)

s.NotNil(err)
}

func (s *ValidateChainIdSuite) TestItReturnsNilIfChainIdsMatch() {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintln(w, `{"jsonrpc":"2.0","id":67,"result":"0x7a69"}`)
}))
defer ts.Close()
localChainId := uint64(31337)

err := validateChainId(context.Background(), localChainId, ts.URL)

s.Nil(err)
}
8 changes: 8 additions & 0 deletions cmd/cartesi-rollups-node/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ func main() {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()

if err := validateChainId(
ctx,
config.GetCartesiBlockchainId(),
config.GetCartesiBlockchainHttpEndpoint(),
); err != nil {
config.ErrorLogger.Fatal(err)
}

sunodoValidatorEnabled := config.GetCartesiExperimentalSunodoValidatorEnabled()
if !sunodoValidatorEnabled {
// add Redis first
Expand Down

0 comments on commit f5c29bc

Please sign in to comment.