Merge #950: V0.12.1.x governance pr 2

13316a4 Return true from IsBlockValueValid when masternode data is not synced
  - This restores behavior very close to that in 12.0
  - Needed to prevent the forking problem currently being seen on
    testnet between online and offline nodes
  - This is expected to be a temporary fix while we develop a
    long-term solution for this problem

427086e Restore miner payments for superblocks

794b90d Added IsSynced field to JSON output of mnsync status RPC command
  - This is needed to allow fixing RPC tests so that they wait until
    the nodes are fully synced before performing tests

a9ddf6f Wait for nodes to sync masternode data during p2p-fullblocktest
This commit is contained in:
Tim Flynn 2016-08-19 07:53:49 -04:00 committed by Holger Schinzel
parent c05231c2a7
commit 123aa04d5b
7 changed files with 52 additions and 20 deletions

View File

@ -34,6 +34,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
self.tip = None self.tip = None
self.block_time = None self.block_time = None
NetworkThread().start() # Start up network handling in another thread NetworkThread().start() # Start up network handling in another thread
sync_masternodes(self.nodes)
test.run() test.run()
def get_tests(self): def get_tests(self):

View File

@ -44,6 +44,7 @@ class FullBlockTest(ComparisonTestFramework):
test = TestManager(self, self.options.tmpdir) test = TestManager(self, self.options.tmpdir)
test.add_all_connections(self.nodes) test.add_all_connections(self.nodes)
NetworkThread().start() # Start up network handling in another thread NetworkThread().start() # Start up network handling in another thread
sync_masternodes(self.nodes)
test.run() test.run()
def add_transactions_to_block(self, block, tx_list): def add_transactions_to_block(self, block, tx_list):

View File

@ -55,6 +55,15 @@ def get_rpc_proxy(url, node_number, timeout=None):
return coverage.AuthServiceProxyWrapper(proxy, coverage_logfile) return coverage.AuthServiceProxyWrapper(proxy, coverage_logfile)
def get_mnsync_status(node):
result = node.mnsync("status")
return result['IsSynced']
def wait_to_sync(node):
synced = False
while not synced:
synced = get_mnsync_status(node)
time.sleep(0.5)
def p2p_port(n): def p2p_port(n):
return 11000 + n + os.getpid()%999 return 11000 + n + os.getpid()%999
@ -96,6 +105,10 @@ def sync_mempools(rpc_connections, wait=1):
break break
time.sleep(wait) time.sleep(wait)
def sync_masternodes(rpc_connections):
for node in rpc_connections:
wait_to_sync(node)
bitcoind_processes = {} bitcoind_processes = {}
def initialize_datadir(dirname, n): def initialize_datadir(dirname, n):

View File

