gecko/genesis/genesis.go

273 lines
7.6 KiB
Go
Raw Normal View History

2020-03-10 12:20:34 -07:00
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package genesis
import (
2020-03-10 13:15:54 -07:00
"errors"
2020-03-10 12:20:34 -07:00
"fmt"
2020-03-30 13:23:06 -07:00
"time"
2020-03-10 12:20:34 -07:00
"github.com/ava-labs/gecko/ids"
2020-03-30 13:23:06 -07:00
"github.com/ava-labs/gecko/utils/formatting"
"github.com/ava-labs/gecko/utils/json"
"github.com/ava-labs/gecko/utils/units"
2020-04-02 20:43:02 -07:00
"github.com/ava-labs/gecko/utils/wrappers"
2020-03-10 12:20:34 -07:00
"github.com/ava-labs/gecko/vms/avm"
2020-06-15 10:20:30 -07:00
"github.com/ava-labs/gecko/utils/codec"
2020-03-30 13:23:06 -07:00
"github.com/ava-labs/gecko/vms/nftfx"
2020-03-10 12:20:34 -07:00
"github.com/ava-labs/gecko/vms/platformvm"
2020-03-30 14:46:18 -07:00
"github.com/ava-labs/gecko/vms/propertyfx"
2020-03-26 15:04:41 -07:00
"github.com/ava-labs/gecko/vms/secp256k1fx"
2020-03-10 12:20:34 -07:00
"github.com/ava-labs/gecko/vms/spchainvm"
"github.com/ava-labs/gecko/vms/spdagvm"
"github.com/ava-labs/gecko/vms/timestampvm"
)
// ID of the EVM VM
var (
EVMID = ids.NewID([32]byte{'e', 'v', 'm'})
)
2020-04-02 20:43:02 -07:00
// Genesis returns the genesis data of the Platform Chain.
// 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].
2020-03-10 12:20:34 -07:00
2020-04-02 20:43:02 -07:00
// FromConfig ...
func FromConfig(networkID uint32, config *Config) ([]byte, error) {
if err := config.init(); err != nil {
return nil, err
2020-03-10 12:20:34 -07:00
}
2020-03-30 13:23:06 -07:00
// Specify the genesis state of the AVM
avmArgs := avm.BuildGenesisArgs{}
{
2020-04-02 20:43:02 -07:00
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{
2020-03-30 13:23:06 -07:00
Amount: json.Uint64(45 * units.MegaAva),
Address: addr,
})
}
2020-04-02 20:43:02 -07:00
2020-03-30 13:23:06 -07:00
avmArgs.GenesisData = map[string]avm.AssetDefinition{
// The AVM starts out with one asset, $AVA
2020-04-02 20:43:02 -07:00
"AVA": ava,
2020-03-30 13:23:06 -07:00
}
}
avmReply := avm.BuildGenesisReply{}
avmSS := avm.StaticService{}
err := avmSS.BuildGenesis(nil, &avmArgs, &avmReply)
if err != nil {
2020-03-10 13:15:54 -07:00
return nil, err
2020-03-30 13:23:06 -07:00
}
// Specify the genesis state of the simple payments DAG
spdagvmArgs := spdagvm.BuildGenesisArgs{}
2020-04-02 20:43:02 -07:00
for _, addr := range config.ParsedFundedAddresses {
2020-03-30 13:23:06 -07:00
spdagvmArgs.Outputs = append(spdagvmArgs.Outputs,
spdagvm.APIOutput{
Amount: json.Uint64(20 * units.KiloAva),
Threshold: 1,
Addresses: []ids.ShortID{addr},
},
)
}
spdagvmReply := spdagvm.BuildGenesisReply{}
spdagvmSS := spdagvm.StaticService{}
if err := spdagvmSS.BuildGenesis(nil, &spdagvmArgs, &spdagvmReply); err != nil {
2020-03-10 13:15:54 -07:00
return nil, fmt.Errorf("problem creating simple payments DAG: %w", err)
2020-03-30 13:23:06 -07:00
}
// Specify the genesis state of the simple payments chain
spchainvmArgs := spchainvm.BuildGenesisArgs{}
2020-04-02 20:43:02 -07:00
for _, addr := range config.ParsedFundedAddresses {
2020-03-30 13:23:06 -07:00
spchainvmArgs.Accounts = append(spchainvmArgs.Accounts,
spchainvm.APIAccount{
Address: addr,
Balance: json.Uint64(20 * units.KiloAva),
},
)
2020-03-10 12:20:34 -07:00
}
2020-03-30 13:23:06 -07:00
spchainvmReply := spchainvm.BuildGenesisReply{}
spchainvmSS := spchainvm.StaticService{}
if err := spchainvmSS.BuildGenesis(nil, &spchainvmArgs, &spchainvmReply); err != nil {
2020-03-10 13:15:54 -07:00
return nil, fmt.Errorf("problem creating simple payments chain: %w", err)
2020-03-30 13:23:06 -07:00
}
// Specify the initial state of the Platform Chain
platformvmArgs := platformvm.BuildGenesisArgs{
NetworkID: json.Uint32(networkID),
}
2020-04-02 20:43:02 -07:00
for _, addr := range config.ParsedFundedAddresses {
2020-03-30 13:23:06 -07:00
platformvmArgs.Accounts = append(platformvmArgs.Accounts,
platformvm.APIAccount{
Address: addr,
Balance: json.Uint64(20 * units.KiloAva),
},
)
}
genesisTime := time.Date(
/*year=*/ 2019,
/*month=*/ time.November,
/*day=*/ 1,
/*hour=*/ 0,
/*minute=*/ 0,
/*second=*/ 0,
/*nano-second=*/ 0,
/*location=*/ time.UTC,
)
stakingDuration := 365 * 24 * time.Hour // ~ 1 year
endStakingTime := genesisTime.Add(stakingDuration)
2020-04-02 20:43:02 -07:00
for i, validatorID := range config.ParsedStakerIDs {
2020-03-30 13:23:06 -07:00
weight := json.Uint64(20 * units.KiloAva)
platformvmArgs.Validators = append(platformvmArgs.Validators,
platformvm.APIDefaultSubnetValidator{
APIValidator: platformvm.APIValidator{
StartTime: json.Uint64(genesisTime.Unix()),
EndTime: json.Uint64(endStakingTime.Unix()),
Weight: &weight,
ID: validatorID,
},
2020-04-02 20:43:02 -07:00
Destination: config.ParsedFundedAddresses[i%len(config.ParsedFundedAddresses)],
2020-03-30 13:23:06 -07:00
},
)
}
// Specify the chains that exist upon this network's creation
platformvmArgs.Chains = []platformvm.APIChain{
platformvm.APIChain{
GenesisData: avmReply.Bytes,
SubnetID: platformvm.DefaultSubnetID,
2020-03-30 13:23:06 -07:00
VMID: avm.ID,
FxIDs: []ids.ID{
secp256k1fx.ID,
nftfx.ID,
2020-03-30 14:46:18 -07:00
propertyfx.ID,
2020-03-30 13:23:06 -07:00
},
Name: "X-Chain",
},
platformvm.APIChain{
GenesisData: formatting.CB58{Bytes: config.EVMBytes},
SubnetID: platformvm.DefaultSubnetID,
VMID: EVMID,
2020-03-30 13:23:06 -07:00
Name: "C-Chain",
},
platformvm.APIChain{
GenesisData: spdagvmReply.Bytes,
SubnetID: platformvm.DefaultSubnetID,
2020-03-30 13:23:06 -07:00
VMID: spdagvm.ID,
Name: "Simple DAG Payments",
},
platformvm.APIChain{
GenesisData: spchainvmReply.Bytes,
SubnetID: platformvm.DefaultSubnetID,
2020-03-30 13:23:06 -07:00
VMID: spchainvm.ID,
Name: "Simple Chain Payments",
},
platformvm.APIChain{
GenesisData: formatting.CB58{Bytes: []byte{}}, // There is no genesis data
SubnetID: platformvm.DefaultSubnetID,
2020-03-30 13:23:06 -07:00
VMID: timestampvm.ID,
Name: "Simple Timestamp Server",
},
}
platformvmArgs.Time = json.Uint64(genesisTime.Unix())
platformvmReply := platformvm.BuildGenesisReply{}
platformvmSS := platformvm.StaticService{}
if err := platformvmSS.BuildGenesis(nil, &platformvmArgs, &platformvmReply); err != nil {
2020-03-10 13:15:54 -07:00
return nil, fmt.Errorf("problem while building platform chain's genesis state: %w", err)
2020-03-30 13:23:06 -07:00
}
2020-03-10 13:15:54 -07:00
return platformvmReply.Bytes.Bytes, nil
2020-03-10 12:20:34 -07:00
}
2020-04-02 20:43:02 -07:00
// Genesis ...
func Genesis(networkID uint32) ([]byte, error) { return FromConfig(networkID, GetConfig(networkID)) }
2020-03-10 12:20:34 -07:00
// VMGenesis ...
2020-04-02 20:43:02 -07:00
func VMGenesis(networkID uint32, vmID ids.ID) (*platformvm.CreateChainTx, error) {
genesisBytes, err := Genesis(networkID)
if err != nil {
return nil, err
}
2020-03-10 12:20:34 -07:00
genesis := platformvm.Genesis{}
platformvm.Codec.Unmarshal(genesisBytes, &genesis)
2020-03-17 13:07:33 -07:00
if err := genesis.Initialize(); err != nil {
2020-04-02 20:43:02 -07:00
return nil, err
2020-03-17 13:07:33 -07:00
}
2020-03-10 12:20:34 -07:00
for _, chain := range genesis.Chains {
if chain.VMID.Equals(vmID) {
2020-04-02 20:43:02 -07:00
return chain, nil
2020-03-10 12:20:34 -07:00
}
}
2020-04-02 20:43:02 -07:00
return nil, fmt.Errorf("couldn't find subnet with VM ID %s", vmID)
2020-03-10 12:20:34 -07:00
}
2020-03-26 15:04:41 -07:00
// AVAAssetID ...
2020-04-02 20:43:02 -07:00
func AVAAssetID(networkID uint32) (ids.ID, error) {
createAVM, err := VMGenesis(networkID, avm.ID)
if err != nil {
return ids.ID{}, err
}
2020-03-26 15:04:41 -07:00
c := codec.NewDefault()
2020-04-02 20:43:02 -07:00
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
}
2020-03-26 15:04:41 -07:00
genesis := avm.Genesis{}
2020-04-02 20:43:02 -07:00
if err := c.Unmarshal(createAVM.GenesisData, &genesis); err != nil {
return ids.ID{}, err
}
2020-03-26 15:04:41 -07:00
2020-04-02 20:43:02 -07:00
if len(genesis.Txs) == 0 {
return ids.ID{}, errors.New("genesis creates no transactions")
}
2020-03-26 15:04:41 -07:00
genesisTx := genesis.Txs[0]
2020-04-02 20:43:02 -07:00
2020-03-26 15:04:41 -07:00
tx := avm.Tx{UnsignedTx: &genesisTx.CreateAssetTx}
2020-04-02 20:43:02 -07:00
txBytes, err := c.Marshal(&tx)
if err != nil {
return ids.ID{}, err
}
2020-03-26 15:04:41 -07:00
tx.Initialize(txBytes)
2020-04-02 20:43:02 -07:00
return tx.ID(), nil
2020-03-26 15:04:41 -07:00
}