Browse Source

Documented Block, some renames

pull/9/head
Jae Kwon 10 years ago
parent
commit
62ff48c02b
12 changed files with 174 additions and 83 deletions
  1. +61
    -0
      block/README.md
  2. +26
    -18
      block/block.go
  3. +5
    -6
      block/part_set.go
  4. +34
    -18
      block/store.go
  5. +16
    -12
      block/tx.go
  6. +8
    -7
      block/vote.go
  7. +2
    -2
      common/bit_array.go
  8. +1
    -1
      consensus/pol.go
  9. +14
    -13
      consensus/state.go
  10. +4
    -4
      consensus/vote_set.go
  11. +1
    -0
      state/state_test.go
  12. +2
    -2
      state/validator_set.go

+ 61
- 0
block/README.md View File

@ -0,0 +1,61 @@
# `tendermint/block`
## Block
TODO: document
### Header
### Validation
### Data
## PartSet
PartSet is used to split a byteslice of data into parts (pieces) for transmission.
By splitting data into smaller parts and computing a Merkle root hash on the list,
you can verify that a part is legitimately part of the complete data, and the
part can be forwarded to other peers before all the parts are known. In short,
it's a fast way to propagate a large file over a gossip network.
PartSet was inspired by the LibSwift project.
Usage:
```Go
data := RandBytes(2 << 20) // Something large
partSet := NewPartSetFromData(data)
partSet.Total() // Total number of 4KB parts
partSet.Count() // Equal to the Total, since we already have all the parts
partSet.Hash() // The Merkle root hash
partSet.BitArray() // A BitArray of partSet.Total() 1's
header := partSet.Header() // Send this to the peer
header.Total // Total number of parts
header.Hash // The merkle root hash
// Now we'll reconstruct the data from the parts
partSet2 := NewPartSetFromHeader(header)
partSet2.Total() // Same total as partSet.Total()
partSet2.Count() // Zero, since this PartSet doesn't have any parts yet.
partSet2.Hash() // Same hash as in partSet.Hash()
partSet2.BitArray() // A BitArray of partSet.Total() 0's
// In a gossip network the parts would arrive in arbitrary order, perhaps
// in response to explicit requests for parts, or optimistically in response
// to the receiving peer's partSet.BitArray().
for !partSet2.IsComplete() {
part := receivePartFromGossipNetwork()
added, err := partSet2.AddPart(part)
if err != nil {
// A wrong part,
// the merkle trail does not hash to partSet2.Hash()
} else if !added {
// A duplicate part already received
}
}
data2, _ := ioutil.ReadAll(partSet2.GetReader())
bytes.Equal(data, data2) // true
```

+ 26
- 18
block/block.go View File

