Add full vote to BeginBlock

This commit is contained in:
folex 2019-09-06 11:20:28 +02:00
parent a13a4b8c77
commit 2a1d0542f3
7 changed files with 163 additions and 3 deletions

View File

@ -311,6 +311,22 @@ message ValidatorUpdate {
message VoteInfo {
Validator validator = 1 [(gogoproto.nullable)=false];
bool signed_last_block = 2;
Vote full_vote = 3;
}
// Vote from LastCommit
message Vote {
int32 type = 1;
// TODO: maybe remove height cause it could be derived from BeginBlock?
int64 height = 2;
int32 round = 3;
// TODO: maybe remove block id cause it's already in the header as last_block_id?
BlockID block_id = 4 [json_name = "block_id"];
google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];
// TODO: maybe remove validator address cause it's already in VoteInfo.validator?
bytes validator_address = 6 [json_name = "validator_address"];
int32 validator_index = 7 [json_name = "validator_index"];
bytes signature = 8;
}
message PubKey {

View File

@ -2153,6 +2153,62 @@ func TestVoteInfoMarshalTo(t *testing.T) {
}
}
func TestVoteProto(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
p := NewPopulatedVote(popr, false)
dAtA, err := github_com_gogo_protobuf_proto.Marshal(p)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &Vote{}
if err := github_com_gogo_protobuf_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
_ = github_com_gogo_protobuf_proto.Unmarshal(littlefuzz, msg)
}
}
func TestVoteMarshalTo(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
p := NewPopulatedVote(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 := &Vote{}
if err := github_com_gogo_protobuf_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 TestPubKeyProto(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
@ -2949,6 +3005,24 @@ func TestVoteInfoJSON(t *testing.T) {
t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)
}
}
func TestVoteJSON(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
p := NewPopulatedVote(popr, true)
marshaler := github_com_gogo_protobuf_jsonpb.Marshaler{}
jsondata, err := marshaler.MarshalToString(p)
if err != nil {
t.Fatalf("seed = %d, err = %v", seed, err)
}
msg := &Vote{}
err = github_com_gogo_protobuf_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 TestPubKeyJSON(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
@ -4049,6 +4123,34 @@ func TestVoteInfoProtoCompactText(t *testing.T) {
}
}
func TestVoteProtoText(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
p := NewPopulatedVote(popr, true)
dAtA := github_com_gogo_protobuf_proto.MarshalTextString(p)
msg := &Vote{}
if err := github_com_gogo_protobuf_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 TestVoteProtoCompactText(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
p := NewPopulatedVote(popr, true)
dAtA := github_com_gogo_protobuf_proto.CompactTextString(p)
msg := &Vote{}
if err := github_com_gogo_protobuf_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 TestPubKeyProtoText(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
@ -4941,6 +5043,28 @@ func TestVoteInfoSize(t *testing.T) {
}
}
func TestVoteSize(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))
p := NewPopulatedVote(popr, true)
size2 := github_com_gogo_protobuf_proto.Size(p)
dAtA, err := github_com_gogo_protobuf_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 := github_com_gogo_protobuf_proto.Size(p)
if size3 != size {
t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3)
}
}
func TestPubKeySize(t *testing.T) {
seed := time.Now().UnixNano()
popr := math_rand.New(math_rand.NewSource(seed))

View File

@ -265,8 +265,7 @@ ResponseCommit requestCommit(RequestCommit requestCommit) {
### BeginBlock
The BeginBlock request can be used to run some code at the beginning of
every block. It also allows Tendermint to send the current block hash
and header to the application, before it sends any of the transactions.
every block. It also allows Tendermint to send the current block hash, header and commit of the last block to the application, before it sends any of the transactions.
The app should remember the latest height and header (ie. from which it
has run a successful Commit) so that it can tell Tendermint where to

View File

@ -449,6 +449,7 @@ Commit are included in the header of the next block.
- `Validator (Validator)`: A validator
- `SignedLastBlock (bool)`: Indicates whether or not the validator signed
the last block
- `FullVote (Vote)`: Validator's vote
- **Usage**:
- Indicates whether a validator signed the last block, allowing for rewards
based on validator availability
@ -482,7 +483,7 @@ Commit are included in the header of the next block.
- **Fields**:
- `Round (int32)`: Commit round.
- `Votes ([]VoteInfo)`: List of validators addresses in the last validator set
with their voting power and whether or not they signed a vote.
with their voting power, votes and whether or not they signed a vote.
### ConsensusParams

View File

@ -334,6 +334,8 @@ func getBeginBlockValidatorInfo(block *types.Block, stateDB dbm.DB) (abci.LastCo
voteInfo := abci.VoteInfo{
Validator: types.TM2PB.Validator(val),
SignedLastBlock: vote != nil,
// TODO: maybe make it optional, set by config, disabled by default?
FullVote: types.TM2PB.Vote(vote),
}
voteInfos[i] = voteInfo
}

View File

@ -92,9 +92,12 @@ func TestBeginBlockValidators(t *testing.T) {
tc.expectedAbsentValidators[ctr] == i {
assert.False(t, v.SignedLastBlock)
assert.Nil(t, v.FullVote)
ctr++
} else {
assert.True(t, v.SignedLastBlock)
assert.NotNil(t, v.FullVote)
assert.Equal(t, *v.FullVote, types.Vote(*tc.lastCommitPrecommits[i]))
}
}
}

View File

@ -220,3 +220,18 @@ func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error)
}
return tmVals, nil
}
func (tm2pb) Vote(vote *CommitSig) *abci.Vote {
blockID := TM2PB.BlockID(vote.BlockID)
return &abci.Vote{
Type: int32(vote.Type),
Height: vote.Height,
Round: int32(vote.Round),
BlockId: &blockID,
Timestamp: vote.Timestamp,
ValidatorAddress: vote.ValidatorAddress,
ValidatorIndex: int32(vote.ValidatorIndex),
Signature: vote.Signature,
}
}