github.com/evdatsion/aphelion-dpos-bft@v0.32.1/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  	"github.com/evdatsion/aphelion-dpos-bft/crypto/tmhash"
    11  )
    12  
    13  var testProposal *Proposal
    14  
    15  func init() {
    16  	var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z")
    17  	if err != nil {
    18  		panic(err)
    19  	}
    20  	testProposal = &Proposal{
    21  		Height:    12345,
    22  		Round:     23456,
    23  		BlockID:   BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}},
    24  		POLRound:  -1,
    25  		Timestamp: stamp,
    26  	}
    27  }
    28  
    29  func TestProposalSignable(t *testing.T) {
    30  	chainID := "test_chain_id"
    31  	signBytes := testProposal.SignBytes(chainID)
    32  
    33  	expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, testProposal))
    34  	require.NoError(t, err)
    35  	require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal")
    36  }
    37  
    38  func TestProposalString(t *testing.T) {
    39  	str := testProposal.String()
    40  	expected := `Proposal{12345/23456 (010203:111:626C6F636B70, -1) 000000000000 @ 2018-02-11T07:09:22.765Z}`
    41  	if str != expected {
    42  		t.Errorf("Got unexpected string for Proposal. Expected:\n%v\nGot:\n%v", expected, str)
    43  	}
    44  }
    45  
    46  func TestProposalVerifySignature(t *testing.T) {
    47  	privVal := NewMockPV()
    48  	pubKey := privVal.GetPubKey()
    49  
    50  	prop := NewProposal(
    51  		4, 2, 2,
    52  		BlockID{[]byte{1, 2, 3}, PartSetHeader{777, []byte("proper")}})
    53  	signBytes := prop.SignBytes("test_chain_id")
    54  
    55  	// sign it
    56  	err := privVal.SignProposal("test_chain_id", prop)
    57  	require.NoError(t, err)
    58  
    59  	// verify the same proposal
    60  	valid := pubKey.VerifyBytes(signBytes, prop.Signature)
    61  	require.True(t, valid)
    62  
    63  	// serialize, deserialize and verify again....
    64  	newProp := new(Proposal)
    65  	bs, err := cdc.MarshalBinaryLengthPrefixed(prop)
    66  	require.NoError(t, err)
    67  	err = cdc.UnmarshalBinaryLengthPrefixed(bs, &newProp)
    68  	require.NoError(t, err)
    69  
    70  	// verify the transmitted proposal
    71  	newSignBytes := newProp.SignBytes("test_chain_id")
    72  	require.Equal(t, string(signBytes), string(newSignBytes))
    73  	valid = pubKey.VerifyBytes(newSignBytes, newProp.Signature)
    74  	require.True(t, valid)
    75  }
    76  
    77  func BenchmarkProposalWriteSignBytes(b *testing.B) {
    78  	for i := 0; i < b.N; i++ {
    79  		testProposal.SignBytes("test_chain_id")
    80  	}
    81  }
    82  
    83  func BenchmarkProposalSign(b *testing.B) {
    84  	privVal := NewMockPV()
    85  	for i := 0; i < b.N; i++ {
    86  		err := privVal.SignProposal("test_chain_id", testProposal)
    87  		if err != nil {
    88  			b.Error(err)
    89  		}
    90  	}
    91  }
    92  
    93  func BenchmarkProposalVerifySignature(b *testing.B) {
    94  	privVal := NewMockPV()
    95  	err := privVal.SignProposal("test_chain_id", testProposal)
    96  	require.Nil(b, err)
    97  	pubKey := privVal.GetPubKey()
    98  
    99  	for i := 0; i < b.N; i++ {
   100  		pubKey.VerifyBytes(testProposal.SignBytes("test_chain_id"), testProposal.Signature)
   101  	}
   102  }
   103  
   104  func TestProposalValidateBasic(t *testing.T) {
   105  
   106  	privVal := NewMockPV()
   107  	testCases := []struct {
   108  		testName         string
   109  		malleateProposal func(*Proposal)
   110  		expectErr        bool
   111  	}{
   112  		{"Good Proposal", func(p *Proposal) {}, false},
   113  		{"Invalid Type", func(p *Proposal) { p.Type = PrecommitType }, true},
   114  		{"Invalid Height", func(p *Proposal) { p.Height = -1 }, true},
   115  		{"Invalid Round", func(p *Proposal) { p.Round = -1 }, true},
   116  		{"Invalid POLRound", func(p *Proposal) { p.POLRound = -2 }, true},
   117  		{"Invalid BlockId", func(p *Proposal) {
   118  			p.BlockID = BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}}
   119  		}, true},
   120  		{"Invalid Signature", func(p *Proposal) {
   121  			p.Signature = make([]byte, 0)
   122  		}, true},
   123  		{"Too big Signature", func(p *Proposal) {
   124  			p.Signature = make([]byte, MaxSignatureSize+1)
   125  		}, true},
   126  	}
   127  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   128  
   129  	for _, tc := range testCases {
   130  		t.Run(tc.testName, func(t *testing.T) {
   131  			prop := NewProposal(
   132  				4, 2, 2,
   133  				blockID)
   134  			err := privVal.SignProposal("test_chain_id", prop)
   135  			require.NoError(t, err)
   136  			tc.malleateProposal(prop)
   137  			assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   138  		})
   139  	}
   140  }