diff --git a/src/stakeinput.cpp b/src/stakeinput.cpp index ae7f00a0eb6a4..84ec47a5e776d 100644 --- a/src/stakeinput.cpp +++ b/src/stakeinput.cpp @@ -6,7 +6,7 @@ #include "chain.h" #include "txdb.h" -#include "wallet/wallet.h" +#include "validation.h" static bool HasStakeMinAgeOrDepth(int nHeight, uint32_t nTime, const CBlockIndex* pindex) { @@ -79,44 +79,6 @@ CAmount CPivStake::GetValue() const return outputFrom.nValue; } -bool CPivStake::CreateTxOuts(const CWallet* pwallet, std::vector& vout, CAmount nTotal) const -{ - std::vector vSolutions; - txnouttype whichType; - CScript scriptPubKeyKernel = outputFrom.scriptPubKey; - if (!Solver(scriptPubKeyKernel, whichType, vSolutions)) - return error("%s: failed to parse kernel", __func__); - - if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH && whichType != TX_COLDSTAKE) - return error("%s: type=%d (%s) not supported for scriptPubKeyKernel", __func__, whichType, GetTxnOutputType(whichType)); - - CKey key; - if (whichType == TX_PUBKEYHASH || whichType == TX_COLDSTAKE) { - // if P2PKH or P2CS check that we have the input private key - if (!pwallet->GetKey(CKeyID(uint160(vSolutions[0])), key)) - return error("%s: Unable to get staking private key", __func__); - } - - vout.emplace_back(0, scriptPubKeyKernel); - - // Calculate if we need to split the output - if (pwallet->nStakeSplitThreshold > 0) { - int nSplit = static_cast(nTotal / pwallet->nStakeSplitThreshold); - if (nSplit > 1) { - // if nTotal is twice or more of the threshold; create more outputs - int txSizeMax = MAX_STANDARD_TX_SIZE >> 11; // limit splits to <10% of the max TX size (/2048) - if (nSplit > txSizeMax) - nSplit = txSizeMax; - for (int i = nSplit; i > 1; i--) { - LogPrintf("%s: StakeSplit: nTotal = %d; adding output %d of %d\n", __func__, nTotal, (nSplit-i)+2, nSplit); - vout.emplace_back(0, scriptPubKeyKernel); - } - } - } - - return true; -} - CDataStream CPivStake::GetUniqueness() const { //The unique identifier for a PIV stake is the outpoint diff --git a/src/stakeinput.h b/src/stakeinput.h index 44f49d9b7cf84..4a80ba03fb288 100644 --- a/src/stakeinput.h +++ b/src/stakeinput.h @@ -46,7 +46,6 @@ class CPivStake : public CStakeInput CAmount GetValue() const override; CDataStream GetUniqueness() const override; CTxIn GetTxIn() const; - bool CreateTxOuts(const CWallet* pwallet, std::vector& vout, CAmount nTotal) const; bool IsZPIV() const override { return false; } }; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5da801f1e7fba..c430877bfa44d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -161,7 +161,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const LOCK(cs_wallet); std::map::const_iterator it = mapWallet.find(hash); if (it == mapWallet.end()) - return NULL; + return nullptr; return &(it->second); } @@ -3266,6 +3266,48 @@ int CWallet::GetLastBlockHeightLockWallet() const return WITH_LOCK(cs_wallet, return m_last_block_processed_height;); } +bool CWallet::CreateCoinstakeOuts(const CPivStake& stakeInput, std::vector& vout, CAmount nTotal) const +{ + std::vector vSolutions; + txnouttype whichType; + CTxOut stakePrevout; + if (!stakeInput.GetTxOutFrom(stakePrevout)) { + return error("%s: failed to get stake input", __func__); + } + CScript scriptPubKeyKernel = stakePrevout.scriptPubKey; + if (!Solver(scriptPubKeyKernel, whichType, vSolutions)) + return error("%s: failed to parse kernel", __func__); + + if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH && whichType != TX_COLDSTAKE) + return error("%s: type=%d (%s) not supported for scriptPubKeyKernel", __func__, whichType, GetTxnOutputType(whichType)); + + CKey key; + if (whichType == TX_PUBKEYHASH || whichType == TX_COLDSTAKE) { + // if P2PKH or P2CS check that we have the input private key + if (!GetKey(CKeyID(uint160(vSolutions[0])), key)) + return error("%s: Unable to get staking private key", __func__); + } + + vout.emplace_back(0, scriptPubKeyKernel); + + // Calculate if we need to split the output + if (nStakeSplitThreshold > 0) { + int nSplit = static_cast(nTotal / nStakeSplitThreshold); + if (nSplit > 1) { + // if nTotal is twice or more of the threshold; create more outputs + int txSizeMax = MAX_STANDARD_TX_SIZE >> 11; // limit splits to <10% of the max TX size (/2048) + if (nSplit > txSizeMax) + nSplit = txSizeMax; + for (int i = nSplit; i > 1; i--) { + LogPrintf("%s: StakeSplit: nTotal = %d; adding output %d of %d\n", __func__, nTotal, (nSplit-i)+2, nSplit); + vout.emplace_back(0, scriptPubKeyKernel); + } + } + } + + return true; +} + bool CWallet::CreateCoinStake( const CBlockIndex* pindexPrev, unsigned int nBits, @@ -3335,7 +3377,7 @@ bool CWallet::CreateCoinStake( // Create the output transaction(s) std::vector vout; - if (!stakeInput.CreateTxOuts(this, vout, nCredit)) { + if (!CreateCoinstakeOuts(stakeInput, vout, nCredit)) { LogPrintf("%s : failed to create output\n", __func__); it++; continue; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 74a4371c50847..94e27460a1aca 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1096,6 +1096,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface }; CWallet::CommitResult CommitTransaction(CTransactionRef tx, CReserveKey& opReservekey, CConnman* connman); CWallet::CommitResult CommitTransaction(CTransactionRef tx, CReserveKey* reservekey, CConnman* connman, mapValue_t* extraValues=nullptr); + + bool CreateCoinstakeOuts(const CPivStake& stakeInput, std::vector& vout, CAmount nTotal) const; bool CreateCoinStake(const CBlockIndex* pindexPrev, unsigned int nBits, CMutableTransaction& txNew, diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index 94f91e4749dde..5dcf89d12f298 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -39,7 +39,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "wallet/wallet -> wallet/walletdb -> wallet/wallet" "chain -> legacy/stakemodifier -> stakeinput -> chain" "chain -> legacy/stakemodifier -> validation -> chain" - "kernel -> stakeinput -> wallet/wallet -> kernel" "legacy/validation_zerocoin_legacy -> wallet/wallet -> validation -> legacy/validation_zerocoin_legacy" "llmq/quorums_dkgsession -> llmq/quorums_dkgsessionmgr -> llmq/quorums_dkgsessionhandler -> llmq/quorums_dkgsession" "llmq/quorums_dkgsessionhandler -> net_processing -> llmq/quorums_dkgsessionmgr -> llmq/quorums_dkgsessionhandler"