Remove legacy InstantSend code (#3020)

* Remove ppszTypeName from protocol.cpp and reimplement GetCommand

This removes the need to carefully maintain ppszTypeName, which required
correct order and also did not allow to permanently remove old message
types.

To get the command name for an INV type, GetCommandInternal uses a switch
which needs to be maintained from now on.

The way this is implemented also resembles the way it is implemented in
Bitcoin today, but it's not identical. The original PR that introduced the
switch case in Bitcoin was part of the Segwit changes and thus never got
backported. I decided to implement it in a slightly different way that
avoids throwing exceptions when an unknown INV type is encountered.

IsKnownType will now also leverage GetCommandInternal() to figure out if
the INV type is known locally. This has the side effect of old/legacy
message types to return false from now on. We will depend on this side
effect in later commits when we remove legacy InstantSend code.

* Stop handling/relaying legacy IX messages

When we receive an IX message, we simply treat it as a regular TX and relay
it as such.

We'll however still request IX messages when they are announced to us. We
can't simply revert to requesting TX messages in this case as it might
result in the other peer not answering due to the TX not being in mapRelay
yet. We should at some point in the future completely drop handling of IX
messages instead.

* Remove IsNewInstantSendEnabled() and only use IsInstantSendEnabled()

* Remove legacy InstantSend from GUI

* Remove InstantSend from Bitcoin/Dash URIs

* Remove legacy InstantSend from RPC commands

* Remove legacy InstantSend from wallet

* Remove legacy instantsend.h include

* Remove legacy InstantSend from validation code

* Completely remove remaining legacy InstantSend code

* Remove now unused spork

* Fix InstantSend related test failures

* Remove now obsolete auto IS tests

* Make spork2 and spork3 disabled by default

This should have no influence on mainnet as these sporks are actually set
there. This will however affect regtest, which shouldn't have LLMQ based
InstantSend enabled by default.

* Remove instantsend tests from dip3-deterministicmns.py

These were only testing legacy InstantSend

* Fix .QCheckBox#checkUsePrivateSend styling a bit

* s/TXLEGACYLOCKREQUEST/LEGACYTXLOCKREQUEST/

* Revert "verified via InstantSend" back to "verified via LLMQ based InstantSend"

* Use cmd == nullptr instead of !cmd

* Remove last parameter from AvailableCoins call

This was for fUseInstantSend which is not present anymore since rebase
This commit is contained in:
Alexander Block 2019-07-09 16:50:08 +02:00 committed by UdjinM6
parent 7a440d626b
commit 2f21e55514
59 changed files with 159 additions and 2775 deletions

View File

@ -12,7 +12,6 @@
* evodb/*: special txes and quorums database
* fee_estimates.dat: stores statistics used to estimate minimum transaction fees and priorities required for confirmation
* governance.dat: stores data for governance obgects
* instantsend.dat: stores data for instantsend locks
* llmq/*: quorum signatures database
* mempool.dat: dump of the mempool's transactions
* mncache.dat: stores data for masternode list

View File

@ -153,7 +153,6 @@ BITCOIN_CORE_H = \
httpserver.h \
indirectmap.h \
init.h \
instantsend.h \
key.h \
keepass.h \
keystore.h \
@ -273,7 +272,6 @@ libdash_server_a_SOURCES = \
httprpc.cpp \
httpserver.cpp \
init.cpp \
instantsend.cpp \
dbwrapper.cpp \
governance/governance.cpp \
governance/governance-classes.cpp \

View File

@ -227,8 +227,6 @@ 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;
@ -409,8 +407,6 @@ 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;
@ -568,8 +564,6 @@ 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;
@ -734,8 +728,6 @@ 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;

View File

@ -125,8 +125,6 @@ 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

@ -4,7 +4,6 @@
#include "chainparams.h"
#include "dsnotificationinterface.h"
#include "instantsend.h"
#include "governance/governance.h"
#include "masternode/masternode-payments.h"
#include "masternode/masternode-sync.h"
@ -50,8 +49,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
// Update global DIP0001 activation status
fDIP0001ActiveAtTip = pindexNew->nHeight >= Params().GetConsensus().DIP0001Height;
// update instantsend autolock activation flag (we reuse the DIP3 deployment)
instantsend.isAutoLockBip9Active = pindexNew->nHeight + 1 >= Params().GetConsensus().DIP0003Height;
if (fInitialDownload)
return;
@ -67,7 +64,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
llmq::quorumInstantSendManager->UpdatedBlockTip(pindexNew);
llmq::chainLocksHandler->UpdatedBlockTip(pindexNew);
instantsend.UpdatedBlockTip(pindexNew);
governance.UpdatedBlockTip(pindexNew, connman);
llmq::quorumManager->UpdatedBlockTip(pindexNew, fInitialDownload);
llmq::quorumDKGSessionManager->UpdatedBlockTip(pindexNew, fInitialDownload);
@ -78,7 +74,6 @@ void CDSNotificationInterface::TransactionAddedToMempool(const CTransactionRef&
llmq::quorumInstantSendManager->TransactionAddedToMempool(ptx);
llmq::chainLocksHandler->TransactionAddedToMempool(ptx);
CPrivateSend::TransactionAddedToMempool(ptx);
instantsend.SyncTransaction(ptx);
}
void CDSNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted)
@ -94,13 +89,6 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock
llmq::quorumInstantSendManager->BlockConnected(pblock, pindex, vtxConflicted);
llmq::chainLocksHandler->BlockConnected(pblock, pindex, vtxConflicted);
CPrivateSend::BlockConnected(pblock, pindex, vtxConflicted);
for (const CTransactionRef& ptx : vtxConflicted) {
instantsend.SyncTransaction(ptx);
}
for (size_t i = 0; i < pblock->vtx.size(); i++) {
instantsend.SyncTransaction(pblock->vtx[i], pindex, i);
}
}
void CDSNotificationInterface::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected)
@ -108,10 +96,6 @@ void CDSNotificationInterface::BlockDisconnected(const std::shared_ptr<const CBl
llmq::quorumInstantSendManager->BlockDisconnected(pblock, pindexDisconnected);
llmq::chainLocksHandler->BlockDisconnected(pblock, pindexDisconnected);
CPrivateSend::BlockDisconnected(pblock, pindexDisconnected);
for (const CTransactionRef& ptx : pblock->vtx) {
instantsend.SyncTransaction(ptx, pindexDisconnected->pprev, -1);
}
}
void CDSNotificationInterface::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff)

View File

@ -52,7 +52,6 @@
#include "dsnotificationinterface.h"
#include "flat-database.h"
#include "governance/governance.h"
#include "instantsend.h"
#ifdef ENABLE_WALLET
#include "keepass.h"
#endif
@ -267,11 +266,6 @@ void PrepareShutdown()
flatdb3.Dump(governance);
CFlatDB<CNetFulfilledRequestManager> flatdb4("netfulfilled.dat", "magicFulfilledCache");
flatdb4.Dump(netfulfilledman);
if(fEnableInstantSend)
{
CFlatDB<CInstantSend> flatdb5("instantsend.dat", "magicInstantSendCache");
flatdb5.Dump(instantsend);
}
CFlatDB<CSporkManager> flatdb6("sporks.dat", "magicSporkCache");
flatdb6.Dump(sporkManager);
}
@ -616,7 +610,6 @@ std::string HelpMessage(HelpMessageMode mode)
#endif // ENABLE_WALLET
strUsage += HelpMessageGroup(_("InstantSend options:"));
strUsage += HelpMessageOpt("-enableinstantsend", strprintf(_("Enable InstantSend, show confirmations for locked transactions (0-1, default: %u)"), 1));
strUsage += HelpMessageOpt("-instantsendnotify=<cmd>", _("Execute command when a wallet InstantSend transaction is successfully locked (%s in cmd is replaced by TxID)"));
@ -2029,11 +2022,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
CPrivateSend::InitStandardDenominations();
// ********************************************************* Step 10b: setup InstantSend
fEnableInstantSend = gArgs.GetBoolArg("-enableinstantsend", 1);
// ********************************************************* Step 10c: Load cache data
// ********************************************************* Step 10b: Load cache data
// LOAD SERIALIZED DAT FILES INTO DATA CACHES FOR INTERNAL USE
@ -2063,27 +2052,15 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
if(!flatdb4.Load(netfulfilledman)) {
return InitError(_("Failed to load fulfilled requests cache from") + "\n" + (pathDB / strDBName).string());
}
if(fEnableInstantSend)
{
strDBName = "instantsend.dat";
uiInterface.InitMessage(_("Loading InstantSend data cache..."));
CFlatDB<CInstantSend> flatdb5(strDBName, "magicInstantSendCache");
if(!flatdb5.Load(instantsend)) {
return InitError(_("Failed to load InstantSend data cache from") + "\n" + (pathDB / strDBName).string());
}
}
}
// ********************************************************* Step 10d: schedule Dash-specific tasks
// ********************************************************* Step 10c: schedule Dash-specific tasks
if (!fLiteMode) {
scheduler.scheduleEvery(boost::bind(&CNetFulfilledRequestManager::DoMaintenance, boost::ref(netfulfilledman)), 60 * 1000);
scheduler.scheduleEvery(boost::bind(&CMasternodeSync::DoMaintenance, boost::ref(masternodeSync), boost::ref(*g_connman)), 1 * 1000);
scheduler.scheduleEvery(boost::bind(&CGovernanceManager::DoMaintenance, boost::ref(governance), boost::ref(*g_connman)), 60 * 5 * 1000);
scheduler.scheduleEvery(boost::bind(&CInstantSend::DoMaintenance, boost::ref(instantsend)), 60 * 1000);
}
scheduler.scheduleEvery(boost::bind(&CMasternodeUtils::DoMaintenance, boost::ref(*g_connman)), 1 * 1000);

File diff suppressed because it is too large Load Diff

View File

@ -1,392 +0,0 @@
// Copyright (c) 2014-2019 The Dash Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef INSTANTX_H
#define INSTANTX_H
#include "chain.h"
#include "net.h"
#include "primitives/transaction.h"
#include "evo/deterministicmns.h"
class CTxLockVote;
class COutPointLock;
class CTxLockRequest;
class CTxLockCandidate;
class CInstantSend;
extern CInstantSend instantsend;
/*
At 15 signatures, 1/2 of the masternode network can be owned by
one party without compromising the security of InstantSend
(1000/2150.0)**10 = 0.00047382219560689856
(1000/2900.0)**10 = 2.3769498616783657e-05
### getting 5 of 10 signatures w/ 1000 nodes of 2900
(1000/2900.0)**5 = 0.004875397277841433
*/
static const int MIN_INSTANTSEND_PROTO_VERSION = 70213;
/// For how long we are going to accept votes/locks
/// after we saw the first one for a specific transaction
static const int INSTANTSEND_LOCK_TIMEOUT_SECONDS = 15;
/// For how long we are going to keep invalid votes and votes for failed lock attempts,
/// must be greater than INSTANTSEND_LOCK_TIMEOUT_SECONDS
static const int INSTANTSEND_FAILED_TIMEOUT_SECONDS = 60;
extern bool fEnableInstantSend;
/**
* Manages InstantSend. Processes lock requests, candidates, and votes.
*/
class CInstantSend
{
public:
/// Automatic locks of "simple" transactions are only allowed
/// when mempool usage is lower than this threshold
static const double AUTO_IX_MEMPOOL_THRESHOLD;
private:
static const std::string SERIALIZATION_VERSION_STRING;
// Keep track of current block height
int nCachedBlockHeight;
// maps for AlreadyHave
std::map<uint256, CTxLockRequest> mapLockRequestAccepted; ///< Tx hash - Tx
std::map<uint256, CTxLockRequest> mapLockRequestRejected; ///< Tx hash - Tx
std::map<uint256, CTxLockVote> mapTxLockVotes; ///< Vote hash - Vote
std::map<uint256, CTxLockVote> mapTxLockVotesOrphan; ///< Vote hash - Vote
std::map<uint256, CTxLockCandidate> mapTxLockCandidates; ///< Tx hash - Lock candidate
std::map<COutPoint, std::set<uint256> > mapVotedOutpoints; ///< UTXO - Tx hash set
std::map<COutPoint, uint256> mapLockedOutpoints; ///< UTXO - Tx hash
/// Track masternodes who voted with no txlockrequest (for DOS protection)
std::map<COutPoint, int64_t> mapMasternodeOrphanVotes; ///< MN outpoint - Time
bool CreateTxLockCandidate(const CTxLockRequest& txLockRequest);
void CreateEmptyTxLockCandidate(const uint256& txHash);
void Vote(CTxLockCandidate& txLockCandidate, CConnman& connman);
/// Process consensus vote message
bool ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, CConnman& connman);
void UpdateVotedOutpoints(const CTxLockVote& vote, CTxLockCandidate& txLockCandidate);
bool ProcessOrphanTxLockVote(const CTxLockVote& vote);
void ProcessOrphanTxLockVotes();
int64_t GetAverageMasternodeOrphanVoteTime();
void TryToFinalizeLockCandidate(const CTxLockCandidate& txLockCandidate);
void LockTransactionInputs(const CTxLockCandidate& txLockCandidate);
/// Update UI and notify external script if any
void UpdateLockedTransaction(const CTxLockCandidate& txLockCandidate);
bool ResolveConflicts(const CTxLockCandidate& txLockCandidate);
public:
mutable CCriticalSection cs_instantsend;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
std::string strVersion;
if(ser_action.ForRead()) {
READWRITE(strVersion);
}
else {
strVersion = SERIALIZATION_VERSION_STRING;
READWRITE(strVersion);
}
READWRITE(mapLockRequestAccepted);
READWRITE(mapLockRequestRejected);
READWRITE(mapTxLockVotes);
READWRITE(mapTxLockVotesOrphan);
READWRITE(mapTxLockCandidates);
READWRITE(mapVotedOutpoints);
READWRITE(mapLockedOutpoints);
READWRITE(mapMasternodeOrphanVotes);
READWRITE(nCachedBlockHeight);
if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) {
Clear();
}
}
void Clear();
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
bool ProcessTxLockRequest(const CTxLockRequest& txLockRequest, CConnman& connman);
void Vote(const uint256& txHash, CConnman& connman);
bool AlreadyHave(const uint256& hash);
void AcceptLockRequest(const CTxLockRequest& txLockRequest);
void RejectLockRequest(const CTxLockRequest& txLockRequest);
bool HasTxLockRequest(const uint256& txHash);
bool GetTxLockRequest(const uint256& txHash, CTxLockRequest& txLockRequestRet);
bool GetTxLockVote(const uint256& hash, CTxLockVote& txLockVoteRet);
bool GetLockedOutPointTxHash(const COutPoint& outpoint, uint256& hashRet);
/// Verify if transaction is currently locked
bool IsLockedInstantSendTransaction(const uint256& txHash);
/// Get the actual number of accepted lock signatures
int GetTransactionLockSignatures(const uint256& txHash);
/// Remove expired entries from maps
void CheckAndRemove();
/// Verify if transaction lock timed out
bool IsTxLockCandidateTimedOut(const uint256& txHash);
void Relay(const uint256& txHash, CConnman& connman);
void UpdatedBlockTip(const CBlockIndex *pindex);
void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0);
std::string ToString() const;
void DoMaintenance();
/// checks if we can automatically lock "simple" transactions
static bool CanAutoLock();
/// flag of the AutoLock Bip9 activation
static std::atomic<bool> isAutoLockBip9Active;
};
/**
* An InstantSend transaction lock request.
*/
class CTxLockRequest
{
private:
static const CAmount MIN_FEE = 0.0001 * COIN;
/// If transaction has less or equal inputs than MAX_INPUTS_FOR_AUTO_IX,
/// it will be automatically locked
static const int MAX_INPUTS_FOR_AUTO_IX = 4;
public:
/// Warn for a large number of inputs to an IS tx - fees could be substantial
/// and the number txlvote responses requested large (10 * # of inputs)
static const int WARN_MANY_INPUTS = 100;
CTransactionRef tx;
CTxLockRequest() : tx(MakeTransactionRef()) {}
CTxLockRequest(const CTransaction& _tx) : tx(MakeTransactionRef(_tx)) {};
CTxLockRequest(const CTransactionRef& _tx) : tx(_tx) {};
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(tx);
}
bool IsValid() const;
CAmount GetMinFee(bool fForceMinFee) const;
int GetMaxSignatures() const;
// checks if related transaction is "simple" to lock it automatically
bool IsSimple() const;
const uint256 &GetHash() const {
return tx->GetHash();
}
std::string ToString() const {
return tx->ToString();
}
friend bool operator==(const CTxLockRequest& a, const CTxLockRequest& b)
{
return *a.tx == *b.tx;
}
friend bool operator!=(const CTxLockRequest& a, const CTxLockRequest& b)
{
return *a.tx != *b.tx;
}
explicit operator bool() const
{
return *this != CTxLockRequest();
}
};
/**
* An InstantSend transaction lock vote. Sent by a masternode in response to a
* transaction lock request (ix message) to indicate the transaction input can
* be locked. Contains the proposed transaction's hash and the outpoint being
* locked along with the masternodes outpoint and signature.
* @see CTxLockRequest
*/
class CTxLockVote
{
private:
uint256 txHash;
COutPoint outpoint;
// TODO remove this member (not needed anymore after DIP3 has been deployed)
COutPoint outpointMasternode;
uint256 quorumModifierHash;
uint256 masternodeProTxHash;
std::vector<unsigned char> vchMasternodeSignature;
// local memory only
int nConfirmedHeight; ///< When corresponding tx is 0-confirmed or conflicted, nConfirmedHeight is -1
int64_t nTimeCreated;
public:
CTxLockVote() :
txHash(),
outpoint(),
outpointMasternode(),
quorumModifierHash(),
masternodeProTxHash(),
vchMasternodeSignature(),
nConfirmedHeight(-1),
nTimeCreated(GetTime())
{}
CTxLockVote(const uint256& txHashIn, const COutPoint& outpointIn, const COutPoint& outpointMasternodeIn, const uint256& quorumModifierHashIn, const uint256& masternodeProTxHashIn) :
txHash(txHashIn),
outpoint(outpointIn),
outpointMasternode(outpointMasternodeIn),
quorumModifierHash(quorumModifierHashIn),
masternodeProTxHash(masternodeProTxHashIn),
vchMasternodeSignature(),
nConfirmedHeight(-1),
nTimeCreated(GetTime())
{}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(txHash);
READWRITE(outpoint);
READWRITE(outpointMasternode);
READWRITE(quorumModifierHash);
READWRITE(masternodeProTxHash);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchMasternodeSignature);
}
}
uint256 GetHash() const;
uint256 GetSignatureHash() const;
uint256 GetTxHash() const { return txHash; }
COutPoint GetOutpoint() const { return outpoint; }
COutPoint GetMasternodeOutpoint() const { return outpointMasternode; }
bool IsValid(CNode* pnode, CConnman& connman) const;
void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; }
bool IsExpired(int nHeight) const;
bool IsTimedOut() const;
bool IsFailed() const;
bool Sign();
bool CheckSignature() const;
void Relay(CConnman& connman) const;
};
/**
* An InstantSend OutpointLock.
*/
class COutPointLock
{
private:
COutPoint outpoint; ///< UTXO
std::map<COutPoint, CTxLockVote> mapMasternodeVotes; ///< Masternode outpoint - vote
bool fAttacked = false;
public:
COutPointLock() {}
COutPointLock(const COutPoint& outpointIn) :
outpoint(outpointIn),
mapMasternodeVotes()
{}
COutPoint GetOutpoint() const { return outpoint; }
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(outpoint);
READWRITE(mapMasternodeVotes);
READWRITE(fAttacked);
}
bool AddVote(const CTxLockVote& vote);
std::vector<CTxLockVote> GetVotes() const;
bool HasMasternodeVoted(const COutPoint& outpointMasternodeIn) const;
int CountVotes() const { return fAttacked ? 0 : mapMasternodeVotes.size(); }
bool IsReady() const;
void MarkAsAttacked() { fAttacked = true; }
void Relay(CConnman& connman) const;
};
/**
* An InstantSend transaction lock candidate.
*/
class CTxLockCandidate
{
private:
int nConfirmedHeight; ///<When corresponding tx is 0-confirmed or conflicted, nConfirmedHeight is -1
int64_t nTimeCreated;
public:
CTxLockCandidate() :
nConfirmedHeight(-1),
nTimeCreated(GetTime())
{}
CTxLockCandidate(const CTxLockRequest& txLockRequestIn) :
nConfirmedHeight(-1),
nTimeCreated(GetTime()),
txLockRequest(txLockRequestIn),
mapOutPointLocks()
{}
CTxLockRequest txLockRequest;
std::map<COutPoint, COutPointLock> mapOutPointLocks;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(txLockRequest);
READWRITE(mapOutPointLocks);
READWRITE(nTimeCreated);
READWRITE(nConfirmedHeight);
}
uint256 GetHash() const { return txLockRequest.GetHash(); }
void AddOutPointLock(const COutPoint& outpoint);
void MarkOutpointAsAttacked(const COutPoint& outpoint);
bool AddVote(const CTxLockVote& vote);
bool IsAllOutPointsReady() const;
bool HasMasternodeVoted(const COutPoint& outpointIn, const COutPoint& outpointMasternodeIn);
int CountVotes() const;
void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; }
bool IsExpired(int nHeight) const;
bool IsTimedOut() const;
void Relay(CConnman& connman) const;
};
#endif

