diff --git a/cmd/gossamer/configcmd.go b/cmd/gossamer/configcmd.go index cf80d00512e..b188151b4e6 100644 --- a/cmd/gossamer/configcmd.go +++ b/cmd/gossamer/configcmd.go @@ -26,6 +26,7 @@ import ( "github.com/ChainSafe/gossamer/cmd/utils" "github.com/ChainSafe/gossamer/common" cfg "github.com/ChainSafe/gossamer/config" + "github.com/ChainSafe/gossamer/config/genesis" "github.com/ChainSafe/gossamer/core" "github.com/ChainSafe/gossamer/dot" "github.com/ChainSafe/gossamer/internal/api" @@ -182,7 +183,7 @@ func setP2pConfig(ctx *cli.Context, fig *cfg.P2pCfg) { } // createP2PService starts a p2p network layer from provided config -func createP2PService(fig *cfg.Config, gendata *trie.Genesis) (*p2p.Service, chan []byte) { +func createP2PService(fig *cfg.Config, gendata *genesis.GenesisData) (*p2p.Service, chan []byte) { config := p2p.Config{ BootstrapNodes: append(fig.P2p.BootstrapNodes, common.BytesToStringArray(gendata.Bootnodes)...), Port: fig.P2p.Port, diff --git a/cmd/gossamer/configcmd_test.go b/cmd/gossamer/configcmd_test.go index 978fc033046..f1a898e3c38 100644 --- a/cmd/gossamer/configcmd_test.go +++ b/cmd/gossamer/configcmd_test.go @@ -33,7 +33,6 @@ import ( "github.com/ChainSafe/gossamer/config/genesis" "github.com/ChainSafe/gossamer/internal/api" "github.com/ChainSafe/gossamer/polkadb" - "github.com/ChainSafe/gossamer/trie" log "github.com/ChainSafe/log15" "github.com/urfave/cli" ) @@ -245,8 +244,8 @@ func TestSetGlobalConfig(t *testing.T) { } func TestCreateP2PService(t *testing.T) { - gendata := &trie.Genesis{ - ProtocolId: []byte("gossamer"), + gendata := &genesis.GenesisData{ + ProtocolId: "gossamer", } srv, _ := createP2PService(cfg.DefaultConfig(), gendata) diff --git a/cmd/gossamer/genesis.go b/cmd/gossamer/genesis.go index 7b058c66215..b86126b5093 100644 --- a/cmd/gossamer/genesis.go +++ b/cmd/gossamer/genesis.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/ChainSafe/gossamer/cmd/utils" + "github.com/ChainSafe/gossamer/common" cfg "github.com/ChainSafe/gossamer/config" "github.com/ChainSafe/gossamer/config/genesis" "github.com/ChainSafe/gossamer/polkadb" @@ -20,19 +21,21 @@ func loadGenesis(ctx *cli.Context) error { // read genesis file fp := getGenesisPath(ctx) - gen, err := genesis.LoadGenesisJsonFile(fp) + log.Debug("Loading genesis", "genesisfile", fp, "datadir", fig.Global.DataDir) + + gen, err := genesis.LoadGenesisData(fp) if err != nil { return err } + log.Info("🕸\t Initializing node", "name", gen.Name, "id", gen.Id, "protocolID", gen.ProtocolId, "bootnodes", common.BytesToStringArray(gen.Bootnodes)) + // DB: Create database dir and initialize stateDB and blockDB dbSrv, err := polkadb.NewDbService(fig.Global.DataDir) if err != nil { return err } - log.Info("🕸\t Initializing node", "genesisfile", fp, "datadir", fig.Global.DataDir, "name", gen.Name, "id", gen.Id, "protocolID", gen.ProtocolId, "bootnodes", gen.Bootnodes) - err = dbSrv.Start() if err != nil { return err @@ -52,7 +55,7 @@ func loadGenesis(ctx *cli.Context) error { // create and load storage trie with initial genesis state t := trie.NewEmptyTrie(tdb) - err = t.Load(gen.Genesis.Raw) + err = t.Load(gen.GenesisFields().Raw) if err != nil { return fmt.Errorf("cannot load trie with initial state: %s", err) } @@ -60,17 +63,16 @@ func loadGenesis(ctx *cli.Context) error { // write initial genesis data to DB err = t.StoreInDB() if err != nil { - return err + return fmt.Errorf("cannot store genesis data in db: %s", err) } err = t.StoreHash() if err != nil { - return err + return fmt.Errorf("cannot store genesis hash in db: %s", err) } // store node name, ID, p2p protocol, bootnodes in DB - tgen := trie.NewGenesisFromData(gen) - return t.Db().StoreGenesisData(tgen) + return t.Db().StoreGenesisData(gen) } // getGenesisPath gets the path to the genesis file diff --git a/cmd/gossamer/genesis_test.go b/cmd/gossamer/genesis_test.go index 4ae5235cbf2..336f1bca730 100644 --- a/cmd/gossamer/genesis_test.go +++ b/cmd/gossamer/genesis_test.go @@ -60,10 +60,10 @@ func TestStoreGenesisInfo(t *testing.T) { t.Fatal(err) } - expected := &trie.Genesis{ - Name: []byte(tmpGenesis.Name), - Id: []byte(tmpGenesis.Id), - ProtocolId: []byte(tmpGenesis.ProtocolId), + expected := &genesis.GenesisData{ + Name: tmpGenesis.Name, + Id: tmpGenesis.Id, + ProtocolId: tmpGenesis.ProtocolId, Bootnodes: common.StringArrayToBytes(tmpGenesis.Bootnodes), } diff --git a/codec/decode.go b/codec/decode.go index ef2347b69f4..3abdac21031 100644 --- a/codec/decode.go +++ b/codec/decode.go @@ -383,136 +383,139 @@ func (sd *Decoder) DecodeTuple(t interface{}) (interface{}, error) { for i := 0; i < v.NumField(); i++ { // get the field value at i field := v.Field(i) - fieldValue := field.Addr().Interface() - switch v.Field(i).Interface().(type) { - case byte: - b := make([]byte, 1) - _, err = sd.Reader.Read(b) - - ptr := fieldValue.(*byte) - *ptr = b[0] - case []byte: - o, err = sd.DecodeByteArray() - if err != nil { - break - } - - // get the pointer to the value and set the value - ptr := fieldValue.(*[]byte) - *ptr = o.([]byte) - case int8: - o, err = sd.DecodeFixedWidthInt(int8(0)) - if err != nil { - break - } - - ptr := fieldValue.(*int8) - *ptr = o.(int8) - case int16: - o, err = sd.DecodeFixedWidthInt(int16(0)) - if err != nil { - break - } - - ptr := fieldValue.(*int16) - *ptr = o.(int16) - case int32: - o, err = sd.DecodeFixedWidthInt(int32(0)) - if err != nil { - break - } - - ptr := fieldValue.(*int32) - *ptr = o.(int32) - case int64: - o, err = sd.DecodeFixedWidthInt(int64(0)) - if err != nil { - break - } - - ptr := fieldValue.(*int64) - *ptr = o.(int64) - case uint16: - o, err = sd.DecodeFixedWidthInt(uint16(0)) - if err != nil { - break - } - - ptr := fieldValue.(*uint16) - *ptr = o.(uint16) - case uint32: - o, err = sd.DecodeFixedWidthInt(uint32(0)) - if err != nil { - break + if field.CanInterface() { + fieldValue := field.Addr().Interface() + + switch v.Field(i).Interface().(type) { + case byte: + b := make([]byte, 1) + _, err = sd.Reader.Read(b) + + ptr := fieldValue.(*byte) + *ptr = b[0] + case []byte: + o, err = sd.DecodeByteArray() + if err != nil { + break + } + + // get the pointer to the value and set the value + ptr := fieldValue.(*[]byte) + *ptr = o.([]byte) + case int8: + o, err = sd.DecodeFixedWidthInt(int8(0)) + if err != nil { + break + } + + ptr := fieldValue.(*int8) + *ptr = o.(int8) + case int16: + o, err = sd.DecodeFixedWidthInt(int16(0)) + if err != nil { + break + } + + ptr := fieldValue.(*int16) + *ptr = o.(int16) + case int32: + o, err = sd.DecodeFixedWidthInt(int32(0)) + if err != nil { + break + } + + ptr := fieldValue.(*int32) + *ptr = o.(int32) + case int64: + o, err = sd.DecodeFixedWidthInt(int64(0)) + if err != nil { + break + } + + ptr := fieldValue.(*int64) + *ptr = o.(int64) + case uint16: + o, err = sd.DecodeFixedWidthInt(uint16(0)) + if err != nil { + break + } + + ptr := fieldValue.(*uint16) + *ptr = o.(uint16) + case uint32: + o, err = sd.DecodeFixedWidthInt(uint32(0)) + if err != nil { + break + } + + ptr := fieldValue.(*uint32) + *ptr = o.(uint32) + case uint64: + o, err = sd.DecodeFixedWidthInt(uint64(0)) + if err != nil { + break + } + + ptr := fieldValue.(*uint64) + *ptr = o.(uint64) + case int: + o, err = sd.DecodeFixedWidthInt(int(0)) + if err != nil { + break + } + + ptr := fieldValue.(*int) + *ptr = o.(int) + case uint: + o, err = sd.DecodeFixedWidthInt(uint(0)) + if err != nil { + break + } + + ptr := fieldValue.(*uint) + *ptr = o.(uint) + case bool: + o, err = sd.DecodeBool() + if err != nil { + break + } + + ptr := fieldValue.(*bool) + *ptr = o.(bool) + case *big.Int: + o, err = sd.DecodeBigInt() + if err != nil { + break + } + + ptr := fieldValue.(**big.Int) + *ptr = o.(*big.Int) + case common.Hash: + b := make([]byte, 32) + _, err = sd.Reader.Read(b) + + ptr := fieldValue.(*common.Hash) + *ptr = common.NewHash(b) + case string: + o, err = sd.DecodeByteArray() + if err != nil { + break + } + + // get the pointer to the value and set the value + ptr := fieldValue.(*string) + *ptr = string(o.([]byte)) + default: + _, err = sd.Decode(v.Field(i).Interface()) + if err != nil { + break + } } - ptr := fieldValue.(*uint32) - *ptr = o.(uint32) - case uint64: - o, err = sd.DecodeFixedWidthInt(uint64(0)) if err != nil { break } - - ptr := fieldValue.(*uint64) - *ptr = o.(uint64) - case int: - o, err = sd.DecodeFixedWidthInt(int(0)) - if err != nil { - break - } - - ptr := fieldValue.(*int) - *ptr = o.(int) - case uint: - o, err = sd.DecodeFixedWidthInt(uint(0)) - if err != nil { - break - } - - ptr := fieldValue.(*uint) - *ptr = o.(uint) - case bool: - o, err = sd.DecodeBool() - if err != nil { - break - } - - ptr := fieldValue.(*bool) - *ptr = o.(bool) - case *big.Int: - o, err = sd.DecodeBigInt() - if err != nil { - break - } - - ptr := fieldValue.(**big.Int) - *ptr = o.(*big.Int) - case common.Hash: - b := make([]byte, 32) - _, err = sd.Reader.Read(b) - - ptr := fieldValue.(*common.Hash) - *ptr = common.NewHash(b) - case string: - o, err = sd.DecodeByteArray() - if err != nil { - break - } - - // get the pointer to the value and set the value - ptr := fieldValue.(*string) - *ptr = string(o.([]byte)) - default: - _, err = sd.Decode(v.Field(i).Interface()) - if err != nil { - break - } - } - - if err != nil { - break } } diff --git a/codec/encode.go b/codec/encode.go index 051ad9d333a..5da5be05892 100644 --- a/codec/encode.go +++ b/codec/encode.go @@ -233,10 +233,12 @@ func (se *Encoder) encodeTuple(t interface{}) (bytesEncoded int, err error) { v = reflect.ValueOf(t) } - values := make([]interface{}, v.NumField()) + values := make([]interface{}, 0) for i := 0; i < v.NumField(); i++ { - values[i] = v.Field(i).Interface() + if v.Field(i).CanInterface() { + values = append(values, v.Field(i).Interface()) + } } for _, item := range values { diff --git a/config/genesis/genesis.go b/config/genesis/genesis.go index 0d07d511903..e91ed54a2f9 100644 --- a/config/genesis/genesis.go +++ b/config/genesis/genesis.go @@ -4,6 +4,8 @@ import ( "encoding/json" "io/ioutil" "path/filepath" + + "github.com/ChainSafe/gossamer/common" ) // Genesis stores the data parsed from the genesis configuration file @@ -15,6 +17,15 @@ type Genesis struct { Genesis GenesisFields } +// Genesis stores the data parsed from the genesis configuration file +type GenesisData struct { + Name string + Id string + Bootnodes [][]byte + ProtocolId string + genesisFields GenesisFields +} + type GenesisFields struct { Raw map[string]string } @@ -35,3 +46,22 @@ func LoadGenesisJsonFile(file string) (*Genesis, error) { err = json.Unmarshal(data, g) return g, err } + +func LoadGenesisData(file string) (*GenesisData, error) { + g, err := LoadGenesisJsonFile(file) + if err != nil { + return nil, err + } + + return &GenesisData{ + Name: g.Name, + Id: g.Id, + Bootnodes: common.StringArrayToBytes(g.Bootnodes), + ProtocolId: g.ProtocolId, + genesisFields: g.Genesis, + }, nil +} + +func (g *GenesisData) GenesisFields() GenesisFields { + return g.genesisFields +} diff --git a/trie/database.go b/trie/database.go index ea26cd7b4e4..467e27cd8b7 100644 --- a/trie/database.go +++ b/trie/database.go @@ -69,53 +69,29 @@ func (db *Database) LoadLatestHash() (common.Hash, error) { return common.NewHash(hashbytes), nil } -type Genesis struct { - Name []byte - Id []byte - ProtocolId []byte - Bootnodes [][]byte -} - -func NewGenesisFromData(gen *genesis.Genesis) *Genesis { - bnodes := common.StringArrayToBytes(gen.Bootnodes) - return &Genesis{ - Name: []byte(gen.Name), - Id: []byte(gen.Id), - ProtocolId: []byte(gen.ProtocolId), - Bootnodes: bnodes, - } -} - -func (db *Database) StoreGenesisData(gen *Genesis) error { - data := &Genesis{ - Name: gen.Name, - Id: gen.Id, - Bootnodes: gen.Bootnodes, - ProtocolId: gen.ProtocolId, - } - - enc, err := scale.Encode(data) +func (db *Database) StoreGenesisData(gen *genesis.GenesisData) error { + enc, err := scale.Encode(gen) if err != nil { - return err + return fmt.Errorf("cannot scale encode genesis data: %s", err) } return db.Store(GenesisDataKey, enc) } -func (db *Database) LoadGenesisData() (*Genesis, error) { +func (db *Database) LoadGenesisData() (*genesis.GenesisData, error) { enc, err := db.Load(GenesisDataKey) if err != nil { return nil, err } - data, err := scale.Decode(enc, &Genesis{ + data, err := scale.Decode(enc, &genesis.GenesisData{ Bootnodes: [][]byte{{}}, }) if err != nil { return nil, err } - return data.(*Genesis), nil + return data.(*genesis.GenesisData), nil } // Encode traverses the trie recursively, encodes each node, SCALE encodes the encoded node, and appends them all together diff --git a/trie/database_test.go b/trie/database_test.go index 2341e35b9b8..e95fc74b1d9 100644 --- a/trie/database_test.go +++ b/trie/database_test.go @@ -24,6 +24,7 @@ import ( "strings" "testing" + "github.com/ChainSafe/gossamer/config/genesis" db "github.com/ChainSafe/gossamer/polkadb" ) @@ -205,10 +206,10 @@ func TestStoreAndLoadGenesisData(t *testing.T) { defer trie.closeDb() - expected := &Genesis{ - Name: []byte("gossamer"), - Id: []byte("gossamer"), - ProtocolId: []byte("gossamer"), + expected := &genesis.GenesisData{ + Name: "gossamer", + Id: "gossamer", + ProtocolId: "gossamer", Bootnodes: [][]byte{[]byte("noot")}, }