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.

845 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. gogotypes "github.com/gogo/protobuf/types"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. "github.com/tendermint/tendermint/crypto"
  16. "github.com/tendermint/tendermint/crypto/merkle"
  17. "github.com/tendermint/tendermint/crypto/tmhash"
  18. "github.com/tendermint/tendermint/libs/bits"
  19. "github.com/tendermint/tendermint/libs/bytes"
  20. tmrand "github.com/tendermint/tendermint/libs/rand"
  21. tmproto "github.com/tendermint/tendermint/proto/types"
  22. "github.com/tendermint/tendermint/proto/version"
  23. tmtime "github.com/tendermint/tendermint/types/time"
  24. )
  25. func TestMain(m *testing.M) {
  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. PartSetHeader: 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("F740121F553B5418C3EFBD343C2DBFE9E007BB67B0D020A0741374BAB65242A4")},
  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. switch f := f.Interface().(type) {
  266. case int64, bytes.HexBytes, string:
  267. byteSlices = append(byteSlices, cdcEncode(f))
  268. case time.Time:
  269. bz, err := gogotypes.StdTimeMarshal(f)
  270. require.NoError(t, err)
  271. byteSlices = append(byteSlices, bz)
  272. case version.Consensus:
  273. bz, err := f.Marshal()
  274. require.NoError(t, err)
  275. byteSlices = append(byteSlices, bz)
  276. case BlockID:
  277. pbbi := f.ToProto()
  278. bz, err := pbbi.Marshal()
  279. require.NoError(t, err)
  280. byteSlices = append(byteSlices, bz)
  281. default:
  282. t.Errorf("unknown type %T", f)
  283. }
  284. }
  285. assert.Equal(t,
  286. bytes.HexBytes(merkle.HashFromByteSlices(byteSlices)), tc.header.Hash())
  287. }
  288. })
  289. }
  290. }
  291. func TestMaxHeaderBytes(t *testing.T) {
  292. // Construct a UTF-8 string of MaxChainIDLen length using the supplementary
  293. // characters.
  294. // Each supplementary character takes 4 bytes.
  295. // http://www.i18nguy.com/unicode/supplementary-test.html
  296. maxChainID := ""
  297. for i := 0; i < MaxChainIDLen; i++ {
  298. maxChainID += "𠜎"
  299. }
  300. // time is varint encoded so need to pick the max.
  301. // year int, month Month, day, hour, min, sec, nsec int, loc *Location
  302. timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
  303. h := Header{
  304. Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
  305. ChainID: maxChainID,
  306. Height: math.MaxInt64,
  307. Time: timestamp,
  308. LastBlockID: makeBlockID(make([]byte, tmhash.Size), math.MaxInt32, make([]byte, tmhash.Size)),
  309. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  310. DataHash: tmhash.Sum([]byte("data_hash")),
  311. ValidatorsHash: tmhash.Sum([]byte("validators_hash")),
  312. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  313. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  314. AppHash: tmhash.Sum([]byte("app_hash")),
  315. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  316. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  317. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  318. }
  319. bz, err := h.ToProto().Marshal()
  320. require.NoError(t, err)
  321. assert.EqualValues(t, MaxHeaderBytes, int64(len(bz)))
  322. }
  323. func randCommit(now time.Time) *Commit {
  324. lastID := makeBlockIDRandom()
  325. h := int64(3)
  326. voteSet, _, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  327. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, now)
  328. if err != nil {
  329. panic(err)
  330. }
  331. return commit
  332. }
  333. func hexBytesFromString(s string) bytes.HexBytes {
  334. b, err := hex.DecodeString(s)
  335. if err != nil {
  336. panic(err)
  337. }
  338. return bytes.HexBytes(b)
  339. }
  340. func TestBlockMaxDataBytes(t *testing.T) {
  341. testCases := []struct {
  342. maxBytes int64
  343. valsCount int
  344. evidenceCount int
  345. panics bool
  346. result int64
  347. }{
  348. 0: {-10, 1, 0, true, 0},
  349. 1: {10, 1, 0, true, 0},
  350. 2: {844, 1, 0, true, 0},
  351. 3: {846, 1, 0, false, 0},
  352. 4: {847, 1, 0, false, 1},
  353. }
  354. for i, tc := range testCases {
  355. tc := tc
  356. if tc.panics {
  357. assert.Panics(t, func() {
  358. MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount)
  359. }, "#%v", i)
  360. } else {
  361. assert.Equal(t,
  362. tc.result,
  363. MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount),
  364. "#%v", i)
  365. }
  366. }
  367. }
  368. func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) {
  369. testCases := []struct {
  370. maxBytes int64
  371. maxEvidence uint32
  372. valsCount int
  373. panics bool
  374. result int64
  375. }{
  376. 0: {-10, 0, 1, true, 0},
  377. 1: {10, 0, 1, true, 0},
  378. 2: {845, 0, 1, true, 0},
  379. 3: {846, 0, 1, false, 0},
  380. 4: {1290, 1, 1, false, 0},
  381. 5: {1291, 1, 1, false, 1},
  382. }
  383. for i, tc := range testCases {
  384. tc := tc
  385. if tc.panics {
  386. assert.Panics(t, func() {
  387. MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount, tc.maxEvidence)
  388. }, "#%v", i)
  389. } else {
  390. assert.Equal(t,
  391. tc.result,
  392. MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount, tc.maxEvidence),
  393. "#%v", i)
  394. }
  395. }
  396. }
  397. func TestCommitToVoteSet(t *testing.T) {
  398. lastID := makeBlockIDRandom()
  399. h := int64(3)
  400. voteSet, valSet, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1)
  401. commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now())
  402. assert.NoError(t, err)
  403. chainID := voteSet.ChainID()
  404. voteSet2 := CommitToVoteSet(chainID, commit, valSet)
  405. for i := int32(0); int(i) < len(vals); i++ {
  406. vote1 := voteSet.GetByIndex(i)
  407. vote2 := voteSet2.GetByIndex(i)
  408. vote3 := commit.GetVote(i)
  409. vote1bz, err := vote1.ToProto().Marshal()
  410. require.NoError(t, err)
  411. vote2bz, err := vote2.ToProto().Marshal()
  412. require.NoError(t, err)
  413. vote3bz, err := vote3.ToProto().Marshal()
  414. require.NoError(t, err)
  415. assert.Equal(t, vote1bz, vote2bz)
  416. assert.Equal(t, vote1bz, vote3bz)
  417. }
  418. }
  419. func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) {
  420. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  421. const (
  422. height = int64(3)
  423. round = 0
  424. )
  425. type commitVoteTest struct {
  426. blockIDs []BlockID
  427. numVotes []int // must sum to numValidators
  428. numValidators int
  429. valid bool
  430. }
  431. testCases := []commitVoteTest{
  432. {[]BlockID{blockID, {}}, []int{67, 33}, 100, true},
  433. }
  434. for _, tc := range testCases {
  435. voteSet, valSet, vals := randVoteSet(height-1, round, tmproto.PrecommitType, tc.numValidators, 1)
  436. vi := int32(0)
  437. for n := range tc.blockIDs {
  438. for i := 0; i < tc.numVotes[n]; i++ {
  439. pubKey, err := vals[vi].GetPubKey()
  440. require.NoError(t, err)
  441. vote := &Vote{
  442. ValidatorAddress: pubKey.Address(),
  443. ValidatorIndex: vi,
  444. Height: height - 1,
  445. Round: round,
  446. Type: tmproto.PrecommitType,
  447. BlockID: tc.blockIDs[n],
  448. Timestamp: tmtime.Now(),
  449. }
  450. added, err := signAddVote(vals[vi], vote, voteSet)
  451. assert.NoError(t, err)
  452. assert.True(t, added)
  453. vi++
  454. }
  455. }
  456. if tc.valid {
  457. commit := voteSet.MakeCommit() // panics without > 2/3 valid votes
  458. assert.NotNil(t, commit)
  459. err := valSet.VerifyCommit(voteSet.ChainID(), blockID, height-1, commit)
  460. assert.Nil(t, err)
  461. } else {
  462. assert.Panics(t, func() { voteSet.MakeCommit() })
  463. }
  464. }
  465. }
  466. func TestSignedHeaderValidateBasic(t *testing.T) {
  467. commit := randCommit(time.Now())
  468. chainID := "𠜎"
  469. timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
  470. h := Header{
  471. Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
  472. ChainID: chainID,
  473. Height: commit.Height,
  474. Time: timestamp,
  475. LastBlockID: commit.BlockID,
  476. LastCommitHash: commit.Hash(),
  477. DataHash: commit.Hash(),
  478. ValidatorsHash: commit.Hash(),
  479. NextValidatorsHash: commit.Hash(),
  480. ConsensusHash: commit.Hash(),
  481. AppHash: commit.Hash(),
  482. LastResultsHash: commit.Hash(),
  483. EvidenceHash: commit.Hash(),
  484. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  485. }
  486. validSignedHeader := SignedHeader{Header: &h, Commit: commit}
  487. validSignedHeader.Commit.BlockID.Hash = validSignedHeader.Hash()
  488. invalidSignedHeader := SignedHeader{}
  489. testCases := []struct {
  490. testName string
  491. shHeader *Header
  492. shCommit *Commit
  493. expectErr bool
  494. }{
  495. {"Valid Signed Header", validSignedHeader.Header, validSignedHeader.Commit, false},
  496. {"Invalid Signed Header", invalidSignedHeader.Header, validSignedHeader.Commit, true},
  497. {"Invalid Signed Header", validSignedHeader.Header, invalidSignedHeader.Commit, true},
  498. }
  499. for _, tc := range testCases {
  500. tc := tc
  501. t.Run(tc.testName, func(t *testing.T) {
  502. sh := SignedHeader{
  503. Header: tc.shHeader,
  504. Commit: tc.shCommit,
  505. }
  506. assert.Equal(
  507. t,
  508. tc.expectErr,
  509. sh.ValidateBasic(validSignedHeader.Header.ChainID) != nil,
  510. "Validate Basic had an unexpected result",
  511. )
  512. })
  513. }
  514. }
  515. func TestBlockIDValidateBasic(t *testing.T) {
  516. validBlockID := BlockID{
  517. Hash: bytes.HexBytes{},
  518. PartSetHeader: PartSetHeader{
  519. Total: 1,
  520. Hash: bytes.HexBytes{},
  521. },
  522. }
  523. invalidBlockID := BlockID{
  524. Hash: []byte{0},
  525. PartSetHeader: PartSetHeader{
  526. Total: 1,
  527. Hash: []byte{0},
  528. },
  529. }
  530. testCases := []struct {
  531. testName string
  532. blockIDHash bytes.HexBytes
  533. blockIDPartSetHeader PartSetHeader
  534. expectErr bool
  535. }{
  536. {"Valid BlockID", validBlockID.Hash, validBlockID.PartSetHeader, false},
  537. {"Invalid BlockID", invalidBlockID.Hash, validBlockID.PartSetHeader, true},
  538. {"Invalid BlockID", validBlockID.Hash, invalidBlockID.PartSetHeader, true},
  539. }
  540. for _, tc := range testCases {
  541. tc := tc
  542. t.Run(tc.testName, func(t *testing.T) {
  543. blockID := BlockID{
  544. Hash: tc.blockIDHash,
  545. PartSetHeader: tc.blockIDPartSetHeader,
  546. }
  547. assert.Equal(t, tc.expectErr, blockID.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  548. })
  549. }
  550. }
  551. func TestBlockProtoBuf(t *testing.T) {
  552. h := tmrand.Int63()
  553. c1 := randCommit(time.Now())
  554. b1 := MakeBlock(h, []Tx{Tx([]byte{1})}, &Commit{Signatures: []CommitSig{}}, []Evidence{})
  555. b1.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  556. b2 := MakeBlock(h, []Tx{Tx([]byte{1})}, c1, []Evidence{})
  557. b2.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  558. evi := NewMockEvidence(b2.Height, time.Now(), tmrand.Bytes(32))
  559. b2.Evidence = EvidenceData{Evidence: EvidenceList{evi}}
  560. b2.EvidenceHash = b2.Evidence.Hash()
  561. b3 := MakeBlock(h, []Tx{}, c1, []Evidence{})
  562. b3.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  563. testCases := []struct {
  564. msg string
  565. b1 *Block
  566. expPass bool
  567. expPass2 bool
  568. }{
  569. {"nil block", nil, false, false},
  570. {"b1", b1, true, true},
  571. {"b2", b2, true, true},
  572. {"b3", b3, true, true},
  573. }
  574. for _, tc := range testCases {
  575. pb, err := tc.b1.ToProto()
  576. if tc.expPass {
  577. require.NoError(t, err, tc.msg)
  578. } else {
  579. require.Error(t, err, tc.msg)
  580. }
  581. block, err := BlockFromProto(pb)
  582. if tc.expPass2 {
  583. require.NoError(t, err, tc.msg)
  584. require.EqualValues(t, tc.b1.Header, block.Header, tc.msg)
  585. require.EqualValues(t, tc.b1.Data, block.Data, tc.msg)
  586. require.EqualValues(t, tc.b1.Evidence, block.Evidence, tc.msg)
  587. require.EqualValues(t, *tc.b1.LastCommit, *block.LastCommit, tc.msg)
  588. } else {
  589. require.Error(t, err, tc.msg)
  590. }
  591. }
  592. }
  593. func TestDataProtoBuf(t *testing.T) {
  594. data := &Data{Txs: Txs{Tx([]byte{1}), Tx([]byte{2}), Tx([]byte{3})}}
  595. _ = data.Hash()
  596. data2 := &Data{Txs: Txs{}}
  597. _ = data2.Hash()
  598. testCases := []struct {
  599. msg string
  600. data1 *Data
  601. expPass bool
  602. }{
  603. {"success", data, true},
  604. {"success data2", data2, true},
  605. }
  606. for _, tc := range testCases {
  607. protoData := tc.data1.ToProto()
  608. d, err := DataFromProto(&protoData)
  609. if tc.expPass {
  610. require.NoError(t, err, tc.msg)
  611. require.EqualValues(t, tc.data1, &d, tc.msg)
  612. } else {
  613. require.Error(t, err, tc.msg)
  614. }
  615. }
  616. }
  617. func TestEvidenceDataProtoBuf(t *testing.T) {
  618. val := NewMockPV()
  619. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  620. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  621. const chainID = "mychain"
  622. v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, time.Now())
  623. v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, time.Now())
  624. ev := NewDuplicateVoteEvidence(v2, v)
  625. data := &EvidenceData{Evidence: EvidenceList{ev}}
  626. _ = data.Hash()
  627. testCases := []struct {
  628. msg string
  629. data1 *EvidenceData
  630. expPass1 bool
  631. expPass2 bool
  632. }{
  633. {"success", data, true, true},
  634. {"empty evidenceData", &EvidenceData{Evidence: EvidenceList{}}, true, true},
  635. {"fail nil Data", nil, false, false},
  636. }
  637. for _, tc := range testCases {
  638. protoData, err := tc.data1.ToProto()
  639. if tc.expPass1 {
  640. require.NoError(t, err, tc.msg)
  641. } else {
  642. require.Error(t, err, tc.msg)
  643. }
  644. eviD := new(EvidenceData)
  645. err = eviD.FromProto(protoData)
  646. if tc.expPass2 {
  647. require.NoError(t, err, tc.msg)
  648. require.Equal(t, tc.data1, eviD, tc.msg)
  649. } else {
  650. require.Error(t, err, tc.msg)
  651. }
  652. }
  653. }
  654. func makeRandHeader() Header {
  655. chainID := "test"
  656. t := time.Now()
  657. height := tmrand.Int63()
  658. randBytes := tmrand.Bytes(tmhash.Size)
  659. randAddress := tmrand.Bytes(crypto.AddressSize)
  660. h := Header{
  661. Version: version.Consensus{Block: 1, App: 1},
  662. ChainID: chainID,
  663. Height: height,
  664. Time: t,
  665. LastBlockID: BlockID{},
  666. LastCommitHash: randBytes,
  667. DataHash: randBytes,
  668. ValidatorsHash: randBytes,
  669. NextValidatorsHash: randBytes,
  670. ConsensusHash: randBytes,
  671. AppHash: randBytes,
  672. LastResultsHash: randBytes,
  673. EvidenceHash: randBytes,
  674. ProposerAddress: randAddress,
  675. }
  676. return h
  677. }
  678. func TestHeaderProto(t *testing.T) {
  679. h1 := makeRandHeader()
  680. tc := []struct {
  681. msg string
  682. h1 *Header
  683. expPass bool
  684. }{
  685. {"success", &h1, true},
  686. {"failure empty Header", &Header{}, false},
  687. }
  688. for _, tt := range tc {
  689. tt := tt
  690. t.Run(tt.msg, func(t *testing.T) {
  691. pb := tt.h1.ToProto()
  692. h, err := HeaderFromProto(pb)
  693. if tt.expPass {
  694. require.NoError(t, err, tt.msg)
  695. require.Equal(t, tt.h1, &h, tt.msg)
  696. } else {
  697. require.Error(t, err, tt.msg)
  698. }
  699. })
  700. }
  701. }
  702. func TestBlockIDProtoBuf(t *testing.T) {
  703. blockID := makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  704. testCases := []struct {
  705. msg string
  706. bid1 *BlockID
  707. expPass bool
  708. }{
  709. {"success", &blockID, true},
  710. {"success empty", &BlockID{}, true},
  711. {"failure BlockID nil", nil, false},
  712. }
  713. for _, tc := range testCases {
  714. protoBlockID := tc.bid1.ToProto()
  715. bi, err := BlockIDFromProto(&protoBlockID)
  716. if tc.expPass {
  717. require.NoError(t, err)
  718. require.Equal(t, tc.bid1, bi, tc.msg)
  719. } else {
  720. require.NotEqual(t, tc.bid1, bi, tc.msg)
  721. }
  722. }
  723. }
  724. func TestSignedHeaderProtoBuf(t *testing.T) {
  725. commit := randCommit(time.Now())
  726. h := makeRandHeader()
  727. sh := SignedHeader{Header: &h, Commit: commit}
  728. testCases := []struct {
  729. msg string
  730. sh1 *SignedHeader
  731. expPass bool
  732. }{
  733. {"empty SignedHeader 2", &SignedHeader{}, true},
  734. {"success", &sh, true},
  735. {"failure nil", nil, false},
  736. }
  737. for _, tc := range testCases {
  738. protoSignedHeader := tc.sh1.ToProto()
  739. sh, err := SignedHeaderFromProto(protoSignedHeader)
  740. if tc.expPass {
  741. require.NoError(t, err, tc.msg)
  742. require.Equal(t, tc.sh1, sh, tc.msg)
  743. } else {
  744. require.Error(t, err, tc.msg)
  745. }
  746. }
  747. }