Skip to content

Commit 4f31d0f

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 05f7a0c commit 4f31d0f

File tree

5 files changed

+38
-12
lines changed

5 files changed

+38
-12
lines changed

divi/src/StakableCoin.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
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
unsigned outputIndex;
99
uint256 blockHashOfFirstConfirmation;
1010
COutPoint utxo;
@@ -18,7 +18,7 @@ struct StakableCoin
1818
}
1919

2020
StakableCoin(
21-
const CTransaction* txIn,
21+
const CMerkleTx* txIn,
2222
unsigned outputIndexIn,
2323
uint256 blockHashIn
2424
): tx(txIn)
@@ -32,4 +32,4 @@ struct StakableCoin
3232
return utxo < other.utxo;
3333
}
3434
};
35-
#endif//STAKABLE_COIN_H
35+
#endif//STAKABLE_COIN_H

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/merkletx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@ class CMerkleTx : public CTransaction
5757
bool AcceptToMemoryPool(bool fLimitFree);
5858
bool IsTransactionLockTimedOut() const;
5959
};
60-
#endif// MERKLE_TX_H
60+
#endif// MERKLE_TX_H

divi/src/primitives/transaction.h

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

138138
CTransaction& operator=(const CTransaction& tx);
139139

140+
virtual ~CTransaction() = default;
141+
140142
ADD_SERIALIZE_METHODS;
141143

142144
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
uint256 GetUtxoHash(const CTransaction& tx) const override
192199
{
193-
return 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 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)