mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
fix: adjust GetPaymentsLimit to work correctly with historical blocks, adjust sb params on regtest, tweak tests (#5641)
## Issue being fixed or feature implemented Noticed a couple of things while I was trying to figure out if an [issue](https://github.com/dashpay/dash/pull/5627#discussion_r1367153099) @knst mentioned in #5627 could actually exist: 1. `GetPaymentsLimit()` won't work correctly with historical blocks rn. We don't use it that way internally but it could be done via rpc and it should provide correct results. 2. superblock params on regtest are too small to test them properly 3. because of (2) and a huge v20 activation window (comparing to sb params) `feature_governance.py` doesn't test v20 switching states. There's also no "sb on v20 activation block" test. ~NOTE: based on #5639 atm~ ## What was done? fix it, pls see individual commits ## How Has This Been Tested? run tests ## Breaking Changes n/a ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_
This commit is contained in:
parent
fa19c5ffee
commit
965f5b2063
@ -219,6 +219,7 @@ public:
|
|||||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
|
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 19999999999; // TODO: To be determined later
|
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 19999999999; // TODO: To be determined later
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||||
|
// NOTE: nWindowSize for MN_RR __MUST__ be greater than or equal to nSuperblockMaturityWindow for CSuperblock::GetPaymentsLimit() to work correctly
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 4032; // TODO to be determined before v20 release: choose nWindowSize/nThresholdStart/nThresholdMin
|
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 4032; // TODO to be determined before v20 release: choose nWindowSize/nThresholdStart/nThresholdMin
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 3226; // 80% of 4032
|
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 3226; // 80% of 4032
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 2420; // 60% of 4032
|
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 2420; // 60% of 4032
|
||||||
@ -794,8 +795,8 @@ public:
|
|||||||
consensus.nBudgetPaymentsWindowBlocks = 10;
|
consensus.nBudgetPaymentsWindowBlocks = 10;
|
||||||
consensus.nSuperblockStartBlock = 1500;
|
consensus.nSuperblockStartBlock = 1500;
|
||||||
consensus.nSuperblockStartHash = uint256(); // do not check this on regtest
|
consensus.nSuperblockStartHash = uint256(); // do not check this on regtest
|
||||||
consensus.nSuperblockCycle = 10;
|
consensus.nSuperblockCycle = 20;
|
||||||
consensus.nSuperblockMaturityWindow = 2;
|
consensus.nSuperblockMaturityWindow = 10;
|
||||||
consensus.nGovernanceMinQuorum = 1;
|
consensus.nGovernanceMinQuorum = 1;
|
||||||
consensus.nGovernanceFilterElements = 100;
|
consensus.nGovernanceFilterElements = 100;
|
||||||
consensus.nMasternodeMinimumConfirmations = 1;
|
consensus.nMasternodeMinimumConfirmations = 1;
|
||||||
|
@ -494,14 +494,16 @@ CAmount CSuperblock::GetPaymentsLimit(int nBlockHeight)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CBlockIndex* tipIndex = ::ChainActive().Tip();
|
const CBlockIndex* pindex = ::ChainActive().Tip();
|
||||||
const auto v20_state = llmq::utils::GetV20State(tipIndex);
|
if (pindex->nHeight > nBlockHeight) pindex = pindex->GetAncestor(nBlockHeight);
|
||||||
|
|
||||||
|
const auto v20_state = llmq::utils::GetV20State(pindex);
|
||||||
bool fV20Active{v20_state == ThresholdState::ACTIVE};
|
bool fV20Active{v20_state == ThresholdState::ACTIVE};
|
||||||
if (!fV20Active && nBlockHeight > tipIndex->nHeight) {
|
if (!fV20Active && nBlockHeight > pindex->nHeight) {
|
||||||
// If fV20Active isn't active yet and nBlockHeight refers to a future SuperBlock
|
// If fV20Active isn't active yet and nBlockHeight refers to a future SuperBlock
|
||||||
// then we need to check if the fork is locked_in and see if it will be active by the time of the future SuperBlock
|
// then we need to check if the fork is locked_in and see if it will be active by the time of the future SuperBlock
|
||||||
if (v20_state == ThresholdState::LOCKED_IN) {
|
if (v20_state == ThresholdState::LOCKED_IN) {
|
||||||
int activation_height = llmq::utils::GetV20Since(tipIndex) + static_cast<int>(Params().GetConsensus().vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize);
|
int activation_height = llmq::utils::GetV20Since(pindex) + static_cast<int>(Params().GetConsensus().vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize);
|
||||||
if (nBlockHeight >= activation_height) {
|
if (nBlockHeight >= activation_height) {
|
||||||
fV20Active = true;
|
fV20Active = true;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
|||||||
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment);
|
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ([[maybe_unused]] auto _ : irange::range(9)) {
|
for ([[maybe_unused]] auto _ : irange::range(consensus_params.nSuperblockCycle - 1)) {
|
||||||
CreateAndProcessBlock({}, coinbaseKey);
|
CreateAndProcessBlock({}, coinbaseKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
|||||||
// there will be 19 adjustments, 3 superblocks long each
|
// there will be 19 adjustments, 3 superblocks long each
|
||||||
for ([[maybe_unused]] auto i : irange::range(19)) {
|
for ([[maybe_unused]] auto i : irange::range(19)) {
|
||||||
for ([[maybe_unused]] auto j : irange::range(3)) {
|
for ([[maybe_unused]] auto j : irange::range(3)) {
|
||||||
for ([[maybe_unused]] auto k : irange::range(10)) {
|
for ([[maybe_unused]] auto k : irange::range(consensus_params.nSuperblockCycle)) {
|
||||||
CreateAndProcessBlock({}, coinbaseKey);
|
CreateAndProcessBlock({}, coinbaseKey);
|
||||||
}
|
}
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
@ -256,15 +256,15 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
|||||||
const CAmount block_subsidy = GetBlockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active);
|
const CAmount block_subsidy = GetBlockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active);
|
||||||
const CAmount block_subsidy_sb = GetSuperblockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active);
|
const CAmount block_subsidy_sb = GetSuperblockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active);
|
||||||
CAmount block_subsidy_potential = block_subsidy + block_subsidy_sb;
|
CAmount block_subsidy_potential = block_subsidy + block_subsidy_sb;
|
||||||
BOOST_CHECK_EQUAL(block_subsidy_potential, 113573330);
|
BOOST_CHECK_EQUAL(block_subsidy_potential, 84437941);
|
||||||
CAmount expected_block_reward = block_subsidy_potential - block_subsidy_potential / 5;
|
CAmount expected_block_reward = block_subsidy_potential - block_subsidy_potential / 5;
|
||||||
|
|
||||||
const CAmount masternode_payment = GetMasternodePayment(tip->nHeight, block_subsidy, isV20Active);
|
const CAmount masternode_payment = GetMasternodePayment(tip->nHeight, block_subsidy, isV20Active);
|
||||||
const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey);
|
const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey);
|
||||||
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx[0]->GetValueOut(), expected_block_reward);
|
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx[0]->GetValueOut(), expected_block_reward);
|
||||||
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx[0]->GetValueOut(), 90858664);
|
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx[0]->GetValueOut(), 67550353);
|
||||||
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment);
|
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment);
|
||||||
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, 68143998); // 0.75
|
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, 50662764); // 0.75
|
||||||
}
|
}
|
||||||
BOOST_CHECK(!llmq::utils::IsMNRewardReallocationActive(m_node.chainman->ActiveChain().Tip()));
|
BOOST_CHECK(!llmq::utils::IsMNRewardReallocationActive(m_node.chainman->ActiveChain().Tip()));
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
|||||||
// Reward split should stay ~75/25 after reallocation is done,
|
// Reward split should stay ~75/25 after reallocation is done,
|
||||||
// check 10 next superblocks
|
// check 10 next superblocks
|
||||||
for ([[maybe_unused]] auto i : irange::range(10)) {
|
for ([[maybe_unused]] auto i : irange::range(10)) {
|
||||||
for ([[maybe_unused]] auto k : irange::range(10)) {
|
for ([[maybe_unused]] auto k : irange::range(consensus_params.nSuperblockCycle)) {
|
||||||
CreateAndProcessBlock({}, coinbaseKey);
|
CreateAndProcessBlock({}, coinbaseKey);
|
||||||
}
|
}
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
@ -307,9 +307,9 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
|||||||
masternode_payment -= platform_payment;
|
masternode_payment -= platform_payment;
|
||||||
const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey);
|
const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey);
|
||||||
|
|
||||||
// At this height (3178) the block subsidy is 105460950.
|
|
||||||
CAmount block_subsidy_potential = block_subsidy + block_subsidy_sb;
|
CAmount block_subsidy_potential = block_subsidy + block_subsidy_sb;
|
||||||
BOOST_CHECK_EQUAL(block_subsidy_potential, 105460950);
|
BOOST_CHECK_EQUAL(tip->nHeight, 3858);
|
||||||
|
BOOST_CHECK_EQUAL(block_subsidy_potential, 78406660);
|
||||||
// Treasury is 20% since MNRewardReallocation
|
// Treasury is 20% since MNRewardReallocation
|
||||||
CAmount expected_block_reward = block_subsidy_potential - block_subsidy_potential / 5;
|
CAmount expected_block_reward = block_subsidy_potential - block_subsidy_potential / 5;
|
||||||
// Since MNRewardReallocation, MN reward share is 75% of the block reward
|
// Since MNRewardReallocation, MN reward share is 75% of the block reward
|
||||||
|
@ -5,15 +5,16 @@
|
|||||||
"""Tests around dash governance."""
|
"""Tests around dash governance."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import time
|
|
||||||
|
|
||||||
from test_framework.messages import uint256_to_string
|
from test_framework.messages import uint256_to_string
|
||||||
from test_framework.test_framework import DashTestFramework
|
from test_framework.test_framework import DashTestFramework
|
||||||
from test_framework.util import assert_equal, satoshi_round
|
from test_framework.util import assert_equal, satoshi_round, set_node_times, wait_until
|
||||||
|
|
||||||
class DashGovernanceTest (DashTestFramework):
|
class DashGovernanceTest (DashTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.set_dash_test_params(6, 5, [["-budgetparams=10:10:10"]] * 6)
|
self.v20_start_time = 1417713500
|
||||||
|
# using adjusted v20 deployment params to test an edge case where superblock maturity window is equal to deployment window size
|
||||||
|
self.set_dash_test_params(6, 5, [["-budgetparams=10:10:10", f"-vbparams=v20:{self.v20_start_time}:999999999999:10:8:6:5:-1"]] * 6, fast_dip3_enforcement=True)
|
||||||
|
|
||||||
def prepare_object(self, object_type, parent_hash, creation_time, revision, name, amount, payment_address):
|
def prepare_object(self, object_type, parent_hash, creation_time, revision, name, amount, payment_address):
|
||||||
proposal_rev = revision
|
proposal_rev = revision
|
||||||
@ -23,7 +24,7 @@ class DashGovernanceTest (DashTestFramework):
|
|||||||
"name": name,
|
"name": name,
|
||||||
"start_epoch": proposal_time,
|
"start_epoch": proposal_time,
|
||||||
"end_epoch": proposal_time + 24 * 60 * 60,
|
"end_epoch": proposal_time + 24 * 60 * 60,
|
||||||
"payment_amount": amount,
|
"payment_amount": float(amount),
|
||||||
"payment_address": payment_address,
|
"payment_address": payment_address,
|
||||||
"url": "https://dash.org"
|
"url": "https://dash.org"
|
||||||
}
|
}
|
||||||
@ -38,6 +39,44 @@ class DashGovernanceTest (DashTestFramework):
|
|||||||
"data": proposal_template,
|
"data": proposal_template,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def check_superblockbudget(self, v20_active):
|
||||||
|
v20_state = self.nodes[0].getblockchaininfo()["softforks"]["v20"]
|
||||||
|
assert_equal(v20_state["active"], v20_active)
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(200), self.expected_old_budget)
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(220), self.expected_old_budget)
|
||||||
|
if v20_state["bip9"]["status"] == "locked_in" or v20_state["bip9"]["status"] == "active":
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(240), self.expected_v20_budget)
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(260), self.expected_v20_budget)
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(280), self.expected_v20_budget)
|
||||||
|
else:
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(240), self.expected_old_budget)
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(260), self.expected_old_budget)
|
||||||
|
assert_equal(self.nodes[0].getsuperblockbudget(280), self.expected_old_budget)
|
||||||
|
|
||||||
|
def check_superblock(self):
|
||||||
|
# Make sure Superblock has only payments that fit into the budget
|
||||||
|
# p0 must always be included because it has most votes
|
||||||
|
# p1 and p2 have equal number of votes (but less votes than p0)
|
||||||
|
# so only one of them can be included (depends on proposal hashes).
|
||||||
|
|
||||||
|
coinbase_outputs = self.nodes[0].getblock(self.nodes[0].getbestblockhash(), 2)["tx"][0]["vout"]
|
||||||
|
payments_found = 0
|
||||||
|
for txout in coinbase_outputs:
|
||||||
|
if txout["value"] == self.p0_amount and txout["scriptPubKey"]["addresses"][0] == self.p0_payout_address:
|
||||||
|
payments_found += 1
|
||||||
|
if txout["value"] == self.p1_amount and txout["scriptPubKey"]["addresses"][0] == self.p1_payout_address:
|
||||||
|
if self.p1_hash > self.p2_hash:
|
||||||
|
payments_found += 1
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
if txout["value"] == self.p2_amount and txout["scriptPubKey"]["addresses"][0] == self.p2_payout_address:
|
||||||
|
if self.p2_hash > self.p1_hash:
|
||||||
|
payments_found += 1
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
assert_equal(payments_found, 2)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
map_vote_outcomes = {
|
map_vote_outcomes = {
|
||||||
0: "none",
|
0: "none",
|
||||||
@ -52,6 +91,13 @@ class DashGovernanceTest (DashTestFramework):
|
|||||||
3: "delete",
|
3: "delete",
|
||||||
4: "endorsed"
|
4: "endorsed"
|
||||||
}
|
}
|
||||||
|
sb_cycle = 20
|
||||||
|
sb_maturity_window = 10
|
||||||
|
sb_immaturity_window = sb_cycle - sb_maturity_window
|
||||||
|
self.expected_old_budget = satoshi_round("928.57142840")
|
||||||
|
self.expected_v20_budget = satoshi_round("18.57142860")
|
||||||
|
|
||||||
|
self.activate_dip8()
|
||||||
|
|
||||||
self.nodes[0].sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 4070908800)
|
self.nodes[0].sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 4070908800)
|
||||||
self.nodes[0].sporkupdate("SPORK_9_SUPERBLOCKS_ENABLED", 0)
|
self.nodes[0].sporkupdate("SPORK_9_SUPERBLOCKS_ENABLED", 0)
|
||||||
@ -59,82 +105,101 @@ class DashGovernanceTest (DashTestFramework):
|
|||||||
|
|
||||||
assert_equal(len(self.nodes[0].gobject("list-prepared")), 0)
|
assert_equal(len(self.nodes[0].gobject("list-prepared")), 0)
|
||||||
|
|
||||||
proposal_time = self.mocktime
|
self.nodes[0].generate(3)
|
||||||
sb_block_height = self.nodes[0].getblockcount() + 10 - self.nodes[0].getblockcount() % 10
|
self.bump_mocktime(3)
|
||||||
p0_payout_address = self.nodes[0].getnewaddress()
|
self.sync_blocks()
|
||||||
p1_payout_address = self.nodes[0].getnewaddress()
|
assert_equal(self.nodes[0].getblockcount(), 210)
|
||||||
p2_payout_address = self.nodes[0].getnewaddress()
|
assert_equal(self.nodes[0].getblockchaininfo()["softforks"]["v20"]["bip9"]["status"], "defined")
|
||||||
p0_amount = float(1.1)
|
self.check_superblockbudget(False)
|
||||||
p1_amount = float(3.3)
|
|
||||||
p2_amount = float(self.nodes[0].getsuperblockbudget(sb_block_height)) - p1_amount
|
|
||||||
|
|
||||||
p0_collateral_prepare = self.prepare_object(1, uint256_to_string(0), proposal_time, 1, "Proposal_0", p0_amount, p0_payout_address)
|
assert self.mocktime < self.v20_start_time
|
||||||
p1_collateral_prepare = self.prepare_object(1, uint256_to_string(0), proposal_time, 1, "Proposal_1", p1_amount, p1_payout_address)
|
self.mocktime = self.v20_start_time
|
||||||
p2_collateral_prepare = self.prepare_object(1, uint256_to_string(0), proposal_time, 1, "Proposal_2", p2_amount, p2_payout_address)
|
set_node_times(self.nodes, self.mocktime)
|
||||||
|
|
||||||
|
self.nodes[0].generate(10)
|
||||||
|
self.bump_mocktime(10)
|
||||||
|
self.sync_blocks()
|
||||||
|
assert_equal(self.nodes[0].getblockcount(), 220)
|
||||||
|
assert_equal(self.nodes[0].getblockchaininfo()["softforks"]["v20"]["bip9"]["status"], "started")
|
||||||
|
self.check_superblockbudget(False)
|
||||||
|
|
||||||
|
proposal_time = self.mocktime
|
||||||
|
self.p0_payout_address = self.nodes[0].getnewaddress()
|
||||||
|
self.p1_payout_address = self.nodes[0].getnewaddress()
|
||||||
|
self.p2_payout_address = self.nodes[0].getnewaddress()
|
||||||
|
self.p0_amount = satoshi_round("1.1")
|
||||||
|
self.p1_amount = satoshi_round("3.3")
|
||||||
|
self.p2_amount = self.expected_v20_budget - self.p1_amount
|
||||||
|
|
||||||
|
p0_collateral_prepare = self.prepare_object(1, uint256_to_string(0), proposal_time, 1, "Proposal_0", self.p0_amount, self.p0_payout_address)
|
||||||
|
p1_collateral_prepare = self.prepare_object(1, uint256_to_string(0), proposal_time, 1, "Proposal_1", self.p1_amount, self.p1_payout_address)
|
||||||
|
p2_collateral_prepare = self.prepare_object(1, uint256_to_string(0), proposal_time, 1, "Proposal_2", self.p2_amount, self.p2_payout_address)
|
||||||
|
|
||||||
self.nodes[0].generate(6)
|
self.nodes[0].generate(6)
|
||||||
|
self.bump_mocktime(6)
|
||||||
self.sync_blocks()
|
self.sync_blocks()
|
||||||
|
|
||||||
assert_equal(len(self.nodes[0].gobject("list-prepared")), 3)
|
assert_equal(len(self.nodes[0].gobject("list-prepared")), 3)
|
||||||
assert_equal(len(self.nodes[0].gobject("list")), 0)
|
assert_equal(len(self.nodes[0].gobject("list")), 0)
|
||||||
|
|
||||||
p0_hash = self.nodes[0].gobject("submit", "0", 1, proposal_time, p0_collateral_prepare["hex"], p0_collateral_prepare["collateralHash"])
|
self.p0_hash = self.nodes[0].gobject("submit", "0", 1, proposal_time, p0_collateral_prepare["hex"], p0_collateral_prepare["collateralHash"])
|
||||||
p1_hash = self.nodes[0].gobject("submit", "0", 1, proposal_time, p1_collateral_prepare["hex"], p1_collateral_prepare["collateralHash"])
|
self.p1_hash = self.nodes[0].gobject("submit", "0", 1, proposal_time, p1_collateral_prepare["hex"], p1_collateral_prepare["collateralHash"])
|
||||||
p2_hash = self.nodes[0].gobject("submit", "0", 1, proposal_time, p2_collateral_prepare["hex"], p2_collateral_prepare["collateralHash"])
|
self.p2_hash = self.nodes[0].gobject("submit", "0", 1, proposal_time, p2_collateral_prepare["hex"], p2_collateral_prepare["collateralHash"])
|
||||||
|
|
||||||
assert_equal(len(self.nodes[0].gobject("list")), 3)
|
assert_equal(len(self.nodes[0].gobject("list")), 3)
|
||||||
|
|
||||||
assert_equal(self.nodes[0].gobject("get", p0_hash)["FundingResult"]["YesCount"], 0)
|
assert_equal(self.nodes[0].gobject("get", self.p0_hash)["FundingResult"]["YesCount"], 0)
|
||||||
assert_equal(self.nodes[0].gobject("get", p0_hash)["FundingResult"]["NoCount"], 0)
|
assert_equal(self.nodes[0].gobject("get", self.p0_hash)["FundingResult"]["NoCount"], 0)
|
||||||
|
|
||||||
assert_equal(self.nodes[0].gobject("get", p1_hash)["FundingResult"]["YesCount"], 0)
|
assert_equal(self.nodes[0].gobject("get", self.p1_hash)["FundingResult"]["YesCount"], 0)
|
||||||
assert_equal(self.nodes[0].gobject("get", p1_hash)["FundingResult"]["NoCount"], 0)
|
assert_equal(self.nodes[0].gobject("get", self.p1_hash)["FundingResult"]["NoCount"], 0)
|
||||||
|
|
||||||
assert_equal(self.nodes[0].gobject("get", p2_hash)["FundingResult"]["YesCount"], 0)
|
assert_equal(self.nodes[0].gobject("get", self.p2_hash)["FundingResult"]["YesCount"], 0)
|
||||||
assert_equal(self.nodes[0].gobject("get", p2_hash)["FundingResult"]["NoCount"], 0)
|
assert_equal(self.nodes[0].gobject("get", self.p2_hash)["FundingResult"]["NoCount"], 0)
|
||||||
|
|
||||||
self.nodes[0].gobject("vote-alias", p0_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[0].proTxHash)
|
self.nodes[0].gobject("vote-alias", self.p0_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[0].proTxHash)
|
||||||
self.nodes[0].gobject("vote-many", p0_hash, map_vote_signals[1], map_vote_outcomes[1])
|
self.nodes[0].gobject("vote-many", self.p0_hash, map_vote_signals[1], map_vote_outcomes[1])
|
||||||
assert_equal(self.nodes[0].gobject("get", p0_hash)["FundingResult"]["YesCount"], self.mn_count - 1)
|
assert_equal(self.nodes[0].gobject("get", self.p0_hash)["FundingResult"]["YesCount"], self.mn_count - 1)
|
||||||
assert_equal(self.nodes[0].gobject("get", p0_hash)["FundingResult"]["NoCount"], 1)
|
assert_equal(self.nodes[0].gobject("get", self.p0_hash)["FundingResult"]["NoCount"], 1)
|
||||||
|
|
||||||
self.nodes[0].gobject("vote-alias", p1_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[0].proTxHash)
|
self.nodes[0].gobject("vote-alias", self.p1_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[0].proTxHash)
|
||||||
self.nodes[0].gobject("vote-alias", p1_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[1].proTxHash)
|
self.nodes[0].gobject("vote-alias", self.p1_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[1].proTxHash)
|
||||||
self.nodes[0].gobject("vote-many", p1_hash, map_vote_signals[1], map_vote_outcomes[1])
|
self.nodes[0].gobject("vote-many", self.p1_hash, map_vote_signals[1], map_vote_outcomes[1])
|
||||||
assert_equal(self.nodes[0].gobject("get", p1_hash)["FundingResult"]["YesCount"], self.mn_count - 2)
|
assert_equal(self.nodes[0].gobject("get", self.p1_hash)["FundingResult"]["YesCount"], self.mn_count - 2)
|
||||||
assert_equal(self.nodes[0].gobject("get", p1_hash)["FundingResult"]["NoCount"], 2)
|
assert_equal(self.nodes[0].gobject("get", self.p1_hash)["FundingResult"]["NoCount"], 2)
|
||||||
|
|
||||||
self.nodes[0].gobject("vote-alias", p2_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[0].proTxHash)
|
self.nodes[0].gobject("vote-alias", self.p2_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[0].proTxHash)
|
||||||
self.nodes[0].gobject("vote-alias", p2_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[1].proTxHash)
|
self.nodes[0].gobject("vote-alias", self.p2_hash, map_vote_signals[1], map_vote_outcomes[2], self.mninfo[1].proTxHash)
|
||||||
self.nodes[0].gobject("vote-many", p2_hash, map_vote_signals[1], map_vote_outcomes[1])
|
self.nodes[0].gobject("vote-many", self.p2_hash, map_vote_signals[1], map_vote_outcomes[1])
|
||||||
assert_equal(self.nodes[0].gobject("get", p2_hash)["FundingResult"]["YesCount"], self.mn_count - 2)
|
assert_equal(self.nodes[0].gobject("get", self.p2_hash)["FundingResult"]["YesCount"], self.mn_count - 2)
|
||||||
assert_equal(self.nodes[0].gobject("get", p2_hash)["FundingResult"]["NoCount"], 2)
|
assert_equal(self.nodes[0].gobject("get", self.p2_hash)["FundingResult"]["NoCount"], 2)
|
||||||
|
|
||||||
assert_equal(len(self.nodes[0].gobject("list", "valid", "triggers")), 0)
|
assert_equal(len(self.nodes[0].gobject("list", "valid", "triggers")), 0)
|
||||||
|
|
||||||
block_count = self.nodes[0].getblockcount()
|
block_count = self.nodes[0].getblockcount()
|
||||||
sb_cycle = 10
|
|
||||||
sb_maturity_window = 2
|
|
||||||
sb_maturity_cycle = sb_cycle - sb_maturity_window
|
|
||||||
|
|
||||||
# Move until 1 block before the Superblock maturity window starts
|
# Move until 1 block before the Superblock maturity window starts
|
||||||
n = sb_maturity_cycle - block_count % sb_cycle
|
n = sb_immaturity_window - block_count % sb_cycle
|
||||||
self.nodes[0].generate(n - 1)
|
# v20 is expected to be activate since block 240
|
||||||
self.sync_blocks()
|
assert block_count + n < 240
|
||||||
time.sleep(1)
|
for _ in range(n - 1):
|
||||||
|
self.nodes[0].generate(1)
|
||||||
|
self.bump_mocktime(1)
|
||||||
|
self.sync_blocks()
|
||||||
|
self.check_superblockbudget(False)
|
||||||
|
|
||||||
assert_equal(len(self.nodes[0].gobject("list", "valid", "triggers")), 0)
|
assert_equal(len(self.nodes[0].gobject("list", "valid", "triggers")), 0)
|
||||||
|
|
||||||
# Move 1 block enabling the Superblock maturity window
|
# Move 1 block enabling the Superblock maturity window
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
self.bump_mocktime(1)
|
||||||
self.sync_blocks()
|
self.sync_blocks()
|
||||||
time.sleep(1)
|
assert_equal(self.nodes[0].getblockcount(), 230)
|
||||||
|
assert_equal(self.nodes[0].getblockchaininfo()["softforks"]["v20"]["bip9"]["status"], "locked_in")
|
||||||
|
self.check_superblockbudget(False)
|
||||||
|
|
||||||
# The "winner" should submit new trigger and vote for it, no one else should vote yet
|
# The "winner" should submit new trigger and vote for it, no one else should vote yet
|
||||||
valid_triggers = self.nodes[0].gobject("list", "valid", "triggers")
|
wait_until(lambda: len(self.nodes[0].gobject("list", "valid", "triggers")) == 1, timeout=5)
|
||||||
assert_equal(len(valid_triggers), 1)
|
|
||||||
trigger_data = list(valid_triggers.values())[0]
|
|
||||||
assert_equal(trigger_data['YesCount'], 1)
|
|
||||||
|
|
||||||
# Make sure amounts aren't trimmed
|
# Make sure amounts aren't trimmed
|
||||||
payment_amounts_expected = [str(satoshi_round(str(p0_amount))), str(satoshi_round(str(p1_amount))), str(satoshi_round(str(p2_amount)))]
|
payment_amounts_expected = [str(satoshi_round(str(p0_amount))), str(satoshi_round(str(p1_amount))), str(satoshi_round(str(p2_amount)))]
|
||||||
@ -145,45 +210,36 @@ class DashGovernanceTest (DashTestFramework):
|
|||||||
|
|
||||||
# Move 1 block inside the Superblock maturity window
|
# Move 1 block inside the Superblock maturity window
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
self.bump_mocktime(1)
|
||||||
self.sync_blocks()
|
self.sync_blocks()
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# Every MN should vote for the same trigger now, no new triggers should be created
|
# Every MN should vote for the same trigger now, no new triggers should be created
|
||||||
triggers_rpc = self.nodes[0].gobject("list", "valid", "triggers")
|
wait_until(lambda: list(self.nodes[0].gobject("list", "valid", "triggers").values())[0]['YesCount'] == self.mn_count, timeout=5)
|
||||||
assert_equal(len(triggers_rpc), 1)
|
|
||||||
trigger_data = list(triggers_rpc.values())[0]
|
|
||||||
assert_equal(trigger_data['YesCount'], self.mn_count)
|
|
||||||
|
|
||||||
block_count = self.nodes[0].getblockcount()
|
block_count = self.nodes[0].getblockcount()
|
||||||
n = sb_cycle - block_count % sb_cycle
|
n = sb_cycle - block_count % sb_cycle
|
||||||
|
|
||||||
# Move remaining n blocks until actual Superblock
|
# Move remaining n blocks until actual Superblock
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
time.sleep(1)
|
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
self.bump_mocktime(1)
|
||||||
self.sync_blocks()
|
self.sync_blocks()
|
||||||
|
# comparing to 239 because bip9 forks are active when the tip is one block behind the activation height
|
||||||
|
self.check_superblockbudget(block_count + i + 1 >= 239)
|
||||||
|
|
||||||
# Make sure Superblock has only payments that fit into the budget
|
self.check_superblockbudget(True)
|
||||||
# p0 must always be included because it has most votes
|
self.check_superblock()
|
||||||
# p1 and p2 have equal number of votes (but less votes than p0)
|
|
||||||
# so only one of them can be included (depends on proposal hashes).
|
|
||||||
coinbase_outputs = self.nodes[0].getblock(self.nodes[0].getbestblockhash(), 2)["tx"][0]["vout"]
|
|
||||||
payments_found = 0
|
|
||||||
for txout in coinbase_outputs:
|
|
||||||
if txout["value"] == satoshi_round(str(p0_amount)) and txout["scriptPubKey"]["addresses"][0] == p0_payout_address:
|
|
||||||
payments_found += 1
|
|
||||||
if txout["value"] == satoshi_round(str(p1_amount)) and txout["scriptPubKey"]["addresses"][0] == p1_payout_address:
|
|
||||||
if p1_hash > p2_hash:
|
|
||||||
payments_found += 1
|
|
||||||
else:
|
|
||||||
assert False
|
|
||||||
if txout["value"] == satoshi_round(str(p2_amount)) and txout["scriptPubKey"]["addresses"][0] == p2_payout_address:
|
|
||||||
if p2_hash > p1_hash:
|
|
||||||
payments_found += 1
|
|
||||||
else:
|
|
||||||
assert False
|
|
||||||
|
|
||||||
assert_equal(payments_found, 2)
|
# Mine and check a couple more superblocks
|
||||||
|
for i in range(2):
|
||||||
|
for _ in range(20):
|
||||||
|
self.nodes[0].generate(1)
|
||||||
|
self.bump_mocktime(1)
|
||||||
|
self.sync_blocks()
|
||||||
|
assert_equal(self.nodes[0].getblockcount(), 240 + (i + 1) * 20)
|
||||||
|
assert_equal(self.nodes[0].getblockchaininfo()["softforks"]["v20"]["bip9"]["status"], "active")
|
||||||
|
self.check_superblockbudget(True)
|
||||||
|
self.check_superblock()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user