View File

@ -286,7 +286,7 @@ void CChainLocksHandler::TrySignChainTip()
// considered safe when it is ixlocked or at least known since 10 minutes (from mempool or block). These checks are
// performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the
// way down, we consider all TXs to be safe.
if (IsNewInstantSendEnabled() && sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
if (IsInstantSendEnabled() && sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
auto pindexWalk = pindex;
while (pindexWalk) {
if (pindex->nHeight - pindexWalk->nHeight > 5) {
@ -453,7 +453,7 @@ bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid)
if (!sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
return true;
}
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return true;
}

View File

@ -19,9 +19,6 @@
#include "wallet/wallet.h"
#endif
// needed for AUTO_IX_MEMPOOL_THRESHOLD
#include "instantsend.h"
#include <boost/algorithm/string/replace.hpp>
#include <boost/thread.hpp>
@ -383,7 +380,7 @@ void CInstantSendManager::InterruptWorkerThread()
bool CInstantSendManager::ProcessTx(const CTransaction& tx, const Consensus::Params& params)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return true;
}
@ -466,10 +463,6 @@ bool CInstantSendManager::ProcessTx(const CTransaction& tx, const Consensus::Par
bool CInstantSendManager::CheckCanLock(const CTransaction& tx, bool printDebug, const Consensus::Params& params)
{
if (sporkManager.IsSporkActive(SPORK_16_INSTANTSEND_AUTOLOCKS) && (mempool.UsedMemoryShare() > CInstantSend::AUTO_IX_MEMPOOL_THRESHOLD)) {
return false;
}
if (tx.vin.empty()) {
// can't lock TXs without inputs (e.g. quorum commitments)
return false;
@ -485,18 +478,6 @@ bool CInstantSendManager::CheckCanLock(const CTransaction& tx, bool printDebug,
nValueIn += v;
}
// TODO decide if we should limit max input values. This was ok to do in the old system, but in the new system
// where we want to have all TXs locked at some point, this is counterproductive (especially when ChainLocks later
// depend on all TXs being locked first)
// CAmount maxValueIn = sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE);
// if (nValueIn > maxValueIn * COIN) {
// if (printDebug) {
// LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: TX input value too high. nValueIn=%f, maxValueIn=%d", __func__,
// tx.GetHash().ToString(), nValueIn / (double)COIN, maxValueIn);
// }
// return false;
// }
return true;
}
@ -556,7 +537,7 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu
void CInstantSendManager::HandleNewRecoveredSig(const CRecoveredSig& recoveredSig)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return;
}
@ -674,7 +655,7 @@ void CInstantSendManager::HandleNewInstantSendLockRecoveredSig(const llmq::CReco
void CInstantSendManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return;
}
@ -747,7 +728,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks()
return false;
}
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return false;
}
@ -936,7 +917,7 @@ void CInstantSendManager::UpdateWalletTransaction(const CTransactionRef& tx, con
void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const CBlockIndex* pindex)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return;
}
@ -985,7 +966,7 @@ void CInstantSendManager::TransactionAddedToMempool(const CTransactionRef& tx)
void CInstantSendManager::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return;
}
@ -1323,7 +1304,7 @@ bool CInstantSendManager::ProcessPendingRetryLockTxs()
return false;
}
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return false;
}
@ -1380,7 +1361,7 @@ bool CInstantSendManager::ProcessPendingRetryLockTxs()
bool CInstantSendManager::AlreadyHave(const CInv& inv)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return true;
}
@ -1390,7 +1371,7 @@ bool CInstantSendManager::AlreadyHave(const CInv& inv)
bool CInstantSendManager::GetInstantSendLockByHash(const uint256& hash, llmq::CInstantSendLock& ret)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return false;
}
@ -1405,7 +1386,7 @@ bool CInstantSendManager::GetInstantSendLockByHash(const uint256& hash, llmq::CI
bool CInstantSendManager::IsLocked(const uint256& txHash)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return false;
}
@ -1420,7 +1401,7 @@ bool CInstantSendManager::IsConflicted(const CTransaction& tx)
CInstantSendLockPtr CInstantSendManager::GetConflictingLock(const CTransaction& tx)
{
if (!IsNewInstantSendEnabled()) {
if (!IsInstantSendEnabled()) {
return nullptr;
}
@ -1459,16 +1440,6 @@ void CInstantSendManager::WorkThreadMain()
}
}
bool IsOldInstantSendEnabled()
{
return sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED) && !sporkManager.IsSporkActive(SPORK_20_INSTANTSEND_LLMQ_BASED);
}
bool IsNewInstantSendEnabled()
{
return sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED) && sporkManager.IsSporkActive(SPORK_20_INSTANTSEND_LLMQ_BASED);
}
bool IsInstantSendEnabled()
{
return sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED);

