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

Commit

Permalink
Merge pull request #301 from hrharder/development
Browse files Browse the repository at this point in the history
core: implement network ID detection check on startup
  • Loading branch information
albrow authored Jul 24, 2019
2 parents e225c27 + 09e2267 commit ee09eea
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 12 deletions.
28 changes: 28 additions & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ func New(config Config) (*App, error) {
return nil, err
}

// Check if the DB has been previously intialized with a different networkId
if err = initNetworkID(config.EthereumNetworkID, meshDB); 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 +255,29 @@ func initPrivateKey(path string) (p2pcrypto.PrivKey, error) {
return nil, err
}

func initNetworkID(networkID int, meshDB *meshdb.MeshDB) error {
metadata, err := meshDB.GetMetadata()
if err != nil {
if _, ok := err.(db.NotFoundError); ok {
// No stored metadata found (first startup)
metadata = &meshdb.Metadata{EthereumNetworkID: networkID}
if err := meshDB.SaveMetadata(metadata); err != nil {
return err
}
return nil
}
return err
}

// on subsequent startups, verify we are on the same network
if metadata.EthereumNetworkID != networkID {
err := fmt.Errorf("expected networkID to be %d but got %d", metadata.EthereumNetworkID, networkID)
log.WithError(err).Error("Mesh previously started on different Ethereum network; switch networks or remove DB")
return err
}
return nil
}

func (app *App) Start() error {
go func() {
err := app.node.Start()
Expand Down
29 changes: 29 additions & 0 deletions core/core_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// +build !js

package core

import (
"testing"

"github.com/0xProject/0x-mesh/meshdb"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestEthereumNetworkDetection(t *testing.T) {
meshDB, err := meshdb.NewMeshDB("/tmp/meshdb_testing/" + uuid.New().String())
require.NoError(t, err)

// simulate starting up on mainnet
err = initNetworkID(1, meshDB)
require.NoError(t, err)

// simulate restart on same network
err = initNetworkID(1, meshDB)
require.NoError(t, err)

// should error when attempting to start on different network
err = initNetworkID(2, meshDB)
assert.Error(t, err)
}
65 changes: 53 additions & 12 deletions meshdb/meshdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,20 @@ func (o Order) ID() []byte {
return o.Hash.Bytes()
}

// Metadata is the database representation of MeshDB instance metadata
type Metadata struct {
EthereumNetworkID int
}

// ID returns the id used for the metadata collection (one per DB)
func (m Metadata) ID() []byte {
return []byte{0}
}

// MeshDB instantiates the DB connection and creates all the collections used by the application
type MeshDB struct {
database *db.DB
metadata *MetadataCollection
MiniHeaders *MiniHeadersCollection
Orders *OrdersCollection
}
Expand All @@ -67,6 +78,11 @@ type OrdersCollection struct {
IsRemovedIndex *db.Index
}

// MetadataCollection represents a DB collection used to store instance metadata
type MetadataCollection struct {
*db.Collection
}

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

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

return &MeshDB{
database: database,
metadata: metadata,
MiniHeaders: miniHeaders,
Orders: orders,
}, nil
Expand Down Expand Up @@ -170,6 +192,14 @@ 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
}
return &MetadataCollection{col}, nil
}

// Close closes the database connection
func (m *MeshDB) Close() {
m.database.Close()
Expand All @@ -179,8 +209,7 @@ func (m *MeshDB) Close() {
func (m *MeshDB) FindAllMiniHeadersSortedByNumber() ([]*MiniHeader, error) {
miniHeaders := []*MiniHeader{}
query := m.MiniHeaders.NewQuery(m.MiniHeaders.numberIndex.All())
err := query.Run(&miniHeaders)
if err != nil {
if err := query.Run(&miniHeaders); err != nil {
return nil, err
}
return miniHeaders, nil
Expand All @@ -191,8 +220,7 @@ func (m *MeshDB) FindAllMiniHeadersSortedByNumber() ([]*MiniHeader, error) {
func (m *MeshDB) FindLatestMiniHeader() (*MiniHeader, error) {
miniHeaders := []*MiniHeader{}
query := m.MiniHeaders.NewQuery(m.MiniHeaders.numberIndex.All()).Reverse().Max(1)
err := query.Run(&miniHeaders)
if err != nil {
if err := query.Run(&miniHeaders); err != nil {
return nil, err
}
if len(miniHeaders) == 0 {
Expand All @@ -206,8 +234,7 @@ func (m *MeshDB) FindOrdersByMakerAddress(makerAddress common.Address) ([]*Order
prefix := []byte(makerAddress.Hex() + "|")
filter := m.Orders.MakerAddressTokenAddressTokenIDIndex.PrefixFilter(prefix)
orders := []*Order{}
err := m.Orders.NewQuery(filter).Run(&orders)
if err != nil {
if err := m.Orders.NewQuery(filter).Run(&orders); err != nil {
return nil, err
}
return orders, nil
Expand All @@ -222,8 +249,7 @@ func (m *MeshDB) FindOrdersByMakerAddressTokenAddressAndTokenID(makerAddress, to
}
filter := m.Orders.MakerAddressTokenAddressTokenIDIndex.PrefixFilter(prefix)
orders := []*Order{}
err := m.Orders.NewQuery(filter).Run(&orders)
if err != nil {
if err := m.Orders.NewQuery(filter).Run(&orders); err != nil {
return nil, err
}
return orders, nil
Expand All @@ -240,8 +266,7 @@ func (m *MeshDB) FindOrdersByMakerAddressAndMaxSalt(makerAddress common.Address,
limit := []byte(fmt.Sprintf("%s|%080s", makerAddress.Hex(), saltPlusOne.String()))
filter := m.Orders.MakerAddressAndSaltIndex.RangeFilter(start, limit)
orders := []*Order{}
err := m.Orders.NewQuery(filter).Run(&orders)
if err != nil {
if err := m.Orders.NewQuery(filter).Run(&orders); err != nil {
return nil, err
}
return orders, nil
Expand All @@ -254,13 +279,29 @@ func (m *MeshDB) FindOrdersLastUpdatedBefore(lastUpdated time.Time) ([]*Order, e
limit := []byte(lastUpdated.UTC().Format(time.RFC3339Nano))
filter := m.Orders.LastUpdatedIndex.RangeFilter(start, limit)
orders := []*Order{}
err := m.Orders.NewQuery(filter).Run(&orders)
if err != nil {
if err := m.Orders.NewQuery(filter).Run(&orders); err != nil {
return nil, err
}
return orders, nil
}

// GetMetadata returns the metadata (or a db.NotFoundError if no metadata has been found).
func (m *MeshDB) GetMetadata() (*Metadata, error) {
var metadata Metadata
if err := m.metadata.FindByID([]byte{0}, &metadata); err != nil {
return nil, err
}
return &metadata, nil
}

// SaveMetadata inserts the metadata into the database.
func (m *MeshDB) SaveMetadata(metadata *Metadata) error {
if err := m.metadata.Insert(metadata); err != nil {
return err
}
return nil
}

type singleAssetData struct {
Address common.Address
TokenID *big.Int
Expand Down

0 comments on commit ee09eea

Please sign in to comment.