Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2bbac8f
Introduce NotifyChainLock signal and invoke it when CLSIGs get processed
codablock Feb 26, 2019
5bbc122
Implement PushReconstructedRecoveredSig in CSigningManager
codablock Feb 26, 2019
83dbcc4
Implement CInstantSendManager and related P2P messages
codablock Sep 21, 2018
1959f3e
Handle incoming TXs by calling CInstantXManager::ProcessTx
codablock Feb 28, 2019
5ff4db0
Downgrade TXLOCKREQUEST to TX when new IX system is active
codablock Feb 28, 2019
34a8b29
Disable old IX code when the new system is active
codablock Feb 28, 2019
3a6cc2c
Show "verified via LLMQ based InstantSend" in GUI TX status
codablock Feb 28, 2019
1d2d370
Whenever we check for locked TXs, also check for the new system havin…
codablock Feb 28, 2019
68cfdc9
Also call ProcessTx from sendrawtransaction and RelayWalletTransaction
codablock Feb 28, 2019
dc97835
Disable explicit lock requests when the new IX system is active
codablock Feb 28, 2019
7945192
Enforce IX locks from the new system
codablock Feb 28, 2019
bd7edc8
Track txids of new blocks and first-seen time of TXs in CChainLocksHa…
codablock Feb 28, 2019
0a5e8eb
Move ChainLock signing into TrySignChainTip and call it periodically
codablock Feb 28, 2019
96291e7
Cheaper/Faster bailout from TrySignChainTip when already signed before
codablock Mar 1, 2019
2a7a5c6
Only sign ChainLocks when all included TXs are "safe"
codablock Mar 1, 2019
baf8b81
Fix no-wallet build
codablock Mar 1, 2019
f44f09c
Fix crash in BlockAssembler::addPackageTxs
codablock Mar 1, 2019
5b8344e
Use scheduleFromNow instead of schedule+boost::chrono
codablock Mar 1, 2019
e2f99f4
Set llmqForInstantSend for mainnet and testnet
codablock Mar 1, 2019
9e90811
Add override keywork to CDSNotificationInterface::NotifyChainLock
codablock Mar 4, 2019
2806907
Combine loops in CChainLocksHandler::NewPoWValidBlock
codablock Mar 4, 2019
f5dcb00
Introduce spork SPORK_20_INSTANTSEND_LLMQ_BASED to switch between new…
codablock Mar 4, 2019
2299ee2
Rename IXLOCK to ISLOCK and InstantX to InstantSend
codablock Mar 4, 2019
55152cb
Move IS block filtering into ConnectBlock
UdjinM6 Mar 3, 2019
a8da11a
update p2p-instantsend.py to test both "old" and "new" InstantSend
UdjinM6 Mar 3, 2019
843b6d7
update p2p-autoinstantsend.py to test both "old" and "new" InstantSend
UdjinM6 Mar 3, 2019
41a71fe
update autoix-mempool.py to test both "old" and "new" InstantSend (an…
UdjinM6 Mar 3, 2019
3e60d2d
Adjust LLMQ based InstantSend tests for new spork20
codablock Mar 4, 2019
f8f867a
Sync blocks after generating in mine_quorum()
codablock Mar 4, 2019
fae33e0
Let ProcessPendingReconstructedRecoveredSigs return void instead of bool
codablock Mar 4, 2019
4d3365d
Completely disable InstantSend while filling mempool in autoix-mempoo…
codablock Mar 5, 2019
041a1c2
Move safe TX checks into TestForBlock and TestPackageTransactions
codablock Mar 6, 2019
06fc655
Actually remove from finalInstantSendLocks in CInstantSendManager::Re…
codablock Mar 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions qa/rpc-tests/autoix-mempool.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ def fill_mempool(self):
def run_test(self):
# make sure masternodes are synced
sync_masternodes(self.nodes)

self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0)
self.wait_for_sporks_same()
self.mine_quorum()

print("Test old InstantSend")
self.test_auto();

self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.wait_for_sporks_same()

print("Test new InstantSend")
self.test_auto(True);

def test_auto(self, new_is = False):
self.activate_autoix_bip9()
self.set_autoix_spork_state(True)

Expand All @@ -146,13 +161,17 @@ def run_test(self):

# fill mempool with transactions
self.set_autoix_spork_state(False)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800)
self.wait_for_sporks_same()
self.fill_mempool()
self.set_autoix_spork_state(True)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.wait_for_sporks_same()

# autoIX is not working now
assert(not self.send_simple_tx(sender, receiver))
# regular IX is still working
assert(self.send_regular_IX(sender, receiver))
# regular IX is still working for old IS but not for new one
assert(not self.send_regular_IX(sender, receiver) if new_is else self.send_regular_IX(sender, receiver))

# generate one block to clean up mempool and retry auto and regular IX
# generate 2 more blocks to have enough confirmations for IX
Expand Down
42 changes: 29 additions & 13 deletions qa/rpc-tests/p2p-autoinstantsend.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,14 @@ def set_autoix_spork_state(self, state):
self.nodes[0].spork('SPORK_16_INSTANTSEND_AUTOLOCKS', value)

# sends regular IX with high fee and may inputs (not-simple transaction)
def send_regular_IX(self):
def send_regular_IX(self, check_fee = True):
receiver_addr = self.nodes[self.receiver_idx].getnewaddress()
txid = self.nodes[0].instantsendtoaddress(receiver_addr, 1.0)
MIN_FEE = satoshi_round(-0.0001)
fee = self.nodes[0].gettransaction(txid)['fee']
expected_fee = MIN_FEE * len(self.nodes[0].getrawtransaction(txid, True)['vin'])
assert_equal(fee, expected_fee)
if (check_fee):
MIN_FEE = satoshi_round(-0.0001)
fee = self.nodes[0].gettransaction(txid)['fee']
expected_fee = MIN_FEE * len(self.nodes[0].getrawtransaction(txid, True)['vin'])
assert_equal(fee, expected_fee)
return self.wait_for_instantlock(txid, self.nodes[0])

# sends simple trx, it should become IX if autolocks are allowed
Expand All @@ -115,6 +116,21 @@ def send_complex_tx(self):
def run_test(self):
# make sure masternodes are synced
sync_masternodes(self.nodes)

self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0)
self.wait_for_sporks_same()
self.mine_quorum()

print("Test old InstantSend")
self.test_auto();

self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.wait_for_sporks_same()

print("Test new InstantSend")
self.test_auto(True);

def test_auto(self, new_is = False):
# feed the sender with some balance
sender_addr = self.nodes[self.sender_idx].getnewaddress()
self.nodes[0].sendtoaddress(sender_addr, 1)
Expand All @@ -126,26 +142,26 @@ def run_test(self):

assert(not self.get_autoix_spork_state())

assert(self.send_regular_IX())
assert(not self.send_simple_tx())
assert(not self.send_complex_tx())
assert(self.send_regular_IX(not new_is))
assert(self.send_simple_tx() if new_is else not self.send_simple_tx())
assert(self.send_complex_tx() if new_is else not self.send_complex_tx())

self.activate_autoix_bip9()
self.set_autoix_spork_state(True)

assert(self.get_autoix_bip9_status() == 'active')
assert(self.get_autoix_spork_state())

assert(self.send_regular_IX())
assert(self.send_regular_IX(not new_is))
assert(self.send_simple_tx())
assert(not self.send_complex_tx())
assert(self.send_complex_tx() if new_is else not self.send_complex_tx())

self.set_autoix_spork_state(False)
assert(not self.get_autoix_spork_state())

assert(self.send_regular_IX())
assert(not self.send_simple_tx())
assert(not self.send_complex_tx())
assert(self.send_regular_IX(not new_is))
assert(self.send_simple_tx() if new_is else not self.send_simple_tx())
assert(self.send_complex_tx() if new_is else not self.send_complex_tx())


if __name__ == '__main__':
Expand Down
21 changes: 20 additions & 1 deletion qa/rpc-tests/p2p-instantsend.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ def __init__(self):
self.sender_idx = self.num_nodes - 3

def run_test(self):
self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0)
self.wait_for_sporks_same()
self.mine_quorum()

print("Test old InstantSend")
self.test_doublespend()

self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.wait_for_sporks_same()

print("Test new InstantSend")
self.test_doublespend()

def test_doublespend(self):
# feed the sender with some balance
sender_addr = self.nodes[self.sender_idx].getnewaddress()
self.nodes[0].sendtoaddress(sender_addr, 1)
Expand Down Expand Up @@ -73,7 +87,12 @@ def run_test(self):
assert (res['hash'] != wrong_block)
# wait for long time only for first node
timeout = 1

# mine more blocks
# TODO: mine these blocks on an isolated node
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(2)
self.sync_all()

if __name__ == '__main__':
InstantSendTest().main()
9 changes: 9 additions & 0 deletions qa/rpc-tests/test_framework/test_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,36 +498,44 @@ def mine_quorum(self, expected_valid_count=10):
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(skip_count)
sync_blocks(self.nodes)

# Make sure all reached phase 1 (init)
self.wait_for_quorum_phase(1, None, 0)
# Give nodes some time to connect to neighbors
sleep(2)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(2)
sync_blocks(self.nodes)

# Make sure all reached phase 2 (contribute) and received all contributions
self.wait_for_quorum_phase(2, "receivedContributions", expected_valid_count)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(2)
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)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(2)
sync_blocks(self.nodes)

# Make sure all reached phase 4 (justify)
self.wait_for_quorum_phase(4, None, 0)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(2)
sync_blocks(self.nodes)

# Make sure all reached phase 5 (commit)
self.wait_for_quorum_phase(5, "receivedPrematureCommitments", expected_valid_count)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(2)
sync_blocks(self.nodes)

# Make sure all reached phase 6 (mining)
self.wait_for_quorum_phase(6, None, 0)
Expand All @@ -544,6 +552,7 @@ def mine_quorum(self, expected_valid_count=10):
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(1)
sync_blocks(self.nodes)

sync_blocks(self.nodes)

Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ BITCOIN_CORE_H = \
llmq/quorums_dkgsessionmgr.h \
llmq/quorums_dkgsession.h \
llmq/quorums_init.h \
llmq/quorums_instantsend.h \
llmq/quorums_signing.h \
llmq/quorums_signing_shares.h \
llmq/quorums_utils.h \
Expand Down Expand Up @@ -291,6 +292,7 @@ libdash_server_a_SOURCES = \
llmq/quorums_dkgsessionmgr.cpp \
llmq/quorums_dkgsession.cpp \
llmq/quorums_init.cpp \
llmq/quorums_instantsend.cpp \
llmq/quorums_signing.cpp \
llmq/quorums_signing_shares.cpp \
llmq/quorums_utils.cpp \
Expand Down
4 changes: 4 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ class CMainParams : public CChainParams {
consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60;
consensus.llmqs[Consensus::LLMQ_400_85] = llmq400_85;
consensus.llmqChainLocks = Consensus::LLMQ_400_60;
consensus.llmqForInstantSend = Consensus::LLMQ_50_60;

fMiningRequiresPeers = true;
fDefaultConsistencyChecks = false;
Expand Down Expand Up @@ -476,6 +477,7 @@ class CTestNetParams : public CChainParams {
consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60;
consensus.llmqs[Consensus::LLMQ_400_85] = llmq400_85;
consensus.llmqChainLocks = Consensus::LLMQ_50_60;
consensus.llmqForInstantSend = Consensus::LLMQ_50_60;

fMiningRequiresPeers = true;
fDefaultConsistencyChecks = false;
Expand Down Expand Up @@ -623,6 +625,7 @@ class CDevNetParams : public CChainParams {
consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60;
consensus.llmqs[Consensus::LLMQ_400_85] = llmq400_85;
consensus.llmqChainLocks = Consensus::LLMQ_50_60;
consensus.llmqForInstantSend = Consensus::LLMQ_50_60;

fMiningRequiresPeers = true;
fDefaultConsistencyChecks = false;
Expand Down Expand Up @@ -787,6 +790,7 @@ class CRegTestParams : public CChainParams {
consensus.llmqs[Consensus::LLMQ_10_60] = llmq10_60;
consensus.llmqs[Consensus::LLMQ_50_60] = llmq50_60;
consensus.llmqChainLocks = Consensus::LLMQ_10_60;
consensus.llmqForInstantSend = Consensus::LLMQ_10_60;
}

void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold)
Expand Down
1 change: 1 addition & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ struct Params {

std::map<LLMQType, LLMQParams> llmqs;
LLMQType llmqChainLocks;
LLMQType llmqForInstantSend{LLMQ_NONE};
};
} // namespace Consensus

Expand Down
13 changes: 13 additions & 0 deletions src/dsnotificationinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "llmq/quorums.h"
#include "llmq/quorums_chainlocks.h"
#include "llmq/quorums_instantsend.h"
#include "llmq/quorums_dkgsessionmgr.h"

void CDSNotificationInterface::InitializeCurrentBlockTip()
Expand Down Expand Up @@ -70,8 +71,15 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
llmq::quorumDKGSessionManager->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
}

void CDSNotificationInterface::NewPoWValidBlock(const CBlockIndex* pindex, const std::shared_ptr<const CBlock>& block)
{
llmq::chainLocksHandler->NewPoWValidBlock(pindex, block);
}

void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock)
{
llmq::quorumInstantSendManager->SyncTransaction(tx, pindex, posInBlock);
llmq::chainLocksHandler->SyncTransaction(tx, pindex, posInBlock);
instantsend.SyncTransaction(tx, pindex, posInBlock);
CPrivateSend::SyncTransaction(tx, pindex, posInBlock);
}
Expand All @@ -82,3 +90,8 @@ void CDSNotificationInterface::NotifyMasternodeListChanged(const CDeterministicM
governance.CheckMasternodeOrphanVotes(connman);
governance.UpdateCachesAndClean();
}

void CDSNotificationInterface::NotifyChainLock(const CBlockIndex* pindex)
{
llmq::quorumInstantSendManager->NotifyChainLock(pindex);
}
2 changes: 2 additions & 0 deletions src/dsnotificationinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ class CDSNotificationInterface : public CValidationInterface
void AcceptedBlockHeader(const CBlockIndex *pindexNew) override;
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) override;
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) override;
void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) override;
void NotifyMasternodeListChanged(const CDeterministicMNList& newList) override;
void NotifyChainLock(const CBlockIndex* pindex) override;

private:
CConnman& connman;
Expand Down
4 changes: 3 additions & 1 deletion src/governance-object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "util.h"
#include "validation.h"

#include "llmq/quorums_instantsend.h"

#include <string>
#include <univalue.h>

Expand Down Expand Up @@ -618,7 +620,7 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
}

if ((nConfirmationsIn < GOVERNANCE_FEE_CONFIRMATIONS) &&
(!instantsend.IsLockedInstantSendTransaction(nCollateralHash))) {
(!instantsend.IsLockedInstantSendTransaction(nCollateralHash) || llmq::quorumInstantSendManager->IsLocked(nCollateralHash))) {
strError = strprintf("Collateral requires at least %d confirmations to be relayed throughout the network (it has only %d)", GOVERNANCE_FEE_CONFIRMATIONS, nConfirmationsIn);
if (nConfirmationsIn >= GOVERNANCE_MIN_RELAY_FEE_CONFIRMATIONS) {
fMissingConfirmations = true;
Expand Down
Loading