Use smaller (3 out of 5) quorums for regtest/Travis (#2774)

* Require only 3 out of 5 signatures for old InstantSend in regtest mode

* Use LLMQs of size 5 with threshold of 3 for regtest

* Fix wrong check for out-of-range bits in CFixedBitSet

* Reduce number of masternodes in masternode/LLMQ tests

* Add missing \n to LogPrintf call

* Use correct indexes for isolated/receiver/sender nodes

The way it was before resulted in nodes 1-3 being unused and 6-8 being used
for these 3 special nodes even though these are masternodes.

* Avoid stopping/starting isolated node in p2p-instantsend.py

It's enough to disable networking for this node.
This commit is contained in:
Alexander Block 2019-03-15 09:48:24 +01:00 committed by UdjinM6
parent 396ebc2dc7
commit a69a5cf4a0
13 changed files with 62 additions and 52 deletions

View File

@ -23,10 +23,10 @@ AUTO_IX_MEM_THRESHOLD = 0.1
class AutoIXMempoolTest(DashTestFramework):
def __init__(self):
super().__init__(13, 10, ["-maxmempool=%d" % MAX_MEMPOOL_SIZE, '-limitdescendantsize=10'], fast_dip3_enforcement=True)
super().__init__(8, 5, ["-maxmempool=%d" % MAX_MEMPOOL_SIZE, '-limitdescendantsize=10'], fast_dip3_enforcement=True)
# set sender, receiver
self.receiver_idx = self.num_nodes - 2
self.sender_idx = self.num_nodes - 3
self.receiver_idx = 1
self.sender_idx = 2
def get_autoix_bip9_status(self):
info = self.nodes[0].getblockchaininfo()

View File

@ -17,7 +17,7 @@ Checks LLMQs based ChainLocks
class LLMQChainLocksTest(DashTestFramework):
def __init__(self):
super().__init__(11, 10, [], fast_dip3_enforcement=True)
super().__init__(6, 5, [], fast_dip3_enforcement=True)
def run_test(self):

View File

@ -17,7 +17,7 @@ Checks LLMQs signing sessions
class LLMQSigningTest(DashTestFramework):
def __init__(self):
super().__init__(11, 10, [], fast_dip3_enforcement=True)
super().__init__(6, 5, [], fast_dip3_enforcement=True)
def run_test(self):
@ -57,13 +57,13 @@ class LLMQSigningTest(DashTestFramework):
# Initial state
wait_for_sigs(False, False, False, 1)
# Sign 5 shares, should not result in recovered sig
for i in range(5):
# Sign 2 shares, should not result in recovered sig
for i in range(2):
self.mninfo[i].node.quorum("sign", 100, id, msgHash)
assert_sigs_nochange(False, False, False, 3)
# Sign one more share, should result in recovered sig and conflict for msgHashConflict
self.mninfo[6].node.quorum("sign", 100, id, msgHash)
self.mninfo[2].node.quorum("sign", 100, id, msgHash)
wait_for_sigs(True, False, True, 15)
# Mine one more quorum, so that we have 2 active ones, nothing should change
@ -86,9 +86,9 @@ class LLMQSigningTest(DashTestFramework):
# Cleanup starts every 5 seconds
wait_for_sigs(False, False, False, 15)
for i in range(4):
for i in range(2):
self.mninfo[i].node.quorum("sign", 100, id, msgHashConflict)
for i in range(4, 10):
for i in range(2, 5):
self.mninfo[i].node.quorum("sign", 100, id, msgHash)
wait_for_sigs(True, False, True, 15)

View File

@ -16,7 +16,7 @@ Checks simple PoSe system based on LLMQ commitments
class LLMQSimplePoSeTest(DashTestFramework):
def __init__(self):
super().__init__(11, 10, [], fast_dip3_enforcement=True)
super().__init__(6, 5, [], fast_dip3_enforcement=True)
def run_test(self):
@ -25,7 +25,7 @@ class LLMQSimplePoSeTest(DashTestFramework):
# check if mining quorums with all nodes being online succeeds without punishment/banning
for i in range(3):
self.mine_quorum(expected_valid_count=10)
self.mine_quorum()
for mn in self.mninfo:
assert(not self.check_punished(mn) and not self.check_punished(mn))

View File

@ -23,11 +23,10 @@ transactions with high fee.
class AutoInstantSendTest(DashTestFramework):
def __init__(self):
super().__init__(14, 10, [], fast_dip3_enforcement=True)
super().__init__(8, 5, [], fast_dip3_enforcement=True)
# set sender, receiver, isolated nodes
self.isolated_idx = self.num_nodes - 1
self.receiver_idx = self.num_nodes - 2
self.sender_idx = self.num_nodes - 3
self.receiver_idx = 1
self.sender_idx = 2
def get_autoix_bip9_status(self):
info = self.nodes[0].getblockchaininfo()

View File

@ -14,11 +14,11 @@ InstantSendTest -- test InstantSend functionality (prevent doublespend for uncon
class InstantSendTest(DashTestFramework):
def __init__(self):
super().__init__(14, 10, [], fast_dip3_enforcement=True)
super().__init__(9, 5, [], fast_dip3_enforcement=True)
# set sender, receiver, isolated nodes
self.isolated_idx = self.num_nodes - 1
self.receiver_idx = self.num_nodes - 2
self.sender_idx = self.num_nodes - 3
self.isolated_idx = 1
self.receiver_idx = 2
self.sender_idx = 3
def run_test(self):
self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0)
@ -50,7 +50,7 @@ class InstantSendTest(DashTestFramework):
self.nodes[self.isolated_idx],
0.5, 1, 100)
# stop one node to isolate it from network
stop_node(self.nodes[self.isolated_idx], self.isolated_idx)
self.nodes[self.isolated_idx].setnetworkactive(False)
# instantsend to receiver
receiver_addr = self.nodes[self.receiver_idx].getnewaddress()
is_id = self.nodes[self.sender_idx].instantsendtoaddress(receiver_addr, 0.9)
@ -66,10 +66,6 @@ class InstantSendTest(DashTestFramework):
break
sleep(0.1)
assert(locked)
# start last node
self.nodes[self.isolated_idx] = start_node(self.isolated_idx,
self.options.tmpdir,
self.extra_args)
# send doublespend transaction to isolated node
self.nodes[self.isolated_idx].sendrawtransaction(dblspnd_tx['hex'])
# generate block on isolated node with doublespend transaction
@ -78,11 +74,14 @@ class InstantSendTest(DashTestFramework):
self.nodes[self.isolated_idx].generate(1)
wrong_block = self.nodes[self.isolated_idx].getbestblockhash()
# connect isolated block to network
self.nodes[self.isolated_idx].setnetworkactive(True)
for i in range(0, self.isolated_idx):
connect_nodes(self.nodes[i], self.isolated_idx)
# check doublespend block is rejected by other nodes
timeout = 10
for i in range(0, self.isolated_idx):
for i in range(0, self.num_nodes):
if i == self.isolated_idx:
continue
res = self.nodes[i].waitforblock(wrong_block, timeout)
assert (res['hash'] != wrong_block)
# wait for long time only for first node