View File

@ -170,13 +170,6 @@ public:
extern CInstantSendManager* quorumInstantSendManager;
// This involves 2 sporks: SPORK_2_INSTANTSEND_ENABLED and SPORK_20_INSTANTSEND_LLMQ_BASED
// SPORK_2_INSTANTSEND_ENABLED generally enables/disables InstantSend and SPORK_20_INSTANTSEND_LLMQ_BASED switches
// between the old and the new (LLMQ based) system
// TODO When the new system is fully deployed and enabled, we can remove this special handling in a future version
// and revert to only using SPORK_2_INSTANTSEND_ENABLED.
bool IsOldInstantSendEnabled();
bool IsNewInstantSendEnabled();
bool IsInstantSendEnabled();
}

View File

@ -25,10 +25,9 @@
#include "utilstrencodings.h"
#include "validation.h"
#include "instantsend.h"
#include "masternode/masternode-sync.h"
#include "privatesend/privatesend.h"
#include "llmq/quorums_instantsend.h"
#include "evo/deterministicmns.h"
#ifdef WIN32
#include <string.h>
@ -2892,21 +2891,11 @@ void CConnman::RelayTransaction(const CTransaction& tx)
int nInv = MSG_TX;
if (CPrivateSend::GetDSTX(hash)) {
nInv = MSG_DSTX;
} else if (llmq::IsOldInstantSendEnabled() && instantsend.HasTxLockRequest(hash)) {
nInv = MSG_TXLOCK_REQUEST;
}
CInv inv(nInv, hash);
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if (nInv == MSG_TXLOCK_REQUEST) {
// Additional filtering for lock requests.
// Make it here because lock request processing
// differs from simple tx processing in PushInventory
// and tx info will not be available there.
LOCK(pnode->cs_filter);
if(pnode->pfilter && !pnode->pfilter->IsRelevantAndUpdate(tx)) continue;
}
pnode->PushInventory(inv);
}
}

View File

@ -32,7 +32,6 @@
#include "spork.h"
#include "governance/governance.h"
#include "instantsend.h"
#include "masternode/masternode-payments.h"
#include "masternode/masternode-sync.h"
#include "masternode/masternode-meta.h"
@ -954,6 +953,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
switch (inv.type)
{
case MSG_TX:
case MSG_LEGACY_TXLOCK_REQUEST: // we treat legacy IX messages as TX messages
{
assert(recentRejects);
if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip)
@ -989,11 +989,6 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
We're going to be asking many nodes upfront for the full inventory list, so we'll get duplicates of these.
We want to only update the time on new hits, so that we can time out appropriately if needed.
*/
case MSG_TXLOCK_REQUEST:
return instantsend.AlreadyHave(inv.hash);
case MSG_TXLOCK_VOTE:
return instantsend.AlreadyHave(inv.hash);
case MSG_SPORK:
{
@ -1215,8 +1210,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// Send stream from relay memory
bool push = false;
// Only serve MSG_TX from mapRelay.
// Otherwise we may send out a normal TX instead of a IX
if (inv.type == MSG_TX) {
auto mi = mapRelay.find(inv.hash);
if (mi != mapRelay.end()) {
@ -1233,22 +1226,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
if (!push && inv.type == MSG_TXLOCK_REQUEST) {
CTxLockRequest txLockRequest;
if(instantsend.GetTxLockRequest(inv.hash, txLockRequest)) {
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::TXLOCKREQUEST, txLockRequest));
push = true;
}
}
if (!push && inv.type == MSG_TXLOCK_VOTE) {
CTxLockVote vote;
if(instantsend.GetTxLockVote(inv.hash, vote)) {
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::TXLOCKVOTE, vote));
push = true;
}
}
if (!push && inv.type == MSG_SPORK) {
CSporkMessage spork;
if(sporkManager.GetSporkByHash(inv.hash, spork)) {
@ -2087,7 +2064,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
else if (strCommand == NetMsgType::TX || strCommand == NetMsgType::DSTX || strCommand == NetMsgType::TXLOCKREQUEST)
else if (strCommand == NetMsgType::TX || strCommand == NetMsgType::DSTX || strCommand == NetMsgType::LEGACYTXLOCKREQUEST)
{
// Stop processing the transaction early if
// We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off
@ -2100,25 +2077,15 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::deque<COutPoint> vWorkQueue;
std::vector<uint256> vEraseQueue;
CTransactionRef ptx;
CTxLockRequest txLockRequest;
CPrivateSendBroadcastTx dstx;
int nInvType = MSG_TX;
bool fCanAutoLock = false;
// Read data and assign inv type
if(strCommand == NetMsgType::TX) {
vRecv >> ptx;
txLockRequest = CTxLockRequest(ptx);
fCanAutoLock = llmq::IsOldInstantSendEnabled() && CInstantSend::CanAutoLock() && txLockRequest.IsSimple();
} else if(strCommand == NetMsgType::TXLOCKREQUEST) {
vRecv >> txLockRequest;
ptx = txLockRequest.tx;
nInvType = MSG_TXLOCK_REQUEST;
if (llmq::IsNewInstantSendEnabled()) {
// the new system does not require explicit lock requests
// changing the inv type to MSG_TX also results in re-broadcasting the TX as normal TX
nInvType = MSG_TX;
}
} else if(strCommand == NetMsgType::LEGACYTXLOCKREQUEST) {
// we keep processing the legacy IX message here but revert to handling it as a regular TX
vRecv >> ptx;
} else if (strCommand == NetMsgType::DSTX) {
vRecv >> dstx;
ptx = dstx.tx;
@ -2134,18 +2101,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
// Process custom logic, no matter if tx will be accepted to mempool later or not
if (nInvType == MSG_TXLOCK_REQUEST || fCanAutoLock) {
if(!instantsend.ProcessTxLockRequest(txLockRequest, connman)) {
LogPrint(BCLog::INSTANTSEND, "TXLOCKREQUEST -- failed %s\n", txLockRequest.GetHash().ToString());
// Should not really happen for "fCanAutoLock == true" but just in case:
if (!fCanAutoLock) {
// Fail only for "true" IS here
return false;
}
// Fallback for normal txes to process as usual
fCanAutoLock = false;
}
} else if (nInvType == MSG_DSTX) {
if (nInvType == MSG_DSTX) {
uint256 hashTx = tx.GetHash();
if (!dstx.IsValidStructure()) {
LogPrint(BCLog::PRIVATESEND, "DSTX -- Invalid DSTX structure: %s\n", hashTx.ToString());
@ -2190,11 +2146,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LogPrintf("DSTX -- Masternode transaction accepted, txid=%s, peer=%d\n",
tx.GetHash().ToString(), pfrom->GetId());
CPrivateSend::AddDSTX(dstx);
} else if (nInvType == MSG_TXLOCK_REQUEST || fCanAutoLock) {
LogPrintf("TXLOCKREQUEST -- Transaction Lock Request accepted, txid=%s, peer=%d\n",
tx.GetHash().ToString(), pfrom->GetId());
instantsend.AcceptLockRequest(txLockRequest);
instantsend.Vote(tx.GetHash(), connman);
}
mempool.check(pcoinsTip);
@ -2306,19 +2257,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
}
if (nInvType == MSG_TXLOCK_REQUEST && !AlreadyHave(inv)) {
// i.e. AcceptToMemoryPool failed, probably because it's conflicting
// with existing normal tx or tx lock for another tx. For the same tx lock
// AlreadyHave would have return "true" already.
// It's the first time we failed for this tx lock request,
// this should switch AlreadyHave to "true".
instantsend.RejectLockRequest(txLockRequest);
// this lets other nodes to create lock request candidate i.e.
// this allows multiple conflicting lock requests to compete for votes
connman.RelayTransaction(tx);
}
if (pfrom->fWhitelisted && gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) {
// Always relay transactions received from whitelisted peers, even
// if they were already in the mempool or rejected from it due
@ -3020,7 +2958,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
privateSendClient.ProcessMessage(pfrom, strCommand, vRecv, connman);
#endif // ENABLE_WALLET
privateSendServer.ProcessMessage(pfrom, strCommand, vRecv, connman);
instantsend.ProcessMessage(pfrom, strCommand, vRecv, connman);
sporkManager.ProcessSpork(pfrom, strCommand, vRecv, connman);
masternodeSync.ProcessMessage(pfrom, strCommand, vRecv);
governance.ProcessMessage(pfrom, strCommand, vRecv, connman);

View File

@ -39,8 +39,7 @@ const char *CMPCTBLOCK="cmpctblock";
const char *GETBLOCKTXN="getblocktxn";
const char *BLOCKTXN="blocktxn";
// Dash message types
const char *TXLOCKREQUEST="ix";
const char *TXLOCKVOTE="txlvote";
const char *LEGACYTXLOCKREQUEST="ix";
const char *SPORK="spork";
const char *GETSPORKS="getsporks";
const char *DSACCEPT="dsa";
@ -75,43 +74,6 @@ const char *ISLOCK="islock";
const char *MNAUTH="mnauth";
};
static const char* ppszTypeName[] =
{
"ERROR", // Should never occur
NetMsgType::TX,
NetMsgType::BLOCK,
"filtered block", // Should never occur
// Dash message types
// NOTE: include non-implmented here, we must keep this list in sync with enum in protocol.h
NetMsgType::TXLOCKREQUEST,
NetMsgType::TXLOCKVOTE,
NetMsgType::SPORK,
"unused inv type 7",
"unused inv type 8",
"unused inv type 9",
"unused inv type 10",
"unused inv type 11",
"unused inv type 12",
"unused inv type 13",
"unused inv type 14",
"unused inv type 15",
NetMsgType::DSTX,
NetMsgType::MNGOVERNANCEOBJECT,
NetMsgType::MNGOVERNANCEOBJECTVOTE,
"unused inv type 19",
"compact block", // Should never occur
NetMsgType::QFCOMMITMENT,
"qdcommit", // was only shortly used on testnet
NetMsgType::QCONTRIB,
NetMsgType::QCOMPLAINT,
NetMsgType::QJUSTIFICATION,
NetMsgType::QPCOMMITMENT,
"qdebugstatus", // was only shortly used on testnet
NetMsgType::QSIGREC,
NetMsgType::CLSIG,
NetMsgType::ISLOCK,
};
/** All known message types. Keep this in the same order as the list of
* messages above and in protocol.h.
*/
@ -143,8 +105,7 @@ const static std::string allNetMessageTypes[] = {
NetMsgType::BLOCKTXN,
// Dash message types
// NOTE: do NOT include non-implmented here, we want them to be "Unknown command" in ProcessMessage()
NetMsgType::TXLOCKREQUEST,
NetMsgType::TXLOCKVOTE,
NetMsgType::LEGACYTXLOCKREQUEST,
NetMsgType::SPORK,
NetMsgType::GETSPORKS,
NetMsgType::SENDDSQUEUE,
@ -259,22 +220,6 @@ CInv::CInv()
CInv::CInv(int typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
CInv::CInv(const std::string& strType, const uint256& hashIn)
{
unsigned int i;
for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
{
if (strType == ppszTypeName[i])
{
type = i;
break;
}
}
if (i == ARRAYLEN(ppszTypeName))
throw std::out_of_range(strprintf("CInv::CInv(string, uint256): unknown type '%s'", strType));
hash = hashIn;
}
bool operator<(const CInv& a, const CInv& b)
{
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
@ -282,22 +227,51 @@ bool operator<(const CInv& a, const CInv& b)
bool CInv::IsKnownType() const
{
return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
return GetCommandInternal() != nullptr;
}
const char* CInv::GetCommand() const
const char* CInv::GetCommandInternal() const
{
if (!IsKnownType())
switch (type)
{
case MSG_TX: return NetMsgType::TX;
case MSG_BLOCK: return NetMsgType::BLOCK;
case MSG_FILTERED_BLOCK: return NetMsgType::MERKLEBLOCK;
case MSG_LEGACY_TXLOCK_REQUEST: return NetMsgType::LEGACYTXLOCKREQUEST;
case MSG_CMPCT_BLOCK: return NetMsgType::CMPCTBLOCK;
case MSG_SPORK: return NetMsgType::SPORK;
case MSG_DSTX: return NetMsgType::DSTX;
case MSG_GOVERNANCE_OBJECT: return NetMsgType::MNGOVERNANCEOBJECT;
case MSG_GOVERNANCE_OBJECT_VOTE: return NetMsgType::MNGOVERNANCEOBJECTVOTE;
case MSG_QUORUM_FINAL_COMMITMENT: return NetMsgType::QFCOMMITMENT;
case MSG_QUORUM_CONTRIB: return NetMsgType::QCONTRIB;
case MSG_QUORUM_COMPLAINT: return NetMsgType::QCOMPLAINT;
case MSG_QUORUM_JUSTIFICATION: return NetMsgType::QJUSTIFICATION;
case MSG_QUORUM_PREMATURE_COMMITMENT: return NetMsgType::QPCOMMITMENT;
case MSG_QUORUM_RECOVERED_SIG: return NetMsgType::QSIGREC;
case MSG_CLSIG: return NetMsgType::CLSIG;
case MSG_ISLOCK: return NetMsgType::ISLOCK;
default:
return nullptr;
}
}
std::string CInv::GetCommand() const
{
auto cmd = GetCommandInternal();
if (cmd == nullptr) {
throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
return ppszTypeName[type];
}
return cmd;
}
std::string CInv::ToString() const
{
try {
return strprintf("%s %s", GetCommand(), hash.ToString());
} catch(const std::out_of_range &) {
auto cmd = GetCommandInternal();
if (!cmd) {
return strprintf("0x%08x %s", type, hash.ToString());
} else {
return strprintf("%s %s", cmd, hash.ToString());
}
}

View File

@ -239,8 +239,7 @@ extern const char *BLOCKTXN;
// Dash message types
// NOTE: do NOT declare non-implmented here, we don't want them to be exposed to the outside
// TODO: add description
extern const char *TXLOCKREQUEST;
extern const char *TXLOCKVOTE;
extern const char *LEGACYTXLOCKREQUEST; // only present for backwards compatibility
extern const char *SPORK;
extern const char *GETSPORKS;
extern const char *DSACCEPT;
@ -355,8 +354,8 @@ enum GetDataMsg {
MSG_FILTERED_BLOCK = 3, //!< Defined in BIP37
// Dash message types
// NOTE: declare non-implmented here, we must keep this enum consistent and backwards compatible
MSG_TXLOCK_REQUEST = 4,
MSG_TXLOCK_VOTE = 5,
MSG_LEGACY_TXLOCK_REQUEST = 4,
/* MSG_TXLOCK_VOTE = 5, Legacy InstantSend and not used anymore */
MSG_SPORK = 6,
/* 7 - 15 were used in old Dash versions and were mainly budget and MN broadcast/ping related*/
MSG_DSTX = 16,
@ -384,7 +383,6 @@ class CInv
public:
CInv();
CInv(int typeIn, const uint256& hashIn);
CInv(const std::string& strType, const uint256& hashIn);
ADD_SERIALIZE_METHODS;
@ -398,9 +396,12 @@ public:
friend bool operator<(const CInv& a, const CInv& b);
bool IsKnownType() const;
const char* GetCommand() const;
std::string GetCommand() const;
std::string ToString() const;
private:
const char* GetCommandInternal() const;
// TODO: make private (improves encapsulation)
public:
int type;

View File

@ -21,7 +21,6 @@
#include "validation.h" // For mempool
#include "wallet/wallet.h"
#include "instantsend.h"
#include "privatesend/privatesend-client.h"
#include <QApplication>
@ -536,10 +535,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
nBytesInputs += 148; // in all error cases, simply assume 148 here
}
else nBytesInputs += 148;
// Add inputs to calculate InstantSend Fee later
if(coinControl->fUseInstantSend)
txDummy.vin.push_back(CTxIn());
}
// calculation
@ -556,9 +551,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// Fee
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, ::mempool, ::feeEstimator);
// InstantSend Fee
if (coinControl->fUseInstantSend) nPayFee = std::max(nPayFee, CTxLockRequest(txDummy).GetMinFee(true));
if (nPayAmount > 0)
{
nChange = nAmount - nPayAmount;

View File

@ -127,7 +127,7 @@
</property>
</widget>
</item>
<item row="9" column="2">
<item row="8" column="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="receiveButton">
@ -176,23 +176,13 @@
</item>
</layout>
</item>
<item row="9" column="0">
<item row="8" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QCheckBox" name="checkUseInstantSend">
<property name="text">
<string>Request InstantSend</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@ -1278,22 +1278,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkUseInstantSend">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>InstantSend</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">

View File

@ -165,7 +165,6 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
QList<QPair<QString, QString> > items = uriQuery.queryItems();
#endif
rv.fUseInstantSend = false;
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
{
bool fShouldReturnFalse = false;
@ -182,9 +181,7 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
}
if (i->first == "IS")
{
if(i->second.compare(QString("1")) == 0)
rv.fUseInstantSend = true;
// we simply ignore IS
fShouldReturnFalse = false;
}
if (i->first == "message")
@ -253,12 +250,6 @@ QString formatBitcoinURI(const SendCoinsRecipient &info)
paramCount++;
}
if(info.fUseInstantSend)
{
ret += QString("%1IS=1").arg(paramCount == 0 ? "?" : "&");
paramCount++;
}
return ret;
}

View File

@ -18,7 +18,6 @@
#include "utilitydialog.h"
#include "walletmodel.h"
#include "instantsend.h"
#include "masternode/masternode-sync.h"
#include "privatesend/privatesend-client.h"

View File

@ -157,7 +157,6 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
}
SendCoinsRecipient info(address, label,
ui->reqAmount->value(), ui->reqMessage->text());
info.fUseInstantSend = ui->checkUseInstantSend->isChecked();
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModel(model->getOptionsModel());

View File

@ -149,7 +149,6 @@ void ReceiveRequestDialog::update()
html += "<b>"+tr("Label")+"</b>: " + GUIUtil::HtmlEscape(info.label) + "<br>";
if(!info.message.isEmpty())
html += "<b>"+tr("Message")+"</b>: " + GUIUtil::HtmlEscape(info.message) + "<br>";
html += "<b>"+tr("InstantSend")+"</b>: " + (info.fUseInstantSend ? tr("Yes") : tr("No")) + "<br>";
ui->outUri->setText(html);
#ifdef USE_QRCODE

View File

@ -1288,16 +1288,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
}
QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */
color:#555555;
font-weight:bold;
background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0));
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
margin-left:10px;
margin-right:20px;
}

View File

@ -1272,16 +1272,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
}
QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */
color:#616161;
font-weight:bold;
background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0));
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
margin-left:10px;
margin-right:20px;
}

