diff --git a/blockchain/pool.go b/blockchain/pool.go index 06556154..f3bf5d20 100644 --- a/blockchain/pool.go +++ b/blockchain/pool.go @@ -149,8 +149,9 @@ func (pool *BlockPool) IsCaughtUp() bool { return isCaughtUp } -// We need to see the second block's Validation to validate the first block. +// We need to see the second block's Commit to validate the first block. // So we peek two blocks at a time. +// The caller will verify the commit. func (pool *BlockPool) PeekTwoBlocks() (first *types.Block, second *types.Block) { pool.mtx.Lock() // Lock defer pool.mtx.Unlock() @@ -165,7 +166,7 @@ func (pool *BlockPool) PeekTwoBlocks() (first *types.Block, second *types.Block) } // Pop the first block at pool.height -// It must have been validated by 'second'.Validation from PeekTwoBlocks(). +// It must have been validated by 'second'.Commit from PeekTwoBlocks(). func (pool *BlockPool) PopRequest() { pool.mtx.Lock() // Lock defer pool.mtx.Unlock() diff --git a/blockchain/reactor.go b/blockchain/reactor.go index ee524ce6..a668e5f1 100644 --- a/blockchain/reactor.go +++ b/blockchain/reactor.go @@ -222,9 +222,9 @@ FOR_LOOP: } firstParts := first.MakePartSet() firstPartsHeader := firstParts.Header() - // Finally, verify the first block using the second's validation. - err := bcR.state.Validators.VerifyValidation( - bcR.state.ChainID, first.Hash(), firstPartsHeader, first.Height, second.LastValidation) + // Finally, verify the first block using the second's commit + err := bcR.state.Validators.VerifyCommit( + bcR.state.ChainID, first.Hash(), firstPartsHeader, first.Height, second.LastCommit) if err != nil { log.Info("error in validation", "error", err) bcR.pool.RedoRequest(first.Height) @@ -243,7 +243,7 @@ FOR_LOOP: PanicQ(Fmt("Failed to commit block at application: %v", err)) } */ - bcR.store.SaveBlock(first, firstParts, second.LastValidation) + bcR.store.SaveBlock(first, firstParts, second.LastCommit) bcR.state.Save() } } diff --git a/blockchain/store.go b/blockchain/store.go index 491b6955..565e131a 100644 --- a/blockchain/store.go +++ b/blockchain/store.go @@ -18,11 +18,11 @@ 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 precommit votes + - Commit: The commit part of each block, for gossiping precommit votes Currently the precommit 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. +well as the Commit. In the future this may change, perhaps by moving +the Commit data outside the Block. Panics indicate probable corruption in the data */ @@ -104,42 +104,42 @@ func (bs *BlockStore) LoadBlockMeta(height int) *types.BlockMeta { } // The +2/3 and other Precommit-votes for block at `height`. -// This Validation comes from block.LastValidation for `height+1`. -func (bs *BlockStore) LoadBlockValidation(height int) *types.Validation { +// This Commit comes from block.LastCommit for `height+1`. +func (bs *BlockStore) LoadBlockCommit(height int) *types.Commit { var n int var err error - r := bs.GetReader(calcBlockValidationKey(height)) + r := bs.GetReader(calcBlockCommitKey(height)) if r == nil { return nil } - validation := wire.ReadBinary(&types.Validation{}, r, 0, &n, &err).(*types.Validation) + commit := wire.ReadBinary(&types.Commit{}, r, 0, &n, &err).(*types.Commit) if err != nil { - PanicCrisis(Fmt("Error reading validation: %v", err)) + PanicCrisis(Fmt("Error reading commit: %v", err)) } - return validation + return commit } // NOTE: the Precommit-vote heights are for the block at `height` -func (bs *BlockStore) LoadSeenValidation(height int) *types.Validation { +func (bs *BlockStore) LoadSeenCommit(height int) *types.Commit { var n int var err error - r := bs.GetReader(calcSeenValidationKey(height)) + r := bs.GetReader(calcSeenCommitKey(height)) if r == nil { return nil } - validation := wire.ReadBinary(&types.Validation{}, r, 0, &n, &err).(*types.Validation) + commit := wire.ReadBinary(&types.Commit{}, r, 0, &n, &err).(*types.Commit) if err != nil { - PanicCrisis(Fmt("Error reading validation: %v", err)) + PanicCrisis(Fmt("Error reading commit: %v", err)) } - return validation + return commit } -// blockParts: Must be parts of the block -// seenValidation: The +2/3 precommits that were seen which committed at height. -// If all the nodes restart after committing a block, -// we need this to reload the precommits to catch-up nodes to the -// most recent height. Otherwise they'd stall at H-1. -func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenValidation *types.Validation) { +// blockParts: Must be parts of the block +// seenCommit: The +2/3 precommits that were seen which committed at height. +// If all the nodes restart after committing a block, +// we need this to reload the precommits to catch-up nodes to the +// most recent height. Otherwise they'd stall at H-1. +func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) { height := block.Height if height != bs.height+1 { PanicSanity(Fmt("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)) @@ -158,13 +158,13 @@ func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, s bs.saveBlockPart(height, i, blockParts.GetPart(i)) } - // Save block validation (duplicate and separate from the Block) - blockValidationBytes := wire.BinaryBytes(block.LastValidation) - bs.db.Set(calcBlockValidationKey(height-1), blockValidationBytes) + // Save block commit (duplicate and separate from the Block) + blockCommitBytes := wire.BinaryBytes(block.LastCommit) + bs.db.Set(calcBlockCommitKey(height-1), blockCommitBytes) - // Save seen validation (seen +2/3 precommits for block) - seenValidationBytes := wire.BinaryBytes(seenValidation) - bs.db.Set(calcSeenValidationKey(height), seenValidationBytes) + // Save seen commit (seen +2/3 precommits for block) + seenCommitBytes := wire.BinaryBytes(seenCommit) + bs.db.Set(calcSeenCommitKey(height), seenCommitBytes) // Save new BlockStoreStateJSON descriptor BlockStoreStateJSON{Height: height}.Save(bs.db) @@ -191,12 +191,12 @@ func calcBlockPartKey(height int, partIndex int) []byte { return []byte(fmt.Sprintf("P:%v:%v", height, partIndex)) } -func calcBlockValidationKey(height int) []byte { - return []byte(fmt.Sprintf("V:%v", height)) +func calcBlockCommitKey(height int) []byte { + return []byte(fmt.Sprintf("C:%v", height)) } -func calcSeenValidationKey(height int) []byte { - return []byte(fmt.Sprintf("SV:%v", height)) +func calcSeenCommitKey(height int) []byte { + return []byte(fmt.Sprintf("SC:%v", height)) } //----------------------------------------------------------------------------- diff --git a/consensus/reactor.go b/consensus/reactor.go index 664deb6b..c2874df2 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -488,14 +488,14 @@ OUTER_LOOP: } // Catchup logic - // If peer is lagging by more than 1, send Validation. + // If peer is lagging by more than 1, send Commit. if prs.Height != 0 && rs.Height >= prs.Height+2 { - // Load the block validation for prs.Height, + // Load the block commit for prs.Height, // which contains precommit signatures for prs.Height. - validation := conR.blockStore.LoadBlockValidation(prs.Height) - log.Info("Loaded BlockValidation for catch-up", "height", prs.Height, "validation", validation) - if ps.PickSendVote(validation) { - log.Info("Picked Catchup validation to send") + commit := conR.blockStore.LoadBlockCommit(prs.Height) + log.Info("Loaded BlockCommit for catch-up", "height", prs.Height, "commit", commit) + if ps.PickSendVote(commit) { + log.Info("Picked Catchup commit to send") continue OUTER_LOOP } } @@ -696,7 +696,7 @@ func (ps *PeerState) ensureCatchupCommitRound(height, round int, numValidators i } /* NOTE: This is wrong, 'round' could change. - e.g. if orig round is not the same as block LastValidation round. + e.g. if orig round is not the same as block LastCommit round. if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round { PanicSanity(Fmt("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round)) } diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 769bea1c..133d92b9 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -9,14 +9,46 @@ import ( "github.com/tendermint/tendermint/types" ) +/* + If you need to change the signatures, you can use a script as follows: + The privBytes comes from config/tendermint_test/... + + ``` + package main + + import ( + "encoding/hex" + "fmt" + + "github.com/tendermint/go-crypto" + ) + + func main() { + signBytes, err := hex.DecodeString("7B22636861696E5F6964223A2274656E6465726D696E745F74657374222C22766F7465223A7B22626C6F636B5F68617368223A2242453544373939433846353044354645383533364334333932464443384537423342313830373638222C22626C6F636B5F70617274735F686561646572223A506172745365747B543A31204236323237323535464632307D2C22686569676874223A312C22726F756E64223A302C2274797065223A327D7D") + if err != nil { + panic(err) + } + privBytes, err := hex.DecodeString("27F82582AEFAE7AB151CFB01C48BB6C1A0DA78F9BDDA979A9F70A84D074EB07D3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8") + if err != nil { + panic(err) + } + privKey := crypto.PrivKeyEd25519{} + copy(privKey[:], privBytes) + signature := privKey.Sign(signBytes) + signatureEd25519 := signature.(crypto.SignatureEd25519) + fmt.Printf("Signature Bytes: %X\n", signatureEd25519[:]) + } + ``` +*/ + var testLog = `{"time":"2016-01-18T20:46:00.774Z","msg":[3,{"duration":982632969,"height":1,"round":0,"step":1}]} {"time":"2016-01-18T20:46:00.776Z","msg":[1,{"height":1,"round":0,"step":"RoundStepPropose"}]} {"time":"2016-01-18T20:46:00.776Z","msg":[2,{"msg":[17,{"Proposal":{"height":1,"round":0,"block_parts_header":{"total":1,"hash":"B6227255FF20758326B0B7DFF529F20E33E58F45"},"pol_round":-1,"signature":"A1803A1364F6398C154FE45D5649A89129039F18A0FE42B211BADFDF6E81EA53F48F83D3610DDD848C3A5284D3F09BDEB26FA1D856BDF70D48C507BF2453A70E"}}],"peer_key":""}]} {"time":"2016-01-18T20:46:00.777Z","msg":[2,{"msg":[19,{"Height":1,"Round":0,"Part":{"index":0,"bytes":"0101010F74656E6465726D696E745F746573740101142AA030B15DDFC000000000000000000000000000000114C4B01D3810579550997AC5641E759E20D99B51C10001000100","proof":{"aunts":[]}}}],"peer_key":""}]} {"time":"2016-01-18T20:46:00.781Z","msg":[1,{"height":1,"round":0,"step":"RoundStepPrevote"}]} -{"time":"2016-01-18T20:46:00.781Z","msg":[2,{"msg":[20,{"ValidatorIndex":0,"Vote":{"height":1,"round":0,"type":1,"block_hash":"E05D1DB8DEC7CDA507A42C8FF208EE4317C663F6","block_parts_header":{"total":1,"hash":"B6227255FF20758326B0B7DFF529F20E33E58F45"},"signature":"88F5708C802BEE54EFBF438967FBC6C6EAAFC41258A85D92B9B055481175BE9FA71007B1AAF2BFBC3BF3CC0542DB48A9812324B7BBA7307446CCDBF029077F07"}}],"peer_key":""}]} +{"time":"2016-01-18T20:46:00.781Z","msg":[2,{"msg":[20,{"ValidatorIndex":0,"Vote":{"height":1,"round":0,"type":1,"block_hash":"BE5D799C8F50D5FE8536C4392FDC8E7B3B180768","block_parts_header":{"total":1,"hash":"B6227255FF20758326B0B7DFF529F20E33E58F45"},"signature":"A63A15D9155C6C97762E65559E8CD34D853ED5FE22DA8540519453F9B7BE23C9287110929EDAA430DA30183768C60D4CF2811128C9D2E4B6A173EFE28FB54F05"}}],"peer_key":""}]} {"time":"2016-01-18T20:46:00.786Z","msg":[1,{"height":1,"round":0,"step":"RoundStepPrecommit"}]} -{"time":"2016-01-18T20:46:00.786Z","msg":[2,{"msg":[20,{"ValidatorIndex":0,"Vote":{"height":1,"round":0,"type":2,"block_hash":"E05D1DB8DEC7CDA507A42C8FF208EE4317C663F6","block_parts_header":{"total":1,"hash":"B6227255FF20758326B0B7DFF529F20E33E58F45"},"signature":"65B0C9D2A8C9919FC9B036F82C3F1818E706E8BC066A78D99D3316E4814AB06594841E387B323AA7773F926D253C1E4D4A0930F7A8C8AE1E838CA15C673B2B02"}}],"peer_key":""}]} +{"time":"2016-01-18T20:46:00.786Z","msg":[2,{"msg":[20,{"ValidatorIndex":0,"Vote":{"height":1,"round":0,"type":2,"block_hash":"BE5D799C8F50D5FE8536C4392FDC8E7B3B180768","block_parts_header":{"total":1,"hash":"B6227255FF20758326B0B7DFF529F20E33E58F45"},"signature":"7190035C558F7173946581E6121E1EEB6EE91F03F04F2858FD5CBDAC006521FDC50366ED920B69C7357D9EF7621F9578F00E5350757CBC0AE6D441C39170CC07"}}],"peer_key":""}]} ` func TestReplayCatchup(t *testing.T) { diff --git a/consensus/state.go b/consensus/state.go index 51108dab..51d0f7b6 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -432,15 +432,15 @@ func (cs *ConsensusState) sendInternalMessage(mi msgInfo) { } } -// Reconstruct LastCommit from SeenValidation, which we saved along with the block, +// Reconstruct LastCommit from SeenCommit, which we saved along with the block, // (which happens even before saving the state) func (cs *ConsensusState) reconstructLastCommit(state *sm.State) { if state.LastBlockHeight == 0 { return } - seenValidation := cs.blockStore.LoadSeenValidation(state.LastBlockHeight) - lastPrecommits := types.NewVoteSet(state.LastBlockHeight, seenValidation.Round(), types.VoteTypePrecommit, state.LastValidators) - for idx, precommit := range seenValidation.Precommits { + seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight) + lastPrecommits := types.NewVoteSet(state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators) + for idx, precommit := range seenCommit.Precommits { if precommit == nil { continue } @@ -863,17 +863,17 @@ func (cs *ConsensusState) isProposalComplete() bool { // Returns nil block upon error. // NOTE: keep it side-effect free for clarity. func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts *types.PartSet) { - var validation *types.Validation + var commit *types.Commit if cs.Height == 1 { // We're creating a proposal for the first block. - // The validation is empty, but not nil. - validation = &types.Validation{} + // The commit is empty, but not nil. + commit = &types.Commit{} } else if cs.LastCommit.HasTwoThirdsMajority() { - // Make the validation from LastCommit - validation = cs.LastCommit.MakeValidation() + // Make the commit from LastCommit + commit = cs.LastCommit.MakeCommit() } else { // This shouldn't happen. - log.Error("enterPropose: Cannot propose anything: No validation for the previous block.") + log.Error("enterPropose: Cannot propose anything: No commit for the previous block.") return } @@ -892,7 +892,7 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts ValidatorsHash: cs.state.Validators.Hash(), AppHash: cs.state.AppHash, // state merkle root of txs from the previous block. }, - LastValidation: validation, + LastCommit: commit, Data: &types.Data{ Txs: txs, }, @@ -1222,9 +1222,9 @@ func (cs *ConsensusState) finalizeCommit(height int) { // Save to blockStore. if cs.blockStore.Height() < block.Height { - commits := cs.Votes.Precommits(cs.CommitRound) - seenValidation := commits.MakeValidation() - cs.blockStore.SaveBlock(block, blockParts, seenValidation) + precommits := cs.Votes.Precommits(cs.CommitRound) + seenCommit := precommits.MakeCommit() + cs.blockStore.SaveBlock(block, blockParts, seenCommit) } /* diff --git a/state/execution.go b/state/execution.go index 404efa26..67c1d56b 100644 --- a/state/execution.go +++ b/state/execution.go @@ -118,18 +118,18 @@ func (s *State) validateBlock(block *types.Block) error { return err } - // Validate block LastValidation. + // Validate block LastCommit. if block.Height == 1 { - if len(block.LastValidation.Precommits) != 0 { - return errors.New("Block at height 1 (first block) should have no LastValidation precommits") + if len(block.LastCommit.Precommits) != 0 { + return errors.New("Block at height 1 (first block) should have no LastCommit precommits") } } else { - if len(block.LastValidation.Precommits) != s.LastValidators.Size() { - return fmt.Errorf("Invalid block validation size. Expected %v, got %v", - s.LastValidators.Size(), len(block.LastValidation.Precommits)) + if len(block.LastCommit.Precommits) != s.LastValidators.Size() { + return fmt.Errorf("Invalid block commit size. Expected %v, got %v", + s.LastValidators.Size(), len(block.LastCommit.Precommits)) } - err := s.LastValidators.VerifyValidation( - s.ChainID, s.LastBlockHash, s.LastBlockParts, block.Height-1, block.LastValidation) + err := s.LastValidators.VerifyCommit( + s.ChainID, s.LastBlockHash, s.LastBlockParts, block.Height-1, block.LastCommit) if err != nil { return err } @@ -139,11 +139,11 @@ func (s *State) validateBlock(block *types.Block) error { } // Updates the LastCommitHeight of the validators in valSet, in place. -// Assumes that lastValSet matches the valset of block.LastValidation +// Assumes that lastValSet matches the valset of block.LastCommit // CONTRACT: lastValSet is not mutated. func updateValidatorsWithBlock(lastValSet *types.ValidatorSet, valSet *types.ValidatorSet, block *types.Block) { - for i, precommit := range block.LastValidation.Precommits { + for i, precommit := range block.LastCommit.Precommits { if precommit == nil { continue } diff --git a/types/README.md b/types/README.md deleted file mode 100644 index f99294b0..00000000 --- a/types/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# `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 -``` diff --git a/types/block.go b/types/block.go index db88ceb5..45640908 100644 --- a/types/block.go +++ b/types/block.go @@ -15,9 +15,9 @@ import ( const MaxBlockSize = 22020096 // 21MB TODO make it configurable type Block struct { - *Header `json:"header"` - *Data `json:"data"` - LastValidation *Validation `json:"last_validation"` + *Header `json:"header"` + *Data `json:"data"` + LastCommit *Commit `json:"last_commit"` } // Basic validation that doesn't involve state data. @@ -46,11 +46,11 @@ func (b *Block) ValidateBasic(chainID string, lastBlockHeight int, lastBlockHash if !b.LastBlockParts.Equals(lastBlockParts) { return errors.New(Fmt("Wrong Block.Header.LastBlockParts. Expected %v, got %v", lastBlockParts, b.LastBlockParts)) } - if !bytes.Equal(b.LastValidationHash, b.LastValidation.Hash()) { - return errors.New(Fmt("Wrong Block.Header.LastValidationHash. Expected %X, got %X", b.LastValidationHash, b.LastValidation.Hash())) + if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) { + return errors.New(Fmt("Wrong Block.Header.LastCommitHash. Expected %X, got %X", b.LastCommitHash, b.LastCommit.Hash())) } if b.Header.Height != 1 { - if err := b.LastValidation.ValidateBasic(); err != nil { + if err := b.LastCommit.ValidateBasic(); err != nil { return err } } @@ -65,8 +65,8 @@ func (b *Block) ValidateBasic(chainID string, lastBlockHeight int, lastBlockHash } func (b *Block) FillHeader() { - if b.LastValidationHash == nil { - b.LastValidationHash = b.LastValidation.Hash() + if b.LastCommitHash == nil { + b.LastCommitHash = b.LastCommit.Hash() } if b.DataHash == nil { b.DataHash = b.Data.Hash() @@ -76,7 +76,7 @@ func (b *Block) FillHeader() { // Computes and returns the block hash. // If the block is incomplete, block hash is nil for safety. func (b *Block) Hash() []byte { - if b.Header == nil || b.Data == nil || b.LastValidation == nil { + if b.Header == nil || b.Data == nil || b.LastCommit == nil { return nil } b.FillHeader() @@ -115,7 +115,7 @@ func (b *Block) StringIndented(indent string) string { %s}#%X`, indent, b.Header.StringIndented(indent+" "), indent, b.Data.StringIndented(indent+" "), - indent, b.LastValidation.StringIndented(indent+" "), + indent, b.LastCommit.StringIndented(indent+" "), indent, b.Hash()) } @@ -130,17 +130,17 @@ func (b *Block) StringShort() string { //----------------------------------------------------------------------------- type Header struct { - ChainID string `json:"chain_id"` - Height int `json:"height"` - Time time.Time `json:"time"` - Fees int64 `json:"fees"` - NumTxs int `json:"num_txs"` - LastBlockHash []byte `json:"last_block_hash"` - LastBlockParts PartSetHeader `json:"last_block_parts"` - LastValidationHash []byte `json:"last_validation_hash"` - DataHash []byte `json:"data_hash"` - ValidatorsHash []byte `json:"validators_hash"` - AppHash []byte `json:"app_hash"` // state merkle root of txs from the previous block + ChainID string `json:"chain_id"` + Height int `json:"height"` + Time time.Time `json:"time"` + Fees int64 `json:"fees"` + NumTxs int `json:"num_txs"` + LastBlockHash []byte `json:"last_block_hash"` + LastBlockParts PartSetHeader `json:"last_block_parts"` + LastCommitHash []byte `json:"last_commit_hash"` + DataHash []byte `json:"data_hash"` + ValidatorsHash []byte `json:"validators_hash"` + AppHash []byte `json:"app_hash"` // state merkle root of txs from the previous block } // NOTE: hash is nil if required fields are missing. @@ -156,7 +156,7 @@ func (h *Header) Hash() []byte { "NumTxs": h.NumTxs, "LastBlock": h.LastBlockHash, "LastBlockParts": h.LastBlockParts, - "LastValidation": h.LastValidationHash, + "LastCommit": h.LastCommitHash, "Data": h.DataHash, "Validators": h.ValidatorsHash, "App": h.AppHash, @@ -172,10 +172,10 @@ func (h *Header) StringIndented(indent string) string { %s Height: %v %s Time: %v %s Fees: %v -%s NumTxs: %v +%s NumTxs: %v %s LastBlock: %X %s LastBlockParts: %v -%s LastValidation: %X +%s LastCommit: %X %s Data: %X %s Validators: %X %s App: %X @@ -187,7 +187,7 @@ func (h *Header) StringIndented(indent string) string { indent, h.NumTxs, indent, h.LastBlockHash, indent, h.LastBlockParts, - indent, h.LastValidationHash, + indent, h.LastCommitHash, indent, h.DataHash, indent, h.ValidatorsHash, indent, h.AppHash, @@ -196,8 +196,8 @@ func (h *Header) StringIndented(indent string) string { //------------------------------------- -// NOTE: Validation is empty for height 1, but never nil. -type Validation struct { +// NOTE: Commit is empty for height 1, but never nil. +type Commit struct { // NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order. // Any peer with a block can gossip precommits by index with a peer without recalculating the // active ValidatorSet. @@ -209,121 +209,121 @@ type Validation struct { bitArray *BitArray } -func (v *Validation) FirstPrecommit() *Vote { - if len(v.Precommits) == 0 { +func (commit *Commit) FirstPrecommit() *Vote { + if len(commit.Precommits) == 0 { return nil } - if v.firstPrecommit != nil { - return v.firstPrecommit + if commit.firstPrecommit != nil { + return commit.firstPrecommit } - for _, precommit := range v.Precommits { + for _, precommit := range commit.Precommits { if precommit != nil { - v.firstPrecommit = precommit + commit.firstPrecommit = precommit return precommit } } return nil } -func (v *Validation) Height() int { - if len(v.Precommits) == 0 { +func (commit *Commit) Height() int { + if len(commit.Precommits) == 0 { return 0 } - return v.FirstPrecommit().Height + return commit.FirstPrecommit().Height } -func (v *Validation) Round() int { - if len(v.Precommits) == 0 { +func (commit *Commit) Round() int { + if len(commit.Precommits) == 0 { return 0 } - return v.FirstPrecommit().Round + return commit.FirstPrecommit().Round } -func (v *Validation) Type() byte { +func (commit *Commit) Type() byte { return VoteTypePrecommit } -func (v *Validation) Size() int { - if v == nil { +func (commit *Commit) Size() int { + if commit == nil { return 0 } - return len(v.Precommits) + return len(commit.Precommits) } -func (v *Validation) BitArray() *BitArray { - if v.bitArray == nil { - v.bitArray = NewBitArray(len(v.Precommits)) - for i, precommit := range v.Precommits { - v.bitArray.SetIndex(i, precommit != nil) +func (commit *Commit) BitArray() *BitArray { + if commit.bitArray == nil { + commit.bitArray = NewBitArray(len(commit.Precommits)) + for i, precommit := range commit.Precommits { + commit.bitArray.SetIndex(i, precommit != nil) } } - return v.bitArray + return commit.bitArray } -func (v *Validation) GetByIndex(index int) *Vote { - return v.Precommits[index] +func (commit *Commit) GetByIndex(index int) *Vote { + return commit.Precommits[index] } -func (v *Validation) IsCommit() bool { - if len(v.Precommits) == 0 { +func (commit *Commit) IsCommit() bool { + if len(commit.Precommits) == 0 { return false } return true } -func (v *Validation) ValidateBasic() error { - if len(v.Precommits) == 0 { - return errors.New("No precommits in validation") +func (commit *Commit) ValidateBasic() error { + if len(commit.Precommits) == 0 { + return errors.New("No precommits in commit") } - height, round := v.Height(), v.Round() - for _, precommit := range v.Precommits { + height, round := commit.Height(), commit.Round() + for _, precommit := range commit.Precommits { // It's OK for precommits to be missing. if precommit == nil { continue } // Ensure that all votes are precommits if precommit.Type != VoteTypePrecommit { - return fmt.Errorf("Invalid validation vote. Expected precommit, got %v", + return fmt.Errorf("Invalid commit vote. Expected precommit, got %v", precommit.Type) } // Ensure that all heights are the same if precommit.Height != height { - return fmt.Errorf("Invalid validation precommit height. Expected %v, got %v", + return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v", height, precommit.Height) } // Ensure that all rounds are the same if precommit.Round != round { - return fmt.Errorf("Invalid validation precommit round. Expected %v, got %v", + return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v", round, precommit.Round) } } return nil } -func (v *Validation) Hash() []byte { - if v.hash == nil { - bs := make([]interface{}, len(v.Precommits)) - for i, precommit := range v.Precommits { +func (commit *Commit) Hash() []byte { + if commit.hash == nil { + bs := make([]interface{}, len(commit.Precommits)) + for i, precommit := range commit.Precommits { bs[i] = precommit } - v.hash = merkle.SimpleHashFromBinaries(bs) + commit.hash = merkle.SimpleHashFromBinaries(bs) } - return v.hash + return commit.hash } -func (v *Validation) StringIndented(indent string) string { - if v == nil { - return "nil-Validation" +func (commit *Commit) StringIndented(indent string) string { + if commit == nil { + return "nil-Commit" } - precommitStrings := make([]string, len(v.Precommits)) - for i, precommit := range v.Precommits { + precommitStrings := make([]string, len(commit.Precommits)) + for i, precommit := range commit.Precommits { precommitStrings[i] = precommit.String() } - return fmt.Sprintf(`Validation{ + return fmt.Sprintf(`Commit{ %s Precommits: %v %s}#%X`, indent, strings.Join(precommitStrings, "\n"+indent+" "), - indent, v.hash) + indent, commit.hash) } //----------------------------------------------------------------------------- diff --git a/types/validator_set.go b/types/validator_set.go index a56265bf..5a51c79f 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -206,37 +206,37 @@ func (valSet *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) { } // Verify that +2/3 of the set had signed the given signBytes -func (valSet *ValidatorSet) VerifyValidation(chainID string, - hash []byte, parts PartSetHeader, height int, v *Validation) error { - if valSet.Size() != len(v.Precommits) { - return fmt.Errorf("Invalid validation -- wrong set size: %v vs %v", valSet.Size(), len(v.Precommits)) +func (valSet *ValidatorSet) VerifyCommit(chainID string, + hash []byte, parts PartSetHeader, height int, commit *Commit) error { + if valSet.Size() != len(commit.Precommits) { + return fmt.Errorf("Invalid commit -- wrong set size: %v vs %v", valSet.Size(), len(commit.Precommits)) } - if height != v.Height() { - return fmt.Errorf("Invalid validation -- wrong height: %v vs %v", height, v.Height()) + if height != commit.Height() { + return fmt.Errorf("Invalid commit -- wrong height: %v vs %v", height, commit.Height()) } talliedVotingPower := int64(0) - round := v.Round() + round := commit.Round() - for idx, precommit := range v.Precommits { + for idx, precommit := range commit.Precommits { // may be nil if validator skipped. if precommit == nil { continue } if precommit.Height != height { - return fmt.Errorf("Invalid validation -- wrong height: %v vs %v", height, precommit.Height) + return fmt.Errorf("Invalid commit -- wrong height: %v vs %v", height, precommit.Height) } if precommit.Round != round { - return fmt.Errorf("Invalid validation -- wrong round: %v vs %v", round, precommit.Round) + return fmt.Errorf("Invalid commit -- wrong round: %v vs %v", round, precommit.Round) } if precommit.Type != VoteTypePrecommit { - return fmt.Errorf("Invalid validation -- not precommit @ index %v", idx) + return fmt.Errorf("Invalid commit -- not precommit @ index %v", idx) } _, val := valSet.GetByIndex(idx) // Validate signature precommitSignBytes := SignBytes(chainID, precommit) if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) { - return fmt.Errorf("Invalid validation -- invalid signature: %v", precommit) + return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit) } if !bytes.Equal(precommit.BlockHash, hash) { continue // Not an error, but doesn't count @@ -251,7 +251,7 @@ func (valSet *ValidatorSet) VerifyValidation(chainID string, if talliedVotingPower > valSet.TotalVotingPower()*2/3 { return nil } else { - return fmt.Errorf("Invalid validation -- insufficient voting power: got %v, needed %v", + return fmt.Errorf("Invalid commit -- insufficient voting power: got %v, needed %v", talliedVotingPower, (valSet.TotalVotingPower()*2/3 + 1)) } } diff --git a/types/vote.go b/types/vote.go index cd145552..0600c65f 100644 --- a/types/vote.go +++ b/types/vote.go @@ -71,9 +71,9 @@ func (vote *Vote) String() string { } //-------------------------------------------------------------------------------- -// TODO: Move blocks/Validation to here? +// TODO: Move blocks/Commit to here? -// Common interface between *consensus.VoteSet and types.Validation +// Common interface between *consensus.VoteSet and types.Commit type VoteSetReader interface { Height() int Round() int diff --git a/types/vote_set.go b/types/vote_set.go index 44ee5345..8c03f79b 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -270,16 +270,16 @@ func (voteSet *VoteSet) StringShort() string { } //-------------------------------------------------------------------------------- -// Validation +// Commit -func (voteSet *VoteSet) MakeValidation() *Validation { +func (voteSet *VoteSet) MakeCommit() *Commit { if voteSet.type_ != VoteTypePrecommit { - PanicSanity("Cannot MakeValidation() unless VoteSet.Type is VoteTypePrecommit") + PanicSanity("Cannot MakeCommit() unless VoteSet.Type is VoteTypePrecommit") } voteSet.mtx.Lock() defer voteSet.mtx.Unlock() if len(voteSet.maj23Hash) == 0 { - PanicSanity("Cannot MakeValidation() unless a blockhash has +2/3") + PanicSanity("Cannot MakeCommit() unless a blockhash has +2/3") } precommits := make([]*Vote, voteSet.valSet.Size()) voteSet.valSet.Iterate(func(valIndex int, val *Validator) bool { @@ -296,7 +296,7 @@ func (voteSet *VoteSet) MakeValidation() *Validation { precommits[valIndex] = vote return false }) - return &Validation{ + return &Commit{ Precommits: precommits, } } diff --git a/types/vote_set_test.go b/types/vote_set_test.go index d84169a0..b9d154c9 100644 --- a/types/vote_set_test.go +++ b/types/vote_set_test.go @@ -232,7 +232,7 @@ func TestBadVotes(t *testing.T) { } } -func TestMakeValidation(t *testing.T) { +func TestMakeCommit(t *testing.T) { height, round := 1, 0 voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrecommit, 10, 1) blockHash, blockPartsHeader := crypto.CRandBytes(32), PartSetHeader{123, crypto.CRandBytes(32)} @@ -245,8 +245,8 @@ func TestMakeValidation(t *testing.T) { signAddVote(privValidators[i], vote, voteSet) } - // MakeValidation should fail. - AssertPanics(t, "Doesn't have +2/3 majority", func() { voteSet.MakeValidation() }) + // MakeCommit should fail. + AssertPanics(t, "Doesn't have +2/3 majority", func() { voteSet.MakeCommit() }) // 7th voted for some other block. { @@ -260,16 +260,16 @@ func TestMakeValidation(t *testing.T) { signAddVote(privValidators[7], vote, voteSet) } - validation := voteSet.MakeValidation() + commit := voteSet.MakeCommit() - // Validation should have 10 elements - if len(validation.Precommits) != 10 { - t.Errorf("Validation Precommits should have the same number of precommits as validators") + // Commit should have 10 elements + if len(commit.Precommits) != 10 { + t.Errorf("Commit Precommits should have the same number of precommits as validators") } - // Ensure that Validation precommits are ordered. - if err := validation.ValidateBasic(); err != nil { - t.Errorf("Error in Validation.ValidateBasic(): %v", err) + // Ensure that Commit precommits are ordered. + if err := commit.ValidateBasic(); err != nil { + t.Errorf("Error in Commit.ValidateBasic(): %v", err) } }