Skip to content

Commit

Permalink
wip: mirror confirms vote power of previous commit proof
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-rushakoff committed Jan 15, 2025
1 parent 152a3d8 commit 83a9069
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
20 changes: 19 additions & 1 deletion tm/tmengine/internal/tmmirror/mirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,25 @@ RESTART:
return tmconsensus.HandleProposedHeaderBadPrevCommitProofSignature
}

// TODO: confirm that we have majority voting power on the previous block hash.
if ph.Header.Height > m.initialHeight {
// Only confirm the vote power if we are beyond the genesis height,
// as the initial height does not have previous commit proofs.
var prevBlockVotePower, availableVotePower uint64
prevVals := checkResp.PrevValidatorSet.Validators
sigBits := signBitsByHash[string(ph.Header.PrevBlockHash)]
for i, v := range prevVals {
// If we already had the total vote power,
// we could break out of this loop as soon as we cross majority power.
availableVotePower += v.Power
if sigBits.Test(uint(i)) {
prevBlockVotePower += v.Power
}
}

if prevBlockVotePower < tmconsensus.ByzantineMajority(availableVotePower) {
return tmconsensus.HandleProposedHeaderBadPrevCommitVoteCount
}
}

// The hash matches and the proposed header was signed by a validator we know,
// so we can accept the message.
Expand Down
54 changes: 54 additions & 0 deletions tm/tmengine/internal/tmmirror/mirror_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,56 @@ func TestMirror_HandleProposedHeader(t *testing.T) {
})
})

t.Run("rejected when there are insufficient votes in previous commit proof", func(t *testing.T) {
t.Parallel()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

mfx := tmmirrortest.NewFixture(ctx, t, 4)

m := mfx.NewMirror()
defer m.Wait()
defer cancel()

// Proposed header and 3/4 precommits at height 1.
ph1 := mfx.Fx.NextProposedHeader([]byte("app_data_1"), 0)
mfx.Fx.SignProposal(ctx, &ph1, 0)
require.Equal(t, tmconsensus.HandleProposedHeaderAccepted, m.HandleProposedHeader(ctx, ph1))
keyHash, _ := mfx.Fx.ValidatorHashes()
voteMap := map[string][]int{
string(ph1.Header.Hash): {0, 1, 2},
}
precommitProof := tmconsensus.PrecommitSparseProof{
Height: 1,
Round: 0,
PubKeyHash: keyHash,
Proofs: mfx.Fx.SparsePrecommitProofMap(ctx, 1, 0, voteMap),
}
require.Equal(t, tmconsensus.HandleVoteProofsAccepted, m.HandlePrecommitProofs(ctx, precommitProof))

// Now the mirror is ready for the proposed header at height 2.
// So, if we set the previous commit proof to include a double signature for validator 3,
// the mirror should reject the proposed header on account of the double signature.

mfx.Fx.CommitBlock(
ph1.Header, []byte("app_state_height_1"), 0,
mfx.Fx.PrecommitProofMap(ctx, 1, 0, voteMap),
)
ph2 := mfx.Fx.NextProposedHeader([]byte("app_data_2"), 1)

// Clip off the first precommit for ph1,
// which will cause there to only be 50% votes present.
t.Logf("%#v", ph2.Header.PrevCommitProof.Proofs)
ph2.Header.PrevCommitProof.Proofs[string(ph1.Header.Hash)] =
ph2.Header.PrevCommitProof.Proofs[string(ph1.Header.Hash)][1:]

mfx.Fx.RecalculateHash(&ph2.Header)
mfx.Fx.SignProposal(ctx, &ph2, 0)

require.Equal(t, tmconsensus.HandleProposedHeaderBadPrevCommitVoteCount, m.HandleProposedHeader(ctx, ph2))
})

t.Run("rejected when there is a double signature", func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -578,6 +628,10 @@ func TestMirror_HandleProposedHeader(t *testing.T) {
// So, if we set the previous commit proof to include a double signature for validator 3,
// the mirror should reject the proposed header on account of the double signature.

mfx.Fx.CommitBlock(
ph1.Header, []byte("app_state_height_1"), 0,
mfx.Fx.PrecommitProofMap(ctx, 1, 0, voteMap),
)
ph2 := mfx.Fx.NextProposedHeader([]byte("app_data_2"), 1)
voteMap[""] = []int{3}
precommitProof = tmconsensus.PrecommitSparseProof{
Expand Down

0 comments on commit 83a9069

Please sign in to comment.