What we want: P0 miss to lock B as Proposal Block is missing, but set valid block to B after receiving delayed Block Proposal.
(t *testing.T)
| 1269 | // P0 miss to lock B as Proposal Block is missing, but set valid block to B after |
| 1270 | // receiving delayed Block Proposal. |
| 1271 | func TestSetValidBlockOnDelayedProposal(t *testing.T) { |
| 1272 | cs1, vss := randState(4) |
| 1273 | vs2, vs3, vs4 := vss[1], vss[2], vss[3] |
| 1274 | height, round := cs1.Height, cs1.Round |
| 1275 | |
| 1276 | partSize := types.BlockPartSizeBytes |
| 1277 | |
| 1278 | timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) |
| 1279 | timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) |
| 1280 | newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) |
| 1281 | validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) |
| 1282 | pv1, err := cs1.privValidator.GetPubKey() |
| 1283 | require.NoError(t, err) |
| 1284 | addr := pv1.Address() |
| 1285 | voteCh := subscribeToVoter(cs1, addr) |
| 1286 | proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) |
| 1287 | |
| 1288 | round++ // move to round in which P0 is not proposer |
| 1289 | incrementRound(vs2, vs3, vs4) |
| 1290 | |
| 1291 | startTestRound(cs1, cs1.Height, round) |
| 1292 | ensureNewRound(newRoundCh, height, round) |
| 1293 | |
| 1294 | ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) |
| 1295 | |
| 1296 | ensurePrevote(voteCh, height, round) |
| 1297 | validatePrevote(t, cs1, round, vss[0], nil) |
| 1298 | |
| 1299 | prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1) |
| 1300 | propBlockHash := propBlock.Hash() |
| 1301 | propBlockParts := propBlock.MakePartSet(partSize) |
| 1302 | |
| 1303 | // vs2, vs3 and vs4 send prevote for propBlock |
| 1304 | signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4) |
| 1305 | ensureNewValidBlock(validBlockCh, height, round) |
| 1306 | |
| 1307 | ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) |
| 1308 | |
| 1309 | ensurePrecommit(voteCh, height, round) |
| 1310 | validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) |
| 1311 | |
| 1312 | if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { |
| 1313 | t.Fatal(err) |
| 1314 | } |
| 1315 | |
| 1316 | ensureNewProposal(proposalCh, height, round) |
| 1317 | rs := cs1.GetRoundState() |
| 1318 | |
| 1319 | assert.True(t, bytes.Equal(rs.ValidBlock.Hash(), propBlockHash)) |
| 1320 | assert.True(t, rs.ValidBlockParts.Header().Equals(propBlockParts.Header())) |
| 1321 | assert.True(t, rs.ValidRound == round) |
| 1322 | } |
| 1323 | |
| 1324 | // 4 vals, 3 Nil Precommits at P0 |
| 1325 | // What we want: |
nothing calls this directly
no test coverage detected