Skip to content

Commit 8cdd491

Browse files
committed
Use UTXO hasher for spending coins.
Use the UTXO hasher abstraction in the wallet and for staking (i.e. for places where coins are spent). The wallet gets its own instance, which will allow for dependency injection in tests. For now, the hasher used in the wallet is just the normal hasher, i.e. there are no actual changes in behaviour. In the future, the wallet hasher can be changed accordingly for the activation of segwit light.
1 parent 221dd2f commit 8cdd491

8 files changed

+65
-19
lines changed

divi/src/CoinControlSelectionAlgorithm.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#include <CoinControlSelectionAlgorithm.h>
22
#include <coincontrol.h>
3+
#include <wallet.h>
34
#include <WalletTx.h>
45

56
CoinControlSelectionAlgorithm::CoinControlSelectionAlgorithm(
6-
const CCoinControl* coinControl
7-
): coinControl_(coinControl)
7+
const CCoinControl* coinControl,
8+
const CWallet& wallet
9+
): coinControl_(coinControl), wallet_(wallet)
810
{
911
}
1012

@@ -20,7 +22,7 @@ std::set<COutput> CoinControlSelectionAlgorithm::SelectCoins(
2022
for(const COutput& out: vCoins)
2123
{
2224
if (!out.fSpendable ||
23-
(!coinControl_->fAllowOtherInputs && !coinControl_->IsSelected(out.tx->GetHash(),out.i)))
25+
(!coinControl_->fAllowOtherInputs && !coinControl_->IsSelected(wallet_.GetUtxoHash(*out.tx),out.i)))
2426
{
2527
continue;
2628
}
@@ -31,4 +33,4 @@ std::set<COutput> CoinControlSelectionAlgorithm::SelectCoins(
3133
}
3234
fees = totalInputs - transactionToSelectCoinsFor.GetValueOut();
3335
return setCoinsRet;
34-
}
36+
}

divi/src/CoinControlSelectionAlgorithm.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@
22
#define COIN_CONTROL_COIN_SELECTOR_H
33
#include <I_CoinSelectionAlgorithm.h>
44
class CCoinControl;
5+
class CWallet;
56
class CoinControlSelectionAlgorithm: public I_CoinSelectionAlgorithm
67
{
78
private:
89
const CCoinControl* coinControl_;
10+
const CWallet& wallet_;
911
public:
10-
CoinControlSelectionAlgorithm(
11-
const CCoinControl* coinControl);
12+
explicit CoinControlSelectionAlgorithm(
13+
const CCoinControl* coinControl,
14+
const CWallet& wallet);
1215
virtual std::set<COutput> SelectCoins(
1316
const CMutableTransaction& transactionToSelectCoinsFor,
1417
const std::vector<COutput>& vCoins,
1518
CAmount& fees) const;
1619
};
17-
#endif// COIN_CONTROL_COIN_SELECTOR_H
20+
#endif// COIN_CONTROL_COIN_SELECTOR_H