View File

@ -1278,16 +1278,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
}
QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */
color:#616161;
font-weight:bold;
background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0));
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
margin-left:10px;
margin-right:20px;
}

View File

@ -1278,16 +1278,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
}
QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */
color:#616161;
font-weight:bold;
background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0));
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
margin-left:10px;
margin-right:20px;
}

View File

@ -1279,16 +1279,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
}
QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */
color:#616161;
font-weight:bold;
background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0));
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
margin-left:10px;
margin-right:20px;
}

View File

@ -1279,16 +1279,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
}
QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */
color:#616161;
font-weight:bold;
background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0));
border-radius:5px;
padding-top:20px;
padding-bottom:18px;
margin-left:10px;
margin-right:20px;
}

View File

@ -11,11 +11,6 @@ QWidget#contentWidget { /* The actual content with the text/buttons/etc... */
/* SEND DIALOG */
QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */
margin-left:10px;
margin-right:20px;
}
QDialog#SendCoinsDialog QLabel#labelBalance {
margin-left:0px;
padding-left:0px;

View File

@ -82,11 +82,11 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
//TODO remove InstantX sometime after 0.14.1
if (settings.contains("bUseInstantX")) {
settings.setValue("bUseInstantSend", settings.value("bUseInstantX").toBool());
settings.remove("bUseInstantX");
}
if (!settings.contains("bUseInstantSend"))
settings.setValue("bUseInstantSend", false);
if (settings.contains("bUseInstantSend")) {
settings.remove("bUseInstantSend");
}
if (!privateSendClient.fEnablePrivateSend) {
ui->checkUsePrivateSend->setChecked(false);
@ -99,17 +99,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
connect(ui->checkUsePrivateSend, SIGNAL(stateChanged ( int )), this, SLOT(updateDisplayUnit()));
}
if (fLiteMode) {
ui->checkUseInstantSend->setChecked(false);
ui->checkUseInstantSend->setVisible(false);
CoinControlDialog::coinControl->fUseInstantSend = false;
} else{
bool fUseInstantSend = settings.value("bUseInstantSend").toBool();
ui->checkUseInstantSend->setChecked(fUseInstantSend);
CoinControlDialog::coinControl->fUseInstantSend = fUseInstantSend;
connect(ui->checkUseInstantSend, SIGNAL(stateChanged ( int )), this, SLOT(updateInstantSend()));
}
// Coin Control: clipboard actions
QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this);
QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this);
@ -284,14 +273,8 @@ void SendCoinsDialog::on_sendButton_clicked()
strFunds = tr("using") + " <b>" + tr("any available funds (not anonymous)") + "</b>";
}
if(model->IsOldInstantSendEnabled() && ui->checkUseInstantSend->isChecked()) {
strFunds += " ";
strFunds += tr("and InstantSend");
}
for (SendCoinsRecipient& rcp : recipients) {
rcp.inputType = ui->checkUsePrivateSend->isChecked() ? ONLY_DENOMINATED : ALL_COINS;
rcp.fUseInstantSend = model->IsOldInstantSendEnabled() && ui->checkUseInstantSend->isChecked();
}
fNewRecipientAllowed = false;
@ -622,14 +605,6 @@ void SendCoinsDialog::updateDisplayUnit()
updateSmartFeeLabel();
}
void SendCoinsDialog::updateInstantSend()
{
QSettings settings;
settings.setValue("bUseInstantSend", ui->checkUseInstantSend->isChecked());
CoinControlDialog::coinControl->fUseInstantSend = model->IsOldInstantSendEnabled() && ui->checkUseInstantSend->isChecked();
coinControlUpdateLabels();
}
void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg)
{
QPair<QString, CClientUIInterface::MessageBoxFlags> msgParams;

View File

@ -79,7 +79,6 @@ private Q_SLOTS:
void on_buttonMinimizeFee_clicked();
void removeEntry(SendCoinsEntry* entry);
void updateDisplayUnit();
void updateInstantSend();
void coinControlFeatureChanged(bool);
void coinControlButtonClicked();
void coinControlChangeChecked(int);

View File

@ -64,31 +64,20 @@ void URITests::uriTests()
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=1,000.0&label=Some Example"));
QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=100&label=Some Example&message=Some Example Message&IS=1"));
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=100&label=Some Example&message=Some Example Message"));
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg"));
QVERIFY(rv.amount == 10000000000LL);
QVERIFY(rv.label == QString("Some Example"));
QVERIFY(rv.message == QString("Some Example Message"));
QVERIFY(rv.fUseInstantSend == 1);
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=100&label=Some Example&message=Some Example Message&IS=Something Invalid"));
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg"));
QVERIFY(rv.amount == 10000000000LL);
QVERIFY(rv.label == QString("Some Example"));
QVERIFY(rv.message == QString("Some Example Message"));
QVERIFY(rv.fUseInstantSend != 1);
// Verify that IS=xxx does not lead to an error (we ignore the field)
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?IS=1"));
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.fUseInstantSend == 1);
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?IS=0"));
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?req-IS=1"));
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.fUseInstantSend != 1);
uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg"));
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.fUseInstantSend != 1);
}

View File

@ -19,8 +19,6 @@
#include "wallet/db.h"
#include "wallet/wallet.h"
#include "instantsend.h"
#include <stdint.h>
#include <string>
@ -57,26 +55,10 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
}
}
if (wtx.IsLockedByLLMQInstantSend()) {
if (wtx.IsLockedByInstantSend()) {
strTxStatus += " (" + tr("verified via LLMQ based InstantSend") + ")";
return strTxStatus;
}
if(!instantsend.HasTxLockRequest(wtx.GetHash())) return strTxStatus; // regular tx
int nSignatures = instantsend.GetTransactionLockSignatures(wtx.GetHash());
int nSignaturesMax = CTxLockRequest(wtx).GetMaxSignatures();
// InstantSend
strTxStatus += " (";
if(instantsend.IsLockedInstantSendTransaction(wtx.GetHash())) {
strTxStatus += tr("verified via InstantSend");
} else if(!instantsend.IsTxLockCandidateTimedOut(wtx.GetHash())) {
strTxStatus += tr("InstantSend verification in progress - %1 of %2 signatures").arg(nSignatures).arg(nSignaturesMax);
} else {
strTxStatus += tr("InstantSend verification failed");
}
strTxStatus += ")";
return strTxStatus;
}
}

View File

