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.

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