divi/src/PoSTransactionCreator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ void PoSTransactionCreator::CombineUtxos(
145145
for(const StakableCoin& pcoin : stakedCoins_->asSet())
146146
{
147147
if(pcoin.GetTxOut().scriptPubKey == txNew.vout[1].scriptPubKey &&
148-
pcoin.tx->GetHash() != txNew.vin[0].prevout.hash)
148+
wallet_.GetUtxoHash(*pcoin.tx) != txNew.vin[0].prevout.hash)
149149
{
150150
if(pcoin.GetTxOut().nValue + nCredit > nCombineThreshold)
151151
continue;

divi/src/rpcmasternode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ Value allocatefunds(const Array& params, bool fHelp)
102102
SendMoney(acctAddr.Get(), CMasternode::GetTierCollateralAmount(nMasternodeTier), wtx);
103103

104104
Object obj;
105-
obj.push_back(Pair("txhash", wtx.GetHash().GetHex()));
105+
obj.push_back(Pair("txhash", pwalletMain->GetUtxoHash(wtx).GetHex()));
106106
return obj;
107107
}
108108

divi/src/rpcrawtransaction.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ Value listunspent(const Array& params, bool fHelp)
337337
"[ (array of json object)\n"
338338
" {\n"
339339
" \"txid\" : \"txid\", (string) the transaction id \n"
340+
" \"baretxid\" : \"baretxid\", (string) The bare txid (without signatures)\n"
341+
" \"outputhash\" : \"outputhash\", (string) The hash (txid or bare txid) that should be used for spending\n"
340342
" \"vout\" : n, (numeric) the vout value\n"
341343
" \"address\" : \"address\", (string) the divi address\n"
342344
" \"account\" : \"account\", (string) The associated account, or \"\" for the default account\n"
@@ -394,6 +396,8 @@ Value listunspent(const Array& params, bool fHelp)
394396
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
395397
Object entry;
396398
entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
399+
entry.push_back(Pair("baretxid", out.tx->GetBareTxid().GetHex()));
400+
entry.push_back(Pair("outputhash", pwalletMain->GetUtxoHash(*out.tx).GetHex()));
397401
entry.push_back(Pair("vout", out.i));
398402
CTxDestination address;
399403
if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {

divi/src/wallet.cpp

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <Logging.h>
3636
#include <StakableCoin.h>
3737
#include <SpentOutputTracker.h>
38+
#include <UtxoCheckingAndUpdating.h>
3839
#include <WalletTx.h>
3940
#include <WalletTransactionRecord.h>
4041
#include <StochasticSubsetSelectionAlgorithm.h>
@@ -167,10 +168,31 @@ bool WriteTxToDisk(const CWallet* walletPtr, const CWalletTx& transactionToWrite
167168
return CWalletDB(settings, walletPtr->strWalletFile).WriteTx(transactionToWrite.GetHash(),transactionToWrite);
168169
}
169170

171+
namespace
172+
{
173+
174+
/** Dummy UTXO hasher for the wallet. For now, this just always returns
175+
* the normal txid, but we will later change it to return the proper hash
176+
* for a WalletTx. */
177+
class WalletUtxoHasher : public TransactionUtxoHasher
178+
{
179+
180+
public:
181+
182+
uint256 GetUtxoHash(const CTransaction& tx) const override
183+
{
184+
return tx.GetHash();
185+
}
186+
187+
};
188+
189+
} // anonymous namespace
190+
170191
CWallet::CWallet(const CChain& chain, const BlockMap& blockMap
171192
): cs_wallet()
172193
, transactionRecord_(new WalletTransactionRecord(cs_wallet,strWalletFile) )
173194
, outputTracker_( new SpentOutputTracker(*transactionRecord_) )
195+
, utxoHasher(new WalletUtxoHasher() )
174196
, chainActive_(chain)
175197
, mapBlockIndex_(blockMap)
176198
, orderedTransactionIndex()
@@ -334,7 +356,7 @@ CAmount CWallet::ComputeCredit(const CWalletTx& tx, const isminefilter& filter,
334356
{
335357
const CAmount maxMoneyAllowedInOutput = Params().MaxMoneyOut();
336358
CAmount nCredit = 0;
337-
uint256 hash = tx.GetHash();
359+
const uint256 hash = GetUtxoHash(tx);
338360
for (unsigned int i = 0; i < tx.vout.size(); i++) {
339361
if( (creditFilterFlags & REQUIRE_UNSPENT) && IsSpent(tx,i)) continue;
340362
if( (creditFilterFlags & REQUIRE_UNLOCKED) && IsLockedCoin(hash,i)) continue;
@@ -928,7 +950,7 @@ set<uint256> CWallet::GetConflicts(const uint256& txid) const
928950
*/
929951
bool CWallet::IsSpent(const CWalletTx& wtx, unsigned int n) const
930952
{
931-
return outputTracker_->IsSpent(wtx.GetHash(), n);
953+
return outputTracker_->IsSpent(GetUtxoHash(wtx), n);
932954
}
933955

934956
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
@@ -1645,7 +1667,7 @@ bool CWallet::IsAvailableForSpending(
16451667
}
16461668
}
16471669

1648-
const uint256 hash = pcoin->GetHash();
1670+
const uint256 hash = GetUtxoHash(*pcoin);
16491671

16501672
if (IsSpent(*pcoin, i))
16511673
return false;
@@ -1797,7 +1819,7 @@ bool CWallet::SelectStakeCoins(std::set<StakableCoin>& setCoins) const
17971819
continue;
17981820

17991821
//add to our stake set
1800-
setCoins.emplace(*out.tx, COutPoint(out.tx->GetHash(), out.i), out.tx->hashBlock);
1822+
setCoins.emplace(*out.tx, COutPoint(GetUtxoHash(*out.tx), out.i), out.tx->hashBlock);
18011823
nAmountSelected += out.tx->vout[out.i].nValue;
18021824
}
18031825
return true;
@@ -2144,14 +2166,15 @@ static bool SetChangeOutput(
21442166
}
21452167

21462168
static CAmount AttachInputs(
2169+
const TransactionUtxoHasher& utxoHasher,
21472170
const std::set<COutput>& setCoins,
21482171
CMutableTransaction& txWithoutChange)
21492172
{
21502173
// Fill vin
21512174
CAmount nValueIn = 0;
21522175
for(const COutput& coin: setCoins)
21532176
{
2154-
txWithoutChange.vin.emplace_back(coin.tx->GetHash(), coin.i);
2177+
txWithoutChange.vin.emplace_back(utxoHasher.GetUtxoHash(*coin.tx), coin.i);
21552178
nValueIn += coin.Value();
21562179
}
21572180
return nValueIn;
@@ -2160,6 +2183,7 @@ static CAmount AttachInputs(
21602183
static std::pair<string,bool> SelectInputsProvideSignaturesAndFees(
21612184
const CKeyStore& walletKeyStore,
21622185
const I_CoinSelectionAlgorithm* coinSelector,
2186+
const TransactionUtxoHasher& utxoHasher,
21632187
const std::vector<COutput>& vCoins,
21642188
CMutableTransaction& txNew,
21652189
CReserveKey& reservekey,
@@ -2175,7 +2199,7 @@ static std::pair<string,bool> SelectInputsProvideSignaturesAndFees(
21752199
txNew.vin.clear();
21762200
// Choose coins to use
21772201
std::set<COutput> setCoins = coinSelector->SelectCoins(txNew,vCoins,nFeeRet);
2178-
CAmount nValueIn = AttachInputs(setCoins,txNew);
2202+
CAmount nValueIn = AttachInputs(utxoHasher, setCoins, txNew);
21792203
CAmount nTotalValue = totalValueToSend + nFeeRet;
21802204
if (setCoins.empty() || nValueIn < nTotalValue)
21812205
{
@@ -2237,7 +2261,7 @@ std::pair<std::string,bool> CWallet::CreateTransaction(
22372261
{
22382262
return {translate("Transaction output(s) amount too small"),false};
22392263
}
2240-
return SelectInputsProvideSignaturesAndFees(*this, coinSelector,vCoins,txNew,reservekey,wtxNew);
2264+
return SelectInputsProvideSignaturesAndFees(*this, coinSelector, *utxoHasher, vCoins, txNew, reservekey, wtxNew);
22412265
}
22422266

22432267
/**
@@ -2312,6 +2336,11 @@ std::pair<std::string,bool> CWallet::SendMoney(
23122336
return {std::string(""),true};
23132337
}
23142338

2339+
uint256 CWallet::GetUtxoHash(const CMerkleTx& tx) const
2340+
{
2341+
return utxoHasher->GetUtxoHash(tx);
2342+
}
2343+
23152344
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
23162345
{
23172346
if (!fFileBacked)

divi/src/wallet.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <OutputEntry.h>
2828
#include <Output.h>
2929

30+
#include <memory>
31+
3032
class I_SignatureSizeEstimator;
3133
class I_CoinSelectionAlgorithm;
3234
class CKeyMetadata;
@@ -38,6 +40,7 @@ class CBlockIndex;
3840
struct StakableCoin;
3941
class WalletTransactionRecord;
4042
class SpentOutputTracker;
43+
class TransactionUtxoHasher;
4144
class BlockMap;
4245
class CAccountingEntry;
4346
class CChain;
@@ -121,6 +124,7 @@ class CWallet : public CCryptoKeyStore, public NotificationInterface, public I_K
121124
private:
122125
std::unique_ptr<WalletTransactionRecord> transactionRecord_;
123126
std::unique_ptr<SpentOutputTracker> outputTracker_;
127+
std::unique_ptr<TransactionUtxoHasher> utxoHasher;
124128
const CChain& chainActive_;
125129
const BlockMap& mapBlockIndex_;
126130
int64_t orderedTransactionIndex;
@@ -220,6 +224,10 @@ class CWallet : public CCryptoKeyStore, public NotificationInterface, public I_K
220224
void UnlockAllCoins();
221225
void ListLockedCoins(CoinVector& vOutpts);
222226

227+
/** Returns the UTXO hash that should be used for spending outputs
228+
* from the given transaction (which should be part of the wallet). */
229+
uint256 GetUtxoHash(const CMerkleTx& tx) const;
230+
223231
// keystore implementation
224232
// Generate a new key
225233
CPubKey GenerateNewKey(uint32_t nAccountIndex, bool fInternal);

divi/src/walletdustcombiner.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void WalletDustCombiner::CombineDust(CAmount combineThreshold)
6969
if (out.Value() > combineThreshold * COIN)
7070
continue;
7171

72-
COutPoint outpt(out.tx->GetHash(), out.i);
72+
COutPoint outpt(wallet_.GetUtxoHash(*out.tx), out.i);
7373
coinControl->Select(outpt);
7474
coinsToCombine.push_back(out);
7575
nTotalRewardsValue += out.Value();
@@ -92,7 +92,7 @@ void WalletDustCombiner::CombineDust(CAmount combineThreshold)
9292
CWalletTx wtx;
9393
std::pair<std::string,bool> txCreationResult;
9494
{
95-
CoinControlSelectionAlgorithm coinSelectionAlgorithm(coinControl);
95+
CoinControlSelectionAlgorithm coinSelectionAlgorithm(coinControl, wallet_);
9696
txCreationResult = wallet_.SendMoney(vecSend, wtx, ALL_SPENDABLE_COINS,&coinSelectionAlgorithm);
9797
}
9898
delete coinControl;
@@ -115,4 +115,4 @@ void combineWalletDust(const Settings& settings)
115115
settings.GetArg("-combinethreshold",std::numeric_limits<int64_t>::max() ) );
116116
}
117117
}
118-
}
118+
}

0 commit comments

Comments
 (0)