Skip to content

Commit 4444568

Browse files
committed
Segwit light for spending coins.
Handle segwit-light properly when spending coins, either for staking or normal transactions in the wallet. Depending on when a transaction was confirmed, we need to make sure to include the right outpoint (with txid or bare txid) in the transaction spending an output. This is done through a custom UTXO hasher used in the wallet, which specifically works for CWalletTx.
1 parent 6a232b7 commit 4444568

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

divi/src/primitives/transaction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ class CTransaction
139139

140140
CTransaction& operator=(const CTransaction& tx);
141141

142+
virtual ~CTransaction() = default;
143+
142144
ADD_SERIALIZE_METHODS;
143145

144146
template <typename Stream, typename Operation>

divi/src/wallet.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "checkpoints.h"
1414
#include <chain.h>
1515
#include <chainparams.h>
16+
#include "ForkActivation.h"
1617
#include "net.h"
1718
#include "script/script.h"
1819
#include "script/sign.h"
@@ -176,17 +177,42 @@ std::set<CTxDestination> AddressBookManager::GetAccountAddresses(std::string str
176177
namespace
177178
{
178179

179-
/** Dummy UTXO hasher for the wallet. For now, this just always returns
180-
* the normal txid, but we will later change it to return the proper hash
181-
* for a WalletTx. */
180+
/** UTXO hasher for wallet transactions. It uses the transaction's known block
181+
* hash (from CMerkleTx) to determine the activation state of segwit light. */
182182
class WalletUtxoHasher : public TransactionUtxoHasher
183183
{
184184

185+
private:
186+
187+
const I_MerkleTxConfirmationNumberCalculator& confirmationNumberCalculator_;
188+
const CChain& chainActive_;
189+
185190
public:
186191

192+
WalletUtxoHasher(const I_MerkleTxConfirmationNumberCalculator& calc, const CChain& chain)
193+
: confirmationNumberCalculator_(calc), chainActive_(chain)
194+
{}
195+
187196
OutputHash GetUtxoHash(const CTransaction& tx) const override
188197
{
189-
return OutputHash(tx.GetHash());
198+
const CMerkleTx* mtx = dynamic_cast<const CMerkleTx*>(&tx);
199+
assert(mtx != nullptr);
200+
201+
const auto conf = confirmationNumberCalculator_.FindConfirmedBlockIndexAndDepth(*mtx);
202+
const CBlockIndex* pindexBlock = conf.first;
203+
204+
/* If the transaction is not yet confirmed in a block, we use the current
205+
tip to determine the segwit-light activation status. This is not
206+
perfect around the activation time, but there is nothing we can do
207+
in that case anyway. Mempool and wallet discourage spending unconfirmed
208+
outputs around the segwit-light fork anyway. */
209+
if (conf.second <= 0)
210+
pindexBlock = chainActive_.Tip();
211+
212+
assert(pindexBlock != nullptr);
213+
const ActivationState as(pindexBlock);
214+
215+
return OutputHash(as.IsActive(Fork::SegwitLight) ? mtx->GetBareTxid() : mtx->GetHash());
190216
}
191217

192218
};
@@ -211,7 +237,7 @@ CWallet::CWallet(const CChain& chain, const BlockMap& blockMap
211237
, transactionRecord_(new WalletTransactionRecord(cs_wallet,strWalletFile) )
212238
, outputTracker_( new SpentOutputTracker(*transactionRecord_,*confirmationNumberCalculator_) )
213239
, pwalletdbEncryption()
214-
, utxoHasher(new WalletUtxoHasher() )
240+
, utxoHasher(new WalletUtxoHasher(*confirmationNumberCalculator_, chain) )
215241
, nWalletVersion(FEATURE_BASE)
216242
, nWalletMaxVersion(FEATURE_BASE)
217243
, mapKeyMetadata()

0 commit comments

Comments
 (0)