Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

core: implement network ID detection check on startup #301

Merged
merged 12 commits into from
Jul 24, 2019
43 changes: 43 additions & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"encoding/json"
"fmt"
"math/big"
"os"
"path/filepath"
"sync"
Expand Down Expand Up @@ -119,6 +120,12 @@ func New(config Config) (*App, error) {
return nil, err
}

// Check if the DB has been previously intialized with a different networkId
err = initNetworkId(config.EthereumNetworkID, meshDB)
hrharder marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

// Initialize the ETH client, which will be used by various watchers.
ethClient, err := ethclient.Dial(config.EthereumRPCURL)
if err != nil {
Expand Down Expand Up @@ -250,6 +257,42 @@ func initPrivateKey(path string) (p2pcrypto.PrivKey, error) {
return nil, err
}

func initNetworkId(networkID int, db *meshdb.MeshDB) error {
// see if there is already a stored networkID
snapshot, err := db.Metadata.GetSnapshot()
hrharder marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}
hrharder marked this conversation as resolved.
Show resolved Hide resolved

filter := db.Metadata.EthereumNetworkIDIndex.All()
hrharder marked this conversation as resolved.
Show resolved Hide resolved
var metadataCol []*meshdb.Metadata
err = snapshot.NewQuery(filter).Run(&metadataCol)
if err != nil {
return err
}

switch len(metadataCol) {
case 1:
// on subsequent startups, verify we are on the same network
loadedNetworkID := metadataCol[0].EthereumNetworkID.Int64()
if loadedNetworkID != int64(networkID) {
log.Error("Mesh previously started on different Ethereum network; switch networks or remove DB")
hrharder marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("expected networkID to be '%v', got '%v'", networkID, loadedNetworkID)
}
return nil
case 0:
// if this is the first startup, set the networkId in initial metadata
setMetadata := meshdb.Metadata{EthereumNetworkID: big.NewInt(int64(networkID))}
err = db.Metadata.Insert(&setMetadata)
if err != nil {
return err
}
return nil
default:
return fmt.Errorf("Detected more than one 'Metadata' collection (%v); should be one or zero", len(metadataCol))
}
}

func (app *App) Start() error {
go func() {
err := app.node.Start()
Expand Down
38 changes: 38 additions & 0 deletions meshdb/meshdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,22 @@ func (o Order) ID() []byte {
return o.Hash.Bytes()
}

// Metadata is the database representation of MeshDB instance metadata
type Metadata struct {
EthereumNetworkID *big.Int
hrharder marked this conversation as resolved.
Show resolved Hide resolved
}

// ID returns the id used for the metadata collection (one per DB)
func (m Metadata) ID() []byte {
return []byte("metadata")
hrharder marked this conversation as resolved.
Show resolved Hide resolved
}

// MeshDB instantiates the DB connection and creates all the collections used by the application
type MeshDB struct {
database *db.DB
MiniHeaders *MiniHeadersCollection
Orders *OrdersCollection
Metadata *MetadataCollection
}

// MiniHeadersCollection represents a DB collection of mini Ethereum block headers
Expand All @@ -67,6 +78,12 @@ type OrdersCollection struct {
IsRemovedIndex *db.Index
}

// MetadataCollection represents a DB collection used to store instance metadata
type MetadataCollection struct {
*db.Collection
EthereumNetworkIDIndex *db.Index
hrharder marked this conversation as resolved.
Show resolved Hide resolved
}

// NewMeshDB instantiates a new MeshDB instance
func NewMeshDB(path string) (*MeshDB, error) {
database, err := db.Open(path)
Expand All @@ -84,10 +101,16 @@ func NewMeshDB(path string) (*MeshDB, error) {
return nil, err
}

metadata, err := setupMetadata(database)
if err != nil {
return nil, err
}

return &MeshDB{
database: database,
MiniHeaders: miniHeaders,
Orders: orders,
Metadata: metadata,
hrharder marked this conversation as resolved.
Show resolved Hide resolved
}, nil
}

Expand Down Expand Up @@ -170,6 +193,21 @@ func setupMiniHeaders(database *db.DB) (*MiniHeadersCollection, error) {
}, nil
}

func setupMetadata(database *db.DB) (*MetadataCollection, error) {
col, err := database.NewCollection("metadata", &Metadata{})
if err != nil {
return nil, err
}
ethereumNetworkIDIndex := col.AddIndex("ethereumNetworkID", func(m db.Model) []byte {
networkID := m.(*Metadata).EthereumNetworkID
return networkID.Bytes()
})
return &MetadataCollection{
Collection: col,
EthereumNetworkIDIndex: ethereumNetworkIDIndex,
}, nil
}

// Close closes the database connection
func (m *MeshDB) Close() {
m.database.Close()
Expand Down