View File

@ -479,10 +479,10 @@ class DashTestFramework(BitcoinTestFramework):
all_ok = True
for mn in self.mninfo:
s = mn.node.quorum("dkgstatus")["session"]
if "llmq_10" not in s:
if "llmq_5_60" not in s:
all_ok = False
break
s = s["llmq_10"]
s = s["llmq_5_60"]
if "phase" not in s:
all_ok = False
break
@ -508,7 +508,7 @@ class DashTestFramework(BitcoinTestFramework):
all_ok = False
break
s = s["minableCommitments"]
if "llmq_10" not in s:
if "llmq_5_60" not in s:
all_ok = False
break
if all_ok:
@ -516,7 +516,7 @@ class DashTestFramework(BitcoinTestFramework):
sleep(0.1)
raise AssertionError("wait_for_quorum_commitment timed out")
def mine_quorum(self, expected_valid_count=10):
def mine_quorum(self, expected_valid_count=5):
quorums = self.nodes[0].quorum("list")
# move forward to next DKG
@ -544,7 +544,7 @@ class DashTestFramework(BitcoinTestFramework):
sync_blocks(self.nodes)
# Make sure all reached phase 3 (complain) and received all complaints
self.wait_for_quorum_phase(3, "receivedComplaints" if expected_valid_count != 10 else None, expected_valid_count)
self.wait_for_quorum_phase(3, "receivedComplaints" if expected_valid_count != 5 else None, expected_valid_count)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(2)