@ -24,7 +24,6 @@
#include "wallet/wallet.h"
#include "wallet/walletdb.h" // for BackupWallet
#include "instantsend.h"
#include "spork.h"
#include "privatesend/privatesend-client.h"
#include "llmq/quorums_instantsend.h"
@ -217,11 +216,6 @@ int WalletModel::getNumISLocks() const
return cachedNumISLocks;
}
bool WalletModel::IsOldInstantSendEnabled() const
{
return llmq::IsOldInstantSendEnabled();
}
void WalletModel::updateAddressBook(const QString &address, const QString &label,
bool isMine, const QString &purpose, int status)
{
@ -320,12 +314,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return AmountExceedsBalance;
}
if(recipients[0].fUseInstantSend && IsOldInstantSendEnabled() && total > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) {
Q_EMIT message(tr("Send Coins"), tr("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH.").arg(sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)),
CClientUIInterface::MSG_ERROR);
return TransactionCreationFailed;
}
CAmount nFeeRequired = 0;
CAmount nValueOut = 0;
size_t nVinSize = 0;
@ -341,7 +329,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
CWalletTx* newTx = transaction.getTransaction();
CReserveKey *keyChange = transaction.getPossibleKeyChange();
fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl, true, recipients[0].inputType, recipients[0].fUseInstantSend);
fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl, true, recipients[0].inputType);
transaction.setTransactionFee(nFeeRequired);
if (fSubtractFeeFromAmount && fCreated)
transaction.reassignAmounts();
@ -350,18 +338,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
nVinSize = newTx->tx->vin.size();
}
if(recipients[0].fUseInstantSend && IsOldInstantSendEnabled()) {
if(nValueOut > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) {
Q_EMIT message(tr("Send Coins"), tr("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH.").arg(sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)),
CClientUIInterface::MSG_ERROR);
return TransactionCreationFailed;
}
if(nVinSize > CTxLockRequest::WARN_MANY_INPUTS) {
Q_EMIT message(tr("Send Coins"), tr("Used way too many inputs (>%1) for this InstantSend transaction, fees could be huge.").arg(CTxLockRequest::WARN_MANY_INPUTS),
CClientUIInterface::MSG_WARNING);
}
}
if(!fCreated)
{
if(!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance)
@ -414,12 +390,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
CReserveKey *keyChange = transaction.getPossibleKeyChange();
CValidationState state;
// the new IX system does not require explicit IX messages
std::string strCommand = NetMsgType::TX;
if (recipients[0].fUseInstantSend && IsOldInstantSendEnabled()) {
strCommand = NetMsgType::TXLOCKREQUEST;
}
if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get(), state, strCommand))
if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get(), state))
return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(state.GetRejectReason()));
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);

View File

@ -54,7 +54,6 @@ public:
#ifdef ENABLE_WALLET
AvailableCoinsType inputType;
#endif // ENABLE_WALLET
bool fUseInstantSend;
CAmount amount;
// If from a payment request, this is used for storing the memo
QString message;
@ -228,8 +227,6 @@ public:
int getDefaultConfirmTarget() const;
int getNumISLocks() const;
bool IsOldInstantSendEnabled() const;
private:
CWallet *wallet;
bool fHaveWatchOnly;

View File

@ -13,7 +13,6 @@
#include "coins.h"
#include "core_io.h"
#include "consensus/validation.h"
#include "instantsend.h"
#include "validation.h"
#include "core_io.h"
#include "policy/feerate.h"
@ -368,7 +367,6 @@ std::string EntryDescriptionString()
" \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
" \"transactionid\", (string) parent transaction id\n"
" ... ],\n"
" \"instantsend\" : true|false, (boolean) True if this transaction was sent as an InstantSend one\n"
" \"instantlock\" : true|false (boolean) True if this transaction was locked via InstantSend\n";
}
@ -402,8 +400,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e)
}
info.push_back(Pair("depends", depends));
info.push_back(Pair("instantsend", instantsend.HasTxLockRequest(tx.GetHash())));
info.push_back(Pair("instantlock", instantsend.IsLockedInstantSendTransaction(tx.GetHash()) || llmq::quorumInstantSendManager->IsLocked(tx.GetHash())));
info.push_back(Pair("instantlock", llmq::quorumInstantSendManager->IsLocked(tx.GetHash())));
}
UniValue mempoolToJSON(bool fVerbose)

View File

@ -127,7 +127,7 @@ void gobject_prepare_help(CWallet* const pwallet)
"2. revision (numeric, required) object revision in the system\n"
"3. time (numeric, required) time this object was created\n"
"4. data-hex (string, required) data in hex string form\n"
"5. use-IS (boolean, optional, default=false) InstantSend lock the collateral, only requiring one chain confirmation\n"
"5. use-IS (boolean, optional, default=false) Deprecated and ignored\n"
"6. outputHash (string, optional) the single output to submit the proposal fee from\n"
"7. outputIndex (numeric, optional) The output index.\n"
);
@ -160,8 +160,6 @@ UniValue gobject_prepare(const JSONRPCRequest& request)
int nRevision = atoi(strRevision);
int64_t nTime = atoi64(strTime);
std::string strDataHex = request.params[4].get_str();
bool useIS = false;
if (request.params.size() > 5) useIS = request.params[5].getBool();
// CREATE A NEW COLLATERAL TRANSACTION FOR THIS SPECIFIC OBJECT
@ -206,7 +204,7 @@ UniValue gobject_prepare(const JSONRPCRequest& request)
}
CWalletTx wtx;
if (!pwallet->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), useIS, outpoint)) {
if (!pwallet->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), outpoint)) {
std::string err = "Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked.";
if (request.params.size() == 8) err += "Please verify your specified output is valid and is enough for the combined proposal fee and transaction fee.";
throw JSONRPCError(RPC_INTERNAL_ERROR, err);
@ -216,7 +214,7 @@ UniValue gobject_prepare(const JSONRPCRequest& request)
CReserveKey reservekey(pwallet);
// -- send the tx to the network
CValidationState state;
if (!pwallet->CommitTransaction(wtx, reservekey, g_connman.get(), state, NetMsgType::TX)) {
if (!pwallet->CommitTransaction(wtx, reservekey, g_connman.get(), state)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "CommitTransaction failed! Reason given: " + state.GetRejectReason());
}

View File

@ -24,7 +24,6 @@
#include "txmempool.h"
#include "uint256.h"
#include "utilstrencodings.h"
#include "instantsend.h"
#ifdef ENABLE_WALLET
#include "wallet/rpcwallet.h"
#include "wallet/wallet.h"
@ -94,10 +93,9 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
}
}
bool fLocked = instantsend.IsLockedInstantSendTransaction(txid);
bool fLLMQLocked = llmq::quorumInstantSendManager->IsLocked(txid);
entry.push_back(Pair("instantlock", fLocked || fLLMQLocked || chainLock));
entry.push_back(Pair("instantlock_internal", fLocked || fLLMQLocked));
bool fLocked = llmq::quorumInstantSendManager->IsLocked(txid);
entry.push_back(Pair("instantlock", fLocked || chainLock));
entry.push_back(Pair("instantlock_internal", fLocked));
entry.push_back(Pair("chainlock", chainLock));
}
@ -855,7 +853,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
"\nArguments:\n"
"1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
"2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
"3. instantsend (boolean, optional, default=false) Use InstantSend to send this transaction\n"
"3. instantsend (boolean, optional, default=false) Deprecated and ignored\n"
"4. bypasslimits (boolean, optional, default=false) Bypass transaction policy limits\n"
"\nResult:\n"
"\"hex\" (string) The transaction hash in hex\n"
@ -884,10 +882,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
if (request.params.size() > 1 && request.params[1].get_bool())
nMaxRawTxFee = 0;
bool fInstantSend = false;
if (request.params.size() > 2)
fInstantSend = request.params[2].get_bool();
bool fBypassLimits = false;
if (request.params.size() > 3)
fBypassLimits = request.params[3].get_bool();
@ -901,9 +895,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
bool fHaveMempool = mempool.exists(hashTx);
if (!fHaveMempool && !fHaveChain) {
// push to local node and sync with wallets
if (fInstantSend && !instantsend.ProcessTxLockRequest(*tx, *g_connman)) {
throw JSONRPCError(RPC_TRANSACTION_ERROR, "Not a valid InstantSend transaction, see debug.log for more info");
}
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, std::move(tx), !fBypassLimits, &fMissingInputs, false, nMaxRawTxFee)) {

View File

@ -212,7 +212,7 @@ static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const Speci
int nChangePos = -1;
std::string strFailReason;
if (!pwallet->CreateTransaction(vecSend, wtx, reservekey, nFee, nChangePos, strFailReason, &coinControl, false, ALL_COINS, false, tx.vExtraPayload.size())) {
if (!pwallet->CreateTransaction(vecSend, wtx, reservekey, nFee, nChangePos, strFailReason, &coinControl, false, ALL_COINS, tx.vExtraPayload.size())) {
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
}

View File

@ -17,9 +17,8 @@ const std::string CSporkManager::SERIALIZATION_VERSION_STRING = "CSporkManager-V
#define MAKE_SPORK_DEF(name, defaultValue) CSporkDef{name, defaultValue, #name}
std::vector<CSporkDef> sporkDefs = {
MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 0), // ON
MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 0), // ON
MAKE_SPORK_DEF(SPORK_5_INSTANTSEND_MAX_VALUE, 1000), // 1000 Dash
MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_6_NEW_SIGS, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL), // OFF

View File

