Skip to content

Commit df3b700

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 707e9b6 commit df3b700

File tree

4 files changed

+36
-10
lines changed

4 files changed

+36
-10
lines changed

divi/src/StakableCoin.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#ifndef STAKABLE_COIN_H
22
#define STAKABLE_COIN_H
3+
#include <merkletx.h>
34
#include <uint256.h>
4-
#include <primitives/transaction.h>
55
struct StakableCoin
66
{
7-
const CTransaction* tx;
7+
const CMerkleTx* tx;
88
COutPoint utxo;
99
uint256 blockHashOfFirstConfirmation;
1010

1111
explicit StakableCoin(
12-
const CTransaction& txIn,
12+
const CMerkleTx& txIn,
1313
const COutPoint& utxoIn,
1414
uint256 blockHashIn
1515
): tx(&txIn)

divi/src/kernel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ bool CheckProofOfStakeContextAndRecoverStakingData(
254254
uint256 hashBlock;
255255
CTransaction txPrev;
256256
if (!GetTransaction(txin.prevout.hash, txPrev, hashBlock, true))
257-
return error("CheckProofOfStake() : INFO: read txPrev failed");
257+
return error("CheckProofOfStake() : INFO: read txPrev failed for %s", txin.prevout.hash.GetHex());
258258

259259
const CScript &kernelScript = txPrev.vout[txin.prevout.n].scriptPubKey;
260260

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: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,28 +180,52 @@ bool WriteTxToDisk(const CWallet* walletPtr, const CWalletTx& transactionToWrite
180180
namespace
181181
{
182182

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

188+
private:
189+
190+
const CChain& chainActive_;
191+
189192
public:
190193

194+
WalletUtxoHasher(const CChain& chain)
195+
: chainActive_(chain)
196+
{}
197+
191198
OutputHash GetUtxoHash(const CTransaction& tx) const override
192199
{
193-
return OutputHash(tx.GetHash());
200+
const CMerkleTx* mtx = dynamic_cast<const CMerkleTx*>(&tx);
201+
assert(mtx != nullptr);
202+
203+
const CBlockIndex* pindexBlock = nullptr;
204+
const int depth = mtx->GetNumberOfBlockConfirmations(pindexBlock);
205+
206+
/* If the transaction is not yet confirmed in a block, we use the current
207+
tip to determine the segwit-light activation status. This is not
208+
perfect around the activation time, but there is nothing we can do
209+
in that case anyway. Mempool and wallet discourage spending unconfirmed
210+
outputs around the segwit-light fork anyway. */
211+
if (depth <= 0)
212+
pindexBlock = chainActive_.Tip();
213+
214+
assert(pindexBlock != nullptr);
215+
const ActivationState as(pindexBlock);
216+
217+
return OutputHash(as.IsActive(Fork::SegwitLight) ? mtx->GetBareTxid() : mtx->GetHash());
194218
}
195219

196220
};
197221

198-
} // anonymous namespace
222+
}
199223

200224
CWallet::CWallet(const CChain& chain, const BlockMap& blockMap
201225
): cs_wallet()
202226
, transactionRecord_(new WalletTransactionRecord(cs_wallet,strWalletFile) )
203227
, outputTracker_( new SpentOutputTracker(*transactionRecord_) )
204-
, utxoHasher(new WalletUtxoHasher() )
228+
, utxoHasher(new WalletUtxoHasher(chain) )
205229
, chainActive_(chain)
206230
, mapBlockIndex_(blockMap)
207231
, orderedTransactionIndex()

0 commit comments

Comments
 (0)