mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-13 05:11:21 +00:00
everything but binary, common, and blocks are explicitly imported.
This commit is contained in:
@ -13,9 +13,9 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "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"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -102,7 +102,7 @@ type ConsensusReactor struct {
|
|||||||
doActionCh chan RoundAction
|
doActionCh chan RoundAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConsensusReactor(sw *p2p.Switch, blockStore *BlockStore, mempool *Mempool, state *State) *ConsensusReactor {
|
func NewConsensusReactor(sw *p2p.Switch, blockStore *BlockStore, mempool *mempool.Mempool, state *state.State) *ConsensusReactor {
|
||||||
conS := NewConsensusState(state, blockStore, mempool)
|
conS := NewConsensusState(state, blockStore, mempool)
|
||||||
conR := &ConsensusReactor{
|
conR := &ConsensusReactor{
|
||||||
sw: sw,
|
sw: sw,
|
||||||
|
9
consensus/part_set_test.go
Normal file
9
consensus/part_set_test.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package consensus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBasicPartSet(t *testing.T) {
|
||||||
|
// XXX this is fun!
|
||||||
|
}
|
@ -6,7 +6,7 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Proof of lock.
|
// Proof of lock.
|
||||||
@ -42,7 +42,7 @@ func (pol *POL) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns whether +2/3 have voted/committed for BlockHash.
|
// Returns whether +2/3 have voted/committed for BlockHash.
|
||||||
func (pol *POL) Verify(vset *ValidatorSet) error {
|
func (pol *POL) Verify(vset *state.ValidatorSet) error {
|
||||||
|
|
||||||
talliedVotingPower := uint64(0)
|
talliedVotingPower := uint64(0)
|
||||||
voteDoc := BinaryBytes(&Vote{Height: pol.Height, Round: pol.Round,
|
voteDoc := BinaryBytes(&Vote{Height: pol.Height, Round: pol.Round,
|
||||||
|
@ -3,13 +3,13 @@ package consensus
|
|||||||
import (
|
import (
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
db_ "github.com/tendermint/tendermint/db"
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
. "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
type PrivValidator struct {
|
type PrivValidator struct {
|
||||||
PrivAccount
|
state.PrivAccount
|
||||||
db *db_.LevelDB
|
db *db_.LevelDB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/mempool"
|
"github.com/tendermint/tendermint/mempool"
|
||||||
. "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -32,8 +32,8 @@ type RoundState struct {
|
|||||||
Round uint16
|
Round uint16
|
||||||
Step uint8
|
Step uint8
|
||||||
StartTime time.Time
|
StartTime time.Time
|
||||||
Validators *ValidatorSet
|
Validators *state.ValidatorSet
|
||||||
Proposer *Validator
|
Proposer *state.Validator
|
||||||
Proposal *Proposal
|
Proposal *Proposal
|
||||||
ProposalBlock *Block
|
ProposalBlock *Block
|
||||||
ProposalBlockPartSet *PartSet
|
ProposalBlockPartSet *PartSet
|
||||||
@ -52,16 +52,16 @@ type RoundState struct {
|
|||||||
// Tracks consensus state across block heights and rounds.
|
// Tracks consensus state across block heights and rounds.
|
||||||
type ConsensusState struct {
|
type ConsensusState struct {
|
||||||
blockStore *BlockStore
|
blockStore *BlockStore
|
||||||
mempool *Mempool
|
mempool *mempool.Mempool
|
||||||
|
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
RoundState
|
RoundState
|
||||||
state *State // State until height-1.
|
state *state.State // State until height-1.
|
||||||
stagedBlock *Block // Cache last staged block.
|
stagedBlock *Block // Cache last staged block.
|
||||||
stagedState *State // Cache result of staged block.
|
stagedState *state.State // Cache result of staged block.
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConsensusState(state *State, blockStore *BlockStore, mempool *Mempool) *ConsensusState {
|
func NewConsensusState(state *state.State, blockStore *BlockStore, mempool *mempool.Mempool) *ConsensusState {
|
||||||
cs := &ConsensusState{
|
cs := &ConsensusState{
|
||||||
blockStore: blockStore,
|
blockStore: blockStore,
|
||||||
mempool: mempool,
|
mempool: mempool,
|
||||||
@ -77,7 +77,7 @@ func (cs *ConsensusState) GetRoundState() *RoundState {
|
|||||||
return &rs
|
return &rs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ConsensusState) updateToState(state *State) {
|
func (cs *ConsensusState) updateToState(state *state.State) {
|
||||||
// Sanity check state.
|
// Sanity check state.
|
||||||
stateHeight := state.Height
|
stateHeight := state.Height
|
||||||
if stateHeight > 0 && stateHeight != cs.Height+1 {
|
if stateHeight > 0 && stateHeight != cs.Height+1 {
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VoteSet helps collect signatures from validators at each height+round
|
// VoteSet helps collect signatures from validators at each height+round
|
||||||
@ -23,7 +23,7 @@ type VoteSet struct {
|
|||||||
type_ byte
|
type_ byte
|
||||||
|
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
vset *ValidatorSet
|
vset *state.ValidatorSet
|
||||||
votes map[uint64]*Vote
|
votes map[uint64]*Vote
|
||||||
votesBitArray BitArray
|
votesBitArray BitArray
|
||||||
votesByBlockHash map[string]uint64
|
votesByBlockHash map[string]uint64
|
||||||
@ -33,7 +33,7 @@ type VoteSet struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new VoteSet struct used to accumulate votes for each round.
|
// Constructs a new VoteSet struct used to accumulate votes for each round.
|
||||||
func NewVoteSet(height uint32, round uint16, type_ byte, vset *ValidatorSet) *VoteSet {
|
func NewVoteSet(height uint32, round uint16, type_ byte, vset *state.ValidatorSet) *VoteSet {
|
||||||
if type_ == VoteTypeCommit && round != 0 {
|
if type_ == VoteTypeCommit && round != 0 {
|
||||||
panic("Expected round 0 for commit vote set")
|
panic("Expected round 0 for commit vote set")
|
||||||
}
|
}
|
||||||
|
@ -3,29 +3,29 @@ package consensus
|
|||||||
import (
|
import (
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeValidator(id uint64, votingPower uint64) (*Validator, *PrivAccount) {
|
func makeValidator(id uint64, votingPower uint64) (*state.Validator, *state.PrivAccount) {
|
||||||
privAccount := GenPrivAccount()
|
privAccount := state.GenPrivAccount()
|
||||||
privAccount.Id = id
|
privAccount.Id = id
|
||||||
return &Validator{
|
return &state.Validator{
|
||||||
Account: privAccount.Account,
|
Account: privAccount.Account,
|
||||||
VotingPower: votingPower,
|
VotingPower: votingPower,
|
||||||
}, privAccount
|
}, privAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeVoteSet(height uint32, round uint16, numValidators int, votingPower uint64) (*VoteSet, *ValidatorSet, []*PrivAccount) {
|
func makeVoteSet(height uint32, round uint16, numValidators int, votingPower uint64) (*VoteSet, *state.ValidatorSet, []*state.PrivAccount) {
|
||||||
vals := make([]*Validator, numValidators)
|
vals := make([]*state.Validator, numValidators)
|
||||||
privAccounts := make([]*PrivAccount, numValidators)
|
privAccounts := make([]*state.PrivAccount, numValidators)
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
val, privAccount := makeValidator(uint64(i), votingPower)
|
val, privAccount := makeValidator(uint64(i), votingPower)
|
||||||
vals[i] = val
|
vals[i] = val
|
||||||
privAccounts[i] = privAccount
|
privAccounts[i] = privAccount
|
||||||
}
|
}
|
||||||
valSet := NewValidatorSet(vals)
|
valSet := state.NewValidatorSet(vals)
|
||||||
return NewVoteSet(height, round, VoteTypeBare, valSet), valSet, privAccounts
|
return NewVoteSet(height, round, VoteTypeBare, valSet), valSet, privAccounts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,17 +13,17 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mempool struct {
|
type Mempool struct {
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
lastBlock *Block
|
lastBlock *Block
|
||||||
state *State
|
state *state.State
|
||||||
txs []Tx
|
txs []Tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMempool(lastBlock *Block, state *State) *Mempool {
|
func NewMempool(lastBlock *Block, state *state.State) *Mempool {
|
||||||
return &Mempool{
|
return &Mempool{
|
||||||
lastBlock: lastBlock,
|
lastBlock: lastBlock,
|
||||||
state: state,
|
state: state,
|
||||||
@ -45,7 +45,7 @@ func (mem *Mempool) AddTx(tx Tx) (err error) {
|
|||||||
|
|
||||||
// Returns a new block from the current state and associated transactions.
|
// Returns a new block from the current state and associated transactions.
|
||||||
// The block's Validation is empty, and some parts of the header too.
|
// The block's Validation is empty, and some parts of the header too.
|
||||||
func (mem *Mempool) MakeProposalBlock() (*Block, *State) {
|
func (mem *Mempool) MakeProposalBlock() (*Block, *state.State) {
|
||||||
mem.mtx.Lock()
|
mem.mtx.Lock()
|
||||||
defer mem.mtx.Unlock()
|
defer mem.mtx.Unlock()
|
||||||
nextBlock := mem.lastBlock.MakeNextBlock()
|
nextBlock := mem.lastBlock.MakeNextBlock()
|
||||||
@ -57,7 +57,7 @@ func (mem *Mempool) MakeProposalBlock() (*Block, *State) {
|
|||||||
// "state" is the result of state.AppendBlock("block").
|
// "state" is the result of state.AppendBlock("block").
|
||||||
// Txs that are present in "block" are discarded from mempool.
|
// Txs that are present in "block" are discarded from mempool.
|
||||||
// Txs that have become invalid in the new "state" are also discarded.
|
// Txs that have become invalid in the new "state" are also discarded.
|
||||||
func (mem *Mempool) ResetForBlockAndState(block *Block, state *State) {
|
func (mem *Mempool) ResetForBlockAndState(block *Block, state *state.State) {
|
||||||
mem.mtx.Lock()
|
mem.mtx.Lock()
|
||||||
defer mem.mtx.Unlock()
|
defer mem.mtx.Unlock()
|
||||||
mem.lastBlock = block
|
mem.lastBlock = block
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -17,7 +17,7 @@ var (
|
|||||||
|
|
||||||
// MempoolReactor handles mempool tx broadcasting amongst peers.
|
// MempoolReactor handles mempool tx broadcasting amongst peers.
|
||||||
type MempoolReactor struct {
|
type MempoolReactor struct {
|
||||||
sw *Switch
|
sw *p2p.Switch
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
started uint32
|
started uint32
|
||||||
stopped uint32
|
stopped uint32
|
||||||
@ -25,7 +25,7 @@ type MempoolReactor struct {
|
|||||||
mempool *Mempool
|
mempool *Mempool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMempoolReactor(sw *Switch, mempool *Mempool) *MempoolReactor {
|
func NewMempoolReactor(sw *p2p.Switch, mempool *Mempool) *MempoolReactor {
|
||||||
memR := &MempoolReactor{
|
memR := &MempoolReactor{
|
||||||
sw: sw,
|
sw: sw,
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
@ -58,14 +58,14 @@ func (memR *MempoolReactor) BroadcastTx(tx Tx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements Reactor
|
// Implements Reactor
|
||||||
func (pexR *MempoolReactor) AddPeer(peer *Peer) {
|
func (pexR *MempoolReactor) AddPeer(peer *p2p.Peer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements Reactor
|
// Implements Reactor
|
||||||
func (pexR *MempoolReactor) RemovePeer(peer *Peer, err error) {
|
func (pexR *MempoolReactor) RemovePeer(peer *p2p.Peer, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (memR *MempoolReactor) Receive(chId byte, src *Peer, msgBytes []byte) {
|
func (memR *MempoolReactor) Receive(chId byte, src *p2p.Peer, msgBytes []byte) {
|
||||||
_, msg_ := decodeMessage(msgBytes)
|
_, msg_ := decodeMessage(msgBytes)
|
||||||
log.Info("MempoolReactor received %v", msg_)
|
log.Info("MempoolReactor received %v", msg_)
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/db"
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -20,7 +20,7 @@ type IAVLTree struct {
|
|||||||
ndb *nodeDB
|
ndb *nodeDB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIAVLTree(keyCodec, valueCodec Codec, cacheSize int, db DB) *IAVLTree {
|
func NewIAVLTree(keyCodec, valueCodec Codec, cacheSize int, db db_.DB) *IAVLTree {
|
||||||
if db == nil {
|
if db == nil {
|
||||||
// In-memory IAVLTree
|
// In-memory IAVLTree
|
||||||
return &IAVLTree{
|
return &IAVLTree{
|
||||||
@ -178,10 +178,10 @@ type nodeDB struct {
|
|||||||
cache map[string]nodeElement
|
cache map[string]nodeElement
|
||||||
cacheSize int
|
cacheSize int
|
||||||
cacheQueue *list.List
|
cacheQueue *list.List
|
||||||
db DB
|
db db_.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNodeDB(cacheSize int, db DB) *nodeDB {
|
func newNodeDB(cacheSize int, db db_.DB) *nodeDB {
|
||||||
return &nodeDB{
|
return &nodeDB{
|
||||||
cache: make(map[string]nodeElement),
|
cache: make(map[string]nodeElement),
|
||||||
cacheSize: cacheSize,
|
cacheSize: cacheSize,
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/db"
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
"github.com/tendermint/tendermint/merkle"
|
"github.com/tendermint/tendermint/merkle"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ func (txErr InvalidTxError) Error() string {
|
|||||||
|
|
||||||
// NOTE: not goroutine-safe.
|
// NOTE: not goroutine-safe.
|
||||||
type State struct {
|
type State struct {
|
||||||
DB DB
|
DB db_.DB
|
||||||
Height uint32 // Last known block height
|
Height uint32 // Last known block height
|
||||||
BlockHash []byte // Last known block hash
|
BlockHash []byte // Last known block hash
|
||||||
CommitTime time.Time
|
CommitTime time.Time
|
||||||
@ -51,7 +51,7 @@ type State struct {
|
|||||||
UnbondingValidators *ValidatorSet
|
UnbondingValidators *ValidatorSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenesisState(db DB, genesisTime time.Time, accDets []*AccountDetail) *State {
|
func GenesisState(db db_.DB, genesisTime time.Time, accDets []*AccountDetail) *State {
|
||||||
|
|
||||||
// TODO: Use "uint64Codec" instead of BasicCodec
|
// TODO: Use "uint64Codec" instead of BasicCodec
|
||||||
accountDetails := merkle.NewIAVLTree(BasicCodec, AccountDetailCodec, defaultAccountDetailsCacheCapacity, db)
|
accountDetails := merkle.NewIAVLTree(BasicCodec, AccountDetailCodec, defaultAccountDetailsCacheCapacity, db)
|
||||||
@ -84,7 +84,7 @@ func GenesisState(db DB, genesisTime time.Time, accDets []*AccountDetail) *State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadState(db DB) *State {
|
func LoadState(db db_.DB) *State {
|
||||||
s := &State{DB: db}
|
s := &State{DB: db}
|
||||||
buf := db.Get(stateKey)
|
buf := db.Get(stateKey)
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/config"
|
. "github.com/tendermint/tendermint/config"
|
||||||
. "github.com/tendermint/tendermint/db"
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
@ -25,7 +25,7 @@ func randAccountDetail(id uint64, status byte) (*AccountDetail, *PrivAccount) {
|
|||||||
|
|
||||||
// The first numValidators accounts are validators.
|
// The first numValidators accounts are validators.
|
||||||
func randGenesisState(numAccounts int, numValidators int) (*State, []*PrivAccount) {
|
func randGenesisState(numAccounts int, numValidators int) (*State, []*PrivAccount) {
|
||||||
db := NewMemDB()
|
db := db_.NewMemDB()
|
||||||
accountDetails := make([]*AccountDetail, numAccounts)
|
accountDetails := make([]*AccountDetail, numAccounts)
|
||||||
privAccounts := make([]*PrivAccount, numAccounts)
|
privAccounts := make([]*PrivAccount, numAccounts)
|
||||||
for i := 0; i < numAccounts; i++ {
|
for i := 0; i < numAccounts; i++ {
|
||||||
@ -114,7 +114,7 @@ func TestGenesisSaveLoad(t *testing.T) {
|
|||||||
s0.Save(commitTime)
|
s0.Save(commitTime)
|
||||||
|
|
||||||
// Sanity check s0
|
// Sanity check s0
|
||||||
//s0.DB.(*MemDB).Print()
|
//s0.DB.(*db_.MemDB).Print()
|
||||||
if s0.BondedValidators.TotalVotingPower() == 0 {
|
if s0.BondedValidators.TotalVotingPower() == 0 {
|
||||||
t.Error("s0 BondedValidators TotalVotingPower should not be 0")
|
t.Error("s0 BondedValidators TotalVotingPower should not be 0")
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user