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.

1404 lines
39 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. "context"
  6. "crypto/rand"
  7. "encoding/hex"
  8. "math"
  9. mrand "math/rand"
  10. "os"
  11. "reflect"
  12. "testing"
  13. "time"
  14. gogotypes "github.com/gogo/protobuf/types"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/stretchr/testify/require"
  17. "github.com/tendermint/tendermint/crypto"
  18. "github.com/tendermint/tendermint/crypto/merkle"
  19. "github.com/tendermint/tendermint/crypto/tmhash"
  20. "github.com/tendermint/tendermint/libs/bits"
  21. "github.com/tendermint/tendermint/libs/bytes"
  22. tmrand "github.com/tendermint/tendermint/libs/rand"
  23. tmtime "github.com/tendermint/tendermint/libs/time"
  24. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  25. tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
  26. "github.com/tendermint/tendermint/version"
  27. )
  28. func TestMain(m *testing.M) {
  29. code := m.Run()
  30. os.Exit(code)
  31. }
  32. func TestBlockAddEvidence(t *testing.T) {
  33. ctx, cancel := context.WithCancel(context.Background())
  34. defer cancel()
  35. txs := []Tx{Tx("foo"), Tx("bar")}
  36. lastID := makeBlockIDRandom()
  37. h := int64(3)
  38. voteSet, _, vals := randVoteSet(ctx, t, h-1, 1, tmproto.PrecommitType, 10, 1)
  39. commit, err := makeCommit(ctx, lastID, h-1, 1, voteSet, vals, time.Now())
  40. require.NoError(t, err)
  41. ev, err := NewMockDuplicateVoteEvidenceWithValidator(ctx, h, time.Now(), vals[0], "block-test-chain")
  42. require.NoError(t, err)
  43. evList := []Evidence{ev}
  44. block := MakeBlock(h, txs, commit, evList)
  45. require.NotNil(t, block)
  46. require.Equal(t, 1, len(block.Evidence.Evidence))
  47. require.NotNil(t, block.EvidenceHash)
  48. }
  49. func TestBlockValidateBasic(t *testing.T) {
  50. ctx, cancel := context.WithCancel(context.Background())
  51. defer cancel()
  52. require.Error(t, (*Block)(nil).ValidateBasic())
  53. txs := []Tx{Tx("foo"), Tx("bar")}
  54. lastID := makeBlockIDRandom()
  55. h := int64(3)
  56. voteSet, valSet, vals := randVoteSet(ctx, t, h-1, 1, tmproto.PrecommitType, 10, 1)
  57. commit, err := makeCommit(ctx, lastID, h-1, 1, voteSet, vals, time.Now())
  58. require.NoError(t, err)
  59. ev, err := NewMockDuplicateVoteEvidenceWithValidator(ctx, h, time.Now(), vals[0], "block-test-chain")
  60. require.NoError(t, err)
  61. evList := []Evidence{ev}
  62. testCases := []struct {
  63. testName string
  64. malleateBlock func(*Block)
  65. expErr bool
  66. }{
  67. {"Make Block", func(blk *Block) {}, false},
  68. {"Make Block w/ proposer Addr", func(blk *Block) { blk.ProposerAddress = valSet.GetProposer().Address }, false},
  69. {"Negative Height", func(blk *Block) { blk.Height = -1 }, true},
  70. {"Remove 1/2 the commits", func(blk *Block) {
  71. blk.LastCommit.Signatures = commit.Signatures[:commit.Size()/2]
  72. blk.LastCommit.hash = nil // clear hash or change wont be noticed
  73. }, true},
  74. {"Remove LastCommitHash", func(blk *Block) { blk.LastCommitHash = []byte("something else") }, true},
  75. {"Tampered Data", func(blk *Block) {
  76. blk.Data.Txs[0] = Tx("something else")
  77. blk.Data.hash = nil // clear hash or change wont be noticed
  78. }, true},
  79. {"Tampered DataHash", func(blk *Block) {
  80. blk.DataHash = tmrand.Bytes(len(blk.DataHash))
  81. }, true},
  82. {"Tampered EvidenceHash", func(blk *Block) {
  83. blk.EvidenceHash = tmrand.Bytes(len(blk.EvidenceHash))
  84. }, true},
  85. {"Incorrect block protocol version", func(blk *Block) {
  86. blk.Version.Block = 1
  87. }, true},
  88. {"Missing LastCommit", func(blk *Block) {
  89. blk.LastCommit = nil
  90. }, true},
  91. {"Invalid LastCommit", func(blk *Block) {
  92. blk.LastCommit = NewCommit(-1, 0, *voteSet.maj23, nil)
  93. }, true},
  94. {"Invalid Evidence", func(blk *Block) {
  95. emptyEv := &DuplicateVoteEvidence{}
  96. blk.Evidence = EvidenceData{Evidence: []Evidence{emptyEv}}
  97. }, true},
  98. }
  99. for i, tc := range testCases {
  100. tc := tc
  101. i := i
  102. t.Run(tc.testName, func(t *testing.T) {
  103. block := MakeBlock(h, txs, commit, evList)
  104. block.ProposerAddress = valSet.GetProposer().Address
  105. tc.malleateBlock(block)
  106. err = block.ValidateBasic()
  107. t.Log(err)
  108. assert.Equal(t, tc.expErr, err != nil, "#%d: %v", i, err)
  109. })
  110. }
  111. }
  112. func TestBlockHash(t *testing.T) {
  113. assert.Nil(t, (*Block)(nil).Hash())
  114. assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Hash())
  115. }
  116. func TestBlockMakePartSet(t *testing.T) {
  117. bps, err := (*Block)(nil).MakePartSet(2)
  118. assert.Error(t, err)
  119. assert.Nil(t, bps)
  120. partSet, err := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024)
  121. require.NoError(t, err)
  122. assert.NotNil(t, partSet)
  123. assert.EqualValues(t, 1, partSet.Total())
  124. }
  125. func TestBlockMakePartSetWithEvidence(t *testing.T) {
  126. ctx, cancel := context.WithCancel(context.Background())
  127. defer cancel()
  128. bps, err := (*Block)(nil).MakePartSet(2)
  129. assert.Error(t, err)
  130. assert.Nil(t, bps)
  131. lastID := makeBlockIDRandom()
  132. h := int64(3)
  133. voteSet, _, vals := randVoteSet(ctx, t, h-1, 1, tmproto.PrecommitType, 10, 1)
  134. commit, err := makeCommit(ctx, lastID, h-1, 1, voteSet, vals, time.Now())
  135. require.NoError(t, err)
  136. ev, err := NewMockDuplicateVoteEvidenceWithValidator(ctx, h, time.Now(), vals[0], "block-test-chain")
  137. require.NoError(t, err)
  138. evList := []Evidence{ev}
  139. partSet, err := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(512)
  140. require.NoError(t, err)
  141. assert.NotNil(t, partSet)
  142. assert.EqualValues(t, 4, partSet.Total())
  143. }
  144. func TestBlockHashesTo(t *testing.T) {
  145. ctx, cancel := context.WithCancel(context.Background())
  146. defer cancel()
  147. assert.False(t, (*Block)(nil).HashesTo(nil))
  148. lastID := makeBlockIDRandom()
  149. h := int64(3)
  150. voteSet, valSet, vals := randVoteSet(ctx, t, h-1, 1, tmproto.PrecommitType, 10, 1)
  151. commit, err := makeCommit(ctx, lastID, h-1, 1, voteSet, vals, time.Now())
  152. require.NoError(t, err)
  153. ev, err := NewMockDuplicateVoteEvidenceWithValidator(ctx, h, time.Now(), vals[0], "block-test-chain")
  154. require.NoError(t, err)
  155. evList := []Evidence{ev}
  156. block := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList)
  157. block.ValidatorsHash = valSet.Hash()
  158. assert.False(t, block.HashesTo([]byte{}))
  159. assert.False(t, block.HashesTo([]byte("something else")))
  160. assert.True(t, block.HashesTo(block.Hash()))
  161. }
  162. func TestBlockSize(t *testing.T) {
  163. size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Size()
  164. if size <= 0 {
  165. t.Fatal("Size of the block is zero or negative")
  166. }
  167. }
  168. func TestBlockString(t *testing.T) {
  169. assert.Equal(t, "nil-Block", (*Block)(nil).String())
  170. assert.Equal(t, "nil-Block", (*Block)(nil).StringIndented(""))
  171. assert.Equal(t, "nil-Block", (*Block)(nil).StringShort())
  172. block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil)
  173. assert.NotEqual(t, "nil-Block", block.String())
  174. assert.NotEqual(t, "nil-Block", block.StringIndented(""))
  175. assert.NotEqual(t, "nil-Block", block.StringShort())
  176. }
  177. func makeBlockIDRandom() BlockID {
  178. var (
  179. blockHash = make([]byte, tmhash.Size)
  180. partSetHash = make([]byte, tmhash.Size)
  181. )
  182. rand.Read(blockHash) //nolint: errcheck // ignore errcheck for read
  183. rand.Read(partSetHash) //nolint: errcheck // ignore errcheck for read
  184. return BlockID{blockHash, PartSetHeader{123, partSetHash}}
  185. }
  186. func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) BlockID {
  187. var (
  188. h = make([]byte, tmhash.Size)
  189. psH = make([]byte, tmhash.Size)
  190. )
  191. copy(h, hash)
  192. copy(psH, partSetHash)
  193. return BlockID{
  194. Hash: h,
  195. PartSetHeader: PartSetHeader{
  196. Total: partSetSize,
  197. Hash: psH,
  198. },
  199. }
  200. }
  201. var nilBytes []byte
  202. // This follows RFC-6962, i.e. `echo -n '' | sha256sum`
  203. var emptyBytes = []byte{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8,
  204. 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b,
  205. 0x78, 0x52, 0xb8, 0x55}
  206. func TestNilHeaderHashDoesntCrash(t *testing.T) {
  207. assert.Equal(t, nilBytes, []byte((*Header)(nil).Hash()))
  208. assert.Equal(t, nilBytes, []byte((new(Header)).Hash()))
  209. }
  210. func TestNilDataHashDoesntCrash(t *testing.T) {
  211. assert.Equal(t, emptyBytes, []byte((*Data)(nil).Hash()))
  212. assert.Equal(t, emptyBytes, []byte(new(Data).Hash()))
  213. }
  214. func TestCommit(t *testing.T) {
  215. ctx, cancel := context.WithCancel(context.Background())
  216. defer cancel()
  217. lastID := makeBlockIDRandom()
  218. h := int64(3)
  219. voteSet, _, vals := randVoteSet(ctx, t, h-1, 1, tmproto.PrecommitType, 10, 1)
  220. commit, err := makeCommit(ctx, lastID, h-1, 1, voteSet, vals, time.Now())
  221. require.NoError(t, err)
  222. assert.Equal(t, h-1, commit.Height)
  223. assert.EqualValues(t, 1, commit.Round)
  224. assert.Equal(t, tmproto.PrecommitType, tmproto.SignedMsgType(commit.Type()))
  225. if commit.Size() <= 0 {
  226. t.Fatalf("commit %v has a zero or negative size: %d", commit, commit.Size())
  227. }
  228. require.NotNil(t, commit.BitArray())
  229. assert.Equal(t, bits.NewBitArray(10).Size(), commit.BitArray().Size())
  230. assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0))
  231. assert.True(t, commit.IsCommit())
  232. }
  233. func TestCommitValidateBasic(t *testing.T) {
  234. testCases := []struct {
  235. testName string
  236. malleateCommit func(*Commit)
  237. expectErr bool
  238. }{
  239. {"Random Commit", func(com *Commit) {}, false},
  240. {"Incorrect signature", func(com *Commit) { com.Signatures[0].Signature = []byte{0} }, false},
  241. {"Incorrect height", func(com *Commit) { com.Height = int64(-100) }, true},
  242. {"Incorrect round", func(com *Commit) { com.Round = -100 }, true},
  243. }
  244. for _, tc := range testCases {
  245. tc := tc
  246. t.Run(tc.testName, func(t *testing.T) {
  247. ctx, cancel := context.WithCancel(context.Background())
  248. defer cancel()
  249. com := randCommit(ctx, t, time.Now())
  250. tc.malleateCommit(com)
  251. assert.Equal(t, tc.expectErr, com.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  252. })
  253. }
  254. }
  255. func TestMaxCommitBytes(t *testing.T) {
  256. // time is varint encoded so need to pick the max.
  257. // year int, month Month, day, hour, min, sec, nsec int, loc *Location
  258. timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
  259. cs := CommitSig{
  260. BlockIDFlag: BlockIDFlagNil,
  261. ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
  262. Timestamp: timestamp,
  263. Signature: crypto.CRandBytes(MaxSignatureSize),
  264. }
  265. pbSig := cs.ToProto()
  266. // test that a single commit sig doesn't exceed max commit sig bytes
  267. assert.EqualValues(t, MaxCommitSigBytes, pbSig.Size())
  268. // check size with a single commit
  269. commit := &Commit{
  270. Height: math.MaxInt64,
  271. Round: math.MaxInt32,
  272. BlockID: BlockID{
  273. Hash: tmhash.Sum([]byte("blockID_hash")),
  274. PartSetHeader: PartSetHeader{
  275. Total: math.MaxInt32,
  276. Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
  277. },
  278. },
  279. Signatures: []CommitSig{cs},
  280. }
  281. pb := commit.ToProto()
  282. assert.EqualValues(t, MaxCommitBytes(1), int64(pb.Size()))
  283. // check the upper bound of the commit size
  284. for i := 1; i < MaxVotesCount; i++ {
  285. commit.Signatures = append(commit.Signatures, cs)
  286. }
  287. pb = commit.ToProto()
  288. assert.EqualValues(t, MaxCommitBytes(MaxVotesCount), int64(pb.Size()))
  289. }
  290. func TestHeaderHash(t *testing.T) {
  291. testCases := []struct {
  292. desc string
  293. header *Header
  294. expectHash bytes.HexBytes
  295. }{
  296. {"Generates expected hash", &Header{
  297. Version: version.Consensus{Block: 1, App: 2},
  298. ChainID: "chainId",
  299. Height: 3,
  300. Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
  301. LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)),
  302. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  303. DataHash: tmhash.Sum([]byte("data_hash")),
  304. ValidatorsHash: tmhash.Sum([]byte("validators_hash")),
  305. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  306. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  307. AppHash: tmhash.Sum([]byte("app_hash")),
  308. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  309. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  310. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  311. }, hexBytesFromString(t, "F740121F553B5418C3EFBD343C2DBFE9E007BB67B0D020A0741374BAB65242A4")},
  312. {"nil header yields nil", nil, nil},
  313. {"nil ValidatorsHash yields nil", &Header{
  314. Version: version.Consensus{Block: 1, App: 2},
  315. ChainID: "chainId",
  316. Height: 3,
  317. Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
  318. LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)),
  319. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  320. DataHash: tmhash.Sum([]byte("data_hash")),
  321. ValidatorsHash: nil,
  322. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  323. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  324. AppHash: tmhash.Sum([]byte("app_hash")),
  325. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  326. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  327. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  328. }, nil},
  329. }
  330. for _, tc := range testCases {
  331. tc := tc
  332. t.Run(tc.desc, func(t *testing.T) {
  333. assert.Equal(t, tc.expectHash, tc.header.Hash())
  334. // We also make sure that all fields are hashed in struct order, and that all
  335. // fields in the test struct are non-zero.
  336. if tc.header != nil && tc.expectHash != nil {
  337. byteSlices := [][]byte{}
  338. s := reflect.ValueOf(*tc.header)
  339. for i := 0; i < s.NumField(); i++ {
  340. f := s.Field(i)
  341. assert.False(t, f.IsZero(), "Found zero-valued field %v",
  342. s.Type().Field(i).Name)
  343. switch f := f.Interface().(type) {
  344. case int64, bytes.HexBytes, string:
  345. byteSlices = append(byteSlices, cdcEncode(f))
  346. case time.Time:
  347. bz, err := gogotypes.StdTimeMarshal(f)
  348. require.NoError(t, err)
  349. byteSlices = append(byteSlices, bz)
  350. case version.Consensus:
  351. pbc := tmversion.Consensus{
  352. Block: f.Block,
  353. App: f.App,
  354. }
  355. bz, err := pbc.Marshal()
  356. require.NoError(t, err)
  357. byteSlices = append(byteSlices, bz)
  358. case BlockID:
  359. pbbi := f.ToProto()
  360. bz, err := pbbi.Marshal()
  361. require.NoError(t, err)
  362. byteSlices = append(byteSlices, bz)
  363. default:
  364. t.Errorf("unknown type %T", f)
  365. }
  366. }
  367. assert.Equal(t,
  368. bytes.HexBytes(merkle.HashFromByteSlices(byteSlices)), tc.header.Hash())
  369. }
  370. })
  371. }
  372. }
  373. func TestMaxHeaderBytes(t *testing.T) {
  374. // Construct a UTF-8 string of MaxChainIDLen length using the supplementary
  375. // characters.
  376. // Each supplementary character takes 4 bytes.
  377. // http://www.i18nguy.com/unicode/supplementary-test.html
  378. maxChainID := ""
  379. for i := 0; i < MaxChainIDLen; i++ {
  380. maxChainID += "𠜎"
  381. }
  382. // time is varint encoded so need to pick the max.
  383. // year int, month Month, day, hour, min, sec, nsec int, loc *Location
  384. timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
  385. h := Header{
  386. Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
  387. ChainID: maxChainID,
  388. Height: math.MaxInt64,
  389. Time: timestamp,
  390. LastBlockID: makeBlockID(make([]byte, tmhash.Size), math.MaxInt32, make([]byte, tmhash.Size)),
  391. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  392. DataHash: tmhash.Sum([]byte("data_hash")),
  393. ValidatorsHash: tmhash.Sum([]byte("validators_hash")),
  394. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  395. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  396. AppHash: tmhash.Sum([]byte("app_hash")),
  397. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  398. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  399. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  400. }
  401. bz, err := h.ToProto().Marshal()
  402. require.NoError(t, err)
  403. assert.EqualValues(t, MaxHeaderBytes, int64(len(bz)))
  404. }
  405. func randCommit(ctx context.Context, t *testing.T, now time.Time) *Commit {
  406. t.Helper()
  407. lastID := makeBlockIDRandom()
  408. h := int64(3)
  409. voteSet, _, vals := randVoteSet(ctx, t, h-1, 1, tmproto.PrecommitType, 10, 1)
  410. commit, err := makeCommit(ctx, lastID, h-1, 1, voteSet, vals, now)
  411. require.NoError(t, err)
  412. return commit
  413. }
  414. func hexBytesFromString(t *testing.T, s string) bytes.HexBytes {
  415. t.Helper()
  416. b, err := hex.DecodeString(s)
  417. require.NoError(t, err)
  418. return bytes.HexBytes(b)
  419. }
  420. func TestBlockMaxDataBytes(t *testing.T) {
  421. testCases := []struct {
  422. maxBytes int64
  423. valsCount int
  424. evidenceBytes int64
  425. panics bool
  426. result int64
  427. }{
  428. 0: {-10, 1, 0, true, 0},
  429. 1: {10, 1, 0, true, 0},
  430. 2: {841, 1, 0, true, 0},
  431. 3: {842, 1, 0, false, 0},
  432. 4: {843, 1, 0, false, 1},
  433. 5: {954, 2, 0, false, 1},
  434. 6: {1053, 2, 100, false, 0},
  435. }
  436. for i, tc := range testCases {
  437. tc := tc
  438. if tc.panics {
  439. assert.Panics(t, func() {
  440. MaxDataBytes(tc.maxBytes, tc.evidenceBytes, tc.valsCount)
  441. }, "#%v", i)
  442. } else {
  443. assert.Equal(t,
  444. tc.result,
  445. MaxDataBytes(tc.maxBytes, tc.evidenceBytes, tc.valsCount),
  446. "#%v", i)
  447. }
  448. }
  449. }
  450. func TestBlockMaxDataBytesNoEvidence(t *testing.T) {
  451. testCases := []struct {
  452. maxBytes int64
  453. valsCount int
  454. panics bool
  455. result int64
  456. }{
  457. 0: {-10, 1, true, 0},
  458. 1: {10, 1, true, 0},
  459. 2: {841, 1, true, 0},
  460. 3: {842, 1, false, 0},
  461. 4: {843, 1, false, 1},
  462. }
  463. for i, tc := range testCases {
  464. tc := tc
  465. if tc.panics {
  466. assert.Panics(t, func() {
  467. MaxDataBytesNoEvidence(tc.maxBytes, tc.valsCount)
  468. }, "#%v", i)
  469. } else {
  470. assert.Equal(t,
  471. tc.result,
  472. MaxDataBytesNoEvidence(tc.maxBytes, tc.valsCount),
  473. "#%v", i)
  474. }
  475. }
  476. }
  477. func TestCommitToVoteSet(t *testing.T) {
  478. lastID := makeBlockIDRandom()
  479. h := int64(3)
  480. ctx, cancel := context.WithCancel(context.Background())
  481. defer cancel()
  482. voteSet, valSet, vals := randVoteSet(ctx, t, h-1, 1, tmproto.PrecommitType, 10, 1)
  483. commit, err := makeCommit(ctx, lastID, h-1, 1, voteSet, vals, time.Now())
  484. assert.NoError(t, err)
  485. chainID := voteSet.ChainID()
  486. voteSet2 := CommitToVoteSet(chainID, commit, valSet)
  487. for i := int32(0); int(i) < len(vals); i++ {
  488. vote1 := voteSet.GetByIndex(i)
  489. vote2 := voteSet2.GetByIndex(i)
  490. vote3 := commit.GetVote(i)
  491. vote1bz, err := vote1.ToProto().Marshal()
  492. require.NoError(t, err)
  493. vote2bz, err := vote2.ToProto().Marshal()
  494. require.NoError(t, err)
  495. vote3bz, err := vote3.ToProto().Marshal()
  496. require.NoError(t, err)
  497. assert.Equal(t, vote1bz, vote2bz)
  498. assert.Equal(t, vote1bz, vote3bz)
  499. }
  500. }
  501. func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) {
  502. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  503. const (
  504. height = int64(3)
  505. round = 0
  506. )
  507. ctx, cancel := context.WithCancel(context.Background())
  508. defer cancel()
  509. type commitVoteTest struct {
  510. blockIDs []BlockID
  511. numVotes []int // must sum to numValidators
  512. numValidators int
  513. valid bool
  514. }
  515. testCases := []commitVoteTest{
  516. {[]BlockID{blockID, {}}, []int{67, 33}, 100, true},
  517. }
  518. for _, tc := range testCases {
  519. voteSet, valSet, vals := randVoteSet(ctx, t, height-1, round, tmproto.PrecommitType, tc.numValidators, 1)
  520. vi := int32(0)
  521. for n := range tc.blockIDs {
  522. for i := 0; i < tc.numVotes[n]; i++ {
  523. pubKey, err := vals[vi].GetPubKey(ctx)
  524. require.NoError(t, err)
  525. vote := &Vote{
  526. ValidatorAddress: pubKey.Address(),
  527. ValidatorIndex: vi,
  528. Height: height - 1,
  529. Round: round,
  530. Type: tmproto.PrecommitType,
  531. BlockID: tc.blockIDs[n],
  532. Timestamp: tmtime.Now(),
  533. }
  534. added, err := signAddVote(ctx, vals[vi], vote, voteSet)
  535. assert.NoError(t, err)
  536. assert.True(t, added)
  537. vi++
  538. }
  539. }
  540. if tc.valid {
  541. commit := voteSet.MakeCommit() // panics without > 2/3 valid votes
  542. assert.NotNil(t, commit)
  543. err := valSet.VerifyCommit(voteSet.ChainID(), blockID, height-1, commit)
  544. assert.NoError(t, err)
  545. } else {
  546. assert.Panics(t, func() { voteSet.MakeCommit() })
  547. }
  548. }
  549. }
  550. func TestBlockIDValidateBasic(t *testing.T) {
  551. validBlockID := BlockID{
  552. Hash: bytes.HexBytes{},
  553. PartSetHeader: PartSetHeader{
  554. Total: 1,
  555. Hash: bytes.HexBytes{},
  556. },
  557. }
  558. invalidBlockID := BlockID{
  559. Hash: []byte{0},
  560. PartSetHeader: PartSetHeader{
  561. Total: 1,
  562. Hash: []byte{0},
  563. },
  564. }
  565. testCases := []struct {
  566. testName string
  567. blockIDHash bytes.HexBytes
  568. blockIDPartSetHeader PartSetHeader
  569. expectErr bool
  570. }{
  571. {"Valid BlockID", validBlockID.Hash, validBlockID.PartSetHeader, false},
  572. {"Invalid BlockID", invalidBlockID.Hash, validBlockID.PartSetHeader, true},
  573. {"Invalid BlockID", validBlockID.Hash, invalidBlockID.PartSetHeader, true},
  574. }
  575. for _, tc := range testCases {
  576. tc := tc
  577. t.Run(tc.testName, func(t *testing.T) {
  578. blockID := BlockID{
  579. Hash: tc.blockIDHash,
  580. PartSetHeader: tc.blockIDPartSetHeader,
  581. }
  582. assert.Equal(t, tc.expectErr, blockID.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  583. })
  584. }
  585. }
  586. func TestBlockProtoBuf(t *testing.T) {
  587. ctx, cancel := context.WithCancel(context.Background())
  588. defer cancel()
  589. h := mrand.Int63()
  590. c1 := randCommit(ctx, t, time.Now())
  591. b1 := MakeBlock(h, []Tx{Tx([]byte{1})}, &Commit{Signatures: []CommitSig{}}, []Evidence{})
  592. b1.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  593. b2 := MakeBlock(h, []Tx{Tx([]byte{1})}, c1, []Evidence{})
  594. b2.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  595. evidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  596. evi, err := NewMockDuplicateVoteEvidence(ctx, h, evidenceTime, "block-test-chain")
  597. require.NoError(t, err)
  598. b2.Evidence = EvidenceData{Evidence: EvidenceList{evi}}
  599. b2.EvidenceHash = b2.Evidence.Hash()
  600. b3 := MakeBlock(h, []Tx{}, c1, []Evidence{})
  601. b3.ProposerAddress = tmrand.Bytes(crypto.AddressSize)
  602. testCases := []struct {
  603. msg string
  604. b1 *Block
  605. expPass bool
  606. expPass2 bool
  607. }{
  608. {"nil block", nil, false, false},
  609. {"b1", b1, true, true},
  610. {"b2", b2, true, true},
  611. {"b3", b3, true, true},
  612. }
  613. for _, tc := range testCases {
  614. pb, err := tc.b1.ToProto()
  615. if tc.expPass {
  616. require.NoError(t, err, tc.msg)
  617. } else {
  618. require.Error(t, err, tc.msg)
  619. }
  620. block, err := BlockFromProto(pb)
  621. if tc.expPass2 {
  622. require.NoError(t, err, tc.msg)
  623. require.EqualValues(t, tc.b1.Header, block.Header, tc.msg)
  624. require.EqualValues(t, tc.b1.Data, block.Data, tc.msg)
  625. require.EqualValues(t, tc.b1.Evidence.Evidence, block.Evidence.Evidence, tc.msg)
  626. require.EqualValues(t, *tc.b1.LastCommit, *block.LastCommit, tc.msg)
  627. } else {
  628. require.Error(t, err, tc.msg)
  629. }
  630. }
  631. }
  632. func TestDataProtoBuf(t *testing.T) {
  633. data := &Data{Txs: Txs{Tx([]byte{1}), Tx([]byte{2}), Tx([]byte{3})}}
  634. data2 := &Data{Txs: Txs{}}
  635. testCases := []struct {
  636. msg string
  637. data1 *Data
  638. expPass bool
  639. }{
  640. {"success", data, true},
  641. {"success data2", data2, true},
  642. }
  643. for _, tc := range testCases {
  644. protoData := tc.data1.ToProto()
  645. d, err := DataFromProto(&protoData)
  646. if tc.expPass {
  647. require.NoError(t, err, tc.msg)
  648. require.EqualValues(t, tc.data1, &d, tc.msg)
  649. } else {
  650. require.Error(t, err, tc.msg)
  651. }
  652. }
  653. }
  654. // TestEvidenceDataProtoBuf ensures parity in converting to and from proto.
  655. func TestEvidenceDataProtoBuf(t *testing.T) {
  656. ctx, cancel := context.WithCancel(context.Background())
  657. defer cancel()
  658. const chainID = "mychain"
  659. ev, err := NewMockDuplicateVoteEvidence(ctx, math.MaxInt64, time.Now(), chainID)
  660. require.NoError(t, err)
  661. data := &EvidenceData{Evidence: EvidenceList{ev}}
  662. _ = data.ByteSize()
  663. testCases := []struct {
  664. msg string
  665. data1 *EvidenceData
  666. expPass1 bool
  667. expPass2 bool
  668. }{
  669. {"success", data, true, true},
  670. {"empty evidenceData", &EvidenceData{Evidence: EvidenceList{}}, true, true},
  671. {"fail nil Data", nil, false, false},
  672. }
  673. for _, tc := range testCases {
  674. protoData, err := tc.data1.ToProto()
  675. if tc.expPass1 {
  676. require.NoError(t, err, tc.msg)
  677. } else {
  678. require.Error(t, err, tc.msg)
  679. }
  680. eviD := new(EvidenceData)
  681. err = eviD.FromProto(protoData)
  682. if tc.expPass2 {
  683. require.NoError(t, err, tc.msg)
  684. require.Equal(t, tc.data1, eviD, tc.msg)
  685. } else {
  686. require.Error(t, err, tc.msg)
  687. }
  688. }
  689. }
  690. // exposed for testing
  691. func MakeRandHeader() Header {
  692. chainID := "test"
  693. t := time.Now()
  694. height := mrand.Int63()
  695. randBytes := tmrand.Bytes(tmhash.Size)
  696. randAddress := tmrand.Bytes(crypto.AddressSize)
  697. h := Header{
  698. Version: version.Consensus{Block: version.BlockProtocol, App: 1},
  699. ChainID: chainID,
  700. Height: height,
  701. Time: t,
  702. LastBlockID: BlockID{},
  703. LastCommitHash: randBytes,
  704. DataHash: randBytes,
  705. ValidatorsHash: randBytes,
  706. NextValidatorsHash: randBytes,
  707. ConsensusHash: randBytes,
  708. AppHash: randBytes,
  709. LastResultsHash: randBytes,
  710. EvidenceHash: randBytes,
  711. ProposerAddress: randAddress,
  712. }
  713. return h
  714. }
  715. func TestHeaderProto(t *testing.T) {
  716. h1 := MakeRandHeader()
  717. tc := []struct {
  718. msg string
  719. h1 *Header
  720. expPass bool
  721. }{
  722. {"success", &h1, true},
  723. {"failure empty Header", &Header{}, false},
  724. }
  725. for _, tt := range tc {
  726. tt := tt
  727. t.Run(tt.msg, func(t *testing.T) {
  728. pb := tt.h1.ToProto()
  729. h, err := HeaderFromProto(pb)
  730. if tt.expPass {
  731. require.NoError(t, err, tt.msg)
  732. require.Equal(t, tt.h1, &h, tt.msg)
  733. } else {
  734. require.Error(t, err, tt.msg)
  735. }
  736. })
  737. }
  738. }
  739. func TestBlockIDProtoBuf(t *testing.T) {
  740. blockID := makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  741. testCases := []struct {
  742. msg string
  743. bid1 *BlockID
  744. expPass bool
  745. }{
  746. {"success", &blockID, true},
  747. {"success empty", &BlockID{}, true},
  748. {"failure BlockID nil", nil, false},
  749. }
  750. for _, tc := range testCases {
  751. protoBlockID := tc.bid1.ToProto()
  752. bi, err := BlockIDFromProto(&protoBlockID)
  753. if tc.expPass {
  754. require.NoError(t, err)
  755. require.Equal(t, tc.bid1, bi, tc.msg)
  756. } else {
  757. require.NotEqual(t, tc.bid1, bi, tc.msg)
  758. }
  759. }
  760. }
  761. func TestSignedHeaderProtoBuf(t *testing.T) {
  762. ctx, cancel := context.WithCancel(context.Background())
  763. defer cancel()
  764. commit := randCommit(ctx, t, time.Now())
  765. h := MakeRandHeader()
  766. sh := SignedHeader{Header: &h, Commit: commit}
  767. testCases := []struct {
  768. msg string
  769. sh1 *SignedHeader
  770. expPass bool
  771. }{
  772. {"empty SignedHeader 2", &SignedHeader{}, true},
  773. {"success", &sh, true},
  774. {"failure nil", nil, false},
  775. }
  776. for _, tc := range testCases {
  777. protoSignedHeader := tc.sh1.ToProto()
  778. sh, err := SignedHeaderFromProto(protoSignedHeader)
  779. if tc.expPass {
  780. require.NoError(t, err, tc.msg)
  781. require.Equal(t, tc.sh1, sh, tc.msg)
  782. } else {
  783. require.Error(t, err, tc.msg)
  784. }
  785. }
  786. }
  787. func TestBlockIDEquals(t *testing.T) {
  788. var (
  789. blockID = makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  790. blockIDDuplicate = makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  791. blockIDDifferent = makeBlockID([]byte("different_hash"), 2, []byte("part_set_hash"))
  792. blockIDEmpty = BlockID{}
  793. )
  794. assert.True(t, blockID.Equals(blockIDDuplicate))
  795. assert.False(t, blockID.Equals(blockIDDifferent))
  796. assert.False(t, blockID.Equals(blockIDEmpty))
  797. assert.True(t, blockIDEmpty.Equals(blockIDEmpty))
  798. assert.False(t, blockIDEmpty.Equals(blockIDDifferent))
  799. }
  800. func TestCommitSig_ValidateBasic(t *testing.T) {
  801. testCases := []struct {
  802. name string
  803. cs CommitSig
  804. expectErr bool
  805. errString string
  806. }{
  807. {
  808. "invalid ID flag",
  809. CommitSig{BlockIDFlag: BlockIDFlag(0xFF)},
  810. true, "unknown BlockIDFlag",
  811. },
  812. {
  813. "BlockIDFlagAbsent validator address present",
  814. CommitSig{BlockIDFlag: BlockIDFlagAbsent, ValidatorAddress: crypto.Address("testaddr")},
  815. true, "validator address is present",
  816. },
  817. {
  818. "BlockIDFlagAbsent timestamp present",
  819. CommitSig{BlockIDFlag: BlockIDFlagAbsent, Timestamp: time.Now().UTC()},
  820. true, "time is present",
  821. },
  822. {
  823. "BlockIDFlagAbsent signatures present",
  824. CommitSig{BlockIDFlag: BlockIDFlagAbsent, Signature: []byte{0xAA}},
  825. true, "signature is present",
  826. },
  827. {
  828. "BlockIDFlagAbsent valid BlockIDFlagAbsent",
  829. CommitSig{BlockIDFlag: BlockIDFlagAbsent},
  830. false, "",
  831. },
  832. {
  833. "non-BlockIDFlagAbsent invalid validator address",
  834. CommitSig{BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: make([]byte, 1)},
  835. true, "expected ValidatorAddress size",
  836. },
  837. {
  838. "non-BlockIDFlagAbsent invalid signature (zero)",
  839. CommitSig{
  840. BlockIDFlag: BlockIDFlagCommit,
  841. ValidatorAddress: make([]byte, crypto.AddressSize),
  842. Signature: make([]byte, 0),
  843. },
  844. true, "signature is missing",
  845. },
  846. {
  847. "non-BlockIDFlagAbsent invalid signature (too large)",
  848. CommitSig{
  849. BlockIDFlag: BlockIDFlagCommit,
  850. ValidatorAddress: make([]byte, crypto.AddressSize),
  851. Signature: make([]byte, MaxSignatureSize+1),
  852. },
  853. true, "signature is too big",
  854. },
  855. {
  856. "non-BlockIDFlagAbsent valid",
  857. CommitSig{
  858. BlockIDFlag: BlockIDFlagCommit,
  859. ValidatorAddress: make([]byte, crypto.AddressSize),
  860. Signature: make([]byte, MaxSignatureSize),
  861. },
  862. false, "",
  863. },
  864. }
  865. for _, tc := range testCases {
  866. tc := tc
  867. t.Run(tc.name, func(t *testing.T) {
  868. err := tc.cs.ValidateBasic()
  869. if tc.expectErr {
  870. require.Error(t, err)
  871. require.Contains(t, err.Error(), tc.errString)
  872. } else {
  873. require.NoError(t, err)
  874. }
  875. })
  876. }
  877. }
  878. func TestHeader_ValidateBasic(t *testing.T) {
  879. testCases := []struct {
  880. name string
  881. header Header
  882. expectErr bool
  883. errString string
  884. }{
  885. {
  886. "invalid version block",
  887. Header{Version: version.Consensus{Block: version.BlockProtocol + 1}},
  888. true, "block protocol is incorrect",
  889. },
  890. {
  891. "invalid chain ID length",
  892. Header{
  893. Version: version.Consensus{Block: version.BlockProtocol},
  894. ChainID: string(make([]byte, MaxChainIDLen+1)),
  895. },
  896. true, "chainID is too long",
  897. },
  898. {
  899. "invalid height (negative)",
  900. Header{
  901. Version: version.Consensus{Block: version.BlockProtocol},
  902. ChainID: string(make([]byte, MaxChainIDLen)),
  903. Height: -1,
  904. },
  905. true, "negative Height",
  906. },
  907. {
  908. "invalid height (zero)",
  909. Header{
  910. Version: version.Consensus{Block: version.BlockProtocol},
  911. ChainID: string(make([]byte, MaxChainIDLen)),
  912. Height: 0,
  913. },
  914. true, "zero Height",
  915. },
  916. {
  917. "invalid block ID hash",
  918. Header{
  919. Version: version.Consensus{Block: version.BlockProtocol},
  920. ChainID: string(make([]byte, MaxChainIDLen)),
  921. Height: 1,
  922. LastBlockID: BlockID{
  923. Hash: make([]byte, tmhash.Size+1),
  924. },
  925. },
  926. true, "wrong Hash",
  927. },
  928. {
  929. "invalid block ID parts header hash",
  930. Header{
  931. Version: version.Consensus{Block: version.BlockProtocol},
  932. ChainID: string(make([]byte, MaxChainIDLen)),
  933. Height: 1,
  934. LastBlockID: BlockID{
  935. Hash: make([]byte, tmhash.Size),
  936. PartSetHeader: PartSetHeader{
  937. Hash: make([]byte, tmhash.Size+1),
  938. },
  939. },
  940. },
  941. true, "wrong PartSetHeader",
  942. },
  943. {
  944. "invalid last commit hash",
  945. Header{
  946. Version: version.Consensus{Block: version.BlockProtocol},
  947. ChainID: string(make([]byte, MaxChainIDLen)),
  948. Height: 1,
  949. LastBlockID: BlockID{
  950. Hash: make([]byte, tmhash.Size),
  951. PartSetHeader: PartSetHeader{
  952. Hash: make([]byte, tmhash.Size),
  953. },
  954. },
  955. LastCommitHash: make([]byte, tmhash.Size+1),
  956. },
  957. true, "wrong LastCommitHash",
  958. },
  959. {
  960. "invalid data hash",
  961. Header{
  962. Version: version.Consensus{Block: version.BlockProtocol},
  963. ChainID: string(make([]byte, MaxChainIDLen)),
  964. Height: 1,
  965. LastBlockID: BlockID{
  966. Hash: make([]byte, tmhash.Size),
  967. PartSetHeader: PartSetHeader{
  968. Hash: make([]byte, tmhash.Size),
  969. },
  970. },
  971. LastCommitHash: make([]byte, tmhash.Size),
  972. DataHash: make([]byte, tmhash.Size+1),
  973. },
  974. true, "wrong DataHash",
  975. },
  976. {
  977. "invalid evidence hash",
  978. Header{
  979. Version: version.Consensus{Block: version.BlockProtocol},
  980. ChainID: string(make([]byte, MaxChainIDLen)),
  981. Height: 1,
  982. LastBlockID: BlockID{
  983. Hash: make([]byte, tmhash.Size),
  984. PartSetHeader: PartSetHeader{
  985. Hash: make([]byte, tmhash.Size),
  986. },
  987. },
  988. LastCommitHash: make([]byte, tmhash.Size),
  989. DataHash: make([]byte, tmhash.Size),
  990. EvidenceHash: make([]byte, tmhash.Size+1),
  991. },
  992. true, "wrong EvidenceHash",
  993. },
  994. {
  995. "invalid proposer address",
  996. Header{
  997. Version: version.Consensus{Block: version.BlockProtocol},
  998. ChainID: string(make([]byte, MaxChainIDLen)),
  999. Height: 1,
  1000. LastBlockID: BlockID{
  1001. Hash: make([]byte, tmhash.Size),
  1002. PartSetHeader: PartSetHeader{
  1003. Hash: make([]byte, tmhash.Size),
  1004. },
  1005. },
  1006. LastCommitHash: make([]byte, tmhash.Size),
  1007. DataHash: make([]byte, tmhash.Size),
  1008. EvidenceHash: make([]byte, tmhash.Size),
  1009. ProposerAddress: make([]byte, crypto.AddressSize+1),
  1010. },
  1011. true, "invalid ProposerAddress length",
  1012. },
  1013. {
  1014. "invalid validator hash",
  1015. Header{
  1016. Version: version.Consensus{Block: version.BlockProtocol},
  1017. ChainID: string(make([]byte, MaxChainIDLen)),
  1018. Height: 1,
  1019. LastBlockID: BlockID{
  1020. Hash: make([]byte, tmhash.Size),
  1021. PartSetHeader: PartSetHeader{
  1022. Hash: make([]byte, tmhash.Size),
  1023. },
  1024. },
  1025. LastCommitHash: make([]byte, tmhash.Size),
  1026. DataHash: make([]byte, tmhash.Size),
  1027. EvidenceHash: make([]byte, tmhash.Size),
  1028. ProposerAddress: make([]byte, crypto.AddressSize),
  1029. ValidatorsHash: make([]byte, tmhash.Size+1),
  1030. },
  1031. true, "wrong ValidatorsHash",
  1032. },
  1033. {
  1034. "invalid next validator hash",
  1035. Header{
  1036. Version: version.Consensus{Block: version.BlockProtocol},
  1037. ChainID: string(make([]byte, MaxChainIDLen)),
  1038. Height: 1,
  1039. LastBlockID: BlockID{
  1040. Hash: make([]byte, tmhash.Size),
  1041. PartSetHeader: PartSetHeader{
  1042. Hash: make([]byte, tmhash.Size),
  1043. },
  1044. },
  1045. LastCommitHash: make([]byte, tmhash.Size),
  1046. DataHash: make([]byte, tmhash.Size),
  1047. EvidenceHash: make([]byte, tmhash.Size),
  1048. ProposerAddress: make([]byte, crypto.AddressSize),
  1049. ValidatorsHash: make([]byte, tmhash.Size),
  1050. NextValidatorsHash: make([]byte, tmhash.Size+1),
  1051. },
  1052. true, "wrong NextValidatorsHash",
  1053. },
  1054. {
  1055. "invalid consensus hash",
  1056. Header{
  1057. Version: version.Consensus{Block: version.BlockProtocol},
  1058. ChainID: string(make([]byte, MaxChainIDLen)),
  1059. Height: 1,
  1060. LastBlockID: BlockID{
  1061. Hash: make([]byte, tmhash.Size),
  1062. PartSetHeader: PartSetHeader{
  1063. Hash: make([]byte, tmhash.Size),
  1064. },
  1065. },
  1066. LastCommitHash: make([]byte, tmhash.Size),
  1067. DataHash: make([]byte, tmhash.Size),
  1068. EvidenceHash: make([]byte, tmhash.Size),
  1069. ProposerAddress: make([]byte, crypto.AddressSize),
  1070. ValidatorsHash: make([]byte, tmhash.Size),
  1071. NextValidatorsHash: make([]byte, tmhash.Size),
  1072. ConsensusHash: make([]byte, tmhash.Size+1),
  1073. },
  1074. true, "wrong ConsensusHash",
  1075. },
  1076. {
  1077. "invalid last results hash",
  1078. Header{
  1079. Version: version.Consensus{Block: version.BlockProtocol},
  1080. ChainID: string(make([]byte, MaxChainIDLen)),
  1081. Height: 1,
  1082. LastBlockID: BlockID{
  1083. Hash: make([]byte, tmhash.Size),
  1084. PartSetHeader: PartSetHeader{
  1085. Hash: make([]byte, tmhash.Size),
  1086. },
  1087. },
  1088. LastCommitHash: make([]byte, tmhash.Size),
  1089. DataHash: make([]byte, tmhash.Size),
  1090. EvidenceHash: make([]byte, tmhash.Size),
  1091. ProposerAddress: make([]byte, crypto.AddressSize),
  1092. ValidatorsHash: make([]byte, tmhash.Size),
  1093. NextValidatorsHash: make([]byte, tmhash.Size),
  1094. ConsensusHash: make([]byte, tmhash.Size),
  1095. LastResultsHash: make([]byte, tmhash.Size+1),
  1096. },
  1097. true, "wrong LastResultsHash",
  1098. },
  1099. {
  1100. "valid header",
  1101. Header{
  1102. Version: version.Consensus{Block: version.BlockProtocol},
  1103. ChainID: string(make([]byte, MaxChainIDLen)),
  1104. Height: 1,
  1105. LastBlockID: BlockID{
  1106. Hash: make([]byte, tmhash.Size),
  1107. PartSetHeader: PartSetHeader{
  1108. Hash: make([]byte, tmhash.Size),
  1109. },
  1110. },
  1111. LastCommitHash: make([]byte, tmhash.Size),
  1112. DataHash: make([]byte, tmhash.Size),
  1113. EvidenceHash: make([]byte, tmhash.Size),
  1114. ProposerAddress: make([]byte, crypto.AddressSize),
  1115. ValidatorsHash: make([]byte, tmhash.Size),
  1116. NextValidatorsHash: make([]byte, tmhash.Size),
  1117. ConsensusHash: make([]byte, tmhash.Size),
  1118. LastResultsHash: make([]byte, tmhash.Size),
  1119. },
  1120. false, "",
  1121. },
  1122. }
  1123. for _, tc := range testCases {
  1124. tc := tc
  1125. t.Run(tc.name, func(t *testing.T) {
  1126. err := tc.header.ValidateBasic()
  1127. if tc.expectErr {
  1128. require.Error(t, err)
  1129. require.Contains(t, err.Error(), tc.errString)
  1130. } else {
  1131. require.NoError(t, err)
  1132. }
  1133. })
  1134. }
  1135. }
  1136. func TestCommit_ValidateBasic(t *testing.T) {
  1137. testCases := []struct {
  1138. name string
  1139. commit *Commit
  1140. expectErr bool
  1141. errString string
  1142. }{
  1143. {
  1144. "invalid height",
  1145. &Commit{Height: -1},
  1146. true, "negative Height",
  1147. },
  1148. {
  1149. "invalid round",
  1150. &Commit{Height: 1, Round: -1},
  1151. true, "negative Round",
  1152. },
  1153. {
  1154. "invalid block ID",
  1155. &Commit{
  1156. Height: 1,
  1157. Round: 1,
  1158. BlockID: BlockID{},
  1159. },
  1160. true, "commit cannot be for nil block",
  1161. },
  1162. {
  1163. "no signatures",
  1164. &Commit{
  1165. Height: 1,
  1166. Round: 1,
  1167. BlockID: BlockID{
  1168. Hash: make([]byte, tmhash.Size),
  1169. PartSetHeader: PartSetHeader{
  1170. Hash: make([]byte, tmhash.Size),
  1171. },
  1172. },
  1173. },
  1174. true, "no signatures in commit",
  1175. },
  1176. {
  1177. "invalid signature",
  1178. &Commit{
  1179. Height: 1,
  1180. Round: 1,
  1181. BlockID: BlockID{
  1182. Hash: make([]byte, tmhash.Size),
  1183. PartSetHeader: PartSetHeader{
  1184. Hash: make([]byte, tmhash.Size),
  1185. },
  1186. },
  1187. Signatures: []CommitSig{
  1188. {
  1189. BlockIDFlag: BlockIDFlagCommit,
  1190. ValidatorAddress: make([]byte, crypto.AddressSize),
  1191. Signature: make([]byte, MaxSignatureSize+1),
  1192. },
  1193. },
  1194. },
  1195. true, "wrong CommitSig",
  1196. },
  1197. {
  1198. "valid commit",
  1199. &Commit{
  1200. Height: 1,
  1201. Round: 1,
  1202. BlockID: BlockID{
  1203. Hash: make([]byte, tmhash.Size),
  1204. PartSetHeader: PartSetHeader{
  1205. Hash: make([]byte, tmhash.Size),
  1206. },
  1207. },
  1208. Signatures: []CommitSig{
  1209. {
  1210. BlockIDFlag: BlockIDFlagCommit,
  1211. ValidatorAddress: make([]byte, crypto.AddressSize),
  1212. Signature: make([]byte, MaxSignatureSize),
  1213. },
  1214. },
  1215. },
  1216. false, "",
  1217. },
  1218. }
  1219. for _, tc := range testCases {
  1220. tc := tc
  1221. t.Run(tc.name, func(t *testing.T) {
  1222. err := tc.commit.ValidateBasic()
  1223. if tc.expectErr {
  1224. require.Error(t, err)
  1225. require.Contains(t, err.Error(), tc.errString)
  1226. } else {
  1227. require.NoError(t, err)
  1228. }
  1229. })
  1230. }
  1231. }
  1232. func TestHeaderHashVector(t *testing.T) {
  1233. chainID := "test"
  1234. h := Header{
  1235. Version: version.Consensus{Block: 1, App: 1},
  1236. ChainID: chainID,
  1237. Height: 50,
  1238. Time: time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC),
  1239. LastBlockID: BlockID{},
  1240. LastCommitHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1241. DataHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1242. ValidatorsHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1243. NextValidatorsHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1244. ConsensusHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1245. AppHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1246. LastResultsHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1247. EvidenceHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1248. ProposerAddress: []byte("2915b7b15f979e48ebc61774bb1d86ba3136b7eb"),
  1249. }
  1250. testCases := []struct {
  1251. header Header
  1252. expBytes string
  1253. }{
  1254. {header: h, expBytes: "87b6117ac7f827d656f178a3d6d30b24b205db2b6a3a053bae8baf4618570bfc"},
  1255. }
  1256. for _, tc := range testCases {
  1257. hash := tc.header.Hash()
  1258. require.Equal(t, tc.expBytes, hex.EncodeToString(hash))
  1259. }
  1260. }