diff --git a/blockchain/common_test.go b/blockchain/common_test.go index 7e2c1438..79a70822 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -482,6 +482,49 @@ func findDeploymentChoice(deployment *chaincfg.ConsensusDeployment, choiceID str return nil, fmt.Errorf("unable to find vote choice for id %q", choiceID) } +// findDeploymentAllYesChoices returns the deployment version and the OR'ed sum +// of the 'yes' choices for all the passed agendas. +// +// Note that all agendas must be in the same deployment version or this +// function errors. +func findDeploymentAllYesChoices(params *chaincfg.Params, voteIDs []string) (uint32, uint16, error) { + var yesBits uint16 + var deploymentVer uint32 + var foundIDs int + for version, deployments := range params.Deployments { + for _, deployment := range deployments { + for _, wantID := range voteIDs { + if deployment.Vote.Id == wantID { + yesChoice, err := findDeploymentChoice(&deployment, "yes") + if err != nil { + return 0, 0, err + } + deploymentVer = version + foundIDs++ + yesBits |= yesChoice.Bits + } + } + } + + if foundIDs == 0 { + continue + } + + // Agendas can only be voted simultaneously if they belong to + // the same deployment version, so return an error if we found + // some, but not all vote IDs in a specific version. + if foundIDs != len(voteIDs) { + return 0, 0, fmt.Errorf("not all voteIDs were found " + + "in the same deployment version") + } + + return deploymentVer, yesBits, nil + } + + return 0, 0, fmt.Errorf("unable to find deployment for any of the " + + "provided vote IDs") +} + // removeDeployment modifies the passed parameters to remove all deployments for // the provided vote ID. An error is returned when not found. func removeDeployment(params *chaincfg.Params, voteID string) error { @@ -1281,27 +1324,27 @@ func (g *chaingenHarness) AdvanceToStakeValidationHeight() { g.generateToStakeValidationHeight(accept) } -// AdvanceFromSVHToActiveAgenda generates and accepts enough blocks with the -// appropriate vote bits set to reach one block prior to the specified agenda +// AdvanceFromSVHToActiveAgendas generates and accepts enough blocks with the +// appropriate vote bits set to reach one block prior to the specified agendas // becoming active. // // The function will fail with a fatal test error if it is called when the -// harness is not at stake validation height. +// harness is not at stake validation height or if the agendas are not all from +// the same deployment. // // WARNING: This function currently assumes the chain parameters were created // via the quickVoteActivationParams. It should be updated in the future to // work with arbitrary params. -func (g *chaingenHarness) AdvanceFromSVHToActiveAgenda(voteID string) { +func (g *chaingenHarness) AdvanceFromSVHToActiveAgendas(voteIDs ...string) { g.t.Helper() - // Find the correct deployment for the provided ID along with the yes - // vote choice within it. - params := g.Params() - deploymentVer, deployment, err := findDeployment(params, voteID) - if err != nil { - g.t.Fatal(err) + if len(voteIDs) < 1 { + g.t.Fatal("no vote IDs specified") } - yesChoice, err := findDeploymentChoice(deployment, "yes") + + // Sum all yes bits from all the agendas. + params := g.Params() + deploymentVer, yesBits, err := findDeploymentAllYesChoices(params, voteIDs) if err != nil { g.t.Fatal(err) } @@ -1310,6 +1353,11 @@ func (g *chaingenHarness) AdvanceFromSVHToActiveAgenda(voteID string) { stakeValidationHeight := params.StakeValidationHeight stakeVerInterval := params.StakeVersionInterval ruleChangeInterval := int64(params.RuleChangeActivationInterval) + testThresholdState := func(state ThresholdState) { + for _, voteID := range voteIDs { + g.TestThresholdState(voteID, state) + } + } // Only allow this to be called on a harness at SVH. if g.Tip().Header.Height != uint32(stakeValidationHeight) { @@ -1342,7 +1390,7 @@ func (g *chaingenHarness) AdvanceFromSVHToActiveAgenda(voteID string) { g.SaveTipCoinbaseOuts() g.AcceptTipBlock() } - g.TestThresholdState(voteID, ThresholdStarted) + testThresholdState(ThresholdStarted) // --------------------------------------------------------------------- // Generate enough blocks to reach the next rule change interval with @@ -1363,14 +1411,14 @@ func (g *chaingenHarness) AdvanceFromSVHToActiveAgenda(voteID string) { g.NextBlock(blockName, nil, outs[1:], chaingen.ReplaceBlockVersion(int32(deploymentVer)), chaingen.ReplaceStakeVersion(deploymentVer), - chaingen.ReplaceVotes(vbPrevBlockValid|yesChoice.Bits, deploymentVer)) + chaingen.ReplaceVotes(vbPrevBlockValid|yesBits, deploymentVer)) g.SaveTipCoinbaseOuts() g.AcceptTipBlock() } g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*2 - 1)) g.AssertBlockVersion(int32(deploymentVer)) g.AssertStakeVersion(deploymentVer) - g.TestThresholdState(voteID, ThresholdLockedIn) + testThresholdState(ThresholdLockedIn) // --------------------------------------------------------------------- // Generate enough blocks to reach the next rule change interval with @@ -1398,5 +1446,5 @@ func (g *chaingenHarness) AdvanceFromSVHToActiveAgenda(voteID string) { g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*3 - 1)) g.AssertBlockVersion(int32(deploymentVer)) g.AssertStakeVersion(deploymentVer) - g.TestThresholdState(voteID, ThresholdActive) + testThresholdState(ThresholdActive) } diff --git a/blockchain/treasury_test.go b/blockchain/treasury_test.go index a6553f80..2e02dddd 100644 --- a/blockchain/treasury_test.go +++ b/blockchain/treasury_test.go @@ -503,7 +503,7 @@ func TestTSpendVoteCount(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -919,7 +919,7 @@ func TestTSpendEmptyTreasury(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -1096,7 +1096,7 @@ func TestTSpendExpendituresPolicy(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -1595,7 +1595,7 @@ func TestExpendituresReorg(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -1833,7 +1833,7 @@ func TestSpendableTreasuryTxs(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -2131,7 +2131,7 @@ func TestTSpendDupVote(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -2278,7 +2278,7 @@ func TestTSpendTooManyTSpend(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -2392,7 +2392,7 @@ func TestTSpendWindow(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -2515,7 +2515,7 @@ func TestTSpendSignature(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -2733,7 +2733,7 @@ func TestTSpendSignatureInvalid(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -2881,7 +2881,7 @@ func TestTSpendExists(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -3146,7 +3146,7 @@ func TestTreasuryBalance(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -3445,7 +3445,7 @@ func TestTAddCorners(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -3700,7 +3700,7 @@ func TestTreasuryBaseCorners(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -3838,7 +3838,7 @@ func TestTSpendCorners(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -4178,7 +4178,7 @@ func TestTreasuryInRegularTree(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash @@ -4742,7 +4742,7 @@ func TestTSpendTooManyTAdds(t *testing.T) { // --------------------------------------------------------------------- g.AdvanceToStakeValidationHeight() - g.AdvanceFromSVHToActiveAgenda(tVoteID) + g.AdvanceFromSVHToActiveAgendas(tVoteID) // Ensure treasury agenda is active. tipHash := &g.chain.BestSnapshot().Hash