mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 14:52:17 +00:00
state save/load test.
This commit is contained in:
parent
b73b7a54c7
commit
08f86176fc
@ -47,7 +47,7 @@ func (b *Block) ValidateBasic(lastBlockHeight uint32, lastBlockHash []byte) erro
|
|||||||
if b.Header.Network != Config.Network {
|
if b.Header.Network != Config.Network {
|
||||||
return ErrBlockInvalidNetwork
|
return ErrBlockInvalidNetwork
|
||||||
}
|
}
|
||||||
if b.Header.Height != lastBlockHeight {
|
if b.Header.Height != lastBlockHeight+1 {
|
||||||
return ErrBlockInvalidBlockHeight
|
return ErrBlockInvalidBlockHeight
|
||||||
}
|
}
|
||||||
if !bytes.Equal(b.Header.LastBlockHash, lastBlockHash) {
|
if !bytes.Equal(b.Header.LastBlockHash, lastBlockHash) {
|
||||||
|
@ -19,13 +19,13 @@ import (
|
|||||||
var RootDir string
|
var RootDir string
|
||||||
var Config Config_
|
var Config Config_
|
||||||
|
|
||||||
func initFlags(printHelp *bool) {
|
func setFlags(printHelp *bool) {
|
||||||
flag.BoolVar(printHelp, "help", false, "Print this help message.")
|
flag.BoolVar(printHelp, "help", false, "Print this help message.")
|
||||||
flag.StringVar(&Config.LAddr, "laddr", Config.LAddr, "Listen address. (0.0.0.0:0 means any interface, any port)")
|
flag.StringVar(&Config.LAddr, "laddr", Config.LAddr, "Listen address. (0.0.0.0:0 means any interface, any port)")
|
||||||
flag.StringVar(&Config.Seed, "seed", Config.Seed, "Address of seed node")
|
flag.StringVar(&Config.Seed, "seed", Config.Seed, "Address of seed node")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func ParseFlags() {
|
||||||
RootDir = os.Getenv("TMROOT")
|
RootDir = os.Getenv("TMROOT")
|
||||||
if RootDir == "" {
|
if RootDir == "" {
|
||||||
RootDir = os.Getenv("HOME") + "/.tendermint"
|
RootDir = os.Getenv("HOME") + "/.tendermint"
|
||||||
@ -54,7 +54,7 @@ func init() {
|
|||||||
|
|
||||||
// try to parse arg flags, which can override file configuration.
|
// try to parse arg flags, which can override file configuration.
|
||||||
var printHelp bool
|
var printHelp bool
|
||||||
initFlags(&printHelp)
|
setFlags(&printHelp)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if printHelp {
|
if printHelp {
|
||||||
fmt.Println("----------------------------------")
|
fmt.Println("----------------------------------")
|
||||||
|
@ -418,7 +418,7 @@ func (cs *ConsensusState) stageBlock(block *Block) error {
|
|||||||
stateCopy := cs.state.Copy() // Deep copy the state before staging.
|
stateCopy := cs.state.Copy() // Deep copy the state before staging.
|
||||||
|
|
||||||
// Commit block onto the copied state.
|
// Commit block onto the copied state.
|
||||||
err := stateCopy.CommitBlock(block)
|
err := stateCopy.AppendBlock(block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
|
4
log.go
4
log.go
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/tendermint/tendermint/consensus"
|
"github.com/tendermint/tendermint/consensus"
|
||||||
"github.com/tendermint/tendermint/mempool"
|
"github.com/tendermint/tendermint/mempool"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logging.MustGetLogger("main")
|
var log = logging.MustGetLogger("main")
|
||||||
@ -31,6 +32,7 @@ func init() {
|
|||||||
|
|
||||||
blocks.SetBlocksLogger(log)
|
blocks.SetBlocksLogger(log)
|
||||||
consensus.SetConsensusLogger(log)
|
consensus.SetConsensusLogger(log)
|
||||||
p2p.SetP2PLogger(log)
|
|
||||||
mempool.SetMempoolLogger(log)
|
mempool.SetMempoolLogger(log)
|
||||||
|
p2p.SetP2PLogger(log)
|
||||||
|
state.SetStateLogger(log)
|
||||||
}
|
}
|
||||||
|
3
main.go
3
main.go
@ -78,6 +78,9 @@ func (n *Node) inboundConnectionRoutine(l p2p.Listener) {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
// Parse config flags
|
||||||
|
config.ParseFlags()
|
||||||
|
|
||||||
// Create & start node
|
// Create & start node
|
||||||
n := NewNode()
|
n := NewNode()
|
||||||
l := p2p.NewDefaultListener("tcp", config.Config.LAddr)
|
l := p2p.NewDefaultListener("tcp", config.Config.LAddr)
|
||||||
|
@ -34,7 +34,7 @@ func NewMempool(lastBlock *Block, state *State) *Mempool {
|
|||||||
func (mem *Mempool) AddTx(tx Tx) (err error) {
|
func (mem *Mempool) AddTx(tx Tx) (err error) {
|
||||||
mem.mtx.Lock()
|
mem.mtx.Lock()
|
||||||
defer mem.mtx.Unlock()
|
defer mem.mtx.Unlock()
|
||||||
err = mem.state.CommitTx(tx)
|
err = mem.state.ExecTx(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@ -82,7 +82,7 @@ func (mem *Mempool) ResetForBlockAndState(block *Block, state *State) {
|
|||||||
// Next, filter all txs that aren't valid given new state.
|
// Next, filter all txs that aren't valid given new state.
|
||||||
validTxs := []Tx{}
|
validTxs := []Tx{}
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
err := mem.state.CommitTx(tx)
|
err := mem.state.ExecTx(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
validTxs = append(validTxs, tx)
|
validTxs = append(validTxs, tx)
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,7 +42,7 @@ will be at different levels.
|
|||||||
func HashFromHashes(hashes [][]byte) []byte {
|
func HashFromHashes(hashes [][]byte) []byte {
|
||||||
switch len(hashes) {
|
switch len(hashes) {
|
||||||
case 0:
|
case 0:
|
||||||
panic("Cannot compute hash of empty slice")
|
return nil
|
||||||
case 1:
|
case 1:
|
||||||
return hashes[0]
|
return hashes[0]
|
||||||
default:
|
default:
|
||||||
|
15
state/log.go
Normal file
15
state/log.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/op/go-logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
var log = logging.MustGetLogger("state")
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logging.SetFormatter(logging.MustStringFormatter("[%{level:.1s}] %{message}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetStatesLogger(l *logging.Logger) {
|
||||||
|
log = l
|
||||||
|
}
|
@ -13,7 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrStateInvalidSequenceNumber = errors.New("Error State invalid sequence number")
|
ErrStateInvalidSequenceNumber = errors.New("Error State invalid sequence number")
|
||||||
|
ErrStateInvalidValidationStateHash = errors.New("Error State invalid ValidationStateHash")
|
||||||
|
ErrStateInvalidAccountStateHash = errors.New("Error State invalid AccountStateHash")
|
||||||
|
|
||||||
stateKey = []byte("stateKey")
|
stateKey = []byte("stateKey")
|
||||||
)
|
)
|
||||||
@ -33,6 +35,7 @@ func (abc accountBalanceCodec) Read(accBalBytes []byte) (interface{}, error) {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO: make it unsafe, remove mtx, and export fields?
|
||||||
type State struct {
|
type State struct {
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
db DB
|
db DB
|
||||||
@ -175,7 +178,17 @@ func (s *State) AppendBlock(b *Block) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increment validator AccumPowers
|
||||||
s.validators.IncrementAccum()
|
s.validators.IncrementAccum()
|
||||||
|
|
||||||
|
// State hashes should match
|
||||||
|
if !bytes.Equal(s.validators.Hash(), b.ValidationStateHash) {
|
||||||
|
return ErrStateInvalidValidationStateHash
|
||||||
|
}
|
||||||
|
if !bytes.Equal(s.accountBalances.Tree.Hash(), b.AccountStateHash) {
|
||||||
|
return ErrStateInvalidAccountStateHash
|
||||||
|
}
|
||||||
|
|
||||||
s.height = b.Height
|
s.height = b.Height
|
||||||
s.blockHash = b.Hash()
|
s.blockHash = b.Hash()
|
||||||
return nil
|
return nil
|
||||||
@ -193,13 +206,20 @@ func (s *State) CommitTime() time.Time {
|
|||||||
return s.commitTime
|
return s.commitTime
|
||||||
}
|
}
|
||||||
|
|
||||||
// The returned ValidatorSet gets mutated upon s.Commit*().
|
// The returned ValidatorSet gets mutated upon s.ExecTx() and s.AppendBlock().
|
||||||
|
// Caller should copy the returned set before mutating.
|
||||||
func (s *State) Validators() *ValidatorSet {
|
func (s *State) Validators() *ValidatorSet {
|
||||||
s.mtx.Lock()
|
s.mtx.Lock()
|
||||||
defer s.mtx.Unlock()
|
defer s.mtx.Unlock()
|
||||||
return s.validators
|
return s.validators
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *State) BlockHash() []byte {
|
||||||
|
s.mtx.Lock()
|
||||||
|
defer s.mtx.Unlock()
|
||||||
|
return s.blockHash
|
||||||
|
}
|
||||||
|
|
||||||
func (s *State) AccountBalance(accountId uint64) *AccountBalance {
|
func (s *State) AccountBalance(accountId uint64) *AccountBalance {
|
||||||
s.mtx.Lock()
|
s.mtx.Lock()
|
||||||
defer s.mtx.Unlock()
|
defer s.mtx.Unlock()
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
. "github.com/tendermint/tendermint/config"
|
||||||
. "github.com/tendermint/tendermint/db"
|
. "github.com/tendermint/tendermint/db"
|
||||||
|
|
||||||
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -38,9 +41,27 @@ func TestGenesisSaveLoad(t *testing.T) {
|
|||||||
|
|
||||||
// Generate a state, save & load it.
|
// Generate a state, save & load it.
|
||||||
s0 := randGenesisState(10, 5)
|
s0 := randGenesisState(10, 5)
|
||||||
// Mutate the state to append one block.
|
// Figure out what the next state hashes should be.
|
||||||
block := &Block{Data: Data{Txs: []Tx{}}}
|
s0ValsCopy := s0.Validators().Copy()
|
||||||
s0.AppendBlock(block)
|
s0ValsCopy.IncrementAccum()
|
||||||
|
nextValidationStateHash := s0ValsCopy.Hash()
|
||||||
|
nextAccountStateHash := s0.accountBalances.Tree.Hash()
|
||||||
|
// Mutate the state to append one empty block.
|
||||||
|
block := &Block{
|
||||||
|
Header: Header{
|
||||||
|
Network: Config.Network,
|
||||||
|
Height: 1,
|
||||||
|
ValidationStateHash: nextValidationStateHash,
|
||||||
|
AccountStateHash: nextAccountStateHash,
|
||||||
|
},
|
||||||
|
Data: Data{
|
||||||
|
Txs: []Tx{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err := s0.AppendBlock(block)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error appending initial block:", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Save s0, load s1.
|
// Save s0, load s1.
|
||||||
commitTime := time.Now()
|
commitTime := time.Now()
|
||||||
@ -53,7 +74,15 @@ func TestGenesisSaveLoad(t *testing.T) {
|
|||||||
t.Error("CommitTime was not the same")
|
t.Error("CommitTime was not the same")
|
||||||
}
|
}
|
||||||
// Compare height & blockHash
|
// Compare height & blockHash
|
||||||
// XXX
|
if s0.Height() != 1 {
|
||||||
|
t.Error("s0 Height should be 1, got", s0.Height())
|
||||||
|
}
|
||||||
|
if s0.Height() != s1.Height() {
|
||||||
|
t.Error("Height mismatch")
|
||||||
|
}
|
||||||
|
if !bytes.Equal(s0.BlockHash(), s1.BlockHash()) {
|
||||||
|
t.Error("BlockHash mismatch")
|
||||||
|
}
|
||||||
// Compare Validators
|
// Compare Validators
|
||||||
s0Vals := s0.Validators()
|
s0Vals := s0.Validators()
|
||||||
s1Vals := s1.Validators()
|
s1Vals := s1.Validators()
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
"github.com/tendermint/tendermint/merkle"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Holds state for a Validator at a given height+round.
|
// Holds state for a Validator at a given height+round.
|
||||||
@ -155,3 +156,17 @@ func (vset *ValidatorSet) GetProposer() (proposer *Validator) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should uniquely determine the state of the ValidatorSet.
|
||||||
|
func (vset *ValidatorSet) Hash() []byte {
|
||||||
|
ids := []uint64{}
|
||||||
|
for id, _ := range vset.validators {
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
UInt64Slice(ids).Sort()
|
||||||
|
sortedValidators := make([]Binary, len(ids))
|
||||||
|
for i, id := range ids {
|
||||||
|
sortedValidators[i] = vset.validators[id]
|
||||||
|
}
|
||||||
|
return merkle.HashFromBinaries(sortedValidators)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user