From fd083776f4aa909535bda58ede3305274c581f41 Mon Sep 17 00:00:00 2001 From: StephenButtolph Date: Thu, 2 Apr 2020 23:43:02 -0400 Subject: [PATCH] Added multiple genesii --- genesis/aliases.go | 78 +++++++++++ genesis/config.go | 100 ++++++++++++++ genesis/genesis.go | 295 +++++++++++----------------------------- genesis/genesis_test.go | 2 +- genesis/network_id.go | 73 ++++++++++ main/params.go | 36 +++-- node/node.go | 99 ++++++++++---- xputtest/main.go | 12 +- 8 files changed, 436 insertions(+), 259 deletions(-) create mode 100644 genesis/aliases.go create mode 100644 genesis/config.go create mode 100644 genesis/network_id.go diff --git a/genesis/aliases.go b/genesis/aliases.go new file mode 100644 index 0000000..41ff25a --- /dev/null +++ b/genesis/aliases.go @@ -0,0 +1,78 @@ +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package genesis + +import ( + "github.com/ava-labs/gecko/ids" + "github.com/ava-labs/gecko/vms/avm" + "github.com/ava-labs/gecko/vms/evm" + "github.com/ava-labs/gecko/vms/nftfx" + "github.com/ava-labs/gecko/vms/platformvm" + "github.com/ava-labs/gecko/vms/propertyfx" + "github.com/ava-labs/gecko/vms/secp256k1fx" + "github.com/ava-labs/gecko/vms/spchainvm" + "github.com/ava-labs/gecko/vms/spdagvm" + "github.com/ava-labs/gecko/vms/timestampvm" +) + +// Aliases returns the default aliases based on the network ID +func Aliases(networkID uint32) (map[string][]string, map[[32]byte][]string, map[[32]byte][]string, error) { + generalAliases := map[string][]string{ + "vm/" + platformvm.ID.String(): []string{"vm/platform"}, + "vm/" + avm.ID.String(): []string{"vm/avm"}, + "vm/" + evm.ID.String(): []string{"vm/evm"}, + "vm/" + spdagvm.ID.String(): []string{"vm/spdag"}, + "vm/" + spchainvm.ID.String(): []string{"vm/spchain"}, + "vm/" + timestampvm.ID.String(): []string{"vm/timestamp"}, + "bc/" + ids.Empty.String(): []string{"P", "platform", "bc/P", "bc/platform"}, + } + chainAliases := map[[32]byte][]string{ + ids.Empty.Key(): []string{"P", "platform"}, + } + vmAliases := map[[32]byte][]string{ + platformvm.ID.Key(): []string{"platform"}, + avm.ID.Key(): []string{"avm"}, + evm.ID.Key(): []string{"evm"}, + spdagvm.ID.Key(): []string{"spdag"}, + spchainvm.ID.Key(): []string{"spchain"}, + timestampvm.ID.Key(): []string{"timestamp"}, + secp256k1fx.ID.Key(): []string{"secp256k1fx"}, + nftfx.ID.Key(): []string{"nftfx"}, + propertyfx.ID.Key(): []string{"propertyfx"}, + } + + genesisBytes, err := Genesis(networkID) + if err != nil { + return nil, nil, nil, err + } + + genesis := &platformvm.Genesis{} // TODO let's not re-create genesis to do aliasing + if err := platformvm.Codec.Unmarshal(genesisBytes, genesis); err != nil { + return nil, nil, nil, err + } + if err := genesis.Initialize(); err != nil { + return nil, nil, nil, err + } + + for _, chain := range genesis.Chains { + switch { + case avm.ID.Equals(chain.VMID): + generalAliases["bc/"+chain.ID().String()] = []string{"X", "avm", "bc/X", "bc/avm"} + chainAliases[chain.ID().Key()] = []string{"X", "avm"} + case evm.ID.Equals(chain.VMID): + generalAliases["bc/"+chain.ID().String()] = []string{"C", "evm", "bc/C", "bc/evm"} + chainAliases[chain.ID().Key()] = []string{"C", "evm"} + case spdagvm.ID.Equals(chain.VMID): + generalAliases["bc/"+chain.ID().String()] = []string{"bc/spdag"} + chainAliases[chain.ID().Key()] = []string{"spdag"} + case spchainvm.ID.Equals(chain.VMID): + generalAliases["bc/"+chain.ID().String()] = []string{"bc/spchain"} + chainAliases[chain.ID().Key()] = []string{"spchain"} + case timestampvm.ID.Equals(chain.VMID): + generalAliases["bc/"+chain.ID().String()] = []string{"bc/timestamp"} + chainAliases[chain.ID().Key()] = []string{"timestamp"} + } + } + return generalAliases, chainAliases, vmAliases, nil +} diff --git a/genesis/config.go b/genesis/config.go new file mode 100644 index 0000000..bd08298 --- /dev/null +++ b/genesis/config.go @@ -0,0 +1,100 @@ +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package genesis + +import ( + "github.com/ava-labs/gecko/ids" +) + +// Note that since an AVA network has exactly one Platform Chain, +// and the Platform Chain defines the genesis state of the network +// (who is staking, which chains exist, etc.), defining the genesis +// state of the Platform Chain is the same as defining the genesis +// state of the network. + +// Config contains the genesis addresses used to construct a genesis +type Config struct { + MintAddresses, FundedAddresses, StakerIDs []string + ParsedMintAddresses, ParsedFundedAddresses, ParsedStakerIDs []ids.ShortID +} + +func (c *Config) init() error { + c.ParsedMintAddresses = nil + for _, addrStr := range c.MintAddresses { + addr, err := ids.ShortFromString(addrStr) + if err != nil { + return err + } + c.ParsedMintAddresses = append(c.ParsedMintAddresses, addr) + } + c.ParsedFundedAddresses = nil + for _, addrStr := range c.FundedAddresses { + addr, err := ids.ShortFromString(addrStr) + if err != nil { + return err + } + c.ParsedFundedAddresses = append(c.ParsedFundedAddresses, addr) + } + c.ParsedStakerIDs = nil + for _, addrStr := range c.StakerIDs { + addr, err := ids.ShortFromString(addrStr) + if err != nil { + return err + } + c.ParsedStakerIDs = append(c.ParsedStakerIDs, addr) + } + return nil +} + +// Hard coded genesis constants +var ( + CascadeConfig = Config{ + MintAddresses: []string{ + "95YUFjhDG892VePMzpwKF9JzewGKvGRi3", + }, + FundedAddresses: []string{ + "9uKvvA7E35QCwLvAaohXTCfFejbf3Rv17", + "JLrYNMYXANGj43BfWXBxMMAEenUBp1Sbn", + "7TUTzwrU6nbZtWHjTHEpdneUvjKBxb3EM", + "77mPUXBdQKwQpPoX6rckCZGLGGdkuG1G6", + "4gGWdFZ4Gax1B466YKXyKRRpWLb42Afdt", + "CKTkzAPsRxCreyiDTnjGxLmjMarxF28fi", + "4ABm9gFHVtsNdcKSd1xsacFkGneSgzpaa", + "DpL8PTsrjtLzv5J8LL3D2A6YcnCTqrNH9", + "ZdhZv6oZrmXLyFDy6ovXAu6VxmbTsT2h", + "6cesTteH62Y5mLoDBUASaBvCXuL2AthL", + }, + StakerIDs: []string{ + "NX4zVkuiRJZYe6Nzzav7GXN3TakUet3Co", + "CMsa8cMw4eib1Hb8GG4xiUKAq5eE1BwUX", + "DsMP6jLhi1MkDVc3qx9xx9AAZWx8e87Jd", + "N86eodVZja3GEyZJTo3DFUPGpxEEvjGHs", + "EkKeGSLUbHrrtuayBtbwgWDRUiAziC3ao", + }, + } + DefaultConfig = Config{ + MintAddresses: []string{}, + FundedAddresses: []string{ + // Private key: ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN + "6Y3kysjF9jnHnYkdS9yGAuoHyae2eNmeV", + }, + StakerIDs: []string{ + "7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", + "MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ", + "NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN", + "GWPcbFJZFfZreETSoWjPimr846mXEKCtu", + "P7oB2McjBGgW2NXXWVYjV8JEDFoW9xDE5", + }, + } +) + +// GetConfig ... +func GetConfig(networkID uint32) *Config { + switch networkID { + case CascadeID: + return &CascadeConfig + default: + return &DefaultConfig + } +} diff --git a/genesis/genesis.go b/genesis/genesis.go index 5f621a4..f561894 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -6,11 +6,7 @@ package genesis import ( "errors" "fmt" - "math" "math/big" - "regexp" - "strconv" - "strings" "time" "github.com/ava-labs/coreth/core" @@ -22,6 +18,7 @@ import ( "github.com/ava-labs/gecko/utils/formatting" "github.com/ava-labs/gecko/utils/json" "github.com/ava-labs/gecko/utils/units" + "github.com/ava-labs/gecko/utils/wrappers" "github.com/ava-labs/gecko/vms/avm" "github.com/ava-labs/gecko/vms/components/codec" "github.com/ava-labs/gecko/vms/evm" @@ -34,204 +31,45 @@ import ( "github.com/ava-labs/gecko/vms/timestampvm" ) -// Note that since an AVA network has exactly one Platform Chain, -// and the Platform Chain defines the genesis state of the network -// (who is staking, which chains exist, etc.), defining the genesis -// state of the Platform Chain is the same as defining the genesis -// state of the network. - -// Hardcoded network IDs -const ( - MainnetID uint32 = 1 - TestnetID uint32 = 2 - CascadeID uint32 = 2 - LocalID uint32 = 12345 - - MainnetName = "mainnet" - TestnetName = "testnet" - CascadeName = "cascade" - LocalName = "local" -) - -var ( - validNetworkName = regexp.MustCompile(`network-[0-9]+`) -) - -// Hard coded genesis constants -var ( - // Give special names to the mainnet and testnet - NetworkIDToNetworkName = map[uint32]string{ - MainnetID: MainnetName, - TestnetID: CascadeName, - LocalID: LocalName, - } - NetworkNameToNetworkID = map[string]uint32{ - MainnetName: MainnetID, - TestnetName: TestnetID, - CascadeName: CascadeID, - LocalName: LocalID, - } - MintAddresses = []string{ - "95YUFjhDG892VePMzpwKF9JzewGKvGRi3", - } - FundedAddresses = []string{ - "9uKvvA7E35QCwLvAaohXTCfFejbf3Rv17", - "JLrYNMYXANGj43BfWXBxMMAEenUBp1Sbn", - "7TUTzwrU6nbZtWHjTHEpdneUvjKBxb3EM", - "77mPUXBdQKwQpPoX6rckCZGLGGdkuG1G6", - "4gGWdFZ4Gax1B466YKXyKRRpWLb42Afdt", - "CKTkzAPsRxCreyiDTnjGxLmjMarxF28fi", - "4ABm9gFHVtsNdcKSd1xsacFkGneSgzpaa", - "DpL8PTsrjtLzv5J8LL3D2A6YcnCTqrNH9", - "ZdhZv6oZrmXLyFDy6ovXAu6VxmbTsT2h", - "6cesTteH62Y5mLoDBUASaBvCXuL2AthL", - } - - ParsedAddresses = []ids.ShortID{} - StakerIDs = []string{ - "NX4zVkuiRJZYe6Nzzav7GXN3TakUet3Co", - "CMsa8cMw4eib1Hb8GG4xiUKAq5eE1BwUX", - "DsMP6jLhi1MkDVc3qx9xx9AAZWx8e87Jd", - "N86eodVZja3GEyZJTo3DFUPGpxEEvjGHs", - "EkKeGSLUbHrrtuayBtbwgWDRUiAziC3ao", - } - ParsedStakerIDs = []ids.ShortID{} -) - -func init() { - for _, addrStr := range FundedAddresses { - addr, err := ids.ShortFromString(addrStr) - if err != nil { - panic(err) - } - ParsedAddresses = append(ParsedAddresses, addr) - } - for _, stakerIDStr := range StakerIDs { - stakerID, err := ids.ShortFromString(stakerIDStr) - if err != nil { - panic(err) - } - ParsedStakerIDs = append(ParsedStakerIDs, stakerID) - } -} - -// NetworkName returns a human readable name for the network with -// ID [networkID] -func NetworkName(networkID uint32) string { - if name, exists := NetworkIDToNetworkName[networkID]; exists { - return name - } - return fmt.Sprintf("network-%d", networkID) -} - -// NetworkID returns the ID of the network with name [networkName] -func NetworkID(networkName string) (uint32, error) { - networkName = strings.ToLower(networkName) - if id, exists := NetworkNameToNetworkID[networkName]; exists { - return id, nil - } - - if id, err := strconv.ParseUint(networkName, 10, 0); err == nil { - if id > math.MaxUint32 { - return 0, fmt.Errorf("NetworkID %s not in [0, 2^32)", networkName) - } - return uint32(id), nil - } - if validNetworkName.MatchString(networkName) { - if id, err := strconv.Atoi(networkName[8:]); err == nil { - if id > math.MaxUint32 { - return 0, fmt.Errorf("NetworkID %s not in [0, 2^32)", networkName) - } - return uint32(id), nil - } - } - - return 0, fmt.Errorf("Failed to parse %s as a network name", networkName) -} - -// Aliases returns the default aliases based on the network ID -func Aliases(networkID uint32) (generalAliases map[string][]string, chainAliases map[[32]byte][]string, vmAliases map[[32]byte][]string) { - generalAliases = map[string][]string{ - "vm/" + platformvm.ID.String(): []string{"vm/platform"}, - "vm/" + avm.ID.String(): []string{"vm/avm"}, - "vm/" + evm.ID.String(): []string{"vm/evm"}, - "vm/" + spdagvm.ID.String(): []string{"vm/spdag"}, - "vm/" + spchainvm.ID.String(): []string{"vm/spchain"}, - "vm/" + timestampvm.ID.String(): []string{"vm/timestamp"}, - "bc/" + ids.Empty.String(): []string{"P", "platform", "bc/P", "bc/platform"}, - } - chainAliases = map[[32]byte][]string{ - ids.Empty.Key(): []string{"P", "platform"}, - } - vmAliases = map[[32]byte][]string{ - platformvm.ID.Key(): []string{"platform"}, - avm.ID.Key(): []string{"avm"}, - evm.ID.Key(): []string{"evm"}, - spdagvm.ID.Key(): []string{"spdag"}, - spchainvm.ID.Key(): []string{"spchain"}, - timestampvm.ID.Key(): []string{"timestamp"}, - secp256k1fx.ID.Key(): []string{"secp256k1fx"}, - nftfx.ID.Key(): []string{"nftfx"}, - propertyfx.ID.Key(): []string{"propertyfx"}, - } - - genesisBytes, _ := Genesis(networkID) - genesis := &platformvm.Genesis{} // TODO let's not re-create genesis to do aliasing - platformvm.Codec.Unmarshal(genesisBytes, genesis) // TODO check for error - genesis.Initialize() - - for _, chain := range genesis.Chains { - switch { - case avm.ID.Equals(chain.VMID): - generalAliases["bc/"+chain.ID().String()] = []string{"X", "avm", "bc/X", "bc/avm"} - chainAliases[chain.ID().Key()] = []string{"X", "avm"} - case evm.ID.Equals(chain.VMID): - generalAliases["bc/"+chain.ID().String()] = []string{"C", "evm", "bc/C", "bc/evm"} - chainAliases[chain.ID().Key()] = []string{"C", "evm"} - case spdagvm.ID.Equals(chain.VMID): - generalAliases["bc/"+chain.ID().String()] = []string{"bc/spdag"} - chainAliases[chain.ID().Key()] = []string{"spdag"} - case spchainvm.ID.Equals(chain.VMID): - generalAliases["bc/"+chain.ID().String()] = []string{"bc/spchain"} - chainAliases[chain.ID().Key()] = []string{"spchain"} - case timestampvm.ID.Equals(chain.VMID): - generalAliases["bc/"+chain.ID().String()] = []string{"bc/timestamp"} - chainAliases[chain.ID().Key()] = []string{"timestamp"} - } - } - return -} - // Genesis returns the genesis data of the Platform Chain. -// Since the Platform Chain causes the creation of all other -// chains, this function returns the genesis data of the entire network. +// Since an AVA network has exactly one Platform Chain, and the Platform Chain +// defines the genesis state of the network (who is staking, which chains exist, +// etc.), defining the genesis state of the Platform Chain is the same as +// defining the genesis state of the network. // The ID of the new network is [networkID]. -func Genesis(networkID uint32) ([]byte, error) { + +// FromConfig ... +func FromConfig(networkID uint32, config *Config) ([]byte, error) { + if err := config.init(); err != nil { + return nil, err + } + // Specify the genesis state of the AVM avmArgs := avm.BuildGenesisArgs{} { - owners := []interface{}{avm.Owners{ - Threshold: 1, - Minters: MintAddresses, - }} - holders := []interface{}(nil) - for _, addr := range FundedAddresses { - holders = append(holders, avm.Holder{ + ava := avm.AssetDefinition{ + Name: "AVA", + Symbol: "AVA", + Denomination: 9, + InitialState: map[string][]interface{}{}, + } + + if len(config.MintAddresses) > 0 { + ava.InitialState["variableCap"] = []interface{}{avm.Owners{ + Threshold: 1, + Minters: config.MintAddresses, + }} + } + for _, addr := range config.FundedAddresses { + ava.InitialState["fixedCap"] = append(ava.InitialState["fixedCap"], avm.Holder{ Amount: json.Uint64(45 * units.MegaAva), Address: addr, }) } + avmArgs.GenesisData = map[string]avm.AssetDefinition{ // The AVM starts out with one asset, $AVA - "AVA": avm.AssetDefinition{ - Name: "AVA", - Symbol: "AVA", - Denomination: 9, - InitialState: map[string][]interface{}{ - "variableCap": owners, - "fixedCap": holders, - }, - }, + "AVA": ava, } } avmReply := avm.BuildGenesisReply{} @@ -285,7 +123,7 @@ func Genesis(networkID uint32) ([]byte, error) { // Specify the genesis state of the simple payments DAG spdagvmArgs := spdagvm.BuildGenesisArgs{} - for _, addr := range ParsedAddresses { + for _, addr := range config.ParsedFundedAddresses { spdagvmArgs.Outputs = append(spdagvmArgs.Outputs, spdagvm.APIOutput{ Amount: json.Uint64(20 * units.KiloAva), @@ -303,7 +141,7 @@ func Genesis(networkID uint32) ([]byte, error) { // Specify the genesis state of the simple payments chain spchainvmArgs := spchainvm.BuildGenesisArgs{} - for _, addr := range ParsedAddresses { + for _, addr := range config.ParsedFundedAddresses { spchainvmArgs.Accounts = append(spchainvmArgs.Accounts, spchainvm.APIAccount{ Address: addr, @@ -322,7 +160,7 @@ func Genesis(networkID uint32) ([]byte, error) { platformvmArgs := platformvm.BuildGenesisArgs{ NetworkID: json.Uint32(networkID), } - for _, addr := range ParsedAddresses { + for _, addr := range config.ParsedFundedAddresses { platformvmArgs.Accounts = append(platformvmArgs.Accounts, platformvm.APIAccount{ Address: addr, @@ -344,7 +182,7 @@ func Genesis(networkID uint32) ([]byte, error) { stakingDuration := 365 * 24 * time.Hour // ~ 1 year endStakingTime := genesisTime.Add(stakingDuration) - for i, validatorID := range ParsedStakerIDs { + for i, validatorID := range config.ParsedStakerIDs { weight := json.Uint64(20 * units.KiloAva) platformvmArgs.Validators = append(platformvmArgs.Validators, platformvm.APIDefaultSubnetValidator{ @@ -354,7 +192,7 @@ func Genesis(networkID uint32) ([]byte, error) { Weight: &weight, ID: validatorID, }, - Destination: ParsedAddresses[i%len(ParsedAddresses)], + Destination: config.ParsedFundedAddresses[i%len(config.ParsedFundedAddresses)], }, ) } @@ -409,44 +247,69 @@ func Genesis(networkID uint32) ([]byte, error) { return platformvmReply.Bytes.Bytes, nil } +// Genesis ... +func Genesis(networkID uint32) ([]byte, error) { return FromConfig(networkID, GetConfig(networkID)) } + // VMGenesis ... -func VMGenesis(networkID uint32, vmID ids.ID) *platformvm.CreateChainTx { - genesisBytes, _ := Genesis(networkID) +func VMGenesis(networkID uint32, vmID ids.ID) (*platformvm.CreateChainTx, error) { + genesisBytes, err := Genesis(networkID) + if err != nil { + return nil, err + } genesis := platformvm.Genesis{} platformvm.Codec.Unmarshal(genesisBytes, &genesis) if err := genesis.Initialize(); err != nil { - panic(err) + return nil, err } for _, chain := range genesis.Chains { if chain.VMID.Equals(vmID) { - return chain + return chain, nil } } - return nil + return nil, fmt.Errorf("couldn't find subnet with VM ID %s", vmID) } // AVAAssetID ... -func AVAAssetID(networkID uint32) ids.ID { - createAVM := VMGenesis(networkID, avm.ID) +func AVAAssetID(networkID uint32) (ids.ID, error) { + createAVM, err := VMGenesis(networkID, avm.ID) + if err != nil { + return ids.ID{}, err + } c := codec.NewDefault() - c.RegisterType(&avm.BaseTx{}) - c.RegisterType(&avm.CreateAssetTx{}) - c.RegisterType(&avm.OperationTx{}) - c.RegisterType(&avm.ImportTx{}) - c.RegisterType(&avm.ExportTx{}) - c.RegisterType(&secp256k1fx.TransferInput{}) - c.RegisterType(&secp256k1fx.MintOutput{}) - c.RegisterType(&secp256k1fx.TransferOutput{}) - c.RegisterType(&secp256k1fx.MintOperation{}) - c.RegisterType(&secp256k1fx.Credential{}) + errs := wrappers.Errs{} + errs.Add( + c.RegisterType(&avm.BaseTx{}), + c.RegisterType(&avm.CreateAssetTx{}), + c.RegisterType(&avm.OperationTx{}), + c.RegisterType(&avm.ImportTx{}), + c.RegisterType(&avm.ExportTx{}), + c.RegisterType(&secp256k1fx.TransferInput{}), + c.RegisterType(&secp256k1fx.MintOutput{}), + c.RegisterType(&secp256k1fx.TransferOutput{}), + c.RegisterType(&secp256k1fx.MintOperation{}), + c.RegisterType(&secp256k1fx.Credential{}), + ) + if errs.Errored() { + return ids.ID{}, errs.Err + } genesis := avm.Genesis{} - c.Unmarshal(createAVM.GenesisData, &genesis) + if err := c.Unmarshal(createAVM.GenesisData, &genesis); err != nil { + return ids.ID{}, err + } + if len(genesis.Txs) == 0 { + return ids.ID{}, errors.New("genesis creates no transactions") + } genesisTx := genesis.Txs[0] + tx := avm.Tx{UnsignedTx: &genesisTx.CreateAssetTx} - txBytes, _ := c.Marshal(&tx) + txBytes, err := c.Marshal(&tx) + if err != nil { + return ids.ID{}, err + } tx.Initialize(txBytes) - return tx.ID() + + return tx.ID(), nil } diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go index fb97854..999c6a6 100644 --- a/genesis/genesis_test.go +++ b/genesis/genesis_test.go @@ -91,7 +91,7 @@ func TestNetworkID(t *testing.T) { } func TestAliases(t *testing.T) { - generalAliases, _, _ := Aliases(LocalID) + generalAliases, _, _, _ := Aliases(LocalID) if _, exists := generalAliases["vm/"+platformvm.ID.String()]; !exists { t.Fatalf("Should have a custom alias from the vm") } else if _, exists := generalAliases["vm/"+avm.ID.String()]; !exists { diff --git a/genesis/network_id.go b/genesis/network_id.go new file mode 100644 index 0000000..5e5c0dd --- /dev/null +++ b/genesis/network_id.go @@ -0,0 +1,73 @@ +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package genesis + +import ( + "fmt" + "math" + "regexp" + "strconv" + "strings" +) + +// Hardcoded network IDs +var ( + MainnetID uint32 = 1 + TestnetID uint32 = 2 + CascadeID uint32 = 2 + LocalID uint32 = 12345 + + MainnetName = "mainnet" + TestnetName = "testnet" + CascadeName = "cascade" + LocalName = "local" + + NetworkIDToNetworkName = map[uint32]string{ + MainnetID: MainnetName, + TestnetID: CascadeName, + LocalID: LocalName, + } + NetworkNameToNetworkID = map[string]uint32{ + MainnetName: MainnetID, + TestnetName: TestnetID, + CascadeName: CascadeID, + LocalName: LocalID, + } + + validNetworkName = regexp.MustCompile(`network-[0-9]+`) +) + +// NetworkName returns a human readable name for the network with +// ID [networkID] +func NetworkName(networkID uint32) string { + if name, exists := NetworkIDToNetworkName[networkID]; exists { + return name + } + return fmt.Sprintf("network-%d", networkID) +} + +// NetworkID returns the ID of the network with name [networkName] +func NetworkID(networkName string) (uint32, error) { + networkName = strings.ToLower(networkName) + if id, exists := NetworkNameToNetworkID[networkName]; exists { + return id, nil + } + + if id, err := strconv.ParseUint(networkName, 10, 0); err == nil { + if id > math.MaxUint32 { + return 0, fmt.Errorf("NetworkID %s not in [0, 2^32)", networkName) + } + return uint32(id), nil + } + if validNetworkName.MatchString(networkName) { + if id, err := strconv.Atoi(networkName[8:]); err == nil { + if id > math.MaxUint32 { + return 0, fmt.Errorf("NetworkID %s not in [0, 2^32)", networkName) + } + return uint32(id), nil + } + } + + return 0, fmt.Errorf("Failed to parse %s as a network name", networkName) +} diff --git a/main/params.go b/main/params.go index 8156702..43d3d1b 100644 --- a/main/params.go +++ b/main/params.go @@ -33,16 +33,21 @@ var ( Err error ) -// Bootstrap configs -var ( - BootstrapIPs = []string{ - "3.227.207.132:21001", - "34.207.133.167:21001", - "107.23.241.199:21001", - "54.197.215.186:21001", - "18.234.153.22:21001", +// GetIPs returns the default IPs for each network +func GetIPs(networkID uint32) []string { + switch networkID { + case genesis.CascadeID: + return []string{ + "3.227.207.132:21001", + "34.207.133.167:21001", + "107.23.241.199:21001", + "54.197.215.186:21001", + "18.234.153.22:21001", + } + default: + return nil } -) +} var ( errBootstrapMismatch = errors.New("more bootstrap IDs provided than bootstrap IPs") @@ -84,8 +89,8 @@ func init() { fs.StringVar(&Config.HTTPSCertFile, "http-tls-cert-file", "", "TLS certificate file for the HTTPs server") // Bootstrapping: - bootstrapIPs := fs.String("bootstrap-ips", strings.Join(BootstrapIPs, ","), "Comma separated list of bootstrap peer ips to connect to. Example: 127.0.0.1:9630,127.0.0.1:9631") - bootstrapIDs := fs.String("bootstrap-ids", strings.Join(genesis.StakerIDs, ","), "Comma separated list of bootstrap peer ids to connect to. Example: JR4dVmy6ffUGAKCBDkyCbeZbyHQBeDsET,8CrVPQZ4VSqgL8zTdvL14G8HqAfrBr4z") + bootstrapIPs := fs.String("bootstrap-ips", "", "Comma separated list of bootstrap peer ips to connect to. Example: 127.0.0.1:9630,127.0.0.1:9631") + bootstrapIDs := fs.String("bootstrap-ids", "", "Comma separated list of bootstrap peer ids to connect to. Example: JR4dVmy6ffUGAKCBDkyCbeZbyHQBeDsET,8CrVPQZ4VSqgL8zTdvL14G8HqAfrBr4z") // Staking: consensusPort := fs.Uint("staking-port", 9651, "Port of the consensus server") @@ -164,7 +169,11 @@ func init() { } // Bootstrapping: - for _, ip := range strings.Split(*bootstrapIPs, ",") { + bsIPs := strings.Split(*bootstrapIPs, ",") + if *bootstrapIPs == "" { + bsIPs = GetIPs(networkID) + } + for _, ip := range bsIPs { if ip != "" { addr, err := utils.ToIPDesc(ip) errs.Add(err) @@ -173,6 +182,9 @@ func init() { }) } } + if *bootstrapIDs == "" { + *bootstrapIDs = strings.Join(genesis.GetConfig(networkID).StakerIDs, ",") + } if Config.EnableStaking { i := 0 cb58 := formatting.CB58{} diff --git a/node/node.go b/node/node.go index 4c2fee1..caded55 100644 --- a/node/node.go +++ b/node/node.go @@ -36,6 +36,7 @@ import ( "github.com/ava-labs/gecko/snow/validators" "github.com/ava-labs/gecko/utils/hashing" "github.com/ava-labs/gecko/utils/logging" + "github.com/ava-labs/gecko/utils/wrappers" "github.com/ava-labs/gecko/vms" "github.com/ava-labs/gecko/vms/avm" "github.com/ava-labs/gecko/vms/evm" @@ -361,19 +362,29 @@ func (n *Node) initNodeID() error { // AVM, EVM, Simple Payments DAG, Simple Payments Chain // The Platform VM is registered in initStaking because // its factory needs to reference n.chainManager, which is nil right now -func (n *Node) initVMManager() { +func (n *Node) initVMManager() error { + avaAssetID, err := genesis.AVAAssetID(n.Config.NetworkID) + if err != nil { + return err + } + n.vmManager = vms.NewManager(&n.APIServer, n.HTTPLog) - n.vmManager.RegisterVMFactory(avm.ID, &avm.Factory{ - AVA: genesis.AVAAssetID(n.Config.NetworkID), - Platform: ids.Empty, - }) - n.vmManager.RegisterVMFactory(evm.ID, &evm.Factory{}) - n.vmManager.RegisterVMFactory(spdagvm.ID, &spdagvm.Factory{TxFee: n.Config.AvaTxFee}) - n.vmManager.RegisterVMFactory(spchainvm.ID, &spchainvm.Factory{}) - n.vmManager.RegisterVMFactory(timestampvm.ID, ×tampvm.Factory{}) - n.vmManager.RegisterVMFactory(secp256k1fx.ID, &secp256k1fx.Factory{}) - n.vmManager.RegisterVMFactory(nftfx.ID, &nftfx.Factory{}) - n.vmManager.RegisterVMFactory(propertyfx.ID, &propertyfx.Factory{}) + + errs := wrappers.Errs{} + errs.Add( + n.vmManager.RegisterVMFactory(avm.ID, &avm.Factory{ + AVA: avaAssetID, + Platform: ids.Empty, + }), + n.vmManager.RegisterVMFactory(evm.ID, &evm.Factory{}), + n.vmManager.RegisterVMFactory(spdagvm.ID, &spdagvm.Factory{TxFee: n.Config.AvaTxFee}), + n.vmManager.RegisterVMFactory(spchainvm.ID, &spchainvm.Factory{}), + n.vmManager.RegisterVMFactory(timestampvm.ID, ×tampvm.Factory{}), + n.vmManager.RegisterVMFactory(secp256k1fx.ID, &secp256k1fx.Factory{}), + n.vmManager.RegisterVMFactory(nftfx.ID, &nftfx.Factory{}), + n.vmManager.RegisterVMFactory(propertyfx.ID, &propertyfx.Factory{}), + ) + return errs.Err } // Create the EventDispatcher used for hooking events @@ -389,7 +400,7 @@ func (n *Node) initEventDispatcher() { // Initializes the Platform chain. // Its genesis data specifies the other chains that should // be created. -func (n *Node) initChains() { +func (n *Node) initChains() error { n.Log.Info("initializing chains") vdrs := n.vdrs @@ -404,23 +415,38 @@ func (n *Node) initChains() { vdrs.PutValidatorSet(platformvm.DefaultSubnetID, defaultSubnetValidators) } - n.vmManager.RegisterVMFactory( + avaAssetID, err := genesis.AVAAssetID(n.Config.NetworkID) + if err != nil { + return err + } + createAVMTx, err := genesis.VMGenesis(n.Config.NetworkID, avm.ID) + if err != nil { + return err + } + + err = n.vmManager.RegisterVMFactory( /*vmID=*/ platformvm.ID, /*vmFactory=*/ &platformvm.Factory{ ChainManager: n.chainManager, Validators: vdrs, StakingEnabled: n.Config.EnableStaking, - AVA: genesis.AVAAssetID(n.Config.NetworkID), - AVM: genesis.VMGenesis(n.Config.NetworkID, avm.ID).ID(), + AVA: avaAssetID, + AVM: createAVMTx.ID(), }, ) + if err != nil { + return err + } beacons := validators.NewSet() for _, peer := range n.Config.BootstrapPeers { beacons.Add(validators.NewValidator(peer.ID, 1)) } - genesisBytes, _ := genesis.Genesis(n.Config.NetworkID) + genesisBytes, err := genesis.Genesis(n.Config.NetworkID) + if err != nil { + return err + } // Create the Platform Chain n.chainManager.ForceCreateChain(chains.ChainParameters{ @@ -430,6 +456,8 @@ func (n *Node) initChains() { VMAlias: platformvm.ID.String(), CustomBeacons: beacons, }) + + return nil } // initAPIServer initializes the server that handles HTTP calls @@ -528,24 +556,35 @@ func (n *Node) initIPCAPI() { } // Give chains and VMs aliases as specified by the genesis information -func (n *Node) initAliases() { +func (n *Node) initAliases() error { n.Log.Info("initializing aliases") - defaultAliases, chainAliases, vmAliases := genesis.Aliases(n.Config.NetworkID) + defaultAliases, chainAliases, vmAliases, err := genesis.Aliases(n.Config.NetworkID) + if err != nil { + return err + } + for chainIDKey, aliases := range chainAliases { chainID := ids.NewID(chainIDKey) for _, alias := range aliases { - n.Log.AssertNoError(n.chainManager.Alias(chainID, alias)) + if err := n.chainManager.Alias(chainID, alias); err != nil { + return err + } } } for vmIDKey, aliases := range vmAliases { vmID := ids.NewID(vmIDKey) for _, alias := range aliases { - n.Log.AssertNoError(n.vmManager.Alias(vmID, alias)) + if err := n.vmManager.Alias(vmID, alias); err != nil { + return err + } } } for url, aliases := range defaultAliases { - n.APIServer.AddAliases(url, aliases...) + if err := n.APIServer.AddAliases(url, aliases...); err != nil { + return err + } } + return nil } // Initialize this node @@ -580,8 +619,13 @@ func (n *Node) Initialize(Config *Config, logger logging.Logger, logFactory logg if err = n.initNetlib(); err != nil { // Set up all networking return fmt.Errorf("problem initializing networking: %w", err) } - n.initValidatorNet() // Set up the validator handshake + authentication - n.initVMManager() // Set up the vm manager + if err := n.initValidatorNet(); err != nil { // Set up the validator handshake + authentication + return fmt.Errorf("problem initializing validator network: %w", err) + } + if err := n.initVMManager(); err != nil { // Set up the vm manager + return fmt.Errorf("problem initializing the VM manager: %w", err) + } + n.initEventDispatcher() // Set up the event dipatcher n.initChainManager() // Set up the chain manager n.initConsensusNet() // Set up the main consensus network @@ -593,10 +637,11 @@ func (n *Node) Initialize(Config *Config, logger logging.Logger, logFactory logg n.initAdminAPI() // Start the Admin API n.initIPCAPI() // Start the IPC API - n.initAliases() // Set up aliases - n.initChains() // Start the Platform chain - return nil + if err := n.initAliases(); err != nil { // Set up aliases + return err + } + return n.initChains() // Start the Platform chain } // Shutdown this node diff --git a/xputtest/main.go b/xputtest/main.go index 9f791e1..3ed3236 100644 --- a/xputtest/main.go +++ b/xputtest/main.go @@ -76,11 +76,17 @@ func main() { // start the benchmark we want to run switch config.Chain { case spChain: - net.benchmarkSPChain(genesis.VMGenesis(config.NetworkID, spchainvm.ID)) + tx, err := genesis.VMGenesis(config.NetworkID, spchainvm.ID) + log.AssertNoError(err) + net.benchmarkSPChain(tx) case spDAG: - net.benchmarkSPDAG(genesis.VMGenesis(config.NetworkID, spdagvm.ID)) + tx, err := genesis.VMGenesis(config.NetworkID, spdagvm.ID) + log.AssertNoError(err) + net.benchmarkSPChain(tx) case avmDAG: - net.benchmarkAVM(genesis.VMGenesis(config.NetworkID, avm.ID)) + tx, err := genesis.VMGenesis(config.NetworkID, avm.ID) + log.AssertNoError(err) + net.benchmarkSPChain(tx) default: log.Fatal("did not specify whether to test dag or chain. Exiting") return