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.

1364 lines
38 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))
  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 = []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 = 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, block.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. // exposed for testing
  655. func MakeRandHeader() Header {
  656. chainID := "test"
  657. t := time.Now()
  658. height := mrand.Int63()
  659. randBytes := tmrand.Bytes(tmhash.Size)
  660. randAddress := tmrand.Bytes(crypto.AddressSize)
  661. h := Header{
  662. Version: version.Consensus{Block: version.BlockProtocol, App: 1},
  663. ChainID: chainID,
  664. Height: height,
  665. Time: t,
  666. LastBlockID: BlockID{},
  667. LastCommitHash: randBytes,
  668. DataHash: randBytes,
  669. ValidatorsHash: randBytes,
  670. NextValidatorsHash: randBytes,
  671. ConsensusHash: randBytes,
  672. AppHash: randBytes,
  673. LastResultsHash: randBytes,
  674. EvidenceHash: randBytes,
  675. ProposerAddress: randAddress,
  676. }
  677. return h
  678. }
  679. func TestHeaderProto(t *testing.T) {
  680. h1 := MakeRandHeader()
  681. tc := []struct {
  682. msg string
  683. h1 *Header
  684. expPass bool
  685. }{
  686. {"success", &h1, true},
  687. {"failure empty Header", &Header{}, false},
  688. }
  689. for _, tt := range tc {
  690. tt := tt
  691. t.Run(tt.msg, func(t *testing.T) {
  692. pb := tt.h1.ToProto()
  693. h, err := HeaderFromProto(pb)
  694. if tt.expPass {
  695. require.NoError(t, err, tt.msg)
  696. require.Equal(t, tt.h1, &h, tt.msg)
  697. } else {
  698. require.Error(t, err, tt.msg)
  699. }
  700. })
  701. }
  702. }
  703. func TestBlockIDProtoBuf(t *testing.T) {
  704. blockID := makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  705. testCases := []struct {
  706. msg string
  707. bid1 *BlockID
  708. expPass bool
  709. }{
  710. {"success", &blockID, true},
  711. {"success empty", &BlockID{}, true},
  712. {"failure BlockID nil", nil, false},
  713. }
  714. for _, tc := range testCases {
  715. protoBlockID := tc.bid1.ToProto()
  716. bi, err := BlockIDFromProto(&protoBlockID)
  717. if tc.expPass {
  718. require.NoError(t, err)
  719. require.Equal(t, tc.bid1, bi, tc.msg)
  720. } else {
  721. require.NotEqual(t, tc.bid1, bi, tc.msg)
  722. }
  723. }
  724. }
  725. func TestSignedHeaderProtoBuf(t *testing.T) {
  726. ctx, cancel := context.WithCancel(context.Background())
  727. defer cancel()
  728. commit := randCommit(ctx, t, time.Now())
  729. h := MakeRandHeader()
  730. sh := SignedHeader{Header: &h, Commit: commit}
  731. testCases := []struct {
  732. msg string
  733. sh1 *SignedHeader
  734. expPass bool
  735. }{
  736. {"empty SignedHeader 2", &SignedHeader{}, true},
  737. {"success", &sh, true},
  738. {"failure nil", nil, false},
  739. }
  740. for _, tc := range testCases {
  741. protoSignedHeader := tc.sh1.ToProto()
  742. sh, err := SignedHeaderFromProto(protoSignedHeader)
  743. if tc.expPass {
  744. require.NoError(t, err, tc.msg)
  745. require.Equal(t, tc.sh1, sh, tc.msg)
  746. } else {
  747. require.Error(t, err, tc.msg)
  748. }
  749. }
  750. }
  751. func TestBlockIDEquals(t *testing.T) {
  752. var (
  753. blockID = makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  754. blockIDDuplicate = makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
  755. blockIDDifferent = makeBlockID([]byte("different_hash"), 2, []byte("part_set_hash"))
  756. blockIDEmpty = BlockID{}
  757. )
  758. assert.True(t, blockID.Equals(blockIDDuplicate))
  759. assert.False(t, blockID.Equals(blockIDDifferent))
  760. assert.False(t, blockID.Equals(blockIDEmpty))
  761. assert.True(t, blockIDEmpty.Equals(blockIDEmpty))
  762. assert.False(t, blockIDEmpty.Equals(blockIDDifferent))
  763. }
  764. func TestCommitSig_ValidateBasic(t *testing.T) {
  765. testCases := []struct {
  766. name string
  767. cs CommitSig
  768. expectErr bool
  769. errString string
  770. }{
  771. {
  772. "invalid ID flag",
  773. CommitSig{BlockIDFlag: BlockIDFlag(0xFF)},
  774. true, "unknown BlockIDFlag",
  775. },
  776. {
  777. "BlockIDFlagAbsent validator address present",
  778. CommitSig{BlockIDFlag: BlockIDFlagAbsent, ValidatorAddress: crypto.Address("testaddr")},
  779. true, "validator address is present",
  780. },
  781. {
  782. "BlockIDFlagAbsent timestamp present",
  783. CommitSig{BlockIDFlag: BlockIDFlagAbsent, Timestamp: time.Now().UTC()},
  784. true, "time is present",
  785. },
  786. {
  787. "BlockIDFlagAbsent signatures present",
  788. CommitSig{BlockIDFlag: BlockIDFlagAbsent, Signature: []byte{0xAA}},
  789. true, "signature is present",
  790. },
  791. {
  792. "BlockIDFlagAbsent valid BlockIDFlagAbsent",
  793. CommitSig{BlockIDFlag: BlockIDFlagAbsent},
  794. false, "",
  795. },
  796. {
  797. "non-BlockIDFlagAbsent invalid validator address",
  798. CommitSig{BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: make([]byte, 1)},
  799. true, "expected ValidatorAddress size",
  800. },
  801. {
  802. "non-BlockIDFlagAbsent invalid signature (zero)",
  803. CommitSig{
  804. BlockIDFlag: BlockIDFlagCommit,
  805. ValidatorAddress: make([]byte, crypto.AddressSize),
  806. Signature: make([]byte, 0),
  807. },
  808. true, "signature is missing",
  809. },
  810. {
  811. "non-BlockIDFlagAbsent invalid signature (too large)",
  812. CommitSig{
  813. BlockIDFlag: BlockIDFlagCommit,
  814. ValidatorAddress: make([]byte, crypto.AddressSize),
  815. Signature: make([]byte, MaxSignatureSize+1),
  816. },
  817. true, "signature is too big",
  818. },
  819. {
  820. "non-BlockIDFlagAbsent valid",
  821. CommitSig{
  822. BlockIDFlag: BlockIDFlagCommit,
  823. ValidatorAddress: make([]byte, crypto.AddressSize),
  824. Signature: make([]byte, MaxSignatureSize),
  825. },
  826. false, "",
  827. },
  828. }
  829. for _, tc := range testCases {
  830. tc := tc
  831. t.Run(tc.name, func(t *testing.T) {
  832. err := tc.cs.ValidateBasic()
  833. if tc.expectErr {
  834. require.Error(t, err)
  835. require.Contains(t, err.Error(), tc.errString)
  836. } else {
  837. require.NoError(t, err)
  838. }
  839. })
  840. }
  841. }
  842. func TestHeader_ValidateBasic(t *testing.T) {
  843. testCases := []struct {
  844. name string
  845. header Header
  846. expectErr bool
  847. errString string
  848. }{
  849. {
  850. "invalid version block",
  851. Header{Version: version.Consensus{Block: version.BlockProtocol + 1}},
  852. true, "block protocol is incorrect",
  853. },
  854. {
  855. "invalid chain ID length",
  856. Header{
  857. Version: version.Consensus{Block: version.BlockProtocol},
  858. ChainID: string(make([]byte, MaxChainIDLen+1)),
  859. },
  860. true, "chainID is too long",
  861. },
  862. {
  863. "invalid height (negative)",
  864. Header{
  865. Version: version.Consensus{Block: version.BlockProtocol},
  866. ChainID: string(make([]byte, MaxChainIDLen)),
  867. Height: -1,
  868. },
  869. true, "negative Height",
  870. },
  871. {
  872. "invalid height (zero)",
  873. Header{
  874. Version: version.Consensus{Block: version.BlockProtocol},
  875. ChainID: string(make([]byte, MaxChainIDLen)),
  876. Height: 0,
  877. },
  878. true, "zero Height",
  879. },
  880. {
  881. "invalid block ID hash",
  882. Header{
  883. Version: version.Consensus{Block: version.BlockProtocol},
  884. ChainID: string(make([]byte, MaxChainIDLen)),
  885. Height: 1,
  886. LastBlockID: BlockID{
  887. Hash: make([]byte, tmhash.Size+1),
  888. },
  889. },
  890. true, "wrong Hash",
  891. },
  892. {
  893. "invalid block ID parts header hash",
  894. Header{
  895. Version: version.Consensus{Block: version.BlockProtocol},
  896. ChainID: string(make([]byte, MaxChainIDLen)),
  897. Height: 1,
  898. LastBlockID: BlockID{
  899. Hash: make([]byte, tmhash.Size),
  900. PartSetHeader: PartSetHeader{
  901. Hash: make([]byte, tmhash.Size+1),
  902. },
  903. },
  904. },
  905. true, "wrong PartSetHeader",
  906. },
  907. {
  908. "invalid last commit hash",
  909. Header{
  910. Version: version.Consensus{Block: version.BlockProtocol},
  911. ChainID: string(make([]byte, MaxChainIDLen)),
  912. Height: 1,
  913. LastBlockID: BlockID{
  914. Hash: make([]byte, tmhash.Size),
  915. PartSetHeader: PartSetHeader{
  916. Hash: make([]byte, tmhash.Size),
  917. },
  918. },
  919. LastCommitHash: make([]byte, tmhash.Size+1),
  920. },
  921. true, "wrong LastCommitHash",
  922. },
  923. {
  924. "invalid data hash",
  925. Header{
  926. Version: version.Consensus{Block: version.BlockProtocol},
  927. ChainID: string(make([]byte, MaxChainIDLen)),
  928. Height: 1,
  929. LastBlockID: BlockID{
  930. Hash: make([]byte, tmhash.Size),
  931. PartSetHeader: PartSetHeader{
  932. Hash: make([]byte, tmhash.Size),
  933. },
  934. },
  935. LastCommitHash: make([]byte, tmhash.Size),
  936. DataHash: make([]byte, tmhash.Size+1),
  937. },
  938. true, "wrong DataHash",
  939. },
  940. {
  941. "invalid evidence hash",
  942. Header{
  943. Version: version.Consensus{Block: version.BlockProtocol},
  944. ChainID: string(make([]byte, MaxChainIDLen)),
  945. Height: 1,
  946. LastBlockID: BlockID{
  947. Hash: make([]byte, tmhash.Size),
  948. PartSetHeader: PartSetHeader{
  949. Hash: make([]byte, tmhash.Size),
  950. },
  951. },
  952. LastCommitHash: make([]byte, tmhash.Size),
  953. DataHash: make([]byte, tmhash.Size),
  954. EvidenceHash: make([]byte, tmhash.Size+1),
  955. },
  956. true, "wrong EvidenceHash",
  957. },
  958. {
  959. "invalid proposer address",
  960. Header{
  961. Version: version.Consensus{Block: version.BlockProtocol},
  962. ChainID: string(make([]byte, MaxChainIDLen)),
  963. Height: 1,
  964. LastBlockID: BlockID{
  965. Hash: make([]byte, tmhash.Size),
  966. PartSetHeader: PartSetHeader{
  967. Hash: make([]byte, tmhash.Size),
  968. },
  969. },
  970. LastCommitHash: make([]byte, tmhash.Size),
  971. DataHash: make([]byte, tmhash.Size),
  972. EvidenceHash: make([]byte, tmhash.Size),
  973. ProposerAddress: make([]byte, crypto.AddressSize+1),
  974. },
  975. true, "invalid ProposerAddress length",
  976. },
  977. {
  978. "invalid validator hash",
  979. Header{
  980. Version: version.Consensus{Block: version.BlockProtocol},
  981. ChainID: string(make([]byte, MaxChainIDLen)),
  982. Height: 1,
  983. LastBlockID: BlockID{
  984. Hash: make([]byte, tmhash.Size),
  985. PartSetHeader: PartSetHeader{
  986. Hash: make([]byte, tmhash.Size),
  987. },
  988. },
  989. LastCommitHash: make([]byte, tmhash.Size),
  990. DataHash: make([]byte, tmhash.Size),
  991. EvidenceHash: make([]byte, tmhash.Size),
  992. ProposerAddress: make([]byte, crypto.AddressSize),
  993. ValidatorsHash: make([]byte, tmhash.Size+1),
  994. },
  995. true, "wrong ValidatorsHash",
  996. },
  997. {
  998. "invalid next validator hash",
  999. Header{
  1000. Version: version.Consensus{Block: version.BlockProtocol},
  1001. ChainID: string(make([]byte, MaxChainIDLen)),
  1002. Height: 1,
  1003. LastBlockID: BlockID{
  1004. Hash: make([]byte, tmhash.Size),
  1005. PartSetHeader: PartSetHeader{
  1006. Hash: make([]byte, tmhash.Size),
  1007. },
  1008. },
  1009. LastCommitHash: make([]byte, tmhash.Size),
  1010. DataHash: make([]byte, tmhash.Size),
  1011. EvidenceHash: make([]byte, tmhash.Size),
  1012. ProposerAddress: make([]byte, crypto.AddressSize),
  1013. ValidatorsHash: make([]byte, tmhash.Size),
  1014. NextValidatorsHash: make([]byte, tmhash.Size+1),
  1015. },
  1016. true, "wrong NextValidatorsHash",
  1017. },
  1018. {
  1019. "invalid consensus hash",
  1020. Header{
  1021. Version: version.Consensus{Block: version.BlockProtocol},
  1022. ChainID: string(make([]byte, MaxChainIDLen)),
  1023. Height: 1,
  1024. LastBlockID: BlockID{
  1025. Hash: make([]byte, tmhash.Size),
  1026. PartSetHeader: PartSetHeader{
  1027. Hash: make([]byte, tmhash.Size),
  1028. },
  1029. },
  1030. LastCommitHash: make([]byte, tmhash.Size),
  1031. DataHash: make([]byte, tmhash.Size),
  1032. EvidenceHash: make([]byte, tmhash.Size),
  1033. ProposerAddress: make([]byte, crypto.AddressSize),
  1034. ValidatorsHash: make([]byte, tmhash.Size),
  1035. NextValidatorsHash: make([]byte, tmhash.Size),
  1036. ConsensusHash: make([]byte, tmhash.Size+1),
  1037. },
  1038. true, "wrong ConsensusHash",
  1039. },
  1040. {
  1041. "invalid last results hash",
  1042. Header{
  1043. Version: version.Consensus{Block: version.BlockProtocol},
  1044. ChainID: string(make([]byte, MaxChainIDLen)),
  1045. Height: 1,
  1046. LastBlockID: BlockID{
  1047. Hash: make([]byte, tmhash.Size),
  1048. PartSetHeader: PartSetHeader{
  1049. Hash: make([]byte, tmhash.Size),
  1050. },
  1051. },
  1052. LastCommitHash: make([]byte, tmhash.Size),
  1053. DataHash: make([]byte, tmhash.Size),
  1054. EvidenceHash: make([]byte, tmhash.Size),
  1055. ProposerAddress: make([]byte, crypto.AddressSize),
  1056. ValidatorsHash: make([]byte, tmhash.Size),
  1057. NextValidatorsHash: make([]byte, tmhash.Size),
  1058. ConsensusHash: make([]byte, tmhash.Size),
  1059. LastResultsHash: make([]byte, tmhash.Size+1),
  1060. },
  1061. true, "wrong LastResultsHash",
  1062. },
  1063. {
  1064. "valid header",
  1065. Header{
  1066. Version: version.Consensus{Block: version.BlockProtocol},
  1067. ChainID: string(make([]byte, MaxChainIDLen)),
  1068. Height: 1,
  1069. LastBlockID: BlockID{
  1070. Hash: make([]byte, tmhash.Size),
  1071. PartSetHeader: PartSetHeader{
  1072. Hash: make([]byte, tmhash.Size),
  1073. },
  1074. },
  1075. LastCommitHash: make([]byte, tmhash.Size),
  1076. DataHash: make([]byte, tmhash.Size),
  1077. EvidenceHash: make([]byte, tmhash.Size),
  1078. ProposerAddress: make([]byte, crypto.AddressSize),
  1079. ValidatorsHash: make([]byte, tmhash.Size),
  1080. NextValidatorsHash: make([]byte, tmhash.Size),
  1081. ConsensusHash: make([]byte, tmhash.Size),
  1082. LastResultsHash: make([]byte, tmhash.Size),
  1083. },
  1084. false, "",
  1085. },
  1086. }
  1087. for _, tc := range testCases {
  1088. tc := tc
  1089. t.Run(tc.name, func(t *testing.T) {
  1090. err := tc.header.ValidateBasic()
  1091. if tc.expectErr {
  1092. require.Error(t, err)
  1093. require.Contains(t, err.Error(), tc.errString)
  1094. } else {
  1095. require.NoError(t, err)
  1096. }
  1097. })
  1098. }
  1099. }
  1100. func TestCommit_ValidateBasic(t *testing.T) {
  1101. testCases := []struct {
  1102. name string
  1103. commit *Commit
  1104. expectErr bool
  1105. errString string
  1106. }{
  1107. {
  1108. "invalid height",
  1109. &Commit{Height: -1},
  1110. true, "negative Height",
  1111. },
  1112. {
  1113. "invalid round",
  1114. &Commit{Height: 1, Round: -1},
  1115. true, "negative Round",
  1116. },
  1117. {
  1118. "invalid block ID",
  1119. &Commit{
  1120. Height: 1,
  1121. Round: 1,
  1122. BlockID: BlockID{},
  1123. },
  1124. true, "commit cannot be for nil block",
  1125. },
  1126. {
  1127. "no signatures",
  1128. &Commit{
  1129. Height: 1,
  1130. Round: 1,
  1131. BlockID: BlockID{
  1132. Hash: make([]byte, tmhash.Size),
  1133. PartSetHeader: PartSetHeader{
  1134. Hash: make([]byte, tmhash.Size),
  1135. },
  1136. },
  1137. },
  1138. true, "no signatures in commit",
  1139. },
  1140. {
  1141. "invalid signature",
  1142. &Commit{
  1143. Height: 1,
  1144. Round: 1,
  1145. BlockID: BlockID{
  1146. Hash: make([]byte, tmhash.Size),
  1147. PartSetHeader: PartSetHeader{
  1148. Hash: make([]byte, tmhash.Size),
  1149. },
  1150. },
  1151. Signatures: []CommitSig{
  1152. {
  1153. BlockIDFlag: BlockIDFlagCommit,
  1154. ValidatorAddress: make([]byte, crypto.AddressSize),
  1155. Signature: make([]byte, MaxSignatureSize+1),
  1156. },
  1157. },
  1158. },
  1159. true, "wrong CommitSig",
  1160. },
  1161. {
  1162. "valid commit",
  1163. &Commit{
  1164. Height: 1,
  1165. Round: 1,
  1166. BlockID: BlockID{
  1167. Hash: make([]byte, tmhash.Size),
  1168. PartSetHeader: PartSetHeader{
  1169. Hash: make([]byte, tmhash.Size),
  1170. },
  1171. },
  1172. Signatures: []CommitSig{
  1173. {
  1174. BlockIDFlag: BlockIDFlagCommit,
  1175. ValidatorAddress: make([]byte, crypto.AddressSize),
  1176. Signature: make([]byte, MaxSignatureSize),
  1177. },
  1178. },
  1179. },
  1180. false, "",
  1181. },
  1182. }
  1183. for _, tc := range testCases {
  1184. tc := tc
  1185. t.Run(tc.name, func(t *testing.T) {
  1186. err := tc.commit.ValidateBasic()
  1187. if tc.expectErr {
  1188. require.Error(t, err)
  1189. require.Contains(t, err.Error(), tc.errString)
  1190. } else {
  1191. require.NoError(t, err)
  1192. }
  1193. })
  1194. }
  1195. }
  1196. func TestHeaderHashVector(t *testing.T) {
  1197. chainID := "test"
  1198. h := Header{
  1199. Version: version.Consensus{Block: 1, App: 1},
  1200. ChainID: chainID,
  1201. Height: 50,
  1202. Time: time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC),
  1203. LastBlockID: BlockID{},
  1204. LastCommitHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1205. DataHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1206. ValidatorsHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1207. NextValidatorsHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1208. ConsensusHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1209. AppHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1210. LastResultsHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1211. EvidenceHash: []byte("f2564c78071e26643ae9b3e2a19fa0dc10d4d9e873aa0be808660123f11a1e78"),
  1212. ProposerAddress: []byte("2915b7b15f979e48ebc61774bb1d86ba3136b7eb"),
  1213. }
  1214. testCases := []struct {
  1215. header Header
  1216. expBytes string
  1217. }{
  1218. {header: h, expBytes: "87b6117ac7f827d656f178a3d6d30b24b205db2b6a3a053bae8baf4618570bfc"},
  1219. }
  1220. for _, tc := range testCases {
  1221. hash := tc.header.Hash()
  1222. require.Equal(t, tc.expBytes, hex.EncodeToString(hash))
  1223. }
  1224. }