Skip to content

Commit afa2ab6

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 e170cc1 commit afa2ab6

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
@@ -58,4 +58,4 @@ class CMerkleTx : public CTransaction
5858
int GetTransactionLockSignatures() const;
5959
bool IsTransactionLockTimedOut() const;
6060
};
61-
#endif// MERKLE_TX_H
61+
#endif// MERKLE_TX_H

divi/src/primitives/transaction.h

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

201201
CTransaction& operator=(const CTransaction& tx);
202202

203+
virtual ~CTransaction() = default;
204+
203205
ADD_SERIALIZE_METHODS;
204206

205207
template <typename Stream, typename Operation>

divi/src/wallet.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,28 +189,52 @@ bool WriteTxToDisk(const CWallet* walletPtr, const CWalletTx& transactionToWrite
189189
namespace
190190
{
191191

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

197+
private:
198+
199+
const CChain& chainActive_;
200+
198201
public:
199202

203+
WalletUtxoHasher(const CChain& chain)
204+
: chainActive_(chain)
205+
{}
206+
200207
uint256 GetUtxoHash(const CTransaction& tx) const override
201208
{
202-
return tx.GetHash();
209+
const CMerkleTx* mtx = dynamic_cast<const CMerkleTx*>(&tx);
210+
assert(mtx != nullptr);
211+
212+
const CBlockIndex* pindexBlock = nullptr;
213+
const int depth = mtx->GetNumberOfBlockConfirmations(pindexBlock);
214+
215+
/* If the transaction is not yet confirmed in a block, we use the current
216+
tip to determine the segwit-light activation status. This is not
217+
perfect around the activation time, but there is nothing we can do
218+
in that case anyway. Mempool and wallet discourage spending unconfirmed
219+
outputs around the segwit-light fork anyway. */
220+
if (depth <= 0)
221+
pindexBlock = chainActive_.Tip();
222+
223+
assert(pindexBlock != nullptr);
224+
const ActivationState as(pindexBlock);
225+
226+
return as.IsActive(Fork::SegwitLight) ? mtx->GetBareTxid() : mtx->GetHash();
203227
}
204228

205229
};
206230

207-
} // anonymous namespace
231+
}
208232

209233
CWallet::CWallet(const CChain& chain, const BlockMap& blockMap
210234
): cs_wallet()
211235
, transactionRecord_(new WalletTransactionRecord(cs_wallet,strWalletFile) )
212236
, outputTracker_( new SpentOutputTracker(*transactionRecord_) )
213-
, utxoHasher(new WalletUtxoHasher() )
237+
, utxoHasher(new WalletUtxoHasher(chain) )
214238
, chainActive_(chain)
215239
, mapBlockIndex_(blockMap)
216240
, orderedTransactionIndex()

0 commit comments

Comments
 (0)