Refactoring genesis, including PubKey into TxInput

This commit is contained in:
Jae Kwon
2014-12-28 00:44:56 -08:00
parent 70eb75dca7
commit f91665fe07
17 changed files with 308 additions and 178 deletions

View File

@ -36,16 +36,6 @@ type Account struct {
Balance uint64 Balance uint64
} }
func NewAccount(pubKey PubKey) *Account {
address := pubKey.Address()
return &Account{
Address: address,
PubKey: pubKey,
Sequence: uint(0),
Balance: uint64(0),
}
}
func (account *Account) Copy() *Account { func (account *Account) Copy() *Account {
accountCopy := *account accountCopy := *account
return &accountCopy return &accountCopy

View File

@ -26,7 +26,7 @@ const (
func PrivKeyDecoder(r io.Reader, n *int64, err *error) interface{} { func PrivKeyDecoder(r io.Reader, n *int64, err *error) interface{} {
switch t := ReadByte(r, n, err); t { switch t := ReadByte(r, n, err); t {
case PrivKeyTypeEd25519: case PrivKeyTypeEd25519:
return ReadBinary(&PrivKeyEd25519{}, r, n, err) return ReadBinary(PrivKeyEd25519{}, r, n, err)
default: default:
*err = Errorf("Unknown PrivKey type %X", t) *err = Errorf("Unknown PrivKey type %X", t)
return nil return nil

View File

@ -18,8 +18,9 @@ type PubKey interface {
// Types of PubKey implementations // Types of PubKey implementations
const ( const (
PubKeyTypeUnknown = byte(0x00) // For pay-to-pubkey-hash txs. PubKeyTypeNil = byte(0x00)
PubKeyTypeEd25519 = byte(0x01) PubKeyTypeUnknown = byte(0x01) // For pay-to-pubkey-hash txs.
PubKeyTypeEd25519 = byte(0x02)
) )
//------------------------------------- //-------------------------------------
@ -27,10 +28,10 @@ const (
func PubKeyDecoder(r io.Reader, n *int64, err *error) interface{} { func PubKeyDecoder(r io.Reader, n *int64, err *error) interface{} {
switch t := ReadByte(r, n, err); t { switch t := ReadByte(r, n, err); t {
case PubKeyTypeUnknown: case PubKeyTypeNil:
return PubKeyUnknown{} return PubKeyNil{}
case PubKeyTypeEd25519: case PubKeyTypeEd25519:
return ReadBinary(&PubKeyEd25519{}, r, n, err) return ReadBinary(PubKeyEd25519{}, r, n, err)
default: default:
*err = Errorf("Unknown PubKey type %X", t) *err = Errorf("Unknown PubKey type %X", t)
return nil return nil
@ -45,22 +46,16 @@ var _ = RegisterType(&TypeInfo{
//------------------------------------- //-------------------------------------
// Implements PubKey // Implements PubKey
// For pay-to-pubkey-hash txs, where the TxOutput PubKey type PubKeyNil struct{}
// is not known in advance, only its hash (address).
type PubKeyUnknown struct { func (key PubKeyNil) TypeByte() byte { return PubKeyTypeNil }
address []byte
func (key PubKeyNil) Address() []byte {
panic("PubKeyNil has no address")
} }
func NewPubKeyUnknown(address []byte) PubKeyUnknown { return PubKeyUnknown{address} } func (key PubKeyNil) VerifyBytes(msg []byte, sig_ Signature) bool {
panic("PubKeyNil cannot verify messages")
func (key PubKeyUnknown) TypeByte() byte { return PubKeyTypeUnknown }
func (key PubKeyUnknown) Address() []byte {
return key.address
}
func (key PubKeyUnknown) VerifyBytes(msg []byte, sig_ Signature) bool {
panic("PubKeyUnknown cannot verify messages")
} }
//------------------------------------- //-------------------------------------

View File

@ -25,7 +25,7 @@ const (
func SignatureDecoder(r io.Reader, n *int64, err *error) interface{} { func SignatureDecoder(r io.Reader, n *int64, err *error) interface{} {
switch t := ReadByte(r, n, err); t { switch t := ReadByte(r, n, err); t {
case SignatureTypeEd25519: case SignatureTypeEd25519:
return ReadBinary(&SignatureEd25519{}, r, n, err) return ReadBinary(SignatureEd25519{}, r, n, err)
default: default:
*err = Errorf("Unknown Signature type %X", t) *err = Errorf("Unknown Signature type %X", t)
return nil return nil

View File

@ -159,7 +159,7 @@ func ReadUint64(r io.Reader, n *int64, err *error) uint64 {
// Varint // Varint
func WriteVarint(i int, w io.Writer, n *int64, err *error) { func WriteVarint(i int, w io.Writer, n *int64, err *error) {
buf := make([]byte, 9) buf := make([]byte, binary.MaxVarintLen64)
n_ := int64(binary.PutVarint(buf, int64(i))) n_ := int64(binary.PutVarint(buf, int64(i)))
*n += n_ *n += n_
WriteTo(buf[:n_], w, n, err) WriteTo(buf[:n_], w, n, err)
@ -175,7 +175,7 @@ func ReadVarint(r io.Reader, n *int64, err *error) int {
// Uvarint // Uvarint
func WriteUvarint(i uint, w io.Writer, n *int64, err *error) { func WriteUvarint(i uint, w io.Writer, n *int64, err *error) {
buf := make([]byte, 9) buf := make([]byte, binary.MaxVarintLen64)
n_ := int64(binary.PutUvarint(buf, uint64(i))) n_ := int64(binary.PutUvarint(buf, uint64(i)))
*n += n_ *n += n_
WriteTo(buf[:n_], w, n, err) WriteTo(buf[:n_], w, n, err)

View File

@ -15,6 +15,9 @@ var (
ErrTxDuplicateAddress = errors.New("Error duplicate address") ErrTxDuplicateAddress = errors.New("Error duplicate address")
ErrTxInvalidAmount = errors.New("Error invalid amount") ErrTxInvalidAmount = errors.New("Error invalid amount")
ErrTxInsufficientFunds = errors.New("Error insufficient funds") ErrTxInsufficientFunds = errors.New("Error insufficient funds")
ErrTxUnknownPubKey = errors.New("Error unknown pubkey")
ErrTxInvalidPubKey = errors.New("Error invalid pubkey")
ErrTxRedeclaredPubKey = errors.New("Error redeclared pubkey")
ErrTxInvalidSignature = errors.New("Error invalid signature") ErrTxInvalidSignature = errors.New("Error invalid signature")
ErrTxInvalidSequence = errors.New("Error invalid sequence") ErrTxInvalidSequence = errors.New("Error invalid sequence")
) )
@ -79,6 +82,7 @@ type TxInput struct {
Amount uint64 // Must not exceed account balance Amount uint64 // Must not exceed account balance
Sequence uint // Must be 1 greater than the last committed TxInput Sequence uint // Must be 1 greater than the last committed TxInput
Signature Signature // Depends on the PubKey type and the whole Tx Signature Signature // Depends on the PubKey type and the whole Tx
PubKey PubKey // Optional, may be nil
} }
func (txIn *TxInput) ValidateBasic() error { func (txIn *TxInput) ValidateBasic() error {

View File

@ -26,11 +26,11 @@ type Node struct {
func NewNode() *Node { func NewNode() *Node {
// Get BlockStore // Get BlockStore
blockStoreDB := db_.NewMemDB() // TODO configurable db. blockStoreDB := db_.GetDB("blockstore")
blockStore := block.NewBlockStore(blockStoreDB) blockStore := block.NewBlockStore(blockStoreDB)
// Get State // Get State
stateDB := db_.NewMemDB() // TODO configurable db. stateDB := db_.GetDB("state")
state := state_.LoadState(stateDB) state := state_.LoadState(stateDB)
if state == nil { if state == nil {
state = state_.MakeGenesisStateFromFile(stateDB, config.GenesisFile()) state = state_.MakeGenesisStateFromFile(stateDB, config.GenesisFile())

View File

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"os"
"github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/state"
@ -10,14 +9,15 @@ import (
func gen_validator() { func gen_validator() {
// If already exists, bail out.
filename := config.PrivValidatorFile()
if _, err := os.Stat(filename); !os.IsNotExist(err) {
fmt.Printf("Cannot generate new validator, file already exists at %v\n", filename)
}
// Generate private validator
privValidator := state.GenPrivValidator() privValidator := state.GenPrivValidator()
privValidator.Save() privValidatorJSONBytes := privValidator.JSONBytes()
fmt.Printf("Generated a new validator at %v\n", filename) fmt.Printf(`Generated a new validator!
Paste the following JSON into your %v file
%v
`,
config.PrivValidatorFile(),
string(privValidatorJSONBytes),
)
} }

View File

@ -2,9 +2,7 @@ package common
import "sync" import "sync"
/* // CMap is a goroutine-safe map
CMap is a threadsafe map
*/
type CMap struct { type CMap struct {
m map[string]interface{} m map[string]interface{}
l sync.Mutex l sync.Mutex

View File

@ -2,8 +2,14 @@ package common
import ( import (
"fmt" "fmt"
"os"
) )
func Panicf(s string, args ...interface{}) { func Panicf(s string, args ...interface{}) {
panic(fmt.Sprintf(s, args...)) panic(fmt.Sprintf(s, args...))
} }
func Exitf(s string, args ...interface{}) {
fmt.Printf(s+"\n", args...)
os.Exit(1)
}

View File

@ -6,19 +6,117 @@ import (
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
. "github.com/tendermint/tendermint/common"
) )
//-----------------------------------------------------------------------------j
// Configuration types
type ConfigType struct {
Network string
LAddr string
SeedNode string
DB DBConfig
Alert AlertConfig
SMTP SMTPConfig
RPC RPCConfig
}
type DBConfig struct {
Backend string
Dir string
}
type AlertConfig struct {
MinInterval int
TwilioSid string
TwilioToken string
TwilioFrom string
TwilioTo string
EmailRecipients []string
}
type SMTPConfig struct {
User string
Password string
Host string
Port uint
}
type RPCConfig struct {
HTTPPort uint
}
func (cfg *ConfigType) validate() error {
if cfg.Network == "" {
cfg.Network = defaultConfig.Network
}
if cfg.LAddr == "" {
cfg.LAddr = defaultConfig.LAddr
}
if cfg.SeedNode == "" {
cfg.SeedNode = defaultConfig.SeedNode
}
if cfg.DB.Backend == "" {
return errors.New("DB.Backend must be set")
}
return nil
}
func (cfg *ConfigType) bytes() []byte {
configBytes, err := json.MarshalIndent(cfg, "", "\t")
if err != nil {
panic(err)
}
return configBytes
}
func (cfg *ConfigType) write(configFile string) {
if strings.Index(configFile, "/") != -1 {
err := os.MkdirAll(filepath.Dir(configFile), 0700)
if err != nil {
panic(err)
}
}
err := ioutil.WriteFile(configFile, cfg.bytes(), 0600)
if err != nil {
panic(err)
}
}
//-----------------------------------------------------------------------------
var rootDir string var rootDir string
var defaultConfig ConfigType
func init() { func init() {
// Get RootDir
rootDir = os.Getenv("TMROOT") rootDir = os.Getenv("TMROOT")
if rootDir == "" { if rootDir == "" {
rootDir = os.Getenv("HOME") + "/.tendermint" rootDir = os.Getenv("HOME") + "/.tendermint"
} }
// Compute defaultConfig
defaultConfig = ConfigType{
Network: "tendermint_testnet0",
LAddr: "0.0.0.0:0",
SeedNode: "",
DB: DBConfig{
Backend: "leveldb",
Dir: DataDir(),
},
Alert: AlertConfig{},
SMTP: SMTPConfig{},
RPC: RPCConfig{
HTTPPort: 8888,
},
}
} }
func ConfigFile() string { return rootDir + "/config.json" } func ConfigFile() string { return rootDir + "/config.json" }
@ -51,11 +149,11 @@ func ParseFlags() {
Config = ConfigType{} Config = ConfigType{}
err = json.Unmarshal(configBytes, &Config) err = json.Unmarshal(configBytes, &Config)
if err != nil { if err != nil {
log.Panicf("Invalid configuration file %s: %v", configFile, err) Exitf("Invalid configuration file %s: %v", configFile, err)
} }
err = Config.validate() err = Config.validate()
if err != nil { if err != nil {
log.Panicf("Invalid configuration file %s: %v", configFile, err) Exitf("Invalid configuration file %s: %v", configFile, err)
} }
// try to parse arg flags, which can override file configuration. // try to parse arg flags, which can override file configuration.
@ -67,100 +165,3 @@ func ParseFlags() {
os.Exit(0) os.Exit(0)
} }
} }
//-----------------------------------------------------------------------------j
// Default configuration
var defaultConfig = ConfigType{
Network: "tendermint_testnet0",
LAddr: "0.0.0.0:0",
SeedNode: "",
Db: DbConfig{
Type: "level",
Dir: DataDir(),
},
Alert: AlertConfig{},
SMTP: SMTPConfig{},
RPC: RPCConfig{
HTTPPort: 8888,
},
}
//-----------------------------------------------------------------------------j
// Configuration types
type ConfigType struct {
Network string
LAddr string
SeedNode string
Db DbConfig
Alert AlertConfig
SMTP SMTPConfig
RPC RPCConfig
}
type DbConfig struct {
Type string
Dir string
}
type AlertConfig struct {
MinInterval int
TwilioSid string
TwilioToken string
TwilioFrom string
TwilioTo string
EmailRecipients []string
}
type SMTPConfig struct {
User string
Password string
Host string
Port uint
}
type RPCConfig struct {
HTTPPort uint
}
//-----------------------------------------------------------------------------j
func (cfg *ConfigType) validate() error {
if cfg.Network == "" {
cfg.Network = defaultConfig.Network
}
if cfg.LAddr == "" {
cfg.LAddr = defaultConfig.LAddr
}
if cfg.SeedNode == "" {
cfg.SeedNode = defaultConfig.SeedNode
}
if cfg.Db.Type == "" {
return errors.New("Db.Type must be set")
}
return nil
}
func (cfg *ConfigType) bytes() []byte {
configBytes, err := json.MarshalIndent(cfg, "", "\t")
if err != nil {
panic(err)
}
return configBytes
}
func (cfg *ConfigType) write(configFile string) {
if strings.Index(configFile, "/") != -1 {
err := os.MkdirAll(filepath.Dir(configFile), 0700)
if err != nil {
panic(err)
}
}
err := ioutil.WriteFile(configFile, cfg.bytes(), 0600)
if err != nil {
panic(err)
}
}

View File

@ -1,5 +1,12 @@
package db package db
import (
"path"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/config"
)
type DB interface { type DB interface {
Get([]byte) []byte Get([]byte) []byte
Set([]byte, []byte) Set([]byte, []byte)
@ -7,3 +14,33 @@ type DB interface {
Delete([]byte) Delete([]byte)
DeleteSync([]byte) DeleteSync([]byte)
} }
//-----------------------------------------------------------------------------
// Database types
const DBBackendMemDB = "memdb"
const DBBackendLevelDB = "leveldb"
var dbs = NewCMap()
func GetDB(name string) DB {
db := dbs.Get(name)
if db != nil {
return db.(DB)
}
switch Config.DB.Backend {
case DBBackendMemDB:
db := NewMemDB()
dbs.Set(name, db)
return db
case DBBackendLevelDB:
db, err := NewLevelDB(path.Join(Config.DB.Dir, name+".db"))
if err != nil {
panic(err)
}
dbs.Set(name, db)
return db
default:
panic("Unknown DB backend")
}
}

View File

@ -3,6 +3,7 @@ package db
import ( import (
"fmt" "fmt"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/errors"
"github.com/syndtr/goleveldb/leveldb/opt" "github.com/syndtr/goleveldb/leveldb/opt"
"path" "path"
) )
@ -24,8 +25,12 @@ func NewLevelDB(name string) (*LevelDB, error) {
func (db *LevelDB) Get(key []byte) []byte { func (db *LevelDB) Get(key []byte) []byte {
res, err := db.db.Get(key, nil) res, err := db.db.Get(key, nil)
if err != nil { if err != nil {
if err == errors.ErrNotFound {
return nil
} else {
panic(err) panic(err)
} }
}
return res return res
} }
@ -57,7 +62,7 @@ func (db *LevelDB) DeleteSync(key []byte) {
} }
} }
func (db *LevelDB) Db() *leveldb.DB { func (db *LevelDB) DB() *leveldb.DB {
return db.db return db.db
} }

View File

@ -1,6 +1,8 @@
package state package state
import ( import (
"bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"time" "time"
@ -13,10 +15,21 @@ import (
"github.com/tendermint/tendermint/merkle" "github.com/tendermint/tendermint/merkle"
) )
type GenesisAccount struct {
Address string
Amount uint64
}
type GenesisValidator struct {
PubKey string
Amount uint64
UnbondTo []GenesisAccount
}
type GenesisDoc struct { type GenesisDoc struct {
GenesisTime time.Time GenesisTime time.Time
Accounts []*Account Accounts []GenesisAccount
Validators []*ValidatorInfo Validators []GenesisValidator
} }
func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) { func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
@ -38,7 +51,7 @@ func MakeGenesisStateFromFile(db db_.DB, genDocFile string) *State {
func MakeGenesisState(db db_.DB, genDoc *GenesisDoc) *State { func MakeGenesisState(db db_.DB, genDoc *GenesisDoc) *State {
if len(genDoc.Validators) == 0 { if len(genDoc.Validators) == 0 {
panic("Must have some validators") Exitf("The genesis file has no validators")
} }
if genDoc.GenesisTime.IsZero() { if genDoc.GenesisTime.IsZero() {
@ -48,22 +61,59 @@ func MakeGenesisState(db db_.DB, genDoc *GenesisDoc) *State {
// Make accounts state tree // Make accounts state tree
accounts := merkle.NewIAVLTree(BasicCodec, AccountCodec, defaultAccountsCacheCapacity, db) accounts := merkle.NewIAVLTree(BasicCodec, AccountCodec, defaultAccountsCacheCapacity, db)
for _, acc := range genDoc.Accounts { for _, acc := range genDoc.Accounts {
accounts.Set(acc.Address, acc) address, err := base64.StdEncoding.DecodeString(acc.Address)
if err != nil {
Exitf("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 // Make validatorInfos state tree && validators slice
validatorInfos := merkle.NewIAVLTree(BasicCodec, ValidatorInfoCodec, 0, db) validatorInfos := merkle.NewIAVLTree(BasicCodec, ValidatorInfoCodec, 0, db)
for _, valInfo := range genDoc.Validators {
validatorInfos.Set(valInfo.Address, valInfo)
}
// Make validators
validators := make([]*Validator, len(genDoc.Validators)) validators := make([]*Validator, len(genDoc.Validators))
for i, valInfo := range genDoc.Validators { for i, val := range genDoc.Validators {
pubKeyBytes, err := base64.StdEncoding.DecodeString(val.PubKey)
if err != nil {
Exitf("Invalid validator pubkey: %v", val.PubKey)
}
pubKey := ReadBinary(PubKeyEd25519{},
bytes.NewBuffer(pubKeyBytes), new(int64), &err).(PubKeyEd25519)
if err != nil {
Exitf("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 := base64.StdEncoding.DecodeString(unbondTo.Address)
if err != nil {
Exitf("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{ validators[i] = &Validator{
Address: valInfo.Address, Address: address,
PubKey: valInfo.PubKey, PubKey: pubKey,
VotingPower: valInfo.FirstBondAmount, VotingPower: val.Amount,
} }
} }

View File

@ -126,6 +126,14 @@ func (privVal *PrivValidator) Save() {
} }
func (privVal *PrivValidator) save() { func (privVal *PrivValidator) save() {
jsonBytes := privVal.JSONBytes()
err := ioutil.WriteFile(privVal.filename, jsonBytes, 0700)
if err != nil {
panic(err)
}
}
func (privVal *PrivValidator) JSONBytes() []byte {
privValJSON := PrivValidatorJSON{ privValJSON := PrivValidatorJSON{
Address: base64.StdEncoding.EncodeToString(privVal.Address), Address: base64.StdEncoding.EncodeToString(privVal.Address),
PubKey: base64.StdEncoding.EncodeToString(BinaryBytes(privVal.PubKey)), PubKey: base64.StdEncoding.EncodeToString(BinaryBytes(privVal.PubKey)),
@ -134,14 +142,11 @@ func (privVal *PrivValidator) save() {
LastRound: privVal.LastRound, LastRound: privVal.LastRound,
LastStep: privVal.LastStep, LastStep: privVal.LastStep,
} }
privValJSONBytes, err := json.Marshal(privValJSON) privValJSONBytes, err := json.MarshalIndent(privValJSON, "", " ")
if err != nil {
panic(err)
}
err = ioutil.WriteFile(privVal.filename, privValJSONBytes, 0700)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return privValJSONBytes
} }
// TODO: test // TODO: test

View File

@ -108,6 +108,9 @@ func (s *State) Copy() *State {
} }
} }
// The accounts from the TxInputs must either already have
// account.PubKey.(type) != PubKeyNil, (it must be known),
// or it must be specified in the TxInput. But not both.
func (s *State) GetOrMakeAccounts(ins []*TxInput, outs []*TxOutput) (map[string]*Account, error) { func (s *State) GetOrMakeAccounts(ins []*TxInput, outs []*TxOutput) (map[string]*Account, error) {
accounts := map[string]*Account{} accounts := map[string]*Account{}
for _, in := range ins { for _, in := range ins {
@ -119,6 +122,20 @@ func (s *State) GetOrMakeAccounts(ins []*TxInput, outs []*TxOutput) (map[string]
if account == nil { if account == nil {
return nil, ErrTxInvalidAddress return nil, ErrTxInvalidAddress
} }
// PubKey should be present in either "account" or "in"
if _, isNil := account.PubKey.(PubKeyNil); isNil {
if _, isNil := in.PubKey.(PubKeyNil); isNil {
return nil, ErrTxUnknownPubKey
}
if !bytes.Equal(in.PubKey.Address(), account.Address) {
return nil, ErrTxInvalidPubKey
}
account.PubKey = in.PubKey
} else {
if _, isNil := in.PubKey.(PubKeyNil); !isNil {
return nil, ErrTxRedeclaredPubKey
}
}
accounts[string(in.Address)] = account accounts[string(in.Address)] = account
} }
for _, out := range outs { for _, out := range outs {
@ -129,7 +146,12 @@ func (s *State) GetOrMakeAccounts(ins []*TxInput, outs []*TxOutput) (map[string]
account := s.GetAccount(out.Address) account := s.GetAccount(out.Address)
// output account may be nil (new) // output account may be nil (new)
if account == nil { if account == nil {
account = NewAccount(NewPubKeyUnknown(out.Address)) account = &Account{
Address: out.Address,
PubKey: PubKeyNil{},
Sequence: 0,
Balance: 0,
}
} }
accounts[string(out.Address)] = account accounts[string(out.Address)] = account
} }

View File

@ -2,9 +2,11 @@ package state
import ( import (
"bytes" "bytes"
"encoding/base64"
"sort" "sort"
. "github.com/tendermint/tendermint/account" . "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/block" . "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common" . "github.com/tendermint/tendermint/common"
db_ "github.com/tendermint/tendermint/db" db_ "github.com/tendermint/tendermint/db"
@ -24,9 +26,12 @@ func Tempfile(prefix string) (*os.File, string) {
func RandAccount(randBalance bool, minBalance uint64) (*Account, *PrivAccount) { func RandAccount(randBalance bool, minBalance uint64) (*Account, *PrivAccount) {
privAccount := GenPrivAccount() privAccount := GenPrivAccount()
account := NewAccount(privAccount.PubKey) account := &Account{
account.Sequence = RandUint() Address: privAccount.PubKey.Address(),
account.Balance = minBalance PubKey: privAccount.PubKey,
Sequence: RandUint(),
Balance: minBalance,
}
if randBalance { if randBalance {
account.Balance += uint64(RandUint32()) account.Balance += uint64(RandUint32())
} }
@ -53,20 +58,32 @@ func RandValidator(randBonded bool, minBonded uint64) (*ValidatorInfo, *PrivVali
return valInfo, privVal return valInfo, privVal
} }
// The first numValidators accounts are validators.
func RandGenesisState(numAccounts int, randBalance bool, minBalance uint64, numValidators int, randBonded bool, minBonded uint64) (*State, []*PrivAccount, []*PrivValidator) { func RandGenesisState(numAccounts int, randBalance bool, minBalance uint64, numValidators int, randBonded bool, minBonded uint64) (*State, []*PrivAccount, []*PrivValidator) {
db := db_.NewMemDB() db := db_.NewMemDB()
accounts := make([]*Account, numAccounts) accounts := make([]GenesisAccount, numAccounts)
privAccounts := make([]*PrivAccount, numAccounts) privAccounts := make([]*PrivAccount, numAccounts)
for i := 0; i < numAccounts; i++ { for i := 0; i < numAccounts; i++ {
account, privAccount := RandAccount(randBalance, minBalance) account, privAccount := RandAccount(randBalance, minBalance)
accounts[i], privAccounts[i] = account, privAccount accounts[i] = GenesisAccount{
Address: base64.StdEncoding.EncodeToString(account.Address),
Amount: account.Balance,
} }
validators := make([]*ValidatorInfo, numValidators) privAccounts[i] = privAccount
}
validators := make([]GenesisValidator, numValidators)
privValidators := make([]*PrivValidator, numValidators) privValidators := make([]*PrivValidator, numValidators)
for i := 0; i < numValidators; i++ { for i := 0; i < numValidators; i++ {
valInfo, privVal := RandValidator(randBonded, minBonded) valInfo, privVal := RandValidator(randBonded, minBonded)
validators[i] = valInfo validators[i] = GenesisValidator{
PubKey: base64.StdEncoding.EncodeToString(BinaryBytes(valInfo.PubKey)),
Amount: valInfo.FirstBondAmount,
UnbondTo: []GenesisAccount{
{
Address: base64.StdEncoding.EncodeToString(valInfo.PubKey.Address()),
Amount: valInfo.FirstBondAmount,
},
},
}
privValidators[i] = privVal privValidators[i] = privVal
} }
sort.Sort(PrivValidatorsByAddress(privValidators)) sort.Sort(PrivValidatorsByAddress(privValidators))