abci: VoteInfo, ValidatorUpdate. See ADR-018

This commit is contained in:
Ethan Buchman
2018-08-06 00:18:24 -04:00
parent f26b83f15f
commit e3f54ece2f
18 changed files with 706 additions and 452 deletions

View File

@ -7,12 +7,10 @@ import (
// RandVal creates one random validator, with a key derived
// from the input value
func RandVal(i int) types.Validator {
addr := cmn.RandBytes(20)
func RandVal(i int) types.ValidatorUpdate {
pubkey := cmn.RandBytes(32)
power := cmn.RandUint16() + 1
v := types.Ed25519Validator(pubkey, int64(power))
v.Address = addr
v := types.Ed25519ValidatorUpdate(pubkey, int64(power))
return v
}
@ -20,8 +18,8 @@ func RandVal(i int) types.Validator {
// the application. Note that the keys are deterministically
// derived from the index in the array, while the power is
// random (Change this if not desired)
func RandVals(cnt int) []types.Validator {
res := make([]types.Validator, cnt)
func RandVals(cnt int) []types.ValidatorUpdate {
res := make([]types.ValidatorUpdate, cnt)
for i := 0; i < cnt; i++ {
res[i] = RandVal(i)
}

View File

@ -122,11 +122,11 @@ func TestValUpdates(t *testing.T) {
vals1, vals2 := vals[:nInit], kvstore.Validators()
valsEqual(t, vals1, vals2)
var v1, v2, v3 types.Validator
var v1, v2, v3 types.ValidatorUpdate
// add some validators
v1, v2 = vals[nInit], vals[nInit+1]
diff := []types.Validator{v1, v2}
diff := []types.ValidatorUpdate{v1, v2}
tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power)
tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power)
@ -140,7 +140,7 @@ func TestValUpdates(t *testing.T) {
v1.Power = 0
v2.Power = 0
v3.Power = 0
diff = []types.Validator{v1, v2, v3}
diff = []types.ValidatorUpdate{v1, v2, v3}
tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power)
tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power)
@ -158,18 +158,18 @@ func TestValUpdates(t *testing.T) {
} else {
v1.Power = 5
}
diff = []types.Validator{v1}
diff = []types.ValidatorUpdate{v1}
tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
makeApplyBlock(t, kvstore, 3, diff, tx1)
vals1 = append([]types.Validator{v1}, vals1[1:]...)
vals1 = append([]types.ValidatorUpdate{v1}, vals1[1:]...)
vals2 = kvstore.Validators()
valsEqual(t, vals1, vals2)
}
func makeApplyBlock(t *testing.T, kvstore types.Application, heightInt int, diff []types.Validator, txs ...[]byte) {
func makeApplyBlock(t *testing.T, kvstore types.Application, heightInt int, diff []types.ValidatorUpdate, txs ...[]byte) {
// make and apply block
height := int64(heightInt)
hash := []byte("foo")
@ -191,12 +191,12 @@ func makeApplyBlock(t *testing.T, kvstore types.Application, heightInt int, diff
}
// order doesn't matter
func valsEqual(t *testing.T, vals1, vals2 []types.Validator) {
func valsEqual(t *testing.T, vals1, vals2 []types.ValidatorUpdate) {
if len(vals1) != len(vals2) {
t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1))
}
sort.Sort(types.Validators(vals1))
sort.Sort(types.Validators(vals2))
sort.Sort(types.ValidatorUpdates(vals1))
sort.Sort(types.ValidatorUpdates(vals2))
for i, v1 := range vals1 {
v2 := vals2[i]
if !bytes.Equal(v1.PubKey.Data, v2.PubKey.Data) ||

View File

@ -25,7 +25,7 @@ type PersistentKVStoreApplication struct {
app *KVStoreApplication
// validator set
ValUpdates []types.Validator
ValUpdates []types.ValidatorUpdate
logger log.Logger
}
@ -101,7 +101,7 @@ func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) t
// Track the block hash and header information
func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
// reset valset changes
app.ValUpdates = make([]types.Validator, 0)
app.ValUpdates = make([]types.ValidatorUpdate, 0)
return types.ResponseBeginBlock{}
}
@ -113,11 +113,11 @@ func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) typ
//---------------------------------------------
// update validators
func (app *PersistentKVStoreApplication) Validators() (validators []types.Validator) {
func (app *PersistentKVStoreApplication) Validators() (validators []types.ValidatorUpdate) {
itr := app.app.state.db.Iterator(nil, nil)
for ; itr.Valid(); itr.Next() {
if isValidatorTx(itr.Key()) {
validator := new(types.Validator)
validator := new(types.ValidatorUpdate)
err := types.ReadMessage(bytes.NewBuffer(itr.Value()), validator)
if err != nil {
panic(err)
@ -167,11 +167,11 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.Respon
}
// update
return app.updateValidator(types.Ed25519Validator(pubkey, int64(power)))
return app.updateValidator(types.Ed25519ValidatorUpdate(pubkey, int64(power)))
}
// add, update, or remove a validator
func (app *PersistentKVStoreApplication) updateValidator(v types.Validator) types.ResponseDeliverTx {
func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate) types.ResponseDeliverTx {
key := []byte("val:" + string(v.PubKey.Data))
if v.Power == 0 {
// remove validator

View File

@ -12,11 +12,11 @@ import (
func InitChain(client abcicli.Client) error {
total := 10
vals := make([]types.Validator, total)
vals := make([]types.ValidatorUpdate, total)
for i := 0; i < total; i++ {
pubkey := cmn.RandBytes(33)
power := cmn.RandInt()
vals[i] = types.Ed25519Validator(pubkey, int64(power))
vals[i] = types.Ed25519ValidatorUpdate(pubkey, int64(power))
}
_, err := client.InitChainSync(types.RequestInitChain{
Validators: vals,

View File

@ -4,8 +4,8 @@ const (
PubKeyEd25519 = "ed25519"
)
func Ed25519Validator(pubkey []byte, power int64) Validator {
return Validator{
func Ed25519ValidatorUpdate(pubkey []byte, power int64) ValidatorUpdate {
return ValidatorUpdate{
// Address:
PubKey: PubKey{
Type: PubKeyEd25519,

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,7 @@ message RequestInitChain {
google.protobuf.Timestamp time = 1 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];
string chain_id = 2;
ConsensusParams consensus_params = 3;
repeated Validator validators = 4 [(gogoproto.nullable)=false];
repeated ValidatorUpdate validators = 4 [(gogoproto.nullable)=false];
bytes app_state_bytes = 5;
}
@ -143,7 +143,7 @@ message ResponseSetOption {
message ResponseInitChain {
ConsensusParams consensus_params = 1;
repeated Validator validators = 2 [(gogoproto.nullable)=false];
repeated ValidatorUpdate validators = 2 [(gogoproto.nullable)=false];
}
message ResponseQuery {
@ -183,7 +183,7 @@ message ResponseDeliverTx {
}
message ResponseEndBlock {
repeated Validator validator_updates = 1 [(gogoproto.nullable)=false];
repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable)=false];
ConsensusParams consensus_param_updates = 2;
repeated common.KVPair tags = 3 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
}
@ -225,8 +225,7 @@ message BlockGossip {
}
message LastCommitInfo {
int32 commit_round = 1;
repeated SigningValidator validators = 2 [(gogoproto.nullable)=false];
repeated VoteInfo commit_votes = 1 [(gogoproto.nullable)=false];
}
//----------------------------------------
@ -272,14 +271,20 @@ message PartSetHeader {
// Validator
message Validator {
bytes address = 1;
PubKey pub_key = 2 [(gogoproto.nullable)=false];
int64 power = 3;
}
// Validator with an extra bool
message SigningValidator {
// ValidatorUpdate
message ValidatorUpdate {
PubKey pub_key = 1 [(gogoproto.nullable)=false];
int64 power = 2;
}
// VoteInfo
message VoteInfo {
Validator validator = 1 [(gogoproto.nullable)=false];
bool signed_last_block = 2;
int64 commit_round = 3;
}
message PubKey {

View File

@ -42,7 +42,8 @@ It has these top-level messages:
BlockID
PartSetHeader
Validator
SigningValidator
ValidatorUpdate
VoteInfo
PubKey
Evidence
*/
@ -1970,15 +1971,15 @@ func TestValidatorMarshalTo(t *testing.T) {
}
}
func TestSigningValidatorProto(t *testing.T) {
func TestValidatorUpdateProto(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedSigningValidator(popr, false)
p := NewPopulatedValidatorUpdate(popr, false)
dAtA, err := proto.Marshal(p)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &SigningValidator{}
msg := &ValidatorUpdate{}
if err := proto.Unmarshal(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
@ -2001,10 +2002,10 @@ func TestSigningValidatorProto(t *testing.T) {
}
}
func TestSigningValidatorMarshalTo(t *testing.T) {
func TestValidatorUpdateMarshalTo(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedSigningValidator(popr, false)
p := NewPopulatedValidatorUpdate(popr, false)
size := p.Size()
dAtA := make([]byte, size)
for i := range dAtA {
@ -2014,7 +2015,63 @@ func TestSigningValidatorMarshalTo(t *testing.T) {
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &SigningValidator{}
msg := &ValidatorUpdate{}
if err := proto.Unmarshal(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
for i := range dAtA {
dAtA[i] = byte(popr.Intn(256))
}
if !p.Equal(msg) {
t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)
}
}
func TestVoteInfoProto(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedVoteInfo(popr, false)
dAtA, err := proto.Marshal(p)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &VoteInfo{}
if err := proto.Unmarshal(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
littlefuzz := make([]byte, len(dAtA))
copy(littlefuzz, dAtA)
for i := range dAtA {
dAtA[i] = byte(popr.Intn(256))
}
if !p.Equal(msg) {
t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)
}
if len(littlefuzz) > 0 {
fuzzamount := 100
for i := 0; i < fuzzamount; i++ {
littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256))
littlefuzz = append(littlefuzz, byte(popr.Intn(256)))
}
// shouldn't panic
_ = proto.Unmarshal(littlefuzz, msg)
}
}
func TestVoteInfoMarshalTo(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedVoteInfo(popr, false)
size := p.Size()
dAtA := make([]byte, size)
for i := range dAtA {
dAtA[i] = byte(popr.Intn(256))
}
_, err := p.MarshalTo(dAtA)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &VoteInfo{}
if err := proto.Unmarshal(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
@ -2750,16 +2807,34 @@ func TestValidatorJSON(t *testing.T) {
t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)
}
}
func TestSigningValidatorJSON(t *testing.T) {
func TestValidatorUpdateJSON(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedSigningValidator(popr, true)
p := NewPopulatedValidatorUpdate(popr, true)
marshaler := jsonpb.Marshaler{}
jsondata, err := marshaler.MarshalToString(p)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &SigningValidator{}
msg := &ValidatorUpdate{}
err = jsonpb.UnmarshalString(jsondata, msg)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
if !p.Equal(msg) {
t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)
}
}
func TestVoteInfoJSON(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedVoteInfo(popr, true)
marshaler := jsonpb.Marshaler{}
jsondata, err := marshaler.MarshalToString(p)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &VoteInfo{}
err = jsonpb.UnmarshalString(jsondata, msg)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
@ -3756,12 +3831,12 @@ func TestValidatorProtoCompactText(t *testing.T) {
}
}
func TestSigningValidatorProtoText(t *testing.T) {
func TestValidatorUpdateProtoText(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedSigningValidator(popr, true)
p := NewPopulatedValidatorUpdate(popr, true)
dAtA := proto.MarshalTextString(p)
msg := &SigningValidator{}
msg := &ValidatorUpdate{}
if err := proto.UnmarshalText(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
@ -3770,12 +3845,40 @@ func TestSigningValidatorProtoText(t *testing.T) {
}
}
func TestSigningValidatorProtoCompactText(t *testing.T) {
func TestValidatorUpdateProtoCompactText(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedSigningValidator(popr, true)
p := NewPopulatedValidatorUpdate(popr, true)
dAtA := proto.CompactTextString(p)
msg := &SigningValidator{}
msg := &ValidatorUpdate{}
if err := proto.UnmarshalText(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
if !p.Equal(msg) {
t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)
}
}
func TestVoteInfoProtoText(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedVoteInfo(popr, true)
dAtA := proto.MarshalTextString(p)
msg := &VoteInfo{}
if err := proto.UnmarshalText(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
if !p.Equal(msg) {
t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)
}
}
func TestVoteInfoProtoCompactText(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedVoteInfo(popr, true)
dAtA := proto.CompactTextString(p)
msg := &VoteInfo{}
if err := proto.UnmarshalText(dAtA, msg); err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
@ -4588,10 +4691,32 @@ func TestValidatorSize(t *testing.T) {
}
}
func TestSigningValidatorSize(t *testing.T) {
func TestValidatorUpdateSize(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedSigningValidator(popr, true)
p := NewPopulatedValidatorUpdate(popr, true)
size2 := proto.Size(p)
dAtA, err := proto.Marshal(p)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
size := p.Size()
if len(dAtA) != size {
t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA))
}
if size2 != size {
t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2)
}
size3 := proto.Size(p)
if size3 != size {
t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3)
}
}
func TestVoteInfoSize(t *testing.T) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
p := NewPopulatedVoteInfo(popr, true)
size2 := proto.Size(p)
dAtA, err := proto.Marshal(p)
if err != nil {

View File

@ -2,58 +2,33 @@ package types
import (
"bytes"
"encoding/json"
"sort"
cmn "github.com/tendermint/tendermint/libs/common"
)
//------------------------------------------------------------------------------
// Validators is a list of validators that implements the Sort interface
type Validators []Validator
// ValidatorUpdates is a list of validators that implements the Sort interface
type ValidatorUpdates []ValidatorUpdate
var _ sort.Interface = (Validators)(nil)
var _ sort.Interface = (ValidatorUpdates)(nil)
// All these methods for Validators:
// All these methods for ValidatorUpdates:
// Len, Less and Swap
// are for Validators to implement sort.Interface
// are for ValidatorUpdates to implement sort.Interface
// which will be used by the sort package.
// See Issue https://github.com/tendermint/abci/issues/212
func (v Validators) Len() int {
func (v ValidatorUpdates) Len() int {
return len(v)
}
// XXX: doesn't distinguish same validator with different power
func (v Validators) Less(i, j int) bool {
func (v ValidatorUpdates) Less(i, j int) bool {
return bytes.Compare(v[i].PubKey.Data, v[j].PubKey.Data) <= 0
}
func (v Validators) Swap(i, j int) {
func (v ValidatorUpdates) Swap(i, j int) {
v1 := v[i]
v[i] = v[j]
v[j] = v1
}
func ValidatorsString(vs Validators) string {
s := make([]validatorPretty, len(vs))
for i, v := range vs {
s[i] = validatorPretty{
Address: v.Address,
PubKey: v.PubKey.Data,
Power: v.Power,
}
}
b, err := json.Marshal(s)
if err != nil {
panic(err.Error())
}
return string(b)
}
type validatorPretty struct {
Address cmn.HexBytes `json:"address"`
PubKey []byte `json:"pub_key"`
Power int64 `json:"power"`
}

View File

@ -354,7 +354,7 @@ func randConsensusNet(nValidators int, testName string, tickerFunc func() Timeou
}
ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal
app := appFunc()
vals := types.TM2PB.Validators(state.Validators)
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(abci.RequestInitChain{Validators: vals})
css[i] = newConsensusStateWithConfig(thisConfig, state, privVals[i], app)
@ -386,7 +386,7 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF
}
app := appFunc()
vals := types.TM2PB.Validators(state.Validators)
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(abci.RequestInitChain{Validators: vals})
css[i] = newConsensusStateWithConfig(thisConfig, state, privVal, app)

View File

@ -118,7 +118,7 @@ func TestReactorWithEvidence(t *testing.T) {
thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i))
ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal
app := appFunc()
vals := types.TM2PB.Validators(state.Validators)
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(abci.RequestInitChain{Validators: vals})
pv := privVals[i]

View File

@ -266,7 +266,7 @@ func (h *Handshaker) ReplayBlocks(state sm.State, appHash []byte, appBlockHeight
// If appBlockHeight == 0 it means that we are at genesis and hence should send InitChain.
if appBlockHeight == 0 {
nextVals := types.TM2PB.Validators(state.NextValidators) // state.Validators would work too.
nextVals := types.TM2PB.ValidatorUpdates(state.NextValidators) // state.Validators would work too.
csParams := types.TM2PB.ConsensusParams(h.genDoc.ConsensusParams)
req := abci.RequestInitChain{
Time: h.genDoc.GenesisTime,
@ -282,7 +282,7 @@ func (h *Handshaker) ReplayBlocks(state sm.State, appHash []byte, appBlockHeight
// If the app returned validators or consensus params, update the state.
if len(res.Validators) > 0 {
vals, err := types.PB2TM.Validators(res.Validators)
vals, err := types.PB2TM.ValidatorUpdates(res.Validators)
if err != nil {
return nil, err
}

View File

@ -416,7 +416,7 @@ func buildAppStateFromChain(proxyApp proxy.AppConns, stateDB dbm.DB,
}
defer proxyApp.Stop()
validators := types.TM2PB.Validators(state.Validators)
validators := types.TM2PB.ValidatorUpdates(state.Validators)
if _, err := proxyApp.Consensus().InitChainSync(abci.RequestInitChain{
Validators: validators,
}); err != nil {
@ -453,7 +453,7 @@ func buildTMStateFromChain(config *cfg.Config, stateDB dbm.DB, state sm.State, c
}
defer proxyApp.Stop()
validators := types.TM2PB.Validators(state.Validators)
validators := types.TM2PB.ValidatorUpdates(state.Validators)
if _, err := proxyApp.Consensus().InitChainSync(abci.RequestInitChain{
Validators: validators,
}); err != nil {
@ -639,7 +639,7 @@ func (bs *mockBlockStore) LoadSeenCommit(height int64) *types.Commit {
func TestInitChainUpdateValidators(t *testing.T) {
val, _ := types.RandValidator(true, 10)
vals := types.NewValidatorSet([]*types.Validator{val})
app := &initChainApp{vals: types.TM2PB.Validators(vals)}
app := &initChainApp{vals: types.TM2PB.ValidatorUpdates(vals)}
clientCreator := proxy.NewLocalClientCreator(app)
config := ResetConfig("proxy_test_")
@ -666,7 +666,7 @@ func TestInitChainUpdateValidators(t *testing.T) {
assert.Equal(t, newValAddr, expectValAddr)
}
func newInitChainApp(vals []abci.Validator) *initChainApp {
func newInitChainApp(vals []abci.ValidatorUpdate) *initChainApp {
return &initChainApp{
vals: vals,
}
@ -675,7 +675,7 @@ func newInitChainApp(vals []abci.Validator) *initChainApp {
// returns the vals on InitChain
type initChainApp struct {
abci.BaseApplication
vals []abci.Validator
vals []abci.ValidatorUpdate
}
func (ica *initChainApp) InitChain(req abci.RequestInitChain) abci.ResponseInitChain {

View File

@ -184,15 +184,14 @@ func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus,
}
proxyAppConn.SetResponseCallback(proxyCb)
signVals, byzVals := getBeginBlockValidatorInfo(block, lastValSet, stateDB)
voteInfos, byzVals := getBeginBlockValidatorInfo(block, lastValSet, stateDB)
// Begin block.
_, err := proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
Hash: block.Hash(),
Header: types.TM2PB.Header(&block.Header),
LastCommitInfo: abci.LastCommitInfo{
CommitRound: int32(block.LastCommit.Round()),
Validators: signVals,
CommitVotes: voteInfos,
},
ByzantineValidators: byzVals,
})
@ -218,15 +217,15 @@ func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus,
logger.Info("Executed block", "height", block.Height, "validTxs", validTxs, "invalidTxs", invalidTxs)
valUpdates := abciResponses.EndBlock.ValidatorUpdates
if len(valUpdates) > 0 {
logger.Info("Updates to validators", "updates", abci.ValidatorsString(valUpdates))
if len(abciResponses.EndBlock.ValidatorUpdates) > 0 {
// TODO: cleanup the formatting
logger.Info("Updates to validators", "updates", abciResponses.EndBlock.ValidatorUpdates)
}
return abciResponses, nil
}
func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorSet, stateDB dbm.DB) ([]abci.SigningValidator, []abci.Evidence) {
func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorSet, stateDB dbm.DB) ([]abci.VoteInfo, []abci.Evidence) {
// Sanity check that commit length matches validator set size -
// only applies after first block
@ -241,17 +240,22 @@ func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorS
}
// determine which validators did not sign last block.
signVals := make([]abci.SigningValidator, len(lastValSet.Validators))
voteInfos := make([]abci.VoteInfo, len(lastValSet.Validators))
for i, val := range lastValSet.Validators {
var vote *types.Vote
var commitRound = -1
if i < len(block.LastCommit.Precommits) {
vote = block.LastCommit.Precommits[i]
if vote != nil {
commitRound = vote.Round
}
val := abci.SigningValidator{
Validator: types.TM2PB.ValidatorWithoutPubKey(val),
SignedLastBlock: vote != nil,
}
signVals[i] = val
voteInfo := abci.VoteInfo{
Validator: types.TM2PB.Validator(val),
SignedLastBlock: vote != nil, // XXX: should we replace with commitRound == -1 ?
CommitRound: int64(commitRound), //XXX: why is round an int?
}
voteInfos[i] = voteInfo
}
byzVals := make([]abci.Evidence, len(block.Evidence.Evidence))
@ -266,15 +270,15 @@ func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorS
byzVals[i] = types.TM2PB.Evidence(ev, valset, block.Time)
}
return signVals, byzVals
return voteInfos, byzVals
}
// If more or equal than 1/3 of total voting power changed in one block, then
// a light client could never prove the transition externally. See
// ./lite/doc.go for details on how a light client tracks validators.
func updateValidators(currentSet *types.ValidatorSet, abciUpdates []abci.Validator) error {
updates, err := types.PB2TM.Validators(abciUpdates)
func updateValidators(currentSet *types.ValidatorSet, abciUpdates []abci.ValidatorUpdate) error {
updates, err := types.PB2TM.ValidatorUpdates(abciUpdates)
if err != nil {
return err
}

View File

@ -86,7 +86,7 @@ func TestBeginBlockValidators(t *testing.T) {
// -> app receives a list of validators with a bool indicating if they signed
ctr := 0
for i, v := range app.Validators {
for i, v := range app.CommitVotes {
if ctr < len(tc.expectedAbsentValidators) &&
tc.expectedAbsentValidators[ctr] == i {
@ -160,7 +160,7 @@ func TestUpdateValidators(t *testing.T) {
name string
currentSet *types.ValidatorSet
abciUpdates []abci.Validator
abciUpdates []abci.ValidatorUpdate
resultingSet *types.ValidatorSet
shouldErr bool
@ -169,7 +169,7 @@ func TestUpdateValidators(t *testing.T) {
"adding a validator is OK",
types.NewValidatorSet([]*types.Validator{val1}),
[]abci.Validator{{Address: []byte{}, PubKey: types.TM2PB.PubKey(pubkey2), Power: 20}},
[]abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 20}},
types.NewValidatorSet([]*types.Validator{val1, val2}),
false,
@ -178,7 +178,7 @@ func TestUpdateValidators(t *testing.T) {
"updating a validator is OK",
types.NewValidatorSet([]*types.Validator{val1}),
[]abci.Validator{{Address: []byte{}, PubKey: types.TM2PB.PubKey(pubkey1), Power: 20}},
[]abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey1), Power: 20}},
types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}),
false,
@ -187,7 +187,7 @@ func TestUpdateValidators(t *testing.T) {
"removing a validator is OK",
types.NewValidatorSet([]*types.Validator{val1, val2}),
[]abci.Validator{{Address: []byte{}, PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}},
[]abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}},
types.NewValidatorSet([]*types.Validator{val1}),
false,
@ -197,7 +197,7 @@ func TestUpdateValidators(t *testing.T) {
"removing a non-existing validator results in error",
types.NewValidatorSet([]*types.Validator{val1}),
[]abci.Validator{{Address: []byte{}, PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}},
[]abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}},
types.NewValidatorSet([]*types.Validator{val1}),
true,
@ -207,7 +207,7 @@ func TestUpdateValidators(t *testing.T) {
"adding a validator with negative power results in error",
types.NewValidatorSet([]*types.Validator{val1}),
[]abci.Validator{{Address: []byte{}, PubKey: types.TM2PB.PubKey(pubkey2), Power: -100}},
[]abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: -100}},
types.NewValidatorSet([]*types.Validator{val1}),
true,
@ -335,7 +335,7 @@ func makeBlock(state State, height int64) *types.Block {
type testApp struct {
abci.BaseApplication
Validators []abci.SigningValidator
CommitVotes []abci.VoteInfo
ByzantineValidators []abci.Evidence
ValidatorUpdates []abci.Validator
}
@ -347,7 +347,7 @@ func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) {
}
func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock {
app.Validators = req.LastCommitInfo.Validators
app.CommitVotes = req.LastCommitInfo.CommitVotes
app.ByzantineValidators = req.ByzantineValidators
return abci.ResponseBeginBlock{}
}

View File

@ -78,8 +78,8 @@ func TestABCIResponsesSaveLoad1(t *testing.T) {
abciResponses := NewABCIResponses(block)
abciResponses.DeliverTx[0] = &abci.ResponseDeliverTx{Data: []byte("foo"), Tags: nil}
abciResponses.DeliverTx[1] = &abci.ResponseDeliverTx{Data: []byte("bar"), Log: "ok", Tags: nil}
abciResponses.EndBlock = &abci.ResponseEndBlock{ValidatorUpdates: []abci.Validator{
types.TM2PB.ValidatorFromPubKeyAndPower(ed25519.GenPrivKey().PubKey(), 10),
abciResponses.EndBlock = &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{
types.TM2PB.NewValidatorUpdate(ed25519.GenPrivKey().PubKey(), 10),
}}
saveABCIResponses(stateDB, block.Height, abciResponses)
@ -454,9 +454,9 @@ func makeHeaderPartsResponsesValPubKeyChange(state State, height int64,
_, val := state.NextValidators.GetByIndex(0)
if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) {
abciResponses.EndBlock = &abci.ResponseEndBlock{
ValidatorUpdates: []abci.Validator{
types.TM2PB.ValidatorFromPubKeyAndPower(val.PubKey, 0),
types.TM2PB.ValidatorFromPubKeyAndPower(pubkey, 10),
ValidatorUpdates: []abci.ValidatorUpdate{
types.TM2PB.NewValidatorUpdate(val.PubKey, 0),
types.TM2PB.NewValidatorUpdate(pubkey, 10),
},
}
}
@ -476,8 +476,8 @@ func makeHeaderPartsResponsesValPowerChange(state State, height int64,
_, val := state.NextValidators.GetByIndex(0)
if val.VotingPower != power {
abciResponses.EndBlock = &abci.ResponseEndBlock{
ValidatorUpdates: []abci.Validator{
types.TM2PB.ValidatorFromPubKeyAndPower(val.PubKey, power),
ValidatorUpdates: []abci.ValidatorUpdate{
types.TM2PB.NewValidatorUpdate(val.PubKey, power),
},
}
}

View File

@ -1,7 +1,6 @@
package types
import (
"bytes"
"fmt"
"reflect"
"time"
@ -56,7 +55,7 @@ func (tm2pb) Header(header *Header) abci.Header {
}
}
func (tm2pb) ValidatorWithoutPubKey(val *Validator) abci.Validator {
func (tm2pb) Validator(val *Validator) abci.Validator {
return abci.Validator{
Address: val.PubKey.Address(),
Power: val.VotingPower,
@ -78,9 +77,8 @@ func (tm2pb) PartSetHeader(header PartSetHeader) abci.PartSetHeader {
}
// XXX: panics on unknown pubkey type
func (tm2pb) Validator(val *Validator) abci.Validator {
return abci.Validator{
Address: val.PubKey.Address(),
func (tm2pb) ValidatorUpdate(val *Validator) abci.ValidatorUpdate {
return abci.ValidatorUpdate{
PubKey: TM2PB.PubKey(val.PubKey),
Power: val.VotingPower,
}
@ -106,10 +104,10 @@ func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey {
}
// XXX: panics on nil or unknown pubkey type
func (tm2pb) Validators(vals *ValidatorSet) []abci.Validator {
validators := make([]abci.Validator, vals.Size())
func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate {
validators := make([]abci.ValidatorUpdate, vals.Size())
for i, val := range vals.Validators {
validators[i] = TM2PB.Validator(val)
validators[i] = TM2PB.ValidatorUpdate(val)
}
return validators
}
@ -156,7 +154,7 @@ func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.
return abci.Evidence{
Type: evType,
Validator: TM2PB.ValidatorWithoutPubKey(val),
Validator: TM2PB.Validator(val),
Height: ev.Height(),
Time: evTime,
TotalVotingPower: valSet.TotalVotingPower(),
@ -164,10 +162,9 @@ func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.
}
// XXX: panics on nil or unknown pubkey type
func (tm2pb) ValidatorFromPubKeyAndPower(pubkey crypto.PubKey, power int64) abci.Validator {
func (tm2pb) NewValidatorUpdate(pubkey crypto.PubKey, power int64) abci.ValidatorUpdate {
pubkeyABCI := TM2PB.PubKey(pubkey)
return abci.Validator{
Address: pubkey.Address(),
return abci.ValidatorUpdate{
PubKey: pubkeyABCI,
Power: power,
}
@ -205,7 +202,7 @@ func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) {
}
}
func (pb2tm) Validators(vals []abci.Validator) ([]*Validator, error) {
func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error) {
tmVals := make([]*Validator, len(vals))
for i, v := range vals {
pub, err := PB2TM.PubKey(v.PubKey)
@ -214,17 +211,13 @@ func (pb2tm) Validators(vals []abci.Validator) ([]*Validator, error) {
}
// If the app provided an address too, it must match.
// This is just a sanity check.
if len(v.Address) > 0 {
/*if len(v.Address) > 0 {
if !bytes.Equal(pub.Address(), v.Address) {
return nil, fmt.Errorf("Validator.Address (%X) does not match PubKey.Address (%X)",
v.Address, pub.Address())
}
}
tmVals[i] = &Validator{
Address: pub.Address(),
PubKey: pub,
VotingPower: v.Power,
}
}*/
tmVals[i] = NewValidator(pub, v.Power)
}
return tmVals, nil
}

View File

@ -41,26 +41,26 @@ func TestABCIValidators(t *testing.T) {
VotingPower: 10,
}
abciVal := TM2PB.Validator(tmVal)
tmVals, err := PB2TM.Validators([]abci.Validator{abciVal})
abciVal := TM2PB.ValidatorUpdate(tmVal)
tmVals, err := PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal})
assert.Nil(t, err)
assert.Equal(t, tmValExpected, tmVals[0])
abciVals := TM2PB.Validators(NewValidatorSet(tmVals))
assert.Equal(t, []abci.Validator{abciVal}, abciVals)
abciVals := TM2PB.ValidatorUpdates(NewValidatorSet(tmVals))
assert.Equal(t, []abci.ValidatorUpdate{abciVal}, abciVals)
// val with address
tmVal.Address = pkEd.Address()
abciVal = TM2PB.Validator(tmVal)
tmVals, err = PB2TM.Validators([]abci.Validator{abciVal})
abciVal = TM2PB.ValidatorUpdate(tmVal)
tmVals, err = PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal})
assert.Nil(t, err)
assert.Equal(t, tmValExpected, tmVals[0])
// val with incorrect address
abciVal = TM2PB.Validator(tmVal)
abciVal.Address = []byte("incorrect!")
tmVals, err = PB2TM.Validators([]abci.Validator{abciVal})
// val with incorrect pubkey daya
abciVal = TM2PB.ValidatorUpdate(tmVal)
abciVal.PubKey.Data = []byte("incorrect!")
tmVals, err = PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal})
assert.NotNil(t, err)
assert.Nil(t, tmVals)
}
@ -104,9 +104,6 @@ func TestABCIEvidence(t *testing.T) {
)
assert.Equal(t, "duplicate/vote", abciEv.Type)
// test we do not send pubkeys
assert.Empty(t, abciEv.Validator.PubKey)
}
type pubKeyEddie struct{}
@ -119,17 +116,17 @@ func (pubKeyEddie) Equals(crypto.PubKey) bool { return false }
func TestABCIValidatorFromPubKeyAndPower(t *testing.T) {
pubkey := ed25519.GenPrivKey().PubKey()
abciVal := TM2PB.ValidatorFromPubKeyAndPower(pubkey, 10)
abciVal := TM2PB.NewValidatorUpdate(pubkey, 10)
assert.Equal(t, int64(10), abciVal.Power)
assert.Panics(t, func() { TM2PB.ValidatorFromPubKeyAndPower(nil, 10) })
assert.Panics(t, func() { TM2PB.ValidatorFromPubKeyAndPower(pubKeyEddie{}, 10) })
assert.Panics(t, func() { TM2PB.NewValidatorUpdate(nil, 10) })
assert.Panics(t, func() { TM2PB.NewValidatorUpdate(pubKeyEddie{}, 10) })
}
func TestABCIValidatorWithoutPubKey(t *testing.T) {
pkEd := ed25519.GenPrivKey().PubKey()
abciVal := TM2PB.ValidatorWithoutPubKey(&Validator{
abciVal := TM2PB.Validator(&Validator{
Address: pkEd.Address(),
PubKey: pkEd,
VotingPower: 10,