instantsend: Partially revert 3987, add more tests for CL vs IS conflicts (#4146)

* tests: Check that CLs override ISes which invalidated non-CLed blocks earlier

* partial revert 3987: Do not mark blocks which conflict with ISes as "conflicting"
This commit is contained in:
UdjinM6 2021-05-11 19:50:14 +03:00 committed by pasta
parent 1f2ad2e69a
commit ad7d23c606
2 changed files with 20 additions and 9 deletions

View File

@ -1312,8 +1312,8 @@ void CInstantSendManager::ResolveBlockConflicts(const uint256& islockHash, const
CValidationState state; CValidationState state;
// need non-const pointer // need non-const pointer
auto pindex2 = LookupBlockIndex(pindex->GetBlockHash()); auto pindex2 = LookupBlockIndex(pindex->GetBlockHash());
if (!MarkConflictingBlock(state, Params(), pindex2)) { if (!InvalidateBlock(state, Params(), pindex2)) {
LogPrintf("CInstantSendManager::%s -- MarkConflictingBlock failed: %s\n", __func__, FormatStateMessage(state)); LogPrintf("CInstantSendManager::%s -- InvalidateBlock failed: %s\n", __func__, FormatStateMessage(state));
// This should not have happened and we are in a state were it's not safe to continue anymore // This should not have happened and we are in a state were it's not safe to continue anymore
assert(false); assert(false);
} }

View File

@ -69,7 +69,7 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
self.test_chainlock_overrides_islock(False) self.test_chainlock_overrides_islock(False)
self.test_chainlock_overrides_islock(True, False) self.test_chainlock_overrides_islock(True, False)
self.test_chainlock_overrides_islock(True, True) self.test_chainlock_overrides_islock(True, True)
self.test_islock_overrides_nonchainlock() self.test_chainlock_overrides_islock_overrides_nonchainlock()
def test_chainlock_overrides_islock(self, test_block_conflict, mine_confllicting=False): def test_chainlock_overrides_islock(self, test_block_conflict, mine_confllicting=False):
if not test_block_conflict: if not test_block_conflict:
@ -189,7 +189,7 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
assert rawtx['instantlock'] assert rawtx['instantlock']
assert not rawtx['instantlock_internal'] assert not rawtx['instantlock_internal']
def test_islock_overrides_nonchainlock(self): def test_chainlock_overrides_islock_overrides_nonchainlock(self):
# create two raw TXs, they will conflict with each other # create two raw TXs, they will conflict with each other
rawtx1 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100)['hex'] rawtx1 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100)['hex']
rawtx2 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100)['hex'] rawtx2 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100)['hex']
@ -200,11 +200,8 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
# Create an ISLOCK but don't broadcast it yet # Create an ISLOCK but don't broadcast it yet
islock = self.create_islock(rawtx2) islock = self.create_islock(rawtx2)
# Stop enough MNs so that ChainLocks don't work anymore # Disable ChainLocks to avoid accidential locking
for i in range(2): self.nodes[0].spork("SPORK_19_CHAINLOCKS_ENABLED", 4070908800)
self.stop_node(len(self.nodes) - 1)
self.nodes.pop(len(self.nodes) - 1)
self.mninfo.pop(len(self.mninfo) - 1)
# Send tx1, which will later conflict with the ISLOCK # Send tx1, which will later conflict with the ISLOCK
self.nodes[0].sendrawtransaction(rawtx1) self.nodes[0].sendrawtransaction(rawtx1)
@ -221,6 +218,13 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
assert(self.nodes[0].getrawtransaction(rawtx1_txid, True)['confirmations'] > 0) assert(self.nodes[0].getrawtransaction(rawtx1_txid, True)['confirmations'] > 0)
assert_raises_rpc_error(-25, "Missing inputs", self.nodes[0].sendrawtransaction, rawtx2) assert_raises_rpc_error(-25, "Missing inputs", self.nodes[0].sendrawtransaction, rawtx2)
# Create the block and the corresponding clsig but do not relay clsig yet
cl_block = self.create_block(self.nodes[0])
cl = self.create_chainlock(self.nodes[0].getblockcount() + 1, cl_block)
self.nodes[0].submitblock(ToHex(cl_block))
self.sync_all()
assert self.nodes[0].getbestblockhash() == cl_block.hash
# Send the ISLOCK, which should result in the last 2 blocks to be invalidated, even though the nodes don't know # Send the ISLOCK, which should result in the last 2 blocks to be invalidated, even though the nodes don't know
# the locked transaction yet # the locked transaction yet
self.test_node.send_islock(islock) self.test_node.send_islock(islock)
@ -241,6 +245,13 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
assert(self.nodes[0].getbestblockhash() != good_tip) assert(self.nodes[0].getbestblockhash() != good_tip)
assert(self.nodes[1].getbestblockhash() != good_tip) assert(self.nodes[1].getbestblockhash() != good_tip)
# Check that the CL-ed block overrides the one with islocks
self.nodes[0].spork("SPORK_19_CHAINLOCKS_ENABLED", 0) # Re-enable ChainLocks to accept clsig
self.test_node.send_clsig(cl) # relay clsig ASAP to prevent nodes from locking islock-ed tip
self.wait_for_sporks_same()
for node in self.nodes:
self.wait_for_chainlocked_block(node, cl_block.hash)
def create_block(self, node, vtx=[]): def create_block(self, node, vtx=[]):
bt = node.getblocktemplate() bt = node.getblocktemplate()
height = bt['height'] height = bt['height']