View File

@ -107,12 +107,12 @@ static CBlock FindDevNetGenesisBlock(const Consensus::Params& params, const CBlo
}
// this one is for testing only
static Consensus::LLMQParams llmq10_60 = {
.type = Consensus::LLMQ_10_60,
.name = "llmq_10",
.size = 10,
.minSize = 6,
.threshold = 6,
static Consensus::LLMQParams llmq5_60 = {
.type = Consensus::LLMQ_5_60,
.name = "llmq_5_60",
.size = 5,
.minSize = 3,
.threshold = 3,
.dkgInterval = 24, // one DKG per hour
.dkgPhaseBlocks = 2,
@ -203,6 +203,8 @@ public:
consensus.nMasternodePaymentsIncreasePeriod = 576*30; // 17280 - actual historical value
consensus.nInstantSendConfirmationsRequired = 6;
consensus.nInstantSendKeepLock = 24;
consensus.nInstantSendSigsRequired = 6;
consensus.nInstantSendSigsTotal = 10;
consensus.nBudgetPaymentsStartBlock = 328008; // actual historical value
consensus.nBudgetPaymentsCycleBlocks = 16616; // ~(60*24*30)/2.6, actual number of blocks per month is 200700 / 12 = 16725
consensus.nBudgetPaymentsWindowBlocks = 100;
@ -376,6 +378,8 @@ public:
consensus.nMasternodePaymentsIncreasePeriod = 10;
consensus.nInstantSendConfirmationsRequired = 2;
consensus.nInstantSendKeepLock = 6;
consensus.nInstantSendSigsRequired = 6;
consensus.nInstantSendSigsTotal = 10;
consensus.nBudgetPaymentsStartBlock = 4100;
consensus.nBudgetPaymentsCycleBlocks = 50;
consensus.nBudgetPaymentsWindowBlocks = 10;
@ -526,6 +530,8 @@ public:
consensus.nMasternodePaymentsIncreasePeriod = 10;
consensus.nInstantSendConfirmationsRequired = 2;
consensus.nInstantSendKeepLock = 6;
consensus.nInstantSendSigsRequired = 6;
consensus.nInstantSendSigsTotal = 10;
consensus.nBudgetPaymentsStartBlock = 4100;
consensus.nBudgetPaymentsCycleBlocks = 50;
consensus.nBudgetPaymentsWindowBlocks = 10;
@ -683,6 +689,8 @@ public:
consensus.nMasternodePaymentsIncreasePeriod = 10;
consensus.nInstantSendConfirmationsRequired = 2;
consensus.nInstantSendKeepLock = 6;
consensus.nInstantSendSigsRequired = 3;
consensus.nInstantSendSigsTotal = 5;
consensus.nBudgetPaymentsStartBlock = 1000;
consensus.nBudgetPaymentsCycleBlocks = 50;
consensus.nBudgetPaymentsWindowBlocks = 10;
@ -787,10 +795,10 @@ public:
nExtCoinType = 1;
// long living quorum params
consensus.llmqs[Consensus::LLMQ_10_60] = llmq10_60;
consensus.llmqs[Consensus::LLMQ_5_60] = llmq5_60;
consensus.llmqs[Consensus::LLMQ_50_60] = llmq50_60;
consensus.llmqChainLocks = Consensus::LLMQ_10_60;
consensus.llmqForInstantSend = Consensus::LLMQ_10_60;
consensus.llmqChainLocks = Consensus::LLMQ_5_60;
consensus.llmqForInstantSend = Consensus::LLMQ_5_60;
}
void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold)

View File