@ -23,7 +23,6 @@ class CSporkManager;
enum SporkId : int32_t {
SPORK_2_INSTANTSEND_ENABLED = 10001,
SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002,
SPORK_5_INSTANTSEND_MAX_VALUE = 10004,
SPORK_6_NEW_SIGS = 10005,
SPORK_9_SUPERBLOCKS_ENABLED = 10008,
SPORK_15_DETERMINISTIC_MNS_ENABLED = 10014,

View File

@ -7,7 +7,6 @@
#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "instantsend.h"
#include "validation.h"
#include "policy/policy.h"
#include "policy/fees.h"
@ -1394,16 +1393,6 @@ size_t CTxMemPool::DynamicMemoryUsage() const {
return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage;
}
double CTxMemPool::UsedMemoryShare() const
{
// use 1000000 instead of real bytes number in megabyte because of
// this param is calculated in such way in other places (see AppInit
// function in src/init.cpp or mempoolInfoToJSON function in
// src/rpc/blockchain.cpp)
size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
return double(DynamicMemoryUsage()) / maxmempool;
}
void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) {
AssertLockHeld(cs);
UpdateForRemoveFromMempool(stage, updateDescendants);
@ -1418,7 +1407,7 @@ int CTxMemPool::Expire(int64_t time) {
setEntries toremove;
while (it != mapTx.get<entry_time>().end() && it->GetTime() < time) {
// locked txes do not expire until mined and have sufficient confirmations
if (instantsend.IsLockedInstantSendTransaction(it->GetTx().GetHash()) || llmq::quorumInstantSendManager->IsLocked(it->GetTx().GetHash())) {
if (llmq::quorumInstantSendManager->IsLocked(it->GetTx().GetHash())) {
it++;
continue;
}

View File

@ -672,8 +672,6 @@ public:
bool existsProviderTxConflict(const CTransaction &tx) const;
size_t DynamicMemoryUsage() const;
// returns share of the used memory to maximum allowed memory
double UsedMemoryShare() const;
boost::signals2::signal<void (CTransactionRef)> NotifyEntryAdded;
boost::signals2::signal<void (CTransactionRef, MemPoolRemovalReason)> NotifyEntryRemoved;

View File

@ -40,7 +40,6 @@
#include "versionbits.h"
#include "warnings.h"
#include "instantsend.h"
#include "masternode/masternode-payments.h"
#include "evo/specialtx.h"
@ -695,21 +694,6 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
if (pool.exists(hash))
return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-in-mempool");
// If this is a Transaction Lock Request check to see if it's valid
if(instantsend.HasTxLockRequest(hash) && !CTxLockRequest(tx).IsValid())
return state.DoS(10, error("AcceptToMemoryPool : CTxLockRequest %s is invalid", hash.ToString()),
REJECT_INVALID, "bad-txlockrequest");
// Check for conflicts with a completed Transaction Lock
BOOST_FOREACH(const CTxIn &txin, tx.vin)
{
uint256 hashLocked;
if(instantsend.GetLockedOutPointTxHash(txin.prevout, hashLocked) && hash != hashLocked)
return state.DoS(10, error("AcceptToMemoryPool : Transaction %s conflicts with completed Transaction Lock %s",
hash.ToString(), hashLocked.ToString()),
REJECT_INVALID, "tx-txlock-conflict");
}
llmq::CInstantSendLockPtr conflictLock = llmq::quorumInstantSendManager->GetConflictingLock(tx);
if (conflictLock) {
CTransactionRef txConflict;
@ -732,18 +716,6 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
{
const CTransaction *ptxConflicting = itConflicting->second;
// InstantSend txes are not replacable
if(instantsend.HasTxLockRequest(ptxConflicting->GetHash())) {
// this tx conflicts with a Transaction Lock Request candidate
return state.DoS(0, error("AcceptToMemoryPool : Transaction %s conflicts with Transaction Lock Request %s",
hash.ToString(), ptxConflicting->GetHash().ToString()),
REJECT_INVALID, "tx-txlockreq-mempool-conflict");
} else if (instantsend.HasTxLockRequest(hash)) {
// this tx is a tx lock request and it conflicts with a normal tx
return state.DoS(0, error("AcceptToMemoryPool : Transaction Lock Request %s conflicts with transaction %s",
hash.ToString(), ptxConflicting->GetHash().ToString()),
REJECT_INVALID, "txlockreq-tx-mempool-conflict");
}
// Transaction conflicts with mempool and RBF doesn't exist in Dash
return state.Invalid(false, REJECT_CONFLICT, "txn-mempool-conflict");
}
@ -1807,10 +1779,6 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s
}
}
// make sure the flag is reset in case of a chain reorg
// (we reused the DIP3 deployment)
instantsend.isAutoLockBip9Active = pindex->nHeight >= Params().GetConsensus().DIP0003Height;
evoDb->WriteBestBlock(pindex->pprev->GetBlockHash());
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
@ -2251,17 +2219,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
for (const auto& tx : block.vtx) {
// skip txes that have no inputs
if (tx->vin.empty()) continue;
// LOOK FOR TRANSACTION LOCK IN OUR MAP OF OUTPOINTS
for (const auto& txin : tx->vin) {
uint256 hashLocked;
if (instantsend.GetLockedOutPointTxHash(txin.prevout, hashLocked) && hashLocked != tx->GetHash()) {
// The node which relayed this should switch to correct chain.
// TODO: relay instantsend data/proof.
LOCK(cs_main);
return state.DoS(10, error("ConnectBlock(DASH): transaction %s conflicts with transaction lock %s", tx->GetHash().ToString(), hashLocked.ToString()),
REJECT_INVALID, "conflict-tx-lock");
}
}
llmq::CInstantSendLockPtr conflictLock = llmq::quorumInstantSendManager->GetConflictingLock(*tx);
if (!conflictLock) {
continue;

View File

@ -14,7 +14,6 @@ class CCoinControl
public:
CTxDestination destChange;
bool fUsePrivateSend;
bool fUseInstantSend;
//! If false, allows unselected inputs, but requires all selected inputs be used if fAllowOtherInputs is true (default)
bool fAllowOtherInputs;
//! If false, only include as many inputs as necessary to fulfill a coin selection request. Only usable together with fAllowOtherInputs
@ -40,7 +39,6 @@ public:
fRequireAllInputs = true;
fAllowWatchOnly = false;
setSelected.clear();
fUseInstantSend = false;
fUsePrivateSend = true;
nFeeRate = CFeeRate(0);
fOverrideFeeRate = false;

View File

@ -10,7 +10,6 @@
#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
#include "instantsend.h"
#include "net.h"
#include "policy/feerate.h"
#include "policy/fees.h"
@ -65,15 +64,14 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
AssertLockHeld(cs_main); // for mapBlockIndex
int confirms = wtx.GetDepthInMainChain();
bool fLocked = instantsend.IsLockedInstantSendTransaction(wtx.GetHash());
bool fLLMQLocked = llmq::quorumInstantSendManager->IsLocked(wtx.GetHash());
bool fLocked = llmq::quorumInstantSendManager->IsLocked(wtx.GetHash());
bool chainlock = false;
if (confirms > 0) {
chainlock = llmq::chainLocksHandler->HasChainLock(mapBlockIndex[wtx.hashBlock]->nHeight, wtx.hashBlock);
}
entry.push_back(Pair("confirmations", confirms));
entry.push_back(Pair("instantlock", fLocked || fLLMQLocked || chainlock));
entry.push_back(Pair("instantlock_internal", fLocked || fLLMQLocked));
entry.push_back(Pair("instantlock", fLocked || chainlock));
entry.push_back(Pair("instantlock_internal", fLocked));
entry.push_back(Pair("chainlock", chainlock));
if (wtx.IsCoinBase())
entry.push_back(Pair("generated", true));
@ -354,7 +352,7 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request)
return ret;
}
static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, bool fUseInstantSend = false, bool fUsePrivateSend = false)
static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, bool fUsePrivateSend = false)
{
CAmount curBalance = pwallet->GetBalance();
@ -381,18 +379,13 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
if (!pwallet->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet,
strError, NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS, fUseInstantSend)) {
strError, NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS)) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
CValidationState state;
// the new IX system does not require explicit IX messages
std::string strCommand = NetMsgType::TX;
if (fUseInstantSend && llmq::IsOldInstantSendEnabled()) {
strCommand = NetMsgType::TXLOCKREQUEST;
}
if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state, strCommand)) {
if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason());
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
@ -420,7 +413,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
" transaction, just kept in your wallet.\n"
"5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
" The recipient will receive less amount of Dash than you enter in the amount field.\n"
"6. \"use_is\" (bool, optional, default=false) Send this transaction as InstantSend\n"
"6. \"use_is\" (bool, optional, default=false) Deprecated and ignored\n"
"7. \"use_ps\" (bool, optional, default=false) Use anonymized funds only\n"
"\nResult:\n"
"\"txid\" (string) The transaction id.\n"
@ -453,77 +446,25 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
if (request.params.size() > 4)
fSubtractFeeFromAmount = request.params[4].get_bool();
bool fUseInstantSend = false;
bool fUsePrivateSend = false;
if (request.params.size() > 5)
fUseInstantSend = request.params[5].get_bool();
if (request.params.size() > 6)
fUsePrivateSend = request.params[6].get_bool();
EnsureWalletIsUnlocked(pwallet);
SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, fUseInstantSend, fUsePrivateSend);
SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, fUsePrivateSend);
return wtx.GetHash().GetHex();
}
// DEPRECATED
UniValue instantsendtoaddress(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
throw std::runtime_error(
"instantsendtoaddress \"address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
"\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
+ HelpRequiringPassphrase(pwallet) +
"\nArguments:\n"
"1. \"address\" (string, required) The dash address to send to.\n"
"2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
"3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
" This is not part of the transaction, just kept in your wallet.\n"
"4. \"comment_to\" (string, optional) A comment to store the name of the person or organization \n"
" to which you're sending the transaction. This is not part of the \n"
" transaction, just kept in your wallet.\n"
"5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
" The recipient will receive less amount of Dash than you enter in the amount field.\n"
"\nResult:\n"
"\"transactionid\" (string) The transaction id.\n"
"\nExamples:\n"
+ HelpExampleCli("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1")
+ HelpExampleCli("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1 \"donation\" \"seans outpost\"")
+ HelpExampleCli("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1 \"\" \"\" true")
+ HelpExampleRpc("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", 0.1, \"donation\", \"seans outpost\"")
);
LOCK2(cs_main, pwallet->cs_wallet);
CBitcoinAddress address(request.params[0].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
// Amount
CAmount nAmount = AmountFromValue(request.params[1]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
// Wallet comments
CWalletTx wtx;
if (request.params.size() > 2 && !request.params[2].isNull() && !request.params[2].get_str().empty())
wtx.mapValue["comment"] = request.params[2].get_str();
if (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty())
wtx.mapValue["to"] = request.params[3].get_str();
bool fSubtractFeeFromAmount = false;
if (request.params.size() > 4)
fSubtractFeeFromAmount = request.params[4].get_bool();
EnsureWalletIsUnlocked(pwallet);
SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, true);
return wtx.GetHash().GetHex();
if (request.fHelp) {
throw std::runtime_error("instantsendtoaddress is deprecated and sendtoaddress should be used instead");
}
LogPrintf("WARNING: Used deprecated RPC method 'instantsendtoaddress'! Please use 'sendtoaddress' instead\n");
return sendtoaddress(request);
}
UniValue listaddressgroupings(const JSONRPCRequest& request)
@ -1022,7 +963,7 @@ UniValue sendmany(const JSONRPCRequest& request)
" \"address\" (string) Subtract fee from this address\n"
" ,...\n"
" ]\n"
"7. \"use_is\" (bool, optional, default=false) Send this transaction as InstantSend\n"
"7. \"use_is\" (bool, optional, default=false) Deprecated and ignored\n"
"8. \"use_ps\" (bool, optional, default=false) Use anonymized funds only\n"
"\nResult:\n"
"\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
@ -1102,24 +1043,16 @@ UniValue sendmany(const JSONRPCRequest& request)
CAmount nFeeRequired = 0;
int nChangePosRet = -1;
std::string strFailReason;
bool fUseInstantSend = false;
bool fUsePrivateSend = false;
if (request.params.size() > 6)
fUseInstantSend = request.params[6].get_bool();
if (request.params.size() > 7)
fUsePrivateSend = request.params[7].get_bool();
bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason,
NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS, fUseInstantSend);
NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
CValidationState state;
// the new IX system does not require explicit IX messages
std::string strCommand = NetMsgType::TX;
if (fUseInstantSend && llmq::IsOldInstantSendEnabled()) {
strCommand = NetMsgType::TXLOCKREQUEST;
}
if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state, strCommand)) {
if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
}
@ -3065,7 +2998,7 @@ static const CRPCCommand commands[] =
{ "wallet", "removeprunedfunds", &removeprunedfunds, true, {"txid"} },
{ "wallet", "keepass", &keepass, true, {} },
{ "wallet", "instantsendtoaddress", &instantsendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} },
{ "hidden", "instantsendtoaddress", &instantsendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} },
{ "wallet", "dumphdinfo", &dumphdinfo, true, {} },
{ "wallet", "importelectrumwallet", &importelectrumwallet, true, {"filename", "index"} },

View File

