package state import ( "bytes" "encoding/hex" "encoding/json" "io/ioutil" "time" . "github.com/tendermint/tendermint/account" . "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/block" . "github.com/tendermint/tendermint/common" db_ "github.com/tendermint/tendermint/db" "github.com/tendermint/tendermint/merkle" ) type GenesisAccount struct { Address string Amount uint64 } type GenesisValidator struct { PubKey string Amount uint64 UnbondTo []GenesisAccount } type GenesisDoc struct { GenesisTime time.Time Accounts []GenesisAccount Validators []GenesisValidator } func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) { err := json.Unmarshal(jsonBlob, &genState) if err != nil { panic(Fmt("Couldn't read GenesisDoc: %v", err)) } return } func MakeGenesisStateFromFile(db db_.DB, genDocFile string) *State { jsonBlob, err := ioutil.ReadFile(genDocFile) if err != nil { panic(Fmt("Couldn't read GenesisDoc file: %v", err)) } genDoc := GenesisDocFromJSON(jsonBlob) return MakeGenesisState(db, genDoc) } func MakeGenesisState(db db_.DB, genDoc *GenesisDoc) *State { if len(genDoc.Validators) == 0 { Exit(Fmt("The genesis file has no validators")) } if genDoc.GenesisTime.IsZero() { genDoc.GenesisTime = time.Now() } // Make accounts state tree accounts := merkle.NewIAVLTree(BasicCodec, AccountCodec, defaultAccountsCacheCapacity, db) for _, acc := range genDoc.Accounts { address, err := hex.DecodeString(acc.Address) if err != nil { Exit(Fmt("Invalid account address: %v", acc.Address)) } account := &Account{ Address: address, PubKey: PubKeyNil{}, Sequence: 0, Balance: acc.Amount, } accounts.Set(address, account) } // Make validatorInfos state tree && validators slice validatorInfos := merkle.NewIAVLTree(BasicCodec, ValidatorInfoCodec, 0, db) validators := make([]*Validator, len(genDoc.Validators)) for i, val := range genDoc.Validators { pubKeyBytes, err := hex.DecodeString(val.PubKey) if err != nil { Exit(Fmt("Invalid validator pubkey: %v", val.PubKey)) } pubKey := ReadBinary(PubKeyEd25519{}, bytes.NewBuffer(pubKeyBytes), new(int64), &err).(PubKeyEd25519) if err != nil { Exit(Fmt("Invalid validator pubkey: %v", val.PubKey)) } address := pubKey.Address() // Make ValidatorInfo valInfo := &ValidatorInfo{ Address: address, PubKey: pubKey, UnbondTo: make([]*TxOutput, len(val.UnbondTo)), FirstBondHeight: 0, FirstBondAmount: val.Amount, } for i, unbondTo := range val.UnbondTo { address, err := hex.DecodeString(unbondTo.Address) if err != nil { Exit(Fmt("Invalid unbond-to address: %v", unbondTo.Address)) } valInfo.UnbondTo[i] = &TxOutput{ Address: address, Amount: unbondTo.Amount, } } validatorInfos.Set(address, valInfo) // Make validator validators[i] = &Validator{ Address: address, PubKey: pubKey, VotingPower: val.Amount, } } // IAVLTrees must be persisted before copy operations. accounts.Save() validatorInfos.Save() return &State{ DB: db, LastBlockHeight: 0, LastBlockHash: nil, LastBlockParts: PartSetHeader{}, LastBlockTime: genDoc.GenesisTime, BondedValidators: NewValidatorSet(validators), UnbondingValidators: NewValidatorSet(nil), accounts: accounts, validatorInfos: validatorInfos, } }