github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/types/proposal_test.go (about) 1 package types 2 3 import ( 4 "math" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/tendermint/tendermint/crypto/tmhash" 12 ) 13 14 var testProposal *Proposal 15 16 func init() { 17 var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z") 18 if err != nil { 19 panic(err) 20 } 21 testProposal = &Proposal{ 22 Height: 12345, 23 Round: 23456, 24 BlockID: BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}}, 25 POLRound: -1, 26 Timestamp: stamp, 27 } 28 } 29 30 func TestProposalSignable(t *testing.T) { 31 chainID := "test_chain_id" 32 signBytes := testProposal.SignBytes(chainID) 33 34 expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, testProposal)) 35 require.NoError(t, err) 36 require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal") 37 } 38 39 func TestProposalString(t *testing.T) { 40 str := testProposal.String() 41 expected := `Proposal{12345/23456 (010203:111:626C6F636B70, -1) 000000000000 @ 2018-02-11T07:09:22.765Z}` 42 if str != expected { 43 t.Errorf("got unexpected string for Proposal. Expected:\n%v\nGot:\n%v", expected, str) 44 } 45 } 46 47 func TestProposalVerifySignature(t *testing.T) { 48 privVal := NewMockPV() 49 pubKey, err := privVal.GetPubKey() 50 require.NoError(t, err) 51 52 prop := NewProposal( 53 4, 2, 2, 54 BlockID{[]byte{1, 2, 3}, PartSetHeader{777, []byte("proper")}}) 55 signBytes := prop.SignBytes("test_chain_id") 56 57 // sign it 58 err = privVal.SignProposal("test_chain_id", prop) 59 require.NoError(t, err) 60 61 // verify the same proposal 62 valid := pubKey.VerifyBytes(signBytes, prop.Signature) 63 require.True(t, valid) 64 65 // serialize, deserialize and verify again.... 66 newProp := new(Proposal) 67 bs, err := cdc.MarshalBinaryLengthPrefixed(prop) 68 require.NoError(t, err) 69 err = cdc.UnmarshalBinaryLengthPrefixed(bs, &newProp) 70 require.NoError(t, err) 71 72 // verify the transmitted proposal 73 newSignBytes := newProp.SignBytes("test_chain_id") 74 require.Equal(t, string(signBytes), string(newSignBytes)) 75 valid = pubKey.VerifyBytes(newSignBytes, newProp.Signature) 76 require.True(t, valid) 77 } 78 79 func BenchmarkProposalWriteSignBytes(b *testing.B) { 80 for i := 0; i < b.N; i++ { 81 testProposal.SignBytes("test_chain_id") 82 } 83 } 84 85 func BenchmarkProposalSign(b *testing.B) { 86 privVal := NewMockPV() 87 for i := 0; i < b.N; i++ { 88 err := privVal.SignProposal("test_chain_id", testProposal) 89 if err != nil { 90 b.Error(err) 91 } 92 } 93 } 94 95 func BenchmarkProposalVerifySignature(b *testing.B) { 96 privVal := NewMockPV() 97 err := privVal.SignProposal("test_chain_id", testProposal) 98 require.NoError(b, err) 99 pubKey, err := privVal.GetPubKey() 100 require.NoError(b, err) 101 102 for i := 0; i < b.N; i++ { 103 pubKey.VerifyBytes(testProposal.SignBytes("test_chain_id"), testProposal.Signature) 104 } 105 } 106 107 func TestProposalValidateBasic(t *testing.T) { 108 109 privVal := NewMockPV() 110 testCases := []struct { 111 testName string 112 malleateProposal func(*Proposal) 113 expectErr bool 114 }{ 115 {"Good Proposal", func(p *Proposal) {}, false}, 116 {"Invalid Type", func(p *Proposal) { p.Type = PrecommitType }, true}, 117 {"Invalid Height", func(p *Proposal) { p.Height = -1 }, true}, 118 {"Invalid Round", func(p *Proposal) { p.Round = -1 }, true}, 119 {"Invalid POLRound", func(p *Proposal) { p.POLRound = -2 }, true}, 120 {"Invalid BlockId", func(p *Proposal) { 121 p.BlockID = BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}} 122 }, true}, 123 {"Invalid Signature", func(p *Proposal) { 124 p.Signature = make([]byte, 0) 125 }, true}, 126 {"Too big Signature", func(p *Proposal) { 127 p.Signature = make([]byte, MaxSignatureSize+1) 128 }, true}, 129 } 130 blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash"))) 131 132 for _, tc := range testCases { 133 tc := tc 134 t.Run(tc.testName, func(t *testing.T) { 135 prop := NewProposal( 136 4, 2, 2, 137 blockID) 138 err := privVal.SignProposal("test_chain_id", prop) 139 require.NoError(t, err) 140 tc.malleateProposal(prop) 141 assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result") 142 }) 143 } 144 } 145 146 func TestProposalProtoBuf(t *testing.T) { 147 proposal := NewProposal(1, 2, 3, makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))) 148 proposal.Signature = []byte("sig") 149 proposal2 := NewProposal(1, 2, 3, BlockID{}) 150 151 testCases := []struct { 152 msg string 153 p1 *Proposal 154 expPass bool 155 }{ 156 {"success", proposal, true}, 157 {"success", proposal2, false}, // blcokID cannot be empty 158 {"empty proposal failure validatebasic", &Proposal{}, false}, 159 {"nil proposal", nil, false}, 160 } 161 for _, tc := range testCases { 162 protoProposal := tc.p1.ToProto() 163 164 p, err := ProposalFromProto(protoProposal) 165 if tc.expPass { 166 require.NoError(t, err) 167 require.Equal(t, tc.p1, p, tc.msg) 168 } else { 169 require.Error(t, err) 170 } 171 } 172 }