@ -28,20 +28,25 @@ type Block struct {
func (b *Block) ValidateBasic(lastBlockHeight uint, lastBlockHash []byte, func (b *Block) ValidateBasic(lastBlockHeight uint, lastBlockHash []byte,
lastBlockParts PartSetHeader, lastBlockTime time.Time) error { lastBlockParts PartSetHeader, lastBlockTime time.Time) error {
if b.Network != Config.Network { if b.Network != Config.Network {
return errors.New("Invalid block network")
return errors.New("Wrong Block.Header.Network")
} }
if b.Height != lastBlockHeight+1 { if b.Height != lastBlockHeight+1 {
return errors.New("Invalid block height")
return errors.New("Wrong Block.Header.Height")
}
if b.NumTxs != uint(len(b.Data.Txs)) {
return errors.New("Wrong Block.Header.NumTxs")
} }
if !bytes.Equal(b.LastBlockHash, lastBlockHash) { if !bytes.Equal(b.LastBlockHash, lastBlockHash) {
return errors.New("Invalid block hash")
return errors.New("Wrong Block.Header.LastBlockHash")
} }
if !b.LastBlockParts.Equals(lastBlockParts) { if !b.LastBlockParts.Equals(lastBlockParts) {
return errors.New("Invalid block parts header")
}
if !b.Time.After(lastBlockTime) {
return errors.New("Invalid block time")
return errors.New("Wrong Block.Header.LastBlockParts")
} }
/* TODO: Determine bounds.
if !b.Time.After(lastBlockTime) {
return errors.New("Invalid Block.Header.Time")
}
*/
if b.Header.Height != 1 { if b.Header.Height != 1 {
if err := b.Validation.ValidateBasic(); err != nil { if err := b.Validation.ValidateBasic(); err != nil {
return err return err
@ -78,22 +83,22 @@ func (b *Block) HashesTo(hash []byte) bool {
} }
func (b *Block) String() string { func (b *Block) String() string {
return b.StringWithIndent("")
return b.StringIndented("")
} }
func (b *Block) StringWithIndent(indent string) string {
func (b *Block) StringIndented(indent string) string {
return fmt.Sprintf(`Block{ return fmt.Sprintf(`Block{
%s %v %s %v
%s %v %s %v
%s %v %s %v
%s}#%X`, %s}#%X`,
indent, b.Header.StringWithIndent(indent+" "),
indent, b.Validation.StringWithIndent(indent+" "),
indent, b.Data.StringWithIndent(indent+" "),
indent, b.Header.StringIndented(indent+" "),
indent, b.Validation.StringIndented(indent+" "),
indent, b.Data.StringIndented(indent+" "),
indent, b.hash) indent, b.hash)
} }
func (b *Block) Description() string {
func (b *Block) StringShort() string {
if b == nil { if b == nil {
return "nil-Block" return "nil-Block"
} else { } else {
@ -108,6 +113,7 @@ type Header struct {
Height uint Height uint
Time time.Time Time time.Time
Fees uint64 Fees uint64
NumTxs uint
LastBlockHash []byte LastBlockHash []byte
LastBlockParts PartSetHeader LastBlockParts PartSetHeader
StateHash []byte StateHash []byte
@ -128,12 +134,13 @@ func (h *Header) Hash() []byte {
return h.hash return h.hash
} }
func (h *Header) StringWithIndent(indent string) string {
func (h *Header) StringIndented(indent string) string {
return fmt.Sprintf(`Header{ return fmt.Sprintf(`Header{
%s Network: %v %s Network: %v
%s Height: %v %s Height: %v
%s Time: %v %s Time: %v
%s Fees: %v %s Fees: %v
%s NumTxs: %v
%s LastBlockHash: %X %s LastBlockHash: %X
%s LastBlockParts: %v %s LastBlockParts: %v
%s StateHash: %X %s StateHash: %X
@ -142,6 +149,7 @@ func (h *Header) StringWithIndent(indent string) string {
indent, h.Height, indent, h.Height,
indent, h.Time, indent, h.Time,
indent, h.Fees, indent, h.Fees,
indent, h.NumTxs,
indent, h.LastBlockHash, indent, h.LastBlockHash,
indent, h.LastBlockParts, indent, h.LastBlockParts,
indent, h.StateHash, indent, h.StateHash,
@ -166,8 +174,8 @@ func (commit Commit) String() string {
//------------------------------------- //-------------------------------------
// NOTE: The Commits are in order of address to preserve the active ValidatorSet order.
// Any peer with a block can gossip commits by index with a peer catching up without recalculating the
// NOTE: The Commits are in order of address to preserve the bonded ValidatorSet order.
// Any peer with a block can gossip commits by index with a peer without recalculating the
// active ValidatorSet. // active ValidatorSet.
type Validation struct { type Validation struct {
Commits []Commit // Commits (or nil) of all active validators in address order. Commits []Commit // Commits (or nil) of all active validators in address order.
@ -212,7 +220,7 @@ func (v *Validation) Hash() []byte {
return v.hash return v.hash
} }
func (v *Validation) StringWithIndent(indent string) string {
func (v *Validation) StringIndented(indent string) string {
commitStrings := make([]string, len(v.Commits)) commitStrings := make([]string, len(v.Commits))
for i, commit := range v.Commits { for i, commit := range v.Commits {
commitStrings[i] = commit.String() commitStrings[i] = commit.String()
@ -254,7 +262,7 @@ func (data *Data) Hash() []byte {
return data.hash return data.hash
} }
func (data *Data) StringWithIndent(indent string) string {
func (data *Data) StringIndented(indent string) string {
txStrings := make([]string, len(data.Txs)) txStrings := make([]string, len(data.Txs))
for i, tx := range data.Txs { for i, tx := range data.Txs {
txStrings[i] = fmt.Sprintf("Tx:%v", tx) txStrings[i] = fmt.Sprintf("Tx:%v", tx)


+ 5
- 6
block/part_set.go View File

@ -46,10 +46,10 @@ func (part *Part) Hash() []byte {
} }
func (part *Part) String() string { func (part *Part) String() string {
return part.StringWithIndent("")
return part.StringIndented("")
} }
func (part *Part) StringWithIndent(indent string) string {
func (part *Part) StringIndented(indent string) string {
trailStrings := make([]string, len(part.Trail)) trailStrings := make([]string, len(part.Trail))
for i, hash := range part.Trail { for i, hash := range part.Trail {
trailStrings[i] = fmt.Sprintf("%X", hash) trailStrings[i] = fmt.Sprintf("%X", hash)
@ -96,8 +96,8 @@ type PartSet struct {
count uint count uint
} }
// Returns an immutable, full PartSet.
// TODO Name is confusing, Data/Header clash with Block.Data/Header
// Returns an immutable, full PartSet from the data bytes.
// The data bytes are split into "partSize" chunks, and merkle tree computed.
func NewPartSetFromData(data []byte) *PartSet { func NewPartSetFromData(data []byte) *PartSet {
// divide data into 4kb parts. // divide data into 4kb parts.
total := (len(data) + partSize - 1) / partSize total := (len(data) + partSize - 1) / partSize
@ -128,7 +128,6 @@ func NewPartSetFromData(data []byte) *PartSet {
} }
// Returns an empty PartSet ready to be populated. // Returns an empty PartSet ready to be populated.
// TODO Name is confusing, Data/Header clash with Block.Data/Header
func NewPartSetFromHeader(header PartSetHeader) *PartSet { func NewPartSetFromHeader(header PartSetHeader) *PartSet {
return &PartSet{ return &PartSet{
total: header.Total, total: header.Total,
@ -239,7 +238,7 @@ func (ps *PartSet) GetReader() io.Reader {
return bytes.NewReader(buf) return bytes.NewReader(buf)
} }
func (ps *PartSet) Description() string {
func (ps *PartSet) StringShort() string {
if ps == nil { if ps == nil {
return "nil-PartSet" return "nil-PartSet"
} else { } else {


+ 34
- 18
block/store.go View File

@ -11,10 +11,17 @@ import (
db_ "github.com/tendermint/tendermint/db" db_ "github.com/tendermint/tendermint/db"
) )
//-----------------------------------------------------------------------------
/* /*
Simple low level store for blocks, which is actually stored as separte parts (wire format).
Simple low level store for blocks.
There are three types of information stored:
- BlockMeta: Meta information about each block
- Block part: Parts of each block, aggregated w/ PartSet
- Validation: The Validation part of each block, for gossiping commit votes
Currently the commit signatures are duplicated in the Block parts as
well as the Validation. In the future this may change, perhaps by moving
the Validation data outside the Block.
*/ */
type BlockStore struct { type BlockStore struct {
height uint height uint
@ -22,7 +29,7 @@ type BlockStore struct {
} }
func NewBlockStore(db db_.DB) *BlockStore { func NewBlockStore(db db_.DB) *BlockStore {
bsjson := LoadBlockStoreJSON(db)
bsjson := LoadBlockStoreStateJSON(db)
return &BlockStore{ return &BlockStore{
height: bsjson.Height, height: bsjson.Height,
db: db, db: db,
@ -99,23 +106,24 @@ func (bs *BlockStore) SaveBlock(block *Block, blockParts *PartSet) {
if !blockParts.IsComplete() { if !blockParts.IsComplete() {
Panicf("BlockStore can only save complete block part sets") Panicf("BlockStore can only save complete block part sets")
} }
meta := &BlockMeta{
Hash: block.Hash(),
Parts: blockParts.Header(),
Header: block.Header,
}
// Save block meta // Save block meta
meta := makeBlockMeta(block, blockParts)
metaBytes := BinaryBytes(meta) metaBytes := BinaryBytes(meta)
bs.db.Set(calcBlockMetaKey(height), metaBytes) bs.db.Set(calcBlockMetaKey(height), metaBytes)
// Save block parts // Save block parts
for i := uint(0); i < blockParts.Total(); i++ { for i := uint(0); i < blockParts.Total(); i++ {
bs.saveBlockPart(height, i, blockParts.GetPart(i)) bs.saveBlockPart(height, i, blockParts.GetPart(i))
} }
// Save block validation (duplicate and separate) // Save block validation (duplicate and separate)
validationBytes := BinaryBytes(block.Validation) validationBytes := BinaryBytes(block.Validation)
bs.db.Set(calcBlockValidationKey(height), validationBytes) bs.db.Set(calcBlockValidationKey(height), validationBytes)
// Save new BlockStoreJSON descriptor
BlockStoreJSON{Height: height}.Save(bs.db)
// Save new BlockStoreStateJSON descriptor
BlockStoreStateJSON{Height: height}.Save(bs.db)
// Done! // Done!
bs.height = height bs.height = height
} }
@ -131,9 +139,17 @@ func (bs *BlockStore) saveBlockPart(height uint, index uint, part *Part) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
type BlockMeta struct { type BlockMeta struct {
Hash []byte // The BlockHash
Parts PartSetHeader // The PartSetHeader, for transfer
Hash []byte // The block hash
Header *Header // The block's Header Header *Header // The block's Header
Parts PartSetHeader // The PartSetHeader, for transfer
}
func makeBlockMeta(block *Block, blockParts *PartSet) *BlockMeta {
return &BlockMeta{
Hash: block.Hash(),
Header: block.Header,
Parts: blockParts.Header(),
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -154,11 +170,11 @@ func calcBlockValidationKey(height uint) []byte {
var blockStoreKey = []byte("blockStore") var blockStoreKey = []byte("blockStore")
type BlockStoreJSON struct {
type BlockStoreStateJSON struct {
Height uint Height uint
} }
func (bsj BlockStoreJSON) Save(db db_.DB) {
func (bsj BlockStoreStateJSON) Save(db db_.DB) {
bytes, err := json.Marshal(bsj) bytes, err := json.Marshal(bsj)
if err != nil { if err != nil {
Panicf("Could not marshal state bytes: %v", err) Panicf("Could not marshal state bytes: %v", err)
@ -166,14 +182,14 @@ func (bsj BlockStoreJSON) Save(db db_.DB) {
db.Set(blockStoreKey, bytes) db.Set(blockStoreKey, bytes)
} }
func LoadBlockStoreJSON(db db_.DB) BlockStoreJSON {
func LoadBlockStoreStateJSON(db db_.DB) BlockStoreStateJSON {
bytes := db.Get(blockStoreKey) bytes := db.Get(blockStoreKey)
if bytes == nil { if bytes == nil {
return BlockStoreJSON{
return BlockStoreStateJSON{
Height: 0, Height: 0,
} }
} }
bsj := BlockStoreJSON{}
bsj := BlockStoreStateJSON{}
err := json.Unmarshal(bytes, &bsj) err := json.Unmarshal(bytes, &bsj)
if err != nil { if err != nil {
Panicf("Could not unmarshal bytes: %X", bytes) Panicf("Could not unmarshal bytes: %X", bytes)


+ 16
- 12
block/tx.go View File

@ -10,21 +10,31 @@ import (
. "github.com/tendermint/tendermint/common" . "github.com/tendermint/tendermint/common"
) )
var (
ErrTxInvalidAddress = errors.New("Error invalid address")
ErrTxDuplicateAddress = errors.New("Error duplicate address")
ErrTxInvalidAmount = errors.New("Error invalid amount")
ErrTxInsufficientFunds = errors.New("Error insufficient funds")
ErrTxInvalidSignature = errors.New("Error invalid signature")
ErrTxInvalidSequence = errors.New("Error invalid sequence")
)
/* /*
Tx (Transaction) is an atomic operation on the ledger state. Tx (Transaction) is an atomic operation on the ledger state.
Account Txs: Account Txs:
1. SendTx Send coins to address
- SendTx Send coins to address
Validation Txs: Validation Txs:
1. BondTx New validator posts a bond
2. UnbondTx Validator leaves
3. DupeoutTx Validator dupes out (equivocates)
- BondTx New validator posts a bond
- UnbondTx Validator leaves
- DupeoutTx Validator dupes out (equivocates)
*/ */
type Tx interface { type Tx interface {
WriteSignBytes(w io.Writer, n *int64, err *error) WriteSignBytes(w io.Writer, n *int64, err *error)
} }
// Types of Tx implementations
const ( const (
// Account transactions // Account transactions
TxTypeSend = byte(0x01) TxTypeSend = byte(0x01)
@ -36,14 +46,8 @@ const (
TxTypeDupeout = byte(0x14) TxTypeDupeout = byte(0x14)
) )
var (
ErrTxInvalidAddress = errors.New("Error invalid address")
ErrTxDuplicateAddress = errors.New("Error duplicate address")
ErrTxInvalidAmount = errors.New("Error invalid amount")
ErrTxInsufficientFunds = errors.New("Error insufficient funds")
ErrTxInvalidSignature = errors.New("Error invalid signature")
ErrTxInvalidSequence = errors.New("Error invalid sequence")
)
//-------------------------------------
// for binary.readReflect
func TxDecoder(r io.Reader, n *int64, err *error) interface{} { func TxDecoder(r io.Reader, n *int64, err *error) interface{} {
switch t := ReadByte(r, n, err); t { switch t := ReadByte(r, n, err); t {


+ 8
- 7
block/vote.go View File

@ -10,12 +10,6 @@ import (
. "github.com/tendermint/tendermint/common" . "github.com/tendermint/tendermint/common"
) )
const (
VoteTypePrevote = byte(0x00)
VoteTypePrecommit = byte(0x01)
VoteTypeCommit = byte(0x02)
)
var ( var (
ErrVoteUnexpectedStep = errors.New("Unexpected step") ErrVoteUnexpectedStep = errors.New("Unexpected step")
ErrVoteInvalidAccount = errors.New("Invalid round vote account") ErrVoteInvalidAccount = errors.New("Invalid round vote account")
@ -24,7 +18,7 @@ var (
ErrVoteConflictingSignature = errors.New("Conflicting round vote signature") ErrVoteConflictingSignature = errors.New("Conflicting round vote signature")
) )
// Represents a prevote, precommit, or commit vote for proposals from validators.
// Represents a prevote, precommit, or commit vote from validators for consensus.
// Commit votes get aggregated into the next block's Validaiton. // Commit votes get aggregated into the next block's Validaiton.
// See the whitepaper for details. // See the whitepaper for details.
type Vote struct { type Vote struct {
@ -36,6 +30,13 @@ type Vote struct {
Signature SignatureEd25519 Signature SignatureEd25519
} }
// Types of votes
const (
VoteTypePrevote = byte(0x00)
VoteTypePrecommit = byte(0x01)
VoteTypeCommit = byte(0x02)
)
func (vote *Vote) WriteSignBytes(w io.Writer, n *int64, err *error) { func (vote *Vote) WriteSignBytes(w io.Writer, n *int64, err *error) {
WriteUvarint(vote.Height, w, n, err) WriteUvarint(vote.Height, w, n, err)
WriteUvarint(vote.Round, w, n, err) WriteUvarint(vote.Round, w, n, err)


+ 2
- 2
common/bit_array.go View File

@ -139,10 +139,10 @@ func (bA BitArray) PickRandom() (uint, bool) {
} }
func (bA BitArray) String() string { func (bA BitArray) String() string {
return bA.StringWithIndent("")
return bA.StringIndented("")
} }
func (bA BitArray) StringWithIndent(indent string) string {
func (bA BitArray) StringIndented(indent string) string {
lines := []string{} lines := []string{}
bits := "" bits := ""
for i := uint(0); i < bA.Bits; i++ { for i := uint(0); i < bA.Bits; i++ {


+ 1
- 1
consensus/pol.go View File

@ -86,7 +86,7 @@ func (pol *POL) Verify(valSet *state.ValidatorSet) error {
} }
func (pol *POL) Description() string {
func (pol *POL) StringShort() string {
if pol == nil { if pol == nil {
return "nil-POL" return "nil-POL"
} else { } else {


+ 14
- 13
consensus/state.go View File

@ -131,10 +131,10 @@ type RoundState struct {
} }
func (rs *RoundState) String() string { func (rs *RoundState) String() string {
return rs.StringWithIndent("")
return rs.StringIndented("")
} }
func (rs *RoundState) StringWithIndent(indent string) string {
func (rs *RoundState) StringIndented(indent string) string {
return fmt.Sprintf(`RoundState{ return fmt.Sprintf(`RoundState{
%s H:%v R:%v S:%v %s H:%v R:%v S:%v
%s StartTime: %v %s StartTime: %v
@ -153,20 +153,20 @@ func (rs *RoundState) StringWithIndent(indent string) string {
indent, rs.Height, rs.Round, rs.Step, indent, rs.Height, rs.Round, rs.Step,
indent, rs.StartTime, indent, rs.StartTime,
indent, rs.CommitTime, indent, rs.CommitTime,
indent, rs.Validators.StringWithIndent(indent+" "),
indent, rs.Validators.StringIndented(indent+" "),
indent, rs.Proposal, indent, rs.Proposal,
indent, rs.ProposalBlockParts.Description(), rs.ProposalBlock.Description(),
indent, rs.ProposalPOLParts.Description(), rs.ProposalPOL.Description(),
indent, rs.LockedBlockParts.Description(), rs.LockedBlock.Description(),
indent, rs.LockedPOL.Description(),
indent, rs.Prevotes.StringWithIndent(indent+" "),
indent, rs.Precommits.StringWithIndent(indent+" "),
indent, rs.Commits.StringWithIndent(indent+" "),
indent, rs.LastCommits.Description(),
indent, rs.ProposalBlockParts.StringShort(), rs.ProposalBlock.StringShort(),
indent, rs.ProposalPOLParts.StringShort(), rs.ProposalPOL.StringShort(),
indent, rs.LockedBlockParts.StringShort(), rs.LockedBlock.StringShort(),
indent, rs.LockedPOL.StringShort(),
indent, rs.Prevotes.StringIndented(indent+" "),
indent, rs.Precommits.StringIndented(indent+" "),
indent, rs.Commits.StringIndented(indent+" "),
indent, rs.LastCommits.StringShort(),
indent) indent)
} }
func (rs *RoundState) Description() string {
func (rs *RoundState) StringShort() string {
return fmt.Sprintf(`RS{%v/%v/%X %v}`, return fmt.Sprintf(`RS{%v/%v/%X %v}`,
rs.Height, rs.Round, rs.Step, rs.StartTime) rs.Height, rs.Round, rs.Step, rs.StartTime)
} }
@ -306,7 +306,7 @@ ACTION_LOOP:
height, round, action := roundAction.Height, roundAction.Round, roundAction.Action height, round, action := roundAction.Height, roundAction.Round, roundAction.Action
rs := cs.GetRoundState() rs := cs.GetRoundState()
log.Info("Running round action A:%X %v", action, rs.Description())
log.Info("Running round action A:%X %v", action, rs.StringShort())
// Continue if action is not relevant // Continue if action is not relevant
if height != rs.Height { if height != rs.Height {
@ -545,6 +545,7 @@ func (cs *ConsensusState) RunActionPropose(height uint, round uint) {
Height: cs.Height, Height: cs.Height,
Time: time.Now(), Time: time.Now(),
Fees: 0, // TODO fees Fees: 0, // TODO fees
NumTxs: uint(len(txs)),
LastBlockHash: cs.state.LastBlockHash, LastBlockHash: cs.state.LastBlockHash,
LastBlockParts: cs.state.LastBlockParts, LastBlockParts: cs.state.LastBlockParts,
StateHash: nil, // Will set afterwards. StateHash: nil, // Will set afterwards.


+ 4
- 4
consensus/vote_set.go View File

@ -247,14 +247,14 @@ func (voteSet *VoteSet) MakeValidation() *Validation {
} }
func (voteSet *VoteSet) String() string { func (voteSet *VoteSet) String() string {
return voteSet.StringWithIndent("")
return voteSet.StringIndented("")
} }
func (voteSet *VoteSet) StringWithIndent(indent string) string {
func (voteSet *VoteSet) StringIndented(indent string) string {
voteStrings := make([]string, len(voteSet.votes)) voteStrings := make([]string, len(voteSet.votes))
for i, vote := range voteSet.votes { for i, vote := range voteSet.votes {
if vote == nil { if vote == nil {
voteStrings[i] = "nil"
voteStrings[i] = "nil-Vote"
} else { } else {
voteStrings[i] = vote.String() voteStrings[i] = vote.String()
} }
@ -270,7 +270,7 @@ func (voteSet *VoteSet) StringWithIndent(indent string) string {
indent) indent)
} }
func (voteSet *VoteSet) Description() string {
func (voteSet *VoteSet) StringShort() string {
if voteSet == nil { if voteSet == nil {
return "nil-VoteSet" return "nil-VoteSet"
} }


+ 1
- 0
state/state_test.go View File

@ -59,6 +59,7 @@ func TestGenesisSaveLoad(t *testing.T) {
Height: 1, Height: 1,
Time: s0.LastBlockTime.Add(time.Minute), Time: s0.LastBlockTime.Add(time.Minute),
Fees: 0, Fees: 0,
NumTxs: 0,
LastBlockHash: s0.LastBlockHash, LastBlockHash: s0.LastBlockHash,
LastBlockParts: s0.LastBlockParts, LastBlockParts: s0.LastBlockParts,
StateHash: nil, StateHash: nil,


+ 2
- 2
state/validator_set.go View File

@ -197,10 +197,10 @@ func (valSet *ValidatorSet) Iterate(fn func(index uint, val *Validator) bool) {
} }
func (valSet *ValidatorSet) String() string { func (valSet *ValidatorSet) String() string {
return valSet.StringWithIndent("")
return valSet.StringIndented("")
} }
func (valSet *ValidatorSet) StringWithIndent(indent string) string {
func (valSet *ValidatorSet) StringIndented(indent string) string {
valStrings := []string{} valStrings := []string{}
valSet.Iterate(func(index uint, val *Validator) bool { valSet.Iterate(func(index uint, val *Validator) bool {
valStrings = append(valStrings, val.String()) valStrings = append(valStrings, val.String())


Loading…
Cancel
Save