mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-21 17:01:35 +00:00
Refactoring genesis, including PubKey into TxInput
This commit is contained in:
@ -36,16 +36,6 @@ type Account struct {
|
||||
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 {
|
||||
accountCopy := *account
|
||||
return &accountCopy
|
||||
|
@ -26,7 +26,7 @@ const (
|
||||
func PrivKeyDecoder(r io.Reader, n *int64, err *error) interface{} {
|
||||
switch t := ReadByte(r, n, err); t {
|
||||
case PrivKeyTypeEd25519:
|
||||
return ReadBinary(&PrivKeyEd25519{}, r, n, err)
|
||||
return ReadBinary(PrivKeyEd25519{}, r, n, err)
|
||||
default:
|
||||
*err = Errorf("Unknown PrivKey type %X", t)
|
||||
return nil
|
||||
|
@ -18,8 +18,9 @@ type PubKey interface {
|
||||
|
||||
// Types of PubKey implementations
|
||||
const (
|
||||
PubKeyTypeUnknown = byte(0x00) // For pay-to-pubkey-hash txs.
|
||||
PubKeyTypeEd25519 = byte(0x01)
|
||||
PubKeyTypeNil = byte(0x00)
|
||||
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{} {
|
||||
switch t := ReadByte(r, n, err); t {
|
||||
case PubKeyTypeUnknown:
|
||||
return PubKeyUnknown{}
|
||||
case PubKeyTypeNil:
|
||||
return PubKeyNil{}
|
||||
case PubKeyTypeEd25519:
|
||||
return ReadBinary(&PubKeyEd25519{}, r, n, err)
|
||||
return ReadBinary(PubKeyEd25519{}, r, n, err)
|
||||
default:
|
||||
*err = Errorf("Unknown PubKey type %X", t)
|
||||
return nil
|
||||
@ -45,22 +46,16 @@ var _ = RegisterType(&TypeInfo{
|
||||
//-------------------------------------
|
||||
|
||||
// Implements PubKey
|
||||
// For pay-to-pubkey-hash txs, where the TxOutput PubKey
|
||||
// is not known in advance, only its hash (address).
|
||||
type PubKeyUnknown struct {
|
||||
address []byte
|
||||
type PubKeyNil struct{}
|
||||
|
||||
func (key PubKeyNil) TypeByte() byte { return PubKeyTypeNil }
|
||||
|
||||
func (key PubKeyNil) Address() []byte {
|
||||
panic("PubKeyNil has no address")
|
||||
}
|
||||
|
||||
func NewPubKeyUnknown(address []byte) PubKeyUnknown { return PubKeyUnknown{address} }
|
||||
|
||||
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")
|
||||
func (key PubKeyNil) VerifyBytes(msg []byte, sig_ Signature) bool {
|
||||
panic("PubKeyNil cannot verify messages")
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -25,7 +25,7 @@ const (
|
||||
func SignatureDecoder(r io.Reader, n *int64, err *error) interface{} {
|
||||
switch t := ReadByte(r, n, err); t {
|
||||
case SignatureTypeEd25519:
|
||||
return ReadBinary(&SignatureEd25519{}, r, n, err)
|
||||
return ReadBinary(SignatureEd25519{}, r, n, err)
|
||||
default:
|
||||
*err = Errorf("Unknown Signature type %X", t)
|
||||
return nil
|
||||
|
@ -159,7 +159,7 @@ func ReadUint64(r io.Reader, n *int64, err *error) uint64 {
|
||||
// Varint
|
||||
|
||||
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 += n_
|
||||
WriteTo(buf[:n_], w, n, err)
|
||||
@ -175,7 +175,7 @@ func ReadVarint(r io.Reader, n *int64, err *error) int {
|
||||
// Uvarint
|
||||
|
||||
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 += n_
|
||||
WriteTo(buf[:n_], w, n, err)
|
||||
|
@ -15,6 +15,9 @@ var (
|
||||
ErrTxDuplicateAddress = errors.New("Error duplicate address")
|
||||
ErrTxInvalidAmount = errors.New("Error invalid amount")
|
||||
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")
|
||||
ErrTxInvalidSequence = errors.New("Error invalid sequence")
|
||||
)
|
||||
@ -79,6 +82,7 @@ type TxInput struct {
|
||||
Amount uint64 // Must not exceed account balance
|
||||
Sequence uint // Must be 1 greater than the last committed TxInput
|
||||
Signature Signature // Depends on the PubKey type and the whole Tx
|
||||
PubKey PubKey // Optional, may be nil
|
||||
}
|
||||
|
||||
func (txIn *TxInput) ValidateBasic() error {
|
||||
|
@ -26,11 +26,11 @@ type Node struct {
|
||||
|
||||
func NewNode() *Node {
|
||||
// Get BlockStore
|
||||
blockStoreDB := db_.NewMemDB() // TODO configurable db.
|
||||
blockStoreDB := db_.GetDB("blockstore")
|
||||
blockStore := block.NewBlockStore(blockStoreDB)
|
||||
|
||||
// Get State
|
||||
stateDB := db_.NewMemDB() // TODO configurable db.
|
||||
stateDB := db_.GetDB("state")
|
||||
state := state_.LoadState(stateDB)
|
||||
if state == nil {
|
||||
state = state_.MakeGenesisStateFromFile(stateDB, config.GenesisFile())
|
||||
|
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
@ -10,14 +9,15 @@ import (
|
||||
|
||||
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.Save()
|
||||
fmt.Printf("Generated a new validator at %v\n", filename)
|
||||
privValidatorJSONBytes := privValidator.JSONBytes()
|
||||
fmt.Printf(`Generated a new validator!
|
||||
Paste the following JSON into your %v file
|
||||
|
||||
%v
|
||||
|
||||
`,
|
||||
config.PrivValidatorFile(),
|
||||
string(privValidatorJSONBytes),
|
||||
)
|
||||
}
|
||||
|
@ -2,9 +2,7 @@ package common
|
||||
|
||||
import "sync"
|
||||
|
||||
/*
|
||||
CMap is a threadsafe map
|
||||
*/
|
||||
// CMap is a goroutine-safe map
|
||||
type CMap struct {
|
||||
m map[string]interface{}
|
||||
l sync.Mutex
|
||||
|
@ -2,8 +2,14 @@ package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func Panicf(s string, args ...interface{}) {
|
||||
panic(fmt.Sprintf(s, args...))
|
||||
}
|
||||
|
||||
func Exitf(s string, args ...interface{}) {
|
||||
fmt.Printf(s+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
201
config/config.go
201
config/config.go
@ -6,19 +6,117 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"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 defaultConfig ConfigType
|
||||
|
||||
func init() {
|
||||
// Get RootDir
|
||||
rootDir = os.Getenv("TMROOT")
|
||||
if rootDir == "" {
|
||||
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" }
|
||||
@ -51,11 +149,11 @@ func ParseFlags() {
|
||||
Config = ConfigType{}
|
||||
err = json.Unmarshal(configBytes, &Config)
|
||||
if err != nil {
|
||||
log.Panicf("Invalid configuration file %s: %v", configFile, err)
|
||||
Exitf("Invalid configuration file %s: %v", configFile, err)
|
||||
}
|
||||
err = Config.validate()
|
||||
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.
|
||||
@ -67,100 +165,3 @@ func ParseFlags() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
37
db/db.go
37
db/db.go
@ -1,5 +1,12 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
. "github.com/tendermint/tendermint/config"
|
||||
)
|
||||
|
||||
type DB interface {
|
||||
Get([]byte) []byte
|
||||
Set([]byte, []byte)
|
||||
@ -7,3 +14,33 @@ type DB interface {
|
||||
Delete([]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")
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package db
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||
"github.com/syndtr/goleveldb/leveldb/opt"
|
||||
"path"
|
||||
)
|
||||
@ -24,8 +25,12 @@ func NewLevelDB(name string) (*LevelDB, error) {
|
||||
func (db *LevelDB) Get(key []byte) []byte {
|
||||
res, err := db.db.Get(key, nil)
|
||||
if err != nil {
|
||||
if err == errors.ErrNotFound {
|
||||
return nil
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
@ -13,10 +15,21 @@ import (
|
||||
"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 []*Account
|
||||
Validators []*ValidatorInfo
|
||||
Accounts []GenesisAccount
|
||||
Validators []GenesisValidator
|
||||
}
|
||||
|
||||
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 {
|
||||
if len(genDoc.Validators) == 0 {
|
||||
panic("Must have some validators")
|
||||
Exitf("The genesis file has no validators")
|
||||
}
|
||||
|
||||
if genDoc.GenesisTime.IsZero() {
|
||||
@ -48,22 +61,59 @@ func MakeGenesisState(db db_.DB, genDoc *GenesisDoc) *State {
|
||||
// Make accounts state tree
|
||||
accounts := merkle.NewIAVLTree(BasicCodec, AccountCodec, defaultAccountsCacheCapacity, db)
|
||||
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)
|
||||
for _, valInfo := range genDoc.Validators {
|
||||
validatorInfos.Set(valInfo.Address, valInfo)
|
||||
}
|
||||
|
||||
// Make 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{
|
||||
Address: valInfo.Address,
|
||||
PubKey: valInfo.PubKey,
|
||||
VotingPower: valInfo.FirstBondAmount,
|
||||
Address: address,
|
||||
PubKey: pubKey,
|
||||
VotingPower: val.Amount,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,6 +126,14 @@ 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{
|
||||
Address: base64.StdEncoding.EncodeToString(privVal.Address),
|
||||
PubKey: base64.StdEncoding.EncodeToString(BinaryBytes(privVal.PubKey)),
|
||||
@ -134,14 +142,11 @@ func (privVal *PrivValidator) save() {
|
||||
LastRound: privVal.LastRound,
|
||||
LastStep: privVal.LastStep,
|
||||
}
|
||||
privValJSONBytes, err := json.Marshal(privValJSON)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = ioutil.WriteFile(privVal.filename, privValJSONBytes, 0700)
|
||||
privValJSONBytes, err := json.MarshalIndent(privValJSON, "", " ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return privValJSONBytes
|
||||
}
|
||||
|
||||
// TODO: test
|
||||
|
@ -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) {
|
||||
accounts := map[string]*Account{}
|
||||
for _, in := range ins {
|
||||
@ -119,6 +122,20 @@ func (s *State) GetOrMakeAccounts(ins []*TxInput, outs []*TxOutput) (map[string]
|
||||
if account == nil {
|
||||
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
|
||||
}
|
||||
for _, out := range outs {
|
||||
@ -129,7 +146,12 @@ func (s *State) GetOrMakeAccounts(ins []*TxInput, outs []*TxOutput) (map[string]
|
||||
account := s.GetAccount(out.Address)
|
||||
// output account may be nil (new)
|
||||
if account == nil {
|
||||
account = NewAccount(NewPubKeyUnknown(out.Address))
|
||||
account = &Account{
|
||||
Address: out.Address,
|
||||
PubKey: PubKeyNil{},
|
||||
Sequence: 0,
|
||||
Balance: 0,
|
||||
}
|
||||
}
|
||||
accounts[string(out.Address)] = account
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"sort"
|
||||
|
||||
. "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"
|
||||
@ -24,9 +26,12 @@ func Tempfile(prefix string) (*os.File, string) {
|
||||
|
||||
func RandAccount(randBalance bool, minBalance uint64) (*Account, *PrivAccount) {
|
||||
privAccount := GenPrivAccount()
|
||||
account := NewAccount(privAccount.PubKey)
|
||||
account.Sequence = RandUint()
|
||||
account.Balance = minBalance
|
||||
account := &Account{
|
||||
Address: privAccount.PubKey.Address(),
|
||||
PubKey: privAccount.PubKey,
|
||||
Sequence: RandUint(),
|
||||
Balance: minBalance,
|
||||
}
|
||||
if randBalance {
|
||||
account.Balance += uint64(RandUint32())
|
||||
}
|
||||
@ -53,20 +58,32 @@ func RandValidator(randBonded bool, minBonded uint64) (*ValidatorInfo, *PrivVali
|
||||
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) {
|
||||
db := db_.NewMemDB()
|
||||
accounts := make([]*Account, numAccounts)
|
||||
accounts := make([]GenesisAccount, numAccounts)
|
||||
privAccounts := make([]*PrivAccount, numAccounts)
|
||||
for i := 0; i < numAccounts; i++ {
|
||||
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)
|
||||
for i := 0; i < numValidators; i++ {
|
||||
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
|
||||
}
|
||||
sort.Sort(PrivValidatorsByAddress(privValidators))
|
||||
|
Reference in New Issue
Block a user