You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

848 lines
24 KiB

max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmhash.Sum([]byte("proposer_address")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmhash.Sum([]byte("proposer_address")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
  1. package types
  2. import (
  3. // it is ok to use math/rand here: we do not need a cryptographically secure random
  4. // number generator here and we can run the tests a bit faster
  5. "crypto/rand"
  6. "encoding/hex"
  7. "math"
  8. "os"
  9. "reflect"
  10. "testing"
  11. "time"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. "github.com/tendermint/tendermint/crypto"
  15. "github.com/tendermint/tendermint/crypto/merkle"
  16. "github.com/tendermint/tendermint/crypto/tmhash"
  17. "github.com/tendermint/tendermint/libs/bits"
  18. "github.com/tendermint/tendermint/libs/bytes"
  19. tmrand "github.com/tendermint/tendermint/libs/rand"
  20. tmproto "github.com/tendermint/tendermint/proto/types"
  21. "github.com/tendermint/tendermint/proto/version"
  22. tmtime "github.com/tendermint/tendermint/types/time"
  23. )
  24. func TestMain(m *testing.M) {
  25. RegisterMockEvidences(cdc)
  26. code := m.Run()
  27. os.Exit(code)
  28. }
  29. func TestBlockAddEvidence(t *testing.T) {
  30. txs := []Tx{Tx("foo"), Tx("bar")}
  31. lastID := makeBlockIDRandom()
  32. h := int64(3)
  33. voteSet, valSet, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  34. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now())
  35. require.NoError(t, err)
  36. ev := NewMockEvidence(h, time.Now(), valSet.Validators[0].Address)
  37. evList := []Evidence{ev}
  38. block := MakeBlock(h, txs, commit, evList)
  39. require.NotNil(t, block)
  40. require.Equal(t, 1, len(block.Evidence.Evidence))
  41. require.NotNil(t, block.EvidenceHash)
  42. }
  43. func TestBlockValidateBasic(t *testing.T) {
  44. require.Error(t, (*Block)(nil).ValidateBasic())
  45. txs := []Tx{Tx("foo"), Tx("bar")}
  46. lastID := makeBlockIDRandom()
  47. h := int64(3)
  48. voteSet, valSet, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  49. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now())
  50. require.NoError(t, err)
  51. ev := NewMockEvidence(h, time.Now(), valSet.Validators[0].Address)
  52. evList := []Evidence{ev}
  53. testCases := []struct {
  54. testName string
  55. malleateBlock func(*Block)
  56. expErr bool
  57. }{
  58. {"Make Block", func(blk *Block) {}, false},
  59. {"Make Block w/ proposer Addr", func(blk *Block) { blk.ProposerAddress = valSet.GetProposer().Address }, false},
  60. {"Negative Height", func(blk *Block) { blk.Height = -1 }, true},
  61. {"Remove 1/2 the commits", func(blk *Block) {
  62. blk.LastCommit.Signatures = commit.Signatures[:commit.Size()/2]
  63. blk.LastCommit.hash = nil // clear hash or change wont be noticed
  64. }, true},
  65. {"Remove LastCommitHash", func(blk *Block) { blk.LastCommitHash = []byte("something else") }, true},
  66. {"Tampered Data", func(blk *Block) {
  67. blk.Data.Txs[0] = Tx("something else")
  68. blk.Data.hash = nil // clear hash or change wont be noticed
  69. }, true},
  70. {"Tampered DataHash", func(blk *Block) {
  71. blk.DataHash = tmrand.Bytes(len(blk.DataHash))
  72. }, true},
  73. {"Tampered EvidenceHash", func(blk *Block) {
  74. blk.EvidenceHash = []byte("something else")
  75. }, true},
  76. }
  77. for i, tc := range testCases {
  78. tc := tc
  79. i := i
  80. t.Run(tc.testName, func(t *testing.T) {
  81. block := MakeBlock(h, txs, commit, evList)
  82. block.ProposerAddress = valSet.GetProposer().Address
  83. tc.malleateBlock(block)
  84. err = block.ValidateBasic()
  85. assert.Equal(t, tc.expErr, err != nil, "#%d: %v", i, err)
  86. })
  87. }
  88. }
  89. func TestBlockHash(t *testing.T) {
  90. assert.Nil(t, (*Block)(nil).Hash())
  91. assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Hash())
  92. }
  93. func TestBlockMakePartSet(t *testing.T) {
  94. assert.Nil(t, (*Block)(nil).MakePartSet(2))
  95. partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024)
  96. assert.NotNil(t, partSet)
  97. assert.EqualValues(t, 1, partSet.Total())
  98. }
  99. func TestBlockMakePartSetWithEvidence(t *testing.T) {
  100. assert.Nil(t, (*Block)(nil).MakePartSet(2))
  101. lastID := makeBlockIDRandom()
  102. h := int64(3)
  103. voteSet, valSet, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  104. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now())
  105. require.NoError(t, err)
  106. ev := NewMockEvidence(h, time.Now(), valSet.Validators[0].Address)
  107. evList := []Evidence{ev}
  108. partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(512)
  109. assert.NotNil(t, partSet)
  110. assert.EqualValues(t, 3, partSet.Total())
  111. }
  112. func TestBlockHashesTo(t *testing.T) {
  113. assert.False(t, (*Block)(nil).HashesTo(nil))
  114. lastID := makeBlockIDRandom()
  115. h := int64(3)
  116. voteSet, valSet, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  117. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now())
  118. require.NoError(t, err)
  119. ev := NewMockEvidence(h, time.Now(), valSet.Validators[0].Address)
  120. evList := []Evidence{ev}
  121. block := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList)
  122. block.ValidatorsHash = valSet.Hash()
  123. assert.False(t, block.HashesTo([]byte{}))
  124. assert.False(t, block.HashesTo([]byte("something else")))
  125. assert.True(t, block.HashesTo(block.Hash()))
  126. }
  127. func TestBlockSize(t *testing.T) {
  128. size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Size()
  129. if size <= 0 {
  130. t.Fatal("Size of the block is zero or negative")
  131. }
  132. }
  133. func TestBlockString(t *testing.T) {
  134. assert.Equal(t, "nil-Block", (*Block)(nil).String())
  135. assert.Equal(t, "nil-Block", (*Block)(nil).StringIndented(""))
  136. assert.Equal(t, "nil-Block", (*Block)(nil).StringShort())
  137. block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil)
  138. assert.NotEqual(t, "nil-Block", block.String())
  139. assert.NotEqual(t, "nil-Block", block.StringIndented(""))
  140. assert.NotEqual(t, "nil-Block", block.StringShort())
  141. }
  142. func makeBlockIDRandom() BlockID {
  143. var (
  144. blockHash = make([]byte, tmhash.Size)
  145. partSetHash = make([]byte, tmhash.Size)
  146. )
  147. rand.Read(blockHash)
  148. rand.Read(partSetHash)
  149. return BlockID{blockHash, PartSetHeader{123, partSetHash}}
  150. }
  151. func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) BlockID {
  152. var (
  153. h = make([]byte, tmhash.Size)
  154. psH = make([]byte, tmhash.Size)
  155. )
  156. copy(h, hash)
  157. copy(psH, partSetHash)
  158. return BlockID{
  159. Hash: h,
  160. PartsHeader: PartSetHeader{
  161. Total: partSetSize,
  162. Hash: psH,
  163. },
  164. }
  165. }
  166. var nilBytes []byte
  167. func TestNilHeaderHashDoesntCrash(t *testing.T) {
  168. assert.Equal(t, []byte((*Header)(nil).Hash()), nilBytes)
  169. assert.Equal(t, []byte((new(Header)).Hash()), nilBytes)
  170. }
  171. func TestNilDataHashDoesntCrash(t *testing.T) {
  172. assert.Equal(t, []byte((*Data)(nil).Hash()), nilBytes)
  173. assert.Equal(t, []byte(new(Data).Hash()), nilBytes)
  174. }
  175. func TestCommit(t *testing.T) {
  176. lastID := makeBlockIDRandom()
  177. h := int64(3)
  178. voteSet, _, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  179. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now())
  180. require.NoError(t, err)
  181. assert.Equal(t, h-1, commit.Height)
  182. assert.EqualValues(t, 1, commit.Round)
  183. assert.Equal(t, tmproto.PrecommitType, tmproto.SignedMsgType(commit.Type()))
  184. if commit.Size() <= 0 {
  185. t.Fatalf("commit %v has a zero or negative size: %d", commit, commit.Size())
  186. }
  187. require.NotNil(t, commit.BitArray())
  188. assert.Equal(t, bits.NewBitArray(10).Size(), commit.BitArray().Size())
  189. assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0))
  190. assert.True(t, commit.IsCommit())
  191. }
  192. func TestCommitValidateBasic(t *testing.T) {
  193. testCases := []struct {
  194. testName string
  195. malleateCommit func(*Commit)
  196. expectErr bool
  197. }{
  198. {"Random Commit", func(com *Commit) {}, false},
  199. {"Incorrect signature", func(com *Commit) { com.Signatures[0].Signature = []byte{0} }, false},
  200. {"Incorrect height", func(com *Commit) { com.Height = int64(-100) }, true},
  201. {"Incorrect round", func(com *Commit) { com.Round = -100 }, true},
  202. }
  203. for _, tc := range testCases {
  204. tc := tc
  205. t.Run(tc.testName, func(t *testing.T) {
  206. com := randCommit(time.Now())
  207. tc.malleateCommit(com)
  208. assert.Equal(t, tc.expectErr, com.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  209. })
  210. }
  211. }
  212. func TestHeaderHash(t *testing.T) {
  213. testCases := []struct {
  214. desc string
  215. header *Header
  216. expectHash bytes.HexBytes
  217. }{
  218. {"Generates expected hash", &Header{
  219. Version: version.Consensus{Block: 1, App: 2},
  220. ChainID: "chainId",
  221. Height: 3,
  222. Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
  223. LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)),
  224. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  225. DataHash: tmhash.Sum([]byte("data_hash")),
  226. ValidatorsHash: tmhash.Sum([]byte("validators_hash")),
  227. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  228. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  229. AppHash: tmhash.Sum([]byte("app_hash")),
  230. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  231. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  232. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  233. }, hexBytesFromString("ABDC78921B18A47EE6BEF5E31637BADB0F3E587E3C0F4DB2D1E93E9FF0533862")},
  234. {"nil header yields nil", nil, nil},
  235. {"nil ValidatorsHash yields nil", &Header{
  236. Version: version.Consensus{Block: 1, App: 2},
  237. ChainID: "chainId",
  238. Height: 3,
  239. Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
  240. LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)),
  241. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  242. DataHash: tmhash.Sum([]byte("data_hash")),
  243. ValidatorsHash: nil,
  244. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  245. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  246. AppHash: tmhash.Sum([]byte("app_hash")),
  247. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  248. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  249. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  250. }, nil},
  251. }
  252. for _, tc := range testCases {
  253. tc := tc
  254. t.Run(tc.desc, func(t *testing.T) {
  255. assert.Equal(t, tc.expectHash, tc.header.Hash())
  256. // We also make sure that all fields are hashed in struct order, and that all
  257. // fields in the test struct are non-zero.
  258. if tc.header != nil && tc.expectHash != nil {
  259. byteSlices := [][]byte{}
  260. s := reflect.ValueOf(*tc.header)
  261. for i := 0; i < s.NumField(); i++ {
  262. f := s.Field(i)
  263. assert.False(t, f.IsZero(), "Found zero-valued field %v",
  264. s.Type().Field(i).Name)
  265. byteSlices = append(byteSlices, cdcEncode(f.Interface()))
  266. }
  267. assert.Equal(t,
  268. bytes.HexBytes(merkle.SimpleHashFromByteSlices(byteSlices)), tc.header.Hash())
  269. }
  270. })
  271. }
  272. }
  273. func TestMaxHeaderBytes(t *testing.T) {
  274. // Construct a UTF-8 string of MaxChainIDLen length using the supplementary
  275. // characters.
  276. // Each supplementary character takes 4 bytes.
  277. // http://www.i18nguy.com/unicode/supplementary-test.html
  278. maxChainID := ""
  279. for i := 0; i < MaxChainIDLen; i++ {
  280. maxChainID += "𠜎"
  281. }
  282. // time is varint encoded so need to pick the max.
  283. // year int, month Month, day, hour, min, sec, nsec int, loc *Location
  284. timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
  285. h := Header{
  286. Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
  287. ChainID: maxChainID,
  288. Height: math.MaxInt64,
  289. Time: timestamp,
  290. LastBlockID: makeBlockID(make([]byte, tmhash.Size), math.MaxInt32, make([]byte, tmhash.Size)),
  291. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  292. DataHash: tmhash.Sum([]byte("data_hash")),
  293. ValidatorsHash: tmhash.Sum([]byte("validators_hash")),
  294. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  295. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  296. AppHash: tmhash.Sum([]byte("app_hash")),
  297. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  298. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  299. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  300. }
  301. bz, err := cdc.MarshalBinaryLengthPrefixed(h)
  302. require.NoError(t, err)
  303. assert.EqualValues(t, MaxHeaderBytes, int64(len(bz)))
  304. }
  305. func randCommit(now time.Time) *Commit {
  306. lastID := makeBlockIDRandom()
  307. h := int64(3)
  308. voteSet, _, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  309. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, now)
  310. if err != nil {
  311. panic(err)
  312. }
  313. return commit
  314. }
  315. func hexBytesFromString(s string) bytes.HexBytes {
  316. b, err := hex.DecodeString(s)
  317. if err != nil {
  318. panic(err)
  319. }
  320. return bytes.HexBytes(b)
  321. }
  322. func TestBlockMaxDataBytes(t *testing.T) {
  323. testCases := []struct {
  324. maxBytes int64
  325. valsCount int
  326. evidenceCount int
  327. panics bool
  328. result int64
  329. }{
  330. 0: {-10, 1, 0, true, 0},
  331. 1: {10, 1, 0, true, 0},
  332. 2: {849, 1, 0, true, 0},
  333. 3: {850, 1, 0, false, 0},
  334. 4: {851, 1, 0, false, 1},
  335. }
  336. for i, tc := range testCases {
  337. tc := tc
  338. if tc.panics {
  339. assert.Panics(t, func() {
  340. MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount)
  341. }, "#%v", i)
  342. } else {
  343. assert.Equal(t,
  344. tc.result,
  345. MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount),
  346. "#%v", i)
  347. }
  348. }
  349. }
  350. func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) {
  351. testCases := []struct {
  352. maxBytes int64
  353. maxEvidence uint32
  354. valsCount int
  355. panics bool
  356. result int64
  357. }{
  358. 0: {-10, 0, 1, true, 0},
  359. 1: {10, 0, 1, true, 0},
  360. 2: {849, 0, 1, true, 0},
  361. 3: {850, 0, 1, false, 0},
  362. 4: {1294, 1, 1, false, 0},
  363. 5: {1295, 1, 1, false, 1},
  364. }
  365. for i, tc := range testCases {
  366. tc := tc
  367. if tc.panics {
  368. assert.Panics(t, func() {
  369. MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount, tc.maxEvidence)
  370. }, "#%v", i)
  371. } else {
  372. assert.Equal(t,
  373. tc.result,
  374. MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount, tc.maxEvidence),
  375. "#%v", i)
  376. }
  377. }
  378. }
  379. func TestCommitToVoteSet(t *testing.T) {
  380. lastID := makeBlockIDRandom()
  381. h := int64(3)
  382. voteSet, valSet, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  383. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now())
  384. assert.NoError(t, err)
  385. chainID := voteSet.ChainID()
  386. voteSet2 := CommitToVoteSet(chainID, commit, valSet)
  387. for i := int32(0); int(i) < len(vals); i++ {
  388. vote1 := voteSet.GetByIndex(i)
  389. vote2 := voteSet2.GetByIndex(i)
  390. vote3 := commit.GetVote(i)
  391. vote1bz := cdc.MustMarshalBinaryBare(vote1)
  392. vote2bz := cdc.MustMarshalBinaryBare(vote2)
  393. vote3bz := cdc.MustMarshalBinaryBare(vote3)
  394. assert.Equal(t, vote1bz, vote2bz)
  395. assert.Equal(t, vote1bz, vote3bz)
  396. }
  397. }
  398. func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) {
  399. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  400. const (
  401. height = int64(3)
  402. round = 0
  403. )
  404. type commitVoteTest struct {
  405. blockIDs []BlockID
  406. numVotes []int // must sum to numValidators
  407. numValidators int
  408. valid bool
  409. }
  410. testCases := []commitVoteTest{
  411. {[]BlockID{blockID, {}}, []int{67, 33}, 100, true},
  412. }
  413. for _, tc := range testCases {
  414. voteSet, valSet, vals := randVoteSet(height-1, round, tmproto.PrecommitType, tc.numValidators, 1)
  415. vi := int32(0)
  416. for n := range tc.blockIDs {
  417. for i := 0; i < tc.numVotes[n]; i++ {
  418. pubKey, err := vals[vi].GetPubKey()
  419. require.NoError(t, err)
  420. vote := &Vote{
  421. ValidatorAddress: pubKey.Address(),
  422. ValidatorIndex: vi,
  423. Height: height - 1,
  424. Round: round,
  425. Type: tmproto.PrecommitType,
  426. BlockID: tc.blockIDs[n],
  427. Timestamp: tmtime.Now(),
  428. }
  429. added, err := signAddVote(vals[vi], vote, voteSet)
  430. assert.NoError(t, err)
  431. assert.True(t, added)
  432. vi++
  433. }
  434. }
  435. if tc.valid {
  436. commit := voteSet.MakeCommit() // panics without > 2/3 valid votes
  437. assert.NotNil(t, commit)
  438. err := valSet.VerifyCommit(voteSet.ChainID(), blockID, height-1, commit)
  439. assert.Nil(t, err)
  440. } else {
  441. assert.Panics(t, func() { voteSet.MakeCommit() })
  442. }
  443. }
  444. }
  445. func TestSignedHeaderValidateBasic(t *testing.T) {
  446. commit := randCommit(time.Now())
  447. chainID := "𠜎"
  448. timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
  449. h := Header{
  450. Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
  451. ChainID: chainID,
  452. Height: commit.Height,
  453. Time: timestamp,
  454. LastBlockID: commit.BlockID,
  455. LastCommitHash: commit.Hash(),
  456. DataHash: commit.Hash(),
  457. ValidatorsHash: commit.Hash(),
  458. NextValidatorsHash: commit.Hash(),
  459. ConsensusHash: commit.Hash(),
  460. AppHash: commit.Hash(),
  461. LastResultsHash: commit.Hash(),
  462. EvidenceHash: commit.Hash(),
  463. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  464. }
  465. validSignedHeader := SignedHeader{Header: &h, Commit: commit}
  466. validSignedHeader.Commit.BlockID.Hash = validSignedHeader.Hash()
  467. invalidSignedHeader := SignedHeader{}
  468. testCases := []struct {
  469. testName string
  470. shHeader *Header
  471. shCommit *Commit
  472. expectErr bool
  473. }{
  474. {"Valid Signed Header", validSignedHeader.Header, validSignedHeader.Commit, false},
  475. {"Invalid Signed Header", invalidSignedHeader.Header, validSignedHeader.Commit, true},
  476. {"Invalid Signed Header", validSignedHeader.Header, invalidSignedHeader.Commit, true},
  477. }
  478. for _, tc := range testCases {
  479. tc := tc
  480. t.Run(tc.testName, func(t *testing.T) {
  481. sh := SignedHeader{
  482. Header: tc.shHeader,
  483. Commit: tc.shCommit,
  484. }
  485. assert.Equal(
  486. t,
  487. tc.expectErr,
  488. sh.ValidateBasic(validSignedHeader.Header.ChainID) != nil,
  489. "Validate Basic had an unexpected result",
  490. )
  491. })
  492. }
  493. }
  494. func TestBlockIDValidateBasic(t *testing.T) {
  495. validBlockID := BlockID{
  496. Hash: bytes.HexBytes{},
  497. PartsHeader: PartSetHeader{
  498. Total: 1,
  499. Hash: bytes.HexBytes{},
  500. },
  501. }
  502. invalidBlockID := BlockID{
  503. Hash: []byte{0},
  504. PartsHeader: PartSetHeader{
  505. Total: 1,
  506. Hash: []byte{0},
  507. },
  508. }
  509. testCases := []struct {
  510. testName string
  511. blockIDHash bytes.HexBytes
  512. blockIDPartsHeader PartSetHeader
  513. expectErr bool
  514. }{
  515. {"Valid BlockID", validBlockID.Hash, validBlockID.PartsHeader, false},
  516. {"Invalid BlockID", invalidBlockID.Hash, validBlockID.PartsHeader, true},
  517. {"Invalid BlockID", validBlockID.Hash, invalidBlockID.PartsHeader, true},
  518. }
  519. for _, tc := range testCases {
  520. tc := tc
  521. t.Run(tc.testName, func(t *testing.T) {
  522. blockID := BlockID{
  523. Hash: tc.blockIDHash,
  524. PartsHeader: tc.blockIDPartsHeader,
  525. }
  526. assert.Equal(t, tc.expectErr, blockID.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  527. })
  528. }
  529. }
  530. func makeRandHeader() Header {
  531. chainID := "test"
  532. t := time.Now()
  533. height := tmrand.Int63()
  534. randBytes := tmrand.Bytes(tmhash.Size)
  535. randAddress := tmrand.Bytes(crypto.AddressSize)
  536. h := Header{
  537. Version: version.Consensus{Block: 1, App: 1},
  538. ChainID: chainID,
  539. Height: height,
  540. Time: t,
  541. LastBlockID: BlockID{},
  542. LastCommitHash: randBytes,
  543. DataHash: randBytes,
  544. ValidatorsHash: randBytes,
  545. NextValidatorsHash: randBytes,
  546. ConsensusHash: randBytes,
  547. AppHash: randBytes,
  548. LastResultsHash: randBytes,
  549. EvidenceHash: randBytes,
  550. ProposerAddress: randAddress,
  551. }
  552. return h
  553. }
  554. func TestBlockProtoBuf(t *testing.T) {
  555. h := tmrand.Int63()
  556. c1 := randCommit(time.Now())
  557. b1 := MakeBlock(h, []Tx{Tx([]byte{1})}, &Commit{Signatures: []CommitSig{}}, []Evidence{})
  558. b1.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  559. b2 := MakeBlock(h, []Tx{Tx([]byte{1})}, c1, []Evidence{})
  560. b2.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  561. evi := NewMockEvidence(b2.Height, time.Now(), tmrand.Bytes(32))
  562. b2.Evidence = EvidenceData{Evidence: EvidenceList{evi}}
  563. b2.EvidenceHash = b2.Evidence.Hash()
  564. b3 := MakeBlock(h, []Tx{}, c1, []Evidence{})
  565. b3.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  566. testCases := []struct {
  567. msg string
  568. b1 *Block
  569. expPass bool
  570. expPass2 bool
  571. }{
  572. {"nil block", nil, false, false},
  573. {"b1", b1, true, true},
  574. {"b2", b2, true, true},
  575. {"b3", b3, true, true},
  576. }
  577. for _, tc := range testCases {
  578. pb, err := tc.b1.ToProto()
  579. if tc.expPass {
  580. require.NoError(t, err, tc.msg)
  581. } else {
  582. require.Error(t, err, tc.msg)
  583. }
  584. block, err := BlockFromProto(pb)
  585. if tc.expPass2 {
  586. require.NoError(t, err, tc.msg)
  587. require.EqualValues(t, tc.b1.Header, block.Header, tc.msg)
  588. require.EqualValues(t, tc.b1.Data, block.Data, tc.msg)
  589. require.EqualValues(t, tc.b1.Evidence, block.Evidence, tc.msg)
  590. require.EqualValues(t, *tc.b1.LastCommit, *block.LastCommit, tc.msg)
  591. } else {
  592. require.Error(t, err, tc.msg)
  593. }
  594. }
  595. }
  596. func TestDataProtoBuf(t *testing.T) {
  597. data := &Data{Txs: Txs{Tx([]byte{1}), Tx([]byte{2}), Tx([]byte{3})}}
  598. _ = data.Hash()
  599. data2 := &Data{Txs: Txs{}}
  600. _ = data2.Hash()
  601. testCases := []struct {
  602. msg string
  603. data1 *Data
  604. expPass bool
  605. }{
  606. {"success", data, true},
  607. {"success data2", data2, true},
  608. }
  609. for _, tc := range testCases {
  610. protoData := tc.data1.ToProto()
  611. d, err := DataFromProto(&protoData)
  612. if tc.expPass {
  613. require.NoError(t, err, tc.msg)
  614. require.EqualValues(t, tc.data1, &d, tc.msg)
  615. } else {
  616. require.Error(t, err, tc.msg)
  617. }
  618. }
  619. }
  620. func TestHeaderProto(t *testing.T) {
  621. h1 := makeRandHeader()
  622. tc := []struct {
  623. msg string
  624. h1 *Header
  625. expPass bool
  626. }{
  627. {"success", &h1, true},
  628. {"failure empty Header", &Header{}, false},
  629. }
  630. for _, tt := range tc {
  631. tt := tt
  632. t.Run(tt.msg, func(t *testing.T) {
  633. pb := tt.h1.ToProto()
  634. h, err := HeaderFromProto(pb)
  635. if tt.expPass {
  636. require.NoError(t, err, tt.msg)
  637. require.Equal(t, tt.h1, &h, tt.msg)
  638. } else {
  639. require.Error(t, err, tt.msg)
  640. }
  641. })
  642. }
  643. }
  644. func TestBlockIDProtoBuf(t *testing.T) {
  645. blockID := makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  646. testCases := []struct {
  647. msg string
  648. bid1 *BlockID
  649. expPass bool
  650. }{
  651. {"success", &blockID, true},
  652. {"success empty", &BlockID{}, true},
  653. {"failure BlockID nil", nil, false},
  654. }
  655. for _, tc := range testCases {
  656. protoBlockID := tc.bid1.ToProto()
  657. bi, err := BlockIDFromProto(&protoBlockID)
  658. if tc.expPass {
  659. require.NoError(t, err)
  660. require.Equal(t, tc.bid1, bi, tc.msg)
  661. } else {
  662. require.NotEqual(t, tc.bid1, bi, tc.msg)
  663. }
  664. }
  665. }
  666. func TestSignedHeaderProtoBuf(t *testing.T) {
  667. commit := randCommit(time.Now())
  668. h := makeRandHeader()
  669. sh := SignedHeader{Header: &h, Commit: commit}
  670. testCases := []struct {
  671. msg string
  672. sh1 *SignedHeader
  673. expPass bool
  674. }{
  675. {"empty SignedHeader 2", &SignedHeader{}, true},
  676. {"success", &sh, true},
  677. {"failure nil", nil, false},
  678. }
  679. for _, tc := range testCases {
  680. protoSignedHeader := tc.sh1.ToProto()
  681. sh, err := SignedHeaderFromProto(protoSignedHeader)
  682. if tc.expPass {
  683. require.NoError(t, err, tc.msg)
  684. require.Equal(t, tc.sh1, sh, tc.msg)
  685. } else {
  686. require.Error(t, err, tc.msg)
  687. }
  688. }
  689. }
  690. func TestEvidenceDataProtoBuf(t *testing.T) {
  691. val := NewMockPV()
  692. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  693. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  694. const chainID = "mychain"
  695. v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, time.Now())
  696. v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, time.Now())
  697. ev := NewDuplicateVoteEvidence(v2, v)
  698. data := &EvidenceData{Evidence: EvidenceList{ev}}
  699. _ = data.Hash()
  700. testCases := []struct {
  701. msg string
  702. data1 *EvidenceData
  703. expPass1 bool
  704. expPass2 bool
  705. }{
  706. {"success", data, true, true},
  707. {"empty evidenceData", &EvidenceData{Evidence: EvidenceList{}}, true, true},
  708. {"fail nil Data", nil, false, false},
  709. }
  710. for _, tc := range testCases {
  711. protoData, err := tc.data1.ToProto()
  712. if tc.expPass1 {
  713. require.NoError(t, err, tc.msg)
  714. } else {
  715. require.Error(t, err, tc.msg)
  716. }
  717. eviD := new(EvidenceData)
  718. err = eviD.FromProto(protoData)
  719. if tc.expPass2 {
  720. require.NoError(t, err, tc.msg)
  721. require.Equal(t, tc.data1, eviD, tc.msg)
  722. } else {
  723. require.Error(t, err, tc.msg)
  724. }
  725. }
  726. }
  727. func TestCommitProtoBuf(t *testing.T) {
  728. commit := randCommit(time.Now())
  729. testCases := []struct {
  730. msg string
  731. c1 *Commit
  732. expPass bool
  733. }{
  734. {"success", commit, true},
  735. // Empty value sets signatures to nil, signatures should not be nillable
  736. {"empty commit", &Commit{Signatures: []CommitSig{}}, true},
  737. {"fail Commit nil", nil, false},
  738. }
  739. for _, tc := range testCases {
  740. tc := tc
  741. protoCommit := tc.c1.ToProto()
  742. c, err := CommitFromProto(protoCommit)
  743. if tc.expPass {
  744. require.NoError(t, err, tc.msg)
  745. require.Equal(t, tc.c1, c, tc.msg)
  746. } else {
  747. require.Error(t, err, tc.msg)
  748. }
  749. }
  750. }