mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 19:06:51 +00:00
blockchain: Use harness in threshold state tests.
This refactors the threshold state tests in blockchain to use the recently introduced chaingen harness. Since these tests also require non-default choices, a new function named TestThresholdStateChoice is also introduced on the chaingen harness which allows both the state and the choice to be checked.
This commit is contained in:
parent
46e2852c2c
commit
fb59230010
@ -461,6 +461,40 @@ func (g *chaingenHarness) TestThresholdState(id string, state ThresholdState) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestThresholdStateChoice queries the threshold state from the current tip
|
||||
// block associated with the harness generator and expects the returned state
|
||||
// and choice to match the provided value.
|
||||
func (g *chaingenHarness) TestThresholdStateChoice(id string, state ThresholdState, choice uint32) {
|
||||
g.t.Helper()
|
||||
|
||||
tipHash := g.Tip().BlockHash()
|
||||
tipHeight := g.Tip().Header.Height
|
||||
deploymentVer, err := g.lookupDeploymentVersion(id)
|
||||
if err != nil {
|
||||
g.t.Fatalf("block %q (hash %s, height %d) unexpected error when "+
|
||||
"retrieving threshold state: %v", g.TipName(), tipHash, tipHeight,
|
||||
err)
|
||||
}
|
||||
|
||||
s, err := g.chain.NextThresholdState(&tipHash, deploymentVer, id)
|
||||
if err != nil {
|
||||
g.t.Fatalf("block %q (hash %s, height %d) unexpected error when "+
|
||||
"retrieving threshold state: %v", g.TipName(), tipHash, tipHeight,
|
||||
err)
|
||||
}
|
||||
|
||||
if s.State != state {
|
||||
g.t.Fatalf("block %q (hash %s, height %d) unexpected threshold "+
|
||||
"state for %s -- got %v, want %v", g.TipName(), tipHash, tipHeight,
|
||||
id, s.State, state)
|
||||
}
|
||||
if s.Choice != choice {
|
||||
g.t.Fatalf("block %q (hash %s, height %d) unexpected choice for %s -- "+
|
||||
"got %v, want %v", g.TipName(), tipHash, tipHeight, id, s.Choice,
|
||||
choice)
|
||||
}
|
||||
}
|
||||
|
||||
// ForceTipReorg forces the chain instance associated with the generator to
|
||||
// reorganize the current tip of the main chain from the given block to the
|
||||
// given block. An error will result if the provided from block is not actually
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017-2018 The Decred developers
|
||||
// Copyright (c) 2017-2019 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/decred/dcrd/blockchain/chaingen"
|
||||
"github.com/decred/dcrd/chaincfg"
|
||||
"github.com/decred/dcrd/dcrutil"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -139,78 +138,10 @@ func TestThresholdState(t *testing.T) {
|
||||
ExpireTime: math.MaxUint64,
|
||||
})
|
||||
|
||||
// Create a test generator instance initialized with the genesis block
|
||||
// as the tip.
|
||||
g, err := chaingen.MakeGenerator(params)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create generator: %v", err)
|
||||
}
|
||||
|
||||
// Create a new database and chain instance to run tests against.
|
||||
chain, teardownFunc, err := chainSetup("thresholdstatetest", params)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to setup chain instance: %v", err)
|
||||
}
|
||||
// Create a test harness initialized with the genesis block as the tip.
|
||||
g, teardownFunc := newChaingenHarness(t, params, "thresholdstatetest")
|
||||
defer teardownFunc()
|
||||
|
||||
// accepted processes the current tip block associated with the
|
||||
// generator and expects it to be accepted to the main chain.
|
||||
accepted := func() {
|
||||
msgBlock := g.Tip()
|
||||
blockHeight := msgBlock.Header.Height
|
||||
block := dcrutil.NewBlock(msgBlock)
|
||||
t.Logf("Testing block %s (hash %s, height %d)",
|
||||
g.TipName(), block.Hash(), blockHeight)
|
||||
|
||||
forkLen, isOrphan, err := chain.ProcessBlock(block, BFNone)
|
||||
if err != nil {
|
||||
t.Fatalf("block %q (hash %s, height %d) should "+
|
||||
"have been accepted: %v", g.TipName(),
|
||||
block.Hash(), blockHeight, err)
|
||||
}
|
||||
|
||||
// Ensure the main chain and orphan flags match the values
|
||||
// specified in the test.
|
||||
isMainChain := !isOrphan && forkLen == 0
|
||||
if !isMainChain {
|
||||
t.Fatalf("block %q (hash %s, height %d) unexpected main "+
|
||||
"chain flag -- got %v, want true", g.TipName(),
|
||||
block.Hash(), blockHeight, isMainChain)
|
||||
}
|
||||
if isOrphan {
|
||||
t.Fatalf("block %q (hash %s, height %d) unexpected "+
|
||||
"orphan flag -- got %v, want false", g.TipName(),
|
||||
block.Hash(), blockHeight, isOrphan)
|
||||
}
|
||||
}
|
||||
|
||||
// testThresholdState queries the threshold state from the current
|
||||
// tip block associated with the generator and expects the returned
|
||||
// state and choice to match the provided values.
|
||||
testThresholdState := func(id string, state ThresholdState, choice uint32) {
|
||||
tipHash := g.Tip().BlockHash()
|
||||
s, err := chain.NextThresholdState(&tipHash, posVersion, id)
|
||||
if err != nil {
|
||||
t.Fatalf("block %q (hash %s, height %d) unexpected "+
|
||||
"error when retrieving threshold state: %v",
|
||||
g.TipName(), tipHash, g.Tip().Header.Height,
|
||||
err)
|
||||
}
|
||||
|
||||
if s.State != state {
|
||||
t.Fatalf("block %q (hash %s, height %d) unexpected "+
|
||||
"threshold state for %s -- got %v, want %v",
|
||||
g.TipName(), tipHash, g.Tip().Header.Height,
|
||||
id, s.State, state)
|
||||
}
|
||||
if s.Choice != choice {
|
||||
t.Fatalf("block %q (hash %s, height %d) unexpected "+
|
||||
"choice for %s -- got %v, want %v",
|
||||
g.TipName(), tipHash, g.Tip().Header.Height,
|
||||
id, s.Choice, choice)
|
||||
}
|
||||
}
|
||||
|
||||
// Shorter versions of useful params for convenience.
|
||||
ticketsPerBlock := int64(params.TicketsPerBlock)
|
||||
coinbaseMaturity := params.CoinbaseMaturity
|
||||
@ -224,33 +155,37 @@ func TestThresholdState(t *testing.T) {
|
||||
ruleChangeDiv := int64(params.RuleChangeActivationDivisor)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Premine.
|
||||
// Block One.
|
||||
//
|
||||
// NOTE: The advance funcs on the harness are intentionally not used in
|
||||
// these tests since they need to manually test the threshold state at
|
||||
// all key heights.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// Add the required premine block.
|
||||
// Add the required initial block.
|
||||
//
|
||||
// genesis -> bp
|
||||
g.CreatePremineBlock("bp", 0)
|
||||
// genesis -> bfb
|
||||
g.CreatePremineBlock("bfb", 0)
|
||||
g.AssertTipHeight(1)
|
||||
accepted()
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.Accepted()
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to have mature coinbase outputs to work with.
|
||||
//
|
||||
// genesis -> bp -> bm0 -> bm1 -> ... -> bm#
|
||||
// genesis -> bfb -> bm0 -> bm1 -> ... -> bm#
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
for i := uint16(0); i < coinbaseMaturity; i++ {
|
||||
blockName := fmt.Sprintf("bm%d", i)
|
||||
g.NextBlock(blockName, nil, nil)
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(coinbaseMaturity) + 1)
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the stake enabled height while
|
||||
@ -268,11 +203,11 @@ func TestThresholdState(t *testing.T) {
|
||||
blockName := fmt.Sprintf("bse%d", i)
|
||||
g.NextBlock(blockName, nil, ticketOuts)
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeEnabledHeight))
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the stake validation height while
|
||||
@ -303,11 +238,11 @@ func TestThresholdState(t *testing.T) {
|
||||
g.NextBlock(blockName, nil, ticketOuts,
|
||||
chaingen.ReplaceBlockVersion(3))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight))
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach one block before the next stake
|
||||
@ -330,13 +265,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceStakeVersion(0),
|
||||
chaingen.ReplaceVoteVersions(3))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + stakeVerInterval - 1))
|
||||
g.AssertBlockVersion(3)
|
||||
g.AssertStakeVersion(0)
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach one block before the next rule change
|
||||
@ -358,13 +293,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceStakeVersion(3),
|
||||
chaingen.ReplaceVoteVersions(3))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval - 2))
|
||||
g.AssertBlockVersion(3)
|
||||
g.AssertStakeVersion(3)
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach one block before the next stake
|
||||
@ -389,13 +324,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceStakeVersion(3),
|
||||
chaingen.ReplaceVoteVersions(4))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + stakeVerInterval*4 - 1))
|
||||
g.AssertBlockVersion(3)
|
||||
g.AssertStakeVersion(3)
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the next rule change interval with
|
||||
@ -422,13 +357,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceStakeVersion(4),
|
||||
chaingen.ReplaceVoteVersions(4))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*2 - 1))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to achieve proof-of-work block version lockin
|
||||
@ -455,14 +390,14 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceVotes(vbPrevBlockValid|vbTestDummy1Yes|
|
||||
vbTestDummy2No, 4))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*2 -
|
||||
1 + powNumToCheck))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdDefined, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdDefined, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the next rule change interval with
|
||||
@ -488,13 +423,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceVotes(vbPrevBlockValid|vbTestDummy1Yes|
|
||||
vbTestDummy2No, 4))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*3 - 1))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the next rule change interval with
|
||||
@ -518,13 +453,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceVotes(vbPrevBlockValid|vbTestDummy1Yes|
|
||||
vbTestDummy2No, 3))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*4 - 1))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the next rule change interval with
|
||||
@ -554,13 +489,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceVotes(voteBits, 4))
|
||||
totalVotes += ticketsPerBlock
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*5 - 1))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the next rule change interval with
|
||||
@ -598,13 +533,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceVotes(voteBits, 4))
|
||||
totalVotes += ticketsPerBlock
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*6 - 1))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
testThresholdState(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdStarted, invalidChoice)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdStarted, invalidChoice)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the next rule change interval with
|
||||
@ -629,13 +564,13 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceVotes(vbPrevBlockValid|vbTestDummy1Yes|
|
||||
vbTestDummy2No, 4))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*7 - 1))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdLockedIn, testDummy1YesIndex)
|
||||
testThresholdState(testDummy2ID, ThresholdFailed, testDummy2NoIndex)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdLockedIn, testDummy1YesIndex)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdFailed, testDummy2NoIndex)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Generate enough blocks to reach the next rule change interval with
|
||||
@ -662,11 +597,11 @@ func TestThresholdState(t *testing.T) {
|
||||
chaingen.ReplaceVotes(vbPrevBlockValid|vbTestDummy1No|
|
||||
vbTestDummy2Yes, 4))
|
||||
g.SaveTipCoinbaseOuts()
|
||||
accepted()
|
||||
g.Accepted()
|
||||
}
|
||||
g.AssertTipHeight(uint32(stakeValidationHeight + ruleChangeInterval*8 - 1))
|
||||
g.AssertBlockVersion(4)
|
||||
g.AssertStakeVersion(4)
|
||||
testThresholdState(testDummy1ID, ThresholdActive, testDummy1YesIndex)
|
||||
testThresholdState(testDummy2ID, ThresholdFailed, testDummy2NoIndex)
|
||||
g.TestThresholdStateChoice(testDummy1ID, ThresholdActive, testDummy1YesIndex)
|
||||
g.TestThresholdStateChoice(testDummy2ID, ThresholdFailed, testDummy2NoIndex)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user