@ -48,7 +48,7 @@ enum LLMQType : uint8_t
LLMQ_400_85 = 3, // 400 members, 340 (85%) threshold, one every 24 hours
// for testing only
LLMQ_10_60 = 100, // 10 members, 6 (60%) threshold, one per hour
LLMQ_5_60 = 100, // 5 members, 3 (60%) threshold, one per hour
};
// Configures a LLMQ and its DKG
@ -124,6 +124,8 @@ struct Params {
int nMasternodePaymentsIncreasePeriod; // in blocks
int nInstantSendConfirmationsRequired; // in blocks
int nInstantSendKeepLock; // in blocks
int nInstantSendSigsRequired;
int nInstantSendSigsTotal;
int nBudgetPaymentsStartBlock;
int nBudgetPaymentsCycleBlocks;
int nBudgetPaymentsWindowBlocks;

View File

@ -47,8 +47,8 @@ const std::string CInstantSend::SERIALIZATION_VERSION_STRING = "CInstantSend-Ver
// Transaction Locks
//
// step 1) Some node announces intention to lock transaction inputs via "txlockrequest" message (ix)
// step 2) Top COutPointLock::SIGNATURES_TOTAL masternodes per each spent outpoint push "txlockvote" message (txlvote)
// step 3) Once there are COutPointLock::SIGNATURES_REQUIRED valid "txlockvote" messages (txlvote) per each spent outpoint
// step 2) Top nInstantSendSigsTotal masternodes per each spent outpoint push "txlockvote" message (txlvote)
// step 3) Once there are nInstantSendSigsRequired valid "txlockvote" messages (txlvote) per each spent outpoint
// for a corresponding "txlockrequest" message (ix), all outpoints from that tx are treated as locked
//
@ -252,7 +252,7 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman)
continue;
}
int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL;
int nSignaturesTotal = Params().GetConsensus().nInstantSendSigsTotal;
if (nRank > nSignaturesTotal) {
LogPrint("instantsend", "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, nRank);
continue;
@ -1025,7 +1025,7 @@ CAmount CTxLockRequest::GetMinFee(bool fForceMinFee) const
int CTxLockRequest::GetMaxSignatures() const
{
return tx->vin.size() * COutPointLock::SIGNATURES_TOTAL;
return tx->vin.size() * Params().GetConsensus().nInstantSendSigsTotal;
}
bool CTxLockRequest::IsSimple() const
@ -1087,7 +1087,7 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const
LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s, rank=%d\n", outpointMasternode.ToStringShort(), nRank);
int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL;
int nSignaturesTotal = Params().GetConsensus().nInstantSendSigsTotal;
if (nRank > nSignaturesTotal) {
LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s is not in the top %d (%d), vote hash=%s\n",
outpointMasternode.ToStringShort(), nSignaturesTotal, nRank, GetHash().ToString());
@ -1196,6 +1196,11 @@ bool COutPointLock::HasMasternodeVoted(const COutPoint& outpointMasternodeIn) co
return mapMasternodeVotes.count(outpointMasternodeIn);
}
bool COutPointLock::IsReady() const
{
return !fAttacked && CountVotes() >= Params().GetConsensus().nInstantSendSigsRequired;
}
void COutPointLock::Relay(CConnman& connman) const
{
for (const auto& pair : mapMasternodeVotes) {

View File

@ -310,9 +310,6 @@ private:
bool fAttacked = false;
public:
static const int SIGNATURES_REQUIRED = 6;
static const int SIGNATURES_TOTAL = 10;
COutPointLock() {}
COutPointLock(const COutPoint& outpointIn) :
@ -335,7 +332,7 @@ public:
std::vector<CTxLockVote> GetVotes() const;
bool HasMasternodeVoted(const COutPoint& outpointMasternodeIn) const;
int CountVotes() const { return fAttacked ? 0 : mapMasternodeVotes.size(); }
bool IsReady() const { return !fAttacked && CountVotes() >= SIGNATURES_REQUIRED; }
bool IsReady() const;
void MarkAsAttacked() { fAttacked = true; }
void Relay(CConnman& connman) const;

View File

@ -376,7 +376,7 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi
for (const auto& p : msgs) {
if (!p.second) {
LogPrint("net", "%s -- failed to deserialize message, peer=%d", __func__, p.first);
LogPrint("net", "%s -- failed to deserialize message, peer=%d\n", __func__, p.first);
{
LOCK(cs_main);
Misbehaving(p.first, 100);

View File

@ -437,7 +437,7 @@ public:
vec[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
if (vBytes.size() * 8 != size) {
size_t rem = vBytes.size() * 8 - size;
uint8_t m = (uint8_t)(0xff << rem);
uint8_t m = ~(uint8_t)(0xff >> rem);
if (vBytes[vBytes.size() - 1] & m) {
throw std::ios_base::failure("Out-of-range bits set");
}