Skip to content

Commit

Permalink
refactor(types): vote extensions support for multiple types
Browse files Browse the repository at this point in the history
  • Loading branch information
lklimek committed Dec 20, 2023
1 parent 815a4a0 commit 34fd62c
Show file tree
Hide file tree
Showing 38 changed files with 1,186 additions and 1,104 deletions.
4 changes: 2 additions & 2 deletions abci/example/kvstore/kvstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,8 @@ func (app *Application) FinalizeBlock(_ context.Context, req *abci.RequestFinali
if app.shouldCommitVerify {
vsu := app.getActiveValidatorSetUpdates()
qsd := types.QuorumSignData{
Block: makeBlockSignItem(req, btcjson.LLMQType_5_60, vsu.QuorumHash),
Extensions: makeVoteExtensionSignItems(req, btcjson.LLMQType_5_60, vsu.QuorumHash),
Block: makeBlockSignItem(req, btcjson.LLMQType_5_60, vsu.QuorumHash),
ThresholdVoteExtensions: makeVoteExtensionSignItems(req, btcjson.LLMQType_5_60, vsu.QuorumHash),
}
err := app.verifyBlockCommit(qsd, req.Commit)
if err != nil {
Expand Down
45 changes: 9 additions & 36 deletions abci/example/kvstore/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/dashpay/tenderdash/crypto"
"github.com/dashpay/tenderdash/crypto/encoding"
tmbytes "github.com/dashpay/tenderdash/libs/bytes"
types1 "github.com/dashpay/tenderdash/proto/tendermint/types"
"github.com/dashpay/tenderdash/types"
)

Expand All @@ -25,28 +24,11 @@ func (app *Application) verifyBlockCommit(qsd types.QuorumSignData, commit abci.
return err
}
return verifier.Verify(pubKey, types.QuorumSigns{
BlockSign: commit.BlockSignature,
ExtensionSigns: makeThresholdVoteExtensions(commit.ThresholdVoteExtensions),
BlockSign: commit.BlockSignature,
ThresholdVoteExtensions: types.VoteExtensionsFromProto(commit.ThresholdVoteExtensions...),
})
}

func makeThresholdVoteExtensions(pbVoteExtensions []*types1.VoteExtension) []types.ThresholdExtensionSign {
voteExtensions := types.VoteExtensionsFromProto(pbVoteExtensions)
var thresholdExtensionSigns []types.ThresholdExtensionSign
thresholdVoteExtensions, ok := voteExtensions[types1.VoteExtensionType_THRESHOLD_RECOVER]
if !ok {
return nil
}
thresholdExtensionSigns = make([]types.ThresholdExtensionSign, len(thresholdVoteExtensions))
for i, voteExtension := range thresholdVoteExtensions {
thresholdExtensionSigns[i] = types.ThresholdExtensionSign{
Extension: voteExtension.Extension,
ThresholdSignature: voteExtension.Signature,
}
}
return thresholdExtensionSigns
}

func makeBlockSignItem(
req *abci.RequestFinalizeBlock,
quorumType btcjson.LLMQType,
Expand All @@ -68,23 +50,14 @@ func makeVoteExtensionSignItems(
req *abci.RequestFinalizeBlock,
quorumType btcjson.LLMQType,
quorumHash []byte,
) map[types1.VoteExtensionType][]crypto.SignItem {
items := make(map[types1.VoteExtensionType][]crypto.SignItem)
protoExtensionsMap := types1.VoteExtensionsToMap(req.Commit.ThresholdVoteExtensions)
for t, exts := range protoExtensionsMap {
if items[t] == nil && len(exts) > 0 {
items[t] = make([]crypto.SignItem, len(exts))
}
chainID := req.Block.Header.ChainID
for i, ext := range exts {
raw := types.VoteExtensionSignBytes(chainID, req.Height, req.Round, ext)
reqID, err := types.VoteExtensionRequestID(ext, req.Height, req.Round)
if err != nil {
panic(fmt.Errorf("vote extension sign items: %w", err))
}
) []crypto.SignItem {

extensions := types.VoteExtensionsFromProto(req.Commit.ThresholdVoteExtensions...)
chainID := req.Block.Header.ChainID

items[t][i] = crypto.NewSignItem(quorumType, quorumHash, reqID, raw)
}
items, err := extensions.SignItems(chainID, quorumType, quorumHash, req.Height, req.Round)
if err != nil {
panic(fmt.Errorf("vote extension sign items: %w", err))
}
return items
}
187 changes: 103 additions & 84 deletions go.mod

Large diffs are not rendered by default.

701 changes: 293 additions & 408 deletions go.sum

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions internal/blocksync/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ func makeNextBlock(ctx context.Context,
blockID,
&types.CommitSigns{
QuorumSigns: types.QuorumSigns{
BlockSign: vote.BlockSignature,
ExtensionSigns: types.MakeThresholdExtensionSigns(vote.VoteExtensions),
BlockSign: vote.BlockSignature,
ThresholdVoteExtensions: vote.VoteExtensions.Filter(func(ext types.VoteExtensionIf) bool { return ext.IsThresholdRecoverable() }),
},
QuorumHash: state.Validators.QuorumHash,
},
Expand Down
8 changes: 4 additions & 4 deletions internal/consensus/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ func signVote(
blockID types.BlockID,
quorumType btcjson.LLMQType,
quorumHash crypto.QuorumHash) *types.Vote {
exts := make(types.VoteExtensions)
exts := make(types.VoteExtensions, 0)
if voteType == tmproto.PrecommitType && !blockID.IsNil() {
exts.Add(tmproto.VoteExtensionType_DEFAULT, tmproto.VoteExtension{
Type: tmproto.VoteExtensionType_DEFAULT,
exts.Add(tmproto.VoteExtension{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("extension")})
}
v, err := vs.signVote(ctx, voteType, chainID, blockID, quorumType, quorumHash, exts)
Expand Down Expand Up @@ -1111,7 +1111,7 @@ func signDataIsEqual(v1 *types.Vote, v2 *tmproto.Vote) bool {
if v1 == nil || v2 == nil {
return false
}
if v1.VoteExtensions.IsSameWithProto(v2.VoteExtensionsToMap()) {
if v1.VoteExtensions.IsSameWithProto(v2.VoteExtensions) {
return false
}
return v1.Type == v2.Type &&
Expand Down
2 changes: 1 addition & 1 deletion internal/consensus/gossiper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,6 @@ func (suite *GossiperSuiteTest) signVote(vote *types.Vote) {
err := privVal.SignVote(ctx, factory.DefaultTestChainID, suite.valSet.QuorumType, suite.valSet.QuorumHash, protoVote, nil)
suite.Require().NoError(err)
vote.BlockSignature = protoVote.BlockSignature
err = vote.VoteExtensions.CopySignsFromProto(protoVote.VoteExtensionsToMap())
err = vote.VoteExtensions.CopySignsFromProto(protoVote.VoteExtensions)
suite.Require().NoError(err)
}
7 changes: 4 additions & 3 deletions internal/consensus/msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,10 @@ func TestConsMsgsVectors(t *testing.T) {
Round: 0,
Type: tmproto.PrecommitType,
BlockID: bi,
VoteExtensions: types.VoteExtensions{
tmproto.VoteExtensionType_DEFAULT: []tmproto.VoteExtension{{Extension: []byte("extension")}},
},
VoteExtensions: types.VoteExtensionsFromProto(&tmproto.VoteExtension{
Type: tmproto.VoteExtensionType_DEFAULT,
Extension: []byte("extension"),
}),
}

vpb := v.ToProto()
Expand Down
4 changes: 2 additions & 2 deletions internal/consensus/replay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1123,8 +1123,8 @@ func makeBlockchainFromWAL(t *testing.T, wal WAL) ([]*types.Block, []*types.Comm
p.BlockID,
&types.CommitSigns{
QuorumSigns: types.QuorumSigns{
BlockSign: p.BlockSignature,
ExtensionSigns: types.MakeThresholdExtensionSigns(p.VoteExtensions),
BlockSign: p.BlockSignature,
ThresholdVoteExtensions: p.VoteExtensions,
},
QuorumHash: crypto.RandQuorumHash(),
},
Expand Down
59 changes: 39 additions & 20 deletions internal/consensus/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2143,7 +2143,7 @@ func TestExtendVote(t *testing.T) {

voteExtensions := []*abci.ExtendVoteExtension{
{
Type: tmproto.VoteExtensionType_DEFAULT,
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("extension"),
},
}
Expand All @@ -2159,7 +2159,7 @@ func TestExtendVote(t *testing.T) {
m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{
VoteExtensions: []*abci.ExtendVoteExtension{
{
Type: tmproto.VoteExtensionType_DEFAULT,
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("extension"),
},
},
Expand Down Expand Up @@ -2304,7 +2304,7 @@ func TestVerifyVoteExtensionNotCalledOnAbsentPrecommit(t *testing.T) {
defer cancel()
voteExtensions := []*abci.ExtendVoteExtension{
{
Type: tmproto.VoteExtensionType_DEFAULT,
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("extension"),
},
}
Expand Down Expand Up @@ -2381,7 +2381,7 @@ func TestVerifyVoteExtensionNotCalledOnAbsentPrecommit(t *testing.T) {
Round: round,
VoteExtensions: []*abci.ExtendVoteExtension{
{
Type: tmproto.VoteExtensionType_DEFAULT,
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("extension"),
},
},
Expand All @@ -2405,8 +2405,8 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {
m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{
VoteExtensions: []*abci.ExtendVoteExtension{
{
Type: tmproto.VoteExtensionType_DEFAULT,
Extension: []byte("extension"),
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER_RAW,
Extension: crypto.Checksum([]byte("extension-raw")),
},
{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Expand All @@ -2430,7 +2430,24 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {

m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{AppHash: make([]byte, crypto.DefaultAppHashSize)}, nil).Once()
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil)
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil)

// no vote extensions are present
m.On("FinalizeBlock", mock.Anything, mock.MatchedBy(func(r *abci.RequestFinalizeBlock) bool {
return len(r.Commit.ThresholdVoteExtensions) == 0
})).Return(&abci.ResponseFinalizeBlock{}, nil)

// we expect 2 threshold-recovered vote extensions
m.On("FinalizeBlock", mock.Anything, mock.MatchedBy(func(r *abci.RequestFinalizeBlock) bool {
if len(r.Commit.ThresholdVoteExtensions) != 0 {
return false
}
t.Logf("FinalizeBlock with %d vote extensions", len(r.Commit.ThresholdVoteExtensions))

vexts := r.Commit.ThresholdVoteExtensions

return bytes.Equal(vexts[0].Extension, []byte("deterministic")) &&
bytes.Equal(vexts[1].Extension, crypto.Checksum([]byte("raw")))
})).Return(&abci.ResponseFinalizeBlock{}, nil).Once()

cs1, vss := makeState(ctx, t, makeStateArgs{config: config, application: m})
stateData := cs1.GetStateData()
Expand All @@ -2453,21 +2470,22 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {

// create a precommit for each validator with the associated vote extension.
for _, vs := range vss[1:] {
voteExtensions := types.VoteExtensions{
tmproto.VoteExtensionType_DEFAULT: []tmproto.VoteExtension{
{
Type: tmproto.VoteExtensionType_DEFAULT,
Extension: []byte("extension"),
},
voteExtensions := tmproto.VoteExtensions{
{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("extension"),
},
tmproto.VoteExtensionType_THRESHOLD_RECOVER: []tmproto.VoteExtension{
{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("deterministic"),
},
{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("deterministic"),
},
{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER_RAW,
Extension: crypto.Checksum([]byte("raw")),
},
}
signAddPrecommitWithExtension(ctx, t, cs1, config.ChainID(), blockID, voteExtensions, vs)

signAddPrecommitWithExtension(ctx, t, cs1, config.ChainID(), blockID, types.VoteExtensionsFromProto(voteExtensions...), vs)
}

ensurePrevote(t, voteCh, height, round)
Expand All @@ -2491,6 +2509,7 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {
// ensure that the proposer received the list of vote extensions from the
// previous height.
require.Len(t, rpp.LocalLastCommit.ThresholdVoteExtensions, 1)
m.AssertExpectations(t)
}

// 4 vals, 3 Nil Precommits at P0
Expand Down Expand Up @@ -3328,7 +3347,7 @@ func mockProposerApplicationCalls(t *testing.T, m *abcimocks.Application, round
m.On("ExtendVote", mock.Anything, roundMatcher).
Return(&abci.ResponseExtendVote{
VoteExtensions: []*abci.ExtendVoteExtension{{
Type: tmproto.VoteExtensionType_DEFAULT,
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: []byte("extension"),
}},
}, nil).Once()
Expand Down
2 changes: 1 addition & 1 deletion internal/consensus/types/height_vote_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func makeVoteHR(
require.NoError(t, err, "Error signing vote")

vote.BlockSignature = v.BlockSignature
err = vote.VoteExtensions.CopySignsFromProto(v.VoteExtensionsToMap())
err = vote.VoteExtensions.CopySignsFromProto(v.VoteExtensions)
require.NoError(t, err)

return vote
Expand Down
16 changes: 6 additions & 10 deletions internal/consensus/vote_signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,11 @@ func TestVoteSigner_signAddVote(t *testing.T) {
PrivValidator: priVals[0],
ProTxHash: proTxHash,
}
voteExtensions := types.VoteExtensions{
tmproto.VoteExtensionType_THRESHOLD_RECOVER: []tmproto.VoteExtension{
{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: tmbytes.MustHexDecode("524F1D03D1D81E94A099042736D40BD9681B867321443FF58A4568E274DBD83B"),
},
},
}
voteExtensions := tmproto.VoteExtensions{{
Type: tmproto.VoteExtensionType_THRESHOLD_RECOVER,
Extension: tmbytes.MustHexDecode("524F1D03D1D81E94A099042736D40BD9681B867321443FF58A4568E274DBD83B"),
}}

conf := configSetup(t)
stateData := StateData{
config: conf.Consensus,
Expand Down Expand Up @@ -106,7 +103,7 @@ func TestVoteSigner_signAddVote(t *testing.T) {
{
msgType: tmproto.PrecommitType,
blockID: blockID,
voteExtensions: voteExtensions,
voteExtensions: types.VoteExtensionsFromProto(voteExtensions...),
mockFn: mockFn,
wantBlockSign: "B2C484BB07094AAB8EFAB187982F6A8E8172FBEBAE5B6EB6304E527ABAAB7D059D9A43DDDBA82A6D296AF30E67C28D250449A586E9A69C2577057E01FA290BB03C186982D4D45E6016935AD4B9A84EB0911B62A83E457E25CE44DC28516D0E0A",
},
Expand Down Expand Up @@ -145,7 +142,6 @@ func TestVoteSigner_signAddVote(t *testing.T) {
assert.NoError(t, err)

t.Logf("key: %x", key1.Serialize())
t.Logf("%+v", vote.VoteExtensions[tmproto.VoteExtensionType_THRESHOLD_RECOVER])
})
}
}
2 changes: 1 addition & 1 deletion internal/state/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ func buildLastCommitInfo(block *types.Block, initialHeight int64) abci.CommitInf
Round: block.LastCommit.Round,
QuorumHash: block.LastCommit.QuorumHash,
BlockSignature: block.LastCommit.ThresholdBlockSignature,
ThresholdVoteExtensions: types.ThresholdExtensionSignToProto(block.LastCommit.ThresholdVoteExtensions),
ThresholdVoteExtensions: block.LastCommit.ThresholdVoteExtensions.ToProto(),
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/state/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ func TestValidateBlockCommit(t *testing.T) {
require.NoError(t, err, "height %d", height)

goodVote.BlockSignature, badVote.BlockSignature = g.BlockSignature, b.BlockSignature
goodVote.VoteExtensions = types.VoteExtensionsFromProto(g.VoteExtensions)
badVote.VoteExtensions = types.VoteExtensionsFromProto(b.VoteExtensions)
goodVote.VoteExtensions = types.VoteExtensionsFromProto(g.VoteExtensions...)
badVote.VoteExtensions = types.VoteExtensionsFromProto(b.VoteExtensions...)

thresholdSigns, err := types.NewSignsRecoverer([]*types.Vote{badVote}).Recover()
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion internal/store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func makeTestCommit(state sm.State, height int64, timestamp time.Time) *types.Co
_ = privVal.SignVote(context.Background(), "chainID", state.Validators.QuorumType, state.Validators.QuorumHash, g, nil)

goodVote.BlockSignature = g.BlockSignature
goodVote.VoteExtensions = types.VoteExtensionsFromProto(g.VoteExtensions)
goodVote.VoteExtensions = types.VoteExtensionsFromProto(g.VoteExtensions...)
thresholdSigns, _ := types.NewSignsRecoverer([]*types.Vote{goodVote}).Recover()

return types.NewCommit(height, 0,
Expand Down
2 changes: 1 addition & 1 deletion internal/test/factory/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func MakeCommit(
}
vote.BlockSignature = v.BlockSignature

err = vote.VoteExtensions.CopySignsFromProto(v.VoteExtensionsToMap())
err = vote.VoteExtensions.CopySignsFromProto(v.VoteExtensions)
if err != nil {
return nil, err
}
Expand Down
3 changes: 1 addition & 2 deletions internal/test/factory/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ func MakeVote(

v.BlockSignature = vpb.BlockSignature

err = v.VoteExtensions.CopySignsFromProto(vpb.VoteExtensionsToMap())
v.VoteExtensions = types.VoteExtensionsFromProto(vpb.VoteExtensions)
err = v.VoteExtensions.CopySignsFromProto(vpb.VoteExtensions)
if err != nil {

return nil, err
Expand Down
16 changes: 8 additions & 8 deletions privval/dash_core_signer_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,15 +375,15 @@ func (sc *DashCoreSignerClient) signVoteExtensions(
}
return nil
}
for et, extensions := range protoVote.VoteExtensionsToMap() {
for i, ext := range extensions {
signItem := quorumSignData.Extensions[et][i]
resp, err := sc.quorumSignAndVerify(ctx, quorumType, quorumHash, signItem)
if err != nil {
return err
}
ext.Signature = resp.sign

for i, ext := range quorumSignData.ThresholdVoteExtensions {
signItem := ext
resp, err := sc.quorumSignAndVerify(ctx, quorumType, quorumHash, signItem)
if err != nil {
return err
}

protoVote.VoteExtensions[i].Signature = resp.sign
}
return nil
}
Expand Down
Loading

0 comments on commit 34fd62c

Please sign in to comment.