@ -415,9 +415,10 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, CAmount nF
// CONFIGURE SUPERBLOCK OUTPUTS // CONFIGURE SUPERBLOCK OUTPUTS
// Superblock payments are appended to the end of the coinbase vout vector
DBG( cout << "CSuperblockManager::CreateSuperblock Number payments: " << pBlock->CountPayments() << endl; ); DBG( cout << "CSuperblockManager::CreateSuperblock Number payments: " << pBlock->CountPayments() << endl; );
txNew.vout.resize(pBlock->CountPayments());
for(int i = 0; i < pBlock->CountPayments(); i++) { for(int i = 0; i < pBlock->CountPayments(); i++) {
CGovernancePayment payment; CGovernancePayment payment;
DBG( cout << "CSuperblockManager::CreateSuperblock i = " << i << endl; ); DBG( cout << "CSuperblockManager::CreateSuperblock i = " << i << endl; );
@ -425,8 +426,7 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, CAmount nF
DBG( cout << "CSuperblockManager::CreateSuperblock Payment found " << endl; ); DBG( cout << "CSuperblockManager::CreateSuperblock Payment found " << endl; );
// SET COINBASE OUTPUT TO SUPERBLOCK SETTING // SET COINBASE OUTPUT TO SUPERBLOCK SETTING
txNew.vout[i].scriptPubKey = payment.script; txNew.vout.push_back(CTxOut(payment.nAmount, payment.script));
txNew.vout[i].nValue = payment.nAmount;
// PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT // PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
@ -590,27 +590,43 @@ bool CSuperblock::IsValid(const CTransaction& txNew)
// CONFIGURE SUPERBLOCK OUTPUTS // CONFIGURE SUPERBLOCK OUTPUTS
int nOutputs = txNew.vout.size();
int nPayments = CountPayments(); int nPayments = CountPayments();
int nMinerPayments = nOutputs - nPayments;
// We require an exact match (including order) between the expected
// superblock payments and the payments actually in the block, after
// skipping any initial miner payments.
if(nMinerPayments<0) {
// This means the block cannot have all the superblock payments
// so it is not valid.
LogPrintf("CSuperblock::IsValid WARNING: Block invalid: Too few superblock payments");
return false;
}
for(int i = 0; i < nPayments; i++) { for(int i = 0; i < nPayments; i++) {
CGovernancePayment payment; CGovernancePayment payment;
if(GetPayment(i, payment)) { if(!GetPayment(i, payment)) {
// SET COINBASE OUTPUT TO SUPERBLOCK SETTING // This shouldn't happen so log a warning
LogPrintf("CSuperblock::IsValid WARNING: Failed to find payment: %d of %d total payments", i, nPayments);
continue;
}
if(payment.script == txNew.vout[i].scriptPubKey && payment.nAmount == txNew.vout[i].nValue) { int nVoutIndex = nMinerPayments + i;
// WE FOUND THE CORRECT SUPERBLOCK OUTPUT!
} else {
// MISMATCHED SUPERBLOCK OUTPUT!
CTxDestination address1; bool fPaymentMatch = ((payment.script == txNew.vout[nVoutIndex].scriptPubKey) &&
ExtractDestination(payment.script, address1); (payment.nAmount == txNew.vout[nVoutIndex].nValue));
CBitcoinAddress address2(address1);
// TODO: PRINT NICE N.N DASH OUTPUT if(!fPaymentMatch) {
// MISMATCHED SUPERBLOCK OUTPUT!
LogPrintf("SUPERBLOCK: output n %d payment %d to %s\n", i, payment.nAmount, address2.ToString()); CTxDestination address1;
ExtractDestination(payment.script, address1);
CBitcoinAddress address2(address1);
LogPrintf("CSuperblock::IsValid WARNING: Block invalid: output n %d payment %d to %s\n", nVoutIndex, payment.nAmount, address2.ToString());
return false; return false;
}
} }
} }

View File

@ -244,7 +244,7 @@ public:
bool GetPayment(int nPaymentIndex, CGovernancePayment& paymentOut) bool GetPayment(int nPaymentIndex, CGovernancePayment& paymentOut)
{ {
if(nPaymentIndex >= (int)vecPayments.size()) { if((nPaymentIndex<0) || (nPaymentIndex >= (int)vecPayments.size())) {
return false; return false;
} }

View File

@ -72,11 +72,11 @@ bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue){
bool valueok = (block.vtx[0].GetValueOut() <= nExpectedValue); bool valueok = (block.vtx[0].GetValueOut() <= nExpectedValue);
// IF WE'RE NOT SYNCED, WE MAY NOT HAVE SUPERBLOCK DATA, SO RETURN THE USUAL CHECK // IF WE'RE NOT SYNCED, WE MAY NOT HAVE SUPERBLOCK DATA, SO RETURN TRUE FOR NOW
if(!masternodeSync.IsSynced()) { if(!masternodeSync.IsSynced()) {
// IF NOT SYNCED, WE WILL SIMPLY FIND THE LONGEST CHAIN // IF NOT SYNCED, WE WILL SIMPLY FIND THE LONGEST CHAIN
return valueok; return true;
} }
// IF THIS IS A VALID SUPERBLOCK RETURN TRUE SINCE SUPERBLOCKS ARE CHECKED // IF THIS IS A VALID SUPERBLOCK RETURN TRUE SINCE SUPERBLOCKS ARE CHECKED

View File

@ -153,6 +153,7 @@ UniValue mnsync(const UniValue& params, bool fHelp)
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("IsBlockchainSynced", masternodeSync.IsBlockchainSynced())); obj.push_back(Pair("IsBlockchainSynced", masternodeSync.IsBlockchainSynced()));
obj.push_back(Pair("IsSynced", masternodeSync.IsSynced()));
obj.push_back(Pair("CurrentSyncingAssetName", masternodeSync.GetAssetName())); obj.push_back(Pair("CurrentSyncingAssetName", masternodeSync.GetAssetName()));
obj.push_back(Pair("lastMasternodeList", masternodeSync.lastMasternodeList)); obj.push_back(Pair("lastMasternodeList", masternodeSync.lastMasternodeList));
obj.push_back(Pair("lastMasternodeWinner", masternodeSync.lastMasternodeWinner)); obj.push_back(Pair("lastMasternodeWinner", masternodeSync.lastMasternodeWinner));