@ -31,7 +31,6 @@
#include "utilmoneystr.h"
#include "governance/governance.h"
#include "instantsend.h"
#include "keepass.h"
#include "privatesend/privatesend-client.h"
#include "spork.h"
@ -1910,7 +1909,7 @@ void CWallet::ReacceptWalletTransactions()
}
}
bool CWalletTx::RelayWalletTransaction(CConnman* connman, const std::string& strCommand)
bool CWalletTx::RelayWalletTransaction(CConnman* connman)
{
assert(pwallet->GetBroadcastTransactions());
if (!IsCoinBase() && !isAbandoned() && GetDepthInMainChain() == 0)
@ -1921,15 +1920,6 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman, const std::string& str
uint256 hash = GetHash();
LogPrintf("Relaying wtx %s\n", hash.ToString());
if ((strCommand == NetMsgType::TXLOCKREQUEST) ||
((CTxLockRequest(*this).IsSimple()) && CInstantSend::CanAutoLock())) {
if (instantsend.ProcessTxLockRequest((CTxLockRequest)*this, *connman)) {
instantsend.AcceptLockRequest((CTxLockRequest)*this);
} else {
instantsend.RejectLockRequest((CTxLockRequest)*this);
}
}
if (connman) {
connman->RelayTransaction((CTransaction)*this);
return true;
@ -2540,13 +2530,12 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, cons
return balance;
}
void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t &nMaximumCount, const int &nMinDepth, const int &nMaxDepth, AvailableCoinsType nCoinType, bool fUseInstantSend) const
void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t &nMaximumCount, const int &nMinDepth, const int &nMaxDepth, AvailableCoinsType nCoinType) const
{
vCoins.clear();
{
LOCK2(cs_main, cs_wallet);
int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired;
CAmount nTotal = 0;
@ -2562,9 +2551,6 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
continue;
int nDepth = pcoin->GetDepthInMainChain();
// do not use IX for inputs that have less then nInstantSendConfirmationsRequired blockchain confirmations
if (fUseInstantSend && nDepth < nInstantSendConfirmationsRequired)
continue;
// We should not consider coins which aren't at least in our mempool
// It's possible for these to be conflicted via ancestors which we may never be able to detect
@ -2638,19 +2624,13 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
}
static void ApproximateBestSubset(const std::vector<CInputCoin>& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,
std::vector<char>& vfBest, CAmount& nBest, bool fUseInstantSend = false, int iterations = 1000)
std::vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
{
std::vector<char> vfIncluded;
vfBest.assign(vValue.size(), true);
nBest = nTotalLower;
if (!llmq::IsOldInstantSendEnabled()) {
// The new system does not require special handling for InstantSend as this is all done in CInstantSendManager.
// There is also no need for an extra fee anymore.
fUseInstantSend = false;
}
FastRandomContext insecure_rand;
for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
@ -2662,9 +2642,6 @@ static void ApproximateBestSubset(const std::vector<CInputCoin>& vValue, const C
{
for (unsigned int i = 0; i < vValue.size(); i++)
{
if (fUseInstantSend && nTotal + vValue[i].txout.nValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) {
continue;
}
//The solver here uses a randomized algorithm,
//the randomness serves no real security purpose but is just
//needed to prevent degenerate behavior and it is important
@ -2718,27 +2695,16 @@ bool less_then_denom (const COutput& out1, const COutput& out2)
}
bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMine, const int nConfTheirs, const uint64_t nMaxAncestors, std::vector<COutput> vCoins,
std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType, bool fUseInstantSend) const
std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType) const
{
setCoinsRet.clear();
nValueRet = 0;
if (!llmq::IsOldInstantSendEnabled()) {
// The new system does not require special handling for InstantSend as this is all done in CInstantSendManager.
// There is also no need for an extra fee anymore.
fUseInstantSend = false;
}
// List of values less than target
boost::optional<CInputCoin> coinLowestLarger;
std::vector<CInputCoin> vValue;
CAmount nTotalLower = 0;
// TODO: drop SPORK_5_INSTANTSEND_MAX_VALUE spork
if (fUseInstantSend && nTargetValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE) * COIN && llmq::IsOldInstantSendEnabled()) {
return false;
}
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
int tryDenomStart = 0;
@ -2845,9 +2811,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin
std::vector<char> vfBest;
CAmount nBest;
ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, fUseInstantSend);
ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest);
if (nBest != nTargetValue && nTotalLower >= nTargetValue + nMinChange)
ApproximateBestSubset(vValue, nTotalLower, nTargetValue + nMinChange, vfBest, nBest, fUseInstantSend);
ApproximateBestSubset(vValue, nTotalLower, nTargetValue + nMinChange, vfBest, nBest);
// If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
// or the next bigger coin is closer), return the bigger coin
@ -2876,7 +2842,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin
return nCoinType == ONLY_DENOMINATED ? (nValueRet - nTargetValue <= maxTxFee) : true;
}
bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType nCoinType, bool fUseInstantSend) const
bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType nCoinType) const
{
// Note: this function should never be used for "always free" tx types like dstx
@ -2949,13 +2915,13 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
bool res = nTargetValue <= nValueFromPresetInputs ||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, 0, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend) ||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 1, 0, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, 2, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::min((size_t)4, nMaxChainLength/3), vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength/2, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) ||
(bSpendZeroConfChange && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::numeric_limits<uint64_t>::max(), vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend));
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, 0, vCoins, setCoinsRet, nValueRet, nCoinType) ||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 1, 0, vCoins, setCoinsRet, nValueRet, nCoinType) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, 2, vCoins, setCoinsRet, nValueRet, nCoinType)) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::min((size_t)4, nMaxChainLength/3), vCoins, setCoinsRet, nValueRet, nCoinType)) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength/2, vCoins, setCoinsRet, nValueRet, nCoinType)) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength, vCoins, setCoinsRet, nValueRet, nCoinType)) ||
(bSpendZeroConfChange && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::numeric_limits<uint64_t>::max(), vCoins, setCoinsRet, nValueRet, nCoinType));
// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
@ -2994,7 +2960,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
CReserveKey reservekey(this);
CWalletTx wtx;
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false, ALL_COINS, false, nExtraPayloadSize))
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false, ALL_COINS, nExtraPayloadSize))
return false;
if (nChangePosInOut != -1)
@ -3041,7 +3007,7 @@ bool CWallet::SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, C
return false;
}
AvailableCoins(vCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_DENOMINATED, false);
AvailableCoins(vCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_DENOMINATED);
LogPrintf("CWallet::%s -- vCoins.size(): %d\n", __func__, vCoins.size());
std::random_shuffle(vCoins.rbegin(), vCoins.rend(), GetRandInt);
@ -3356,7 +3322,7 @@ bool CWallet::CreateCollateralTransaction(CMutableTransaction& txCollateral, std
return true;
}
bool CWallet::GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, bool fUseInstantSend, const COutPoint& outpoint)
bool CWallet::GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, const COutPoint& outpoint)
{
// make our change address
CReserveKey reservekey(this);
@ -3374,7 +3340,7 @@ bool CWallet::GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount a
if (!outpoint.IsNull()) {
coinControl.Select(outpoint);
}
bool success = CreateTransaction(vecSend, tx, reservekey, nFeeRet, nChangePosRet, strFail, &coinControl, true, ALL_COINS, fUseInstantSend);
bool success = CreateTransaction(vecSend, tx, reservekey, nFeeRet, nChangePosRet, strFail, &coinControl, true, ALL_COINS);
if(!success){
LogPrintf("CWallet::GetBudgetSystemCollateralTX -- Error: %s\n", strFail);
return false;
@ -3402,16 +3368,8 @@ bool CWallet::ConvertList(std::vector<CTxIn> vecTxIn, std::vector<CAmount>& vecA
}
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign, AvailableCoinsType nCoinType, bool fUseInstantSend, int nExtraPayloadSize)
int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign, AvailableCoinsType nCoinType, int nExtraPayloadSize)
{
if (!llmq::IsOldInstantSendEnabled()) {
// The new system does not require special handling for InstantSend as this is all done in CInstantSendManager.
// There is also no need for an extra fee anymore.
fUseInstantSend = false;
}
CAmount nFeePay = fUseInstantSend ? CTxLockRequest().GetMinFee(true) : 0;
CAmount nValue = 0;
int nChangePosRequest = nChangePosInOut;
unsigned int nSubtractFeeFromAmount = 0;
@ -3476,11 +3434,9 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
LOCK2(cs_main, cs_wallet);
{
std::vector<COutput> vAvailableCoins;
AvailableCoins(vAvailableCoins, true, coinControl, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, nCoinType, fUseInstantSend);
int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired;
AvailableCoins(vAvailableCoins, true, coinControl, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, nCoinType);
nFeeRet = 0;
if(nFeePay > 0) nFeeRet = nFeePay;
// Start with no fee and loop until there is enough fee
while (true)
{
@ -3528,7 +3484,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// Choose coins to use
CAmount nValueIn = 0;
setCoins.clear();
if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl, nCoinType, fUseInstantSend))
if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl, nCoinType))
{
if (nCoinType == ONLY_NONDENOMINATED) {
strFailReason = _("Unable to locate enough PrivateSend non-denominated funds for this transaction.");
@ -3537,18 +3493,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
strFailReason += " " + _("PrivateSend uses exact denominated amounts to send funds, you might simply need to anonymize some more coins.");
} else if (nValueIn < nValueToSelect) {
strFailReason = _("Insufficient funds.");
if (fUseInstantSend) {
// could be not true but most likely that's the reason
strFailReason += " " + strprintf(_("InstantSend requires inputs with at least %d confirmations, you might need to wait a few minutes and try again."), nInstantSendConfirmationsRequired);
}
}
return false;
}
if (fUseInstantSend && nValueIn > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) {
strFailReason += " " + strprintf(_("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH."), sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE));
return false;
}
const CAmount nChange = nValueIn - nValueToSelect;
CTxOut newTxOut;
@ -3716,10 +3664,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
if (coinControl && coinControl->nConfirmTarget > 0)
currentConfirmationTarget = coinControl->nConfirmTarget;
CAmount nFeeNeeded = std::max(nFeePay, GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator));
if(fUseInstantSend) {
nFeeNeeded = std::max(nFeeNeeded, CTxLockRequest(txNew).GetMinFee(true));
}
CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator);
if (coinControl && coinControl->fOverrideFeeRate)
nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes);
@ -3813,7 +3758,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
/**
* Call after CreateTransaction unless you want to abort
*/
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state, const std::string& strCommand)
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state)
{
{
LOCK2(cs_main, cs_wallet);
@ -3851,7 +3796,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", state.GetRejectReason());
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
} else {
wtxNew.RelayWalletTransaction(connman, strCommand);
wtxNew.RelayWalletTransaction(connman);
}
}
}
@ -5389,11 +5334,6 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
}
bool CMerkleTx::IsLockedByInstantSend() const
{
return instantsend.IsLockedInstantSendTransaction(GetHash()) || llmq::quorumInstantSendManager->IsLocked(GetHash());
}
bool CMerkleTx::IsLockedByLLMQInstantSend() const
{
return llmq::quorumInstantSendManager->IsLocked(GetHash());
}

View File

@ -268,7 +268,6 @@ public:
int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }
bool IsLockedByInstantSend() const;
bool IsLockedByLLMQInstantSend() const;
bool IsChainLocked() const;
int GetBlocksToMaturity() const;
/** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */
@ -507,7 +506,7 @@ public:
int64_t GetTxTime() const;
int GetRequestCount() const;
bool RelayWalletTransaction(CConnman* connman, const std::string& strCommand="tx");
bool RelayWalletTransaction(CConnman* connman);
std::set<uint256> GetConflicts() const;
};
@ -702,7 +701,7 @@ private:
* all coins from coinControl are selected; Never select unconfirmed coins
* if they are not ours
*/
bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = true) const;
bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType nCoinType=ALL_COINS) const;
CWalletDB *pwalletdbEncryption;
@ -883,7 +882,7 @@ public:
/**
* populate vCoins with vector of available COutputs.
*/
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 9999999, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const;
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 9999999, AvailableCoinsType nCoinType=ALL_COINS) const;
/**
* Shuffle and select coins until nTargetValue is reached while avoiding
@ -891,7 +890,7 @@ public:
* completion the coin set and corresponding actual target value is
* assembled
*/
bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector<COutput> vCoins, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const;
bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector<COutput> vCoins, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType=ALL_COINS) const;
// Coin selection
bool SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet);
@ -1023,7 +1022,7 @@ public:
CAmount GetNormalizedAnonymizedBalance() const;
CAmount GetDenominatedBalance(bool unconfirmed=false) const;
bool GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, bool fUseInstantSend, const COutPoint& outpoint=COutPoint()/*defaults null*/);
bool GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, const COutPoint& outpoint=COutPoint()/*defaults null*/);
/**
* Insert additional inputs into the transaction by
@ -1037,8 +1036,8 @@ public:
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend=false, int nExtraPayloadSize = 0);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state, const std::string& strCommand="tx");
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, AvailableCoinsType nCoinType=ALL_COINS, int nExtraPayloadSize = 0);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state);
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);
bool ConvertList(std::vector<CTxIn> vecTxIn, std::vector<CAmount>& vecAmounts);

View File

@ -22,8 +22,6 @@
#include "governance/governance-object.h"
#include "governance/governance-vote.h"
#include "instantsend.h"
#include "llmq/quorums_chainlocks.h"
#include "llmq/quorums_instantsend.h"

View File

@ -1,123 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) 2018 The Dash Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.mininode import *
from test_framework.test_framework import DashTestFramework
from test_framework.util import *
from time import *
'''
autois-mempool.py
Checks if automatic InstantSend locks stop working when transaction mempool
is full (more than 0.1 part from max value).
'''
MAX_MEMPOOL_SIZE = 1 # max node mempool in MBs
MB_SIZE = 1000000 # C++ code use this coefficient to calc MB in mempool
AUTO_IX_MEM_THRESHOLD = 0.1
class AutoISMempoolTest(DashTestFramework):
def __init__(self):
super().__init__(8, 5, ["-maxmempool=%d" % MAX_MEMPOOL_SIZE, '-limitdescendantsize=10'], fast_dip3_enforcement=True)
# set sender, receiver
self.receiver_idx = 1
self.sender_idx = 2
def get_mempool_usage(self, node):
info = node.getmempoolinfo()
return info['usage']
def fill_mempool(self):
# send lots of txes to yourself just to fill the mempool
counter = 0
sync_period = 10
dummy_address = self.nodes[0].getnewaddress()
while self.get_mempool_usage(self.nodes[self.sender_idx]) < MAX_MEMPOOL_SIZE * MB_SIZE * AUTO_IX_MEM_THRESHOLD:
self.nodes[0].sendtoaddress(dummy_address, 1.0)
counter += 1
if counter % sync_period == 0:
# sync nodes
self.sync_all()
self.sync_all()
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()
self.log.info("Test old InstantSend")
self.test_auto();
# Generate 6 block to avoid retroactive signing overloading Travis
self.nodes[0].generate(6)
sync_blocks(self.nodes)
self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.wait_for_sporks_same()
self.log.info("Test new InstantSend")
self.test_auto(True);
def test_auto(self, new_is = False):
self.activate_autois_bip9(self.nodes[0])
self.set_autois_spork_state(self.nodes[0], True)
# check pre-conditions for autoIS
assert(self.get_autois_bip9_status(self.nodes[0]) == 'active')
assert(self.get_autois_spork_state(self.nodes[0]))
# create 3 inputs for txes on sender node and give them enough confirmations
sender = self.nodes[self.sender_idx]
receiver = self.nodes[self.receiver_idx]
sender_address = sender.getnewaddress()
for i in range(0, 4):
self.nodes[0].sendtoaddress(sender_address, 2.0)
for i in range(0, 2):
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(1)
self.sync_all()
# autoIS is working
assert(self.send_simple_tx(sender, receiver))
# fill mempool with transactions
self.set_autois_spork_state(self.nodes[0], False)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800)
self.wait_for_sporks_same()
self.fill_mempool()
self.set_autois_spork_state(self.nodes[0], True)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.wait_for_sporks_same()
# autoIS is not working now
assert(not self.send_simple_tx(sender, receiver))
# regular IS is still working for old IS but not for new one
assert(not self.send_regular_instantsend(sender, receiver, False) if new_is else self.send_regular_instantsend(sender, receiver))
# generate one block to clean up mempool and retry auto and regular IS
# generate 5 more blocks to avoid retroactive signing (which would overload Travis)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800)
self.wait_for_sporks_same()
self.nodes[0].generate(6)
self.sync_all()
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.wait_for_sporks_same()
assert(self.send_simple_tx(sender, receiver))
assert(self.send_regular_instantsend(sender, receiver, not new_is))
if __name__ == '__main__':
AutoISMempoolTest().main()

View File

@ -114,9 +114,6 @@ class DIP3Test(BitcoinTestFramework):
self.sync_all()
self.assert_mnlists(mns)
self.log.info("testing instant send")
self.test_instantsend(10, 3)
self.log.info("test that MNs disappear from the list when the ProTx collateral is spent")
spend_mns_count = 3
mns_tmp = [] + mns
@ -191,9 +188,6 @@ class DIP3Test(BitcoinTestFramework):
self.start_mn(new_mn)
self.sync_all()
self.log.info("testing instant send with replaced MNs")
self.test_instantsend(10, 3, timeout=20)
def prepare_mn(self, node, idx, alias):
mn = Masternode()
mn.idx = idx
@ -306,57 +300,6 @@ class DIP3Test(BitcoinTestFramework):
return
time.sleep(0.1)
def test_instantsend(self, tx_count, repeat, timeout=20):
self.nodes[0].spork('SPORK_2_INSTANTSEND_ENABLED', 0)
self.wait_for_sporks()
# give all nodes some coins first
for i in range(tx_count):
outputs = {}
for node in self.nodes[1:]:
outputs[node.getnewaddress()] = 1
rawtx = self.nodes[0].createrawtransaction([], outputs)
rawtx = self.nodes[0].fundrawtransaction(rawtx)['hex']
rawtx = self.nodes[0].signrawtransaction(rawtx)['hex']
self.nodes[0].sendrawtransaction(rawtx)
self.nodes[0].generate(1)
self.sync_all()
for j in range(repeat):
for i in range(tx_count):
while True:
from_node_idx = random.randint(1, len(self.nodes) - 1)
from_node = self.nodes[from_node_idx]
if from_node is not None:
break
while True:
to_node_idx = random.randint(0, len(self.nodes) - 1)
to_node = self.nodes[to_node_idx]
if to_node is not None and from_node is not to_node:
break
to_address = to_node.getnewaddress()
txid = from_node.instantsendtoaddress(to_address, 0.1)
for node in self.nodes:
if node is not None:
self.wait_for_instant_lock(node, to_node_idx, txid, timeout=timeout)
self.nodes[0].generate(6)
self.sync_all()
def wait_for_instant_lock(self, node, node_idx, txid, timeout=10):
st = time.time()
while time.time() < st + timeout:
try:
tx = node.getrawtransaction(txid, 1)
except:
tx = None
if tx is None:
time.sleep(0.5)
continue
if tx['instantlock']:
return
time.sleep(0.5)
raise AssertionError("wait_for_instant_lock timed out for: {} on node {}".format(txid, node_idx))
def assert_mnlists(self, mns):
for node in self.nodes:
self.assert_mnlist(node, mns)

View File

@ -91,7 +91,8 @@ class LLMQChainLocksTest(DashTestFramework):
assert(self.nodes[0].getbestblockhash() == self.nodes[1].getbestblockhash())
# Enable LLMQ bases InstantSend, which also enables checks for "safe" transactions
self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.nodes[0].spork("SPORK_3_INSTANTSEND_BLOCK_FILTERING", 0)
self.wait_for_sporks_same()
# Isolate a node and let it create some transactions which won't get IS locked
@ -108,10 +109,10 @@ class LLMQChainLocksTest(DashTestFramework):
sleep(1)
assert(not self.nodes[0].getblock(self.nodes[0].getbestblockhash())["chainlock"])
# Disable LLMQ based InstantSend for a very short time (this never gets propagated to other nodes)
self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 4070908800)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800)
# Now the TXs should be included
self.nodes[0].generate(1)
self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
# Assert that TXs got included now
for txid in txs:
tx = self.nodes[0].getrawtransaction(txid, 1)

View File

@ -61,7 +61,8 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0)
self.nodes[0].spork("SPORK_19_CHAINLOCKS_ENABLED", 0)
self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.nodes[0].spork("SPORK_3_INSTANTSEND_BLOCK_FILTERING", 0)
self.wait_for_sporks_same()
self.mine_quorum()

View File

@ -119,7 +119,7 @@ class MultiKeySporkTest(BitcoinTestFramework):
def run_test(self):
# check test spork default state
for node in self.nodes:
assert(self.get_test_spork_state(node) == 0)
assert(self.get_test_spork_state(node) == 4070908800)
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())

View File

@ -1,99 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) 2018 The Dash Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.mininode import *
from test_framework.test_framework import DashTestFramework
from test_framework.util import *
from time import *
'''
p2p-autoinstantsend.py
Test automatic InstantSend locks functionality.
Checks that simple transactions automatically become InstantSend locked,
complex transactions don't become IS-locked and this functionality is
activated only if SPORK_16_INSTANTSEND_AUTOLOCKS is active.
Also checks that this functionality doesn't influence regular InstantSend
transactions with high fee.
'''
class AutoInstantSendTest(DashTestFramework):
def __init__(self):
super().__init__(8, 5, [], fast_dip3_enforcement=True)
# set sender, receiver, isolated nodes
self.receiver_idx = 1
self.sender_idx = 2
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()
self.log.info("Test old InstantSend")
self.test_auto();
# Generate 6 block to avoid retroactive signing overloading Travis
self.nodes[0].generate(6)
sync_blocks(self.nodes)
self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.wait_for_sporks_same()
self.log.info("Test new InstantSend")
self.test_auto(True);
def test_auto(self, new_is = False):
sender = self.nodes[self.sender_idx]
receiver = self.nodes[self.receiver_idx]
# feed the sender with some balance, make sure there are enough inputs
recipients = {}
for i in range(0, 30):
recipients[sender.getnewaddress()] = 1
# use a single transaction to not overload Travis with InstantSend
self.nodes[0].sendmany("", recipients)
# make sender funds mature for InstantSend
for i in range(0, 2):
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(1)
self.sync_all()
assert(not self.get_autois_spork_state(self.nodes[0]))
assert(self.send_regular_instantsend(sender, receiver, not new_is))
assert(self.send_simple_tx(sender, receiver) if new_is else not self.send_simple_tx(sender, receiver))
assert(self.send_complex_tx(sender, receiver) if new_is else not self.send_complex_tx(sender, receiver))
self.activate_autois_bip9(self.nodes[0])
self.set_autois_spork_state(self.nodes[0], True)
assert(self.get_autois_bip9_status(self.nodes[0]) == 'active')
assert(self.get_autois_spork_state(self.nodes[0]))
assert(self.send_regular_instantsend(sender, receiver, not new_is))
assert(self.send_simple_tx(sender, receiver))
assert(self.send_complex_tx(sender, receiver) if new_is else not self.send_complex_tx(sender, receiver))
self.set_autois_spork_state(self.nodes[0], False)
assert(not self.get_autois_spork_state(self.nodes[0]))
assert(self.send_regular_instantsend(sender, receiver, not new_is))
assert(self.send_simple_tx(sender, receiver) if new_is else not self.send_simple_tx(sender, receiver))
assert(self.send_complex_tx(sender, receiver) if new_is else not self.send_complex_tx(sender, receiver))
# mine all mempool txes
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(1)
self.sync_all()
if __name__ == '__main__':
AutoInstantSendTest().main()

View File

@ -25,17 +25,10 @@ class InstantSendTest(DashTestFramework):
self.wait_for_sporks_same()
self.mine_quorum()
self.log.info("Test old InstantSend")
self.test_block_doublespend()
# Generate 6 block to avoid retroactive signing overloading Travis
self.nodes[0].generate(6)
sync_blocks(self.nodes)
self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.nodes[0].spork("SPORK_3_INSTANTSEND_BLOCK_FILTERING", 0)
self.wait_for_sporks_same()
self.log.info("Test new InstantSend")
self.test_mempool_doublespend()
self.test_block_doublespend()
@ -56,7 +49,7 @@ class InstantSendTest(DashTestFramework):
isolate_node(isolated)
# instantsend to receiver
receiver_addr = receiver.getnewaddress()
is_id = sender.instantsendtoaddress(receiver_addr, 0.9)
is_id = sender.sendtoaddress(receiver_addr, 0.9)
for node in self.nodes:
if node is not isolated:
self.wait_for_instantlock(is_id, node)
@ -112,7 +105,7 @@ class InstantSendTest(DashTestFramework):
# instantsend to receiver. The previously isolated node should prune the doublespend TX and request the correct
# TX from other nodes.
receiver_addr = receiver.getnewaddress()
is_id = sender.instantsendtoaddress(receiver_addr, 0.9)
is_id = sender.sendtoaddress(receiver_addr, 0.9)
for node in self.nodes:
self.wait_for_instantlock(is_id, node)
assert_raises_jsonrpc(-5, "No such mempool or blockchain transaction", isolated.getrawtransaction, dblspnd_txid)

View File

@ -39,16 +39,16 @@ class SporkTest(BitcoinTestFramework):
def run_test(self):
# check test spork default state
assert(self.get_test_spork_state(self.nodes[0]))
assert(self.get_test_spork_state(self.nodes[1]))
assert(self.get_test_spork_state(self.nodes[2]))
assert(not self.get_test_spork_state(self.nodes[0]))
assert(not self.get_test_spork_state(self.nodes[1]))
assert(not self.get_test_spork_state(self.nodes[2]))
# check spork propagation for connected nodes
self.set_test_spork_state(self.nodes[0], False)
self.set_test_spork_state(self.nodes[0], True)
start = time()
sent = False
while True:
if not self.get_test_spork_state(self.nodes[1]):
if self.get_test_spork_state(self.nodes[1]):
sent = True
break
if time() > start + 10:
@ -61,8 +61,8 @@ class SporkTest(BitcoinTestFramework):
self.stop_node(1)
self.nodes[0] = self.start_node(0, self.options.tmpdir)
self.nodes[1] = self.start_node(1, self.options.tmpdir)
assert(not self.get_test_spork_state(self.nodes[0]))
assert(not self.get_test_spork_state(self.nodes[1]))
assert(self.get_test_spork_state(self.nodes[0]))
assert(self.get_test_spork_state(self.nodes[1]))
# Force finish mnsync node as otherwise it will never send out headers to other peers
wait_to_sync(self.nodes[1], fast_mnsync=True)
@ -75,7 +75,7 @@ class SporkTest(BitcoinTestFramework):
start = time()
sent = False
while True:
if not self.get_test_spork_state(self.nodes[2]):
if self.get_test_spork_state(self.nodes[2]):
sent = True
break
if time() > start + 10:

View File

@ -549,66 +549,6 @@ class DashTestFramework(BitcoinTestFramework):
for status in mn_info.values():
assert (status == 'ENABLED')
def get_autois_bip9_status(self, node):
info = node.getblockchaininfo()
# we reuse the dip3 deployment
return info['bip9_softforks']['dip0003']['status']
def activate_autois_bip9(self, node):
# sync nodes periodically
# if we sync them too often, activation takes too many time
# if we sync them too rarely, nodes failed to update its state and
# bip9 status is not updated
# so, in this code nodes are synced once per 20 blocks
counter = 0
sync_period = 10
while self.get_autois_bip9_status(node) == 'defined':
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
node.generate(1)
counter += 1
if counter % sync_period == 0:
# sync nodes
self.sync_all()
while self.get_autois_bip9_status(node) == 'started':
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
node.generate(1)
counter += 1
if counter % sync_period == 0:
# sync nodes
self.sync_all()
while self.get_autois_bip9_status(node) == 'locked_in':
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
node.generate(1)
counter += 1
if counter % sync_period == 0:
# sync nodes
self.sync_all()
# sync nodes
self.sync_all()
assert(self.get_autois_bip9_status(node) == 'active')
def get_autois_spork_state(self, node):
info = node.spork('active')
return info['SPORK_16_INSTANTSEND_AUTOLOCKS']
def set_autois_spork_state(self, node, state):
# Increment mocktime as otherwise nodes will not update sporks
set_mocktime(get_mocktime() + 1)
set_node_times(self.nodes, get_mocktime())
if state:
value = 0
else:
value = 4070908800
node.spork('SPORK_16_INSTANTSEND_AUTOLOCKS', value)
def create_raw_tx(self, node_from, node_to, amount, min_inputs, max_inputs):
assert (min_inputs <= max_inputs)
# fill inputs
@ -656,31 +596,6 @@ class DashTestFramework(BitcoinTestFramework):
ret = {**decoded, **ret}
return ret
# sends regular instantsend with high fee
def send_regular_instantsend(self, sender, receiver, check_fee = True):
receiver_addr = receiver.getnewaddress()
txid = sender.instantsendtoaddress(receiver_addr, 1.0)
if (check_fee):
MIN_FEE = satoshi_round(-0.0001)
fee = sender.gettransaction(txid)['fee']
expected_fee = MIN_FEE * len(sender.getrawtransaction(txid, True)['vin'])
assert_equal(fee, expected_fee)
return self.wait_for_instantlock(txid, sender)
# sends simple tx, it should become locked if autolocks are allowed
def send_simple_tx(self, sender, receiver):
raw_tx = self.create_raw_tx(sender, receiver, 1.0, 1, 4)
txid = self.nodes[0].sendrawtransaction(raw_tx['hex'])
self.sync_all()
return self.wait_for_instantlock(txid, sender)
# sends complex tx, it should never become locked for old instentsend
def send_complex_tx(self, sender, receiver):
raw_tx = self.create_raw_tx(sender, receiver, 1.0, 5, 100)
txid = sender.sendrawtransaction(raw_tx['hex'])
self.sync_all()
return self.wait_for_instantlock(txid, sender)
def wait_for_instantlock(self, txid, node):
# wait for instantsend locks
start = time.time()

View File

@ -60,8 +60,6 @@ BASE_SCRIPTS= [
'p2p-fullblocktest.py', # NOTE: needs dash_hash to pass
'fundrawtransaction.py',
'fundrawtransaction-hd.py',
'p2p-autoinstantsend.py',
'autois-mempool.py',
# vv Tests less than 2m vv
'p2p-instantsend.py',
'wallet.py',