diff --git a/divi/src/StakableCoin.h b/divi/src/StakableCoin.h index f5877febe..dcf8ad162 100644 --- a/divi/src/StakableCoin.h +++ b/divi/src/StakableCoin.h @@ -1,15 +1,15 @@ #ifndef STAKABLE_COIN_H #define STAKABLE_COIN_H +#include #include -#include struct StakableCoin { - const CTransaction* tx; + const CMerkleTx* tx; COutPoint utxo; uint256 blockHashOfFirstConfirmation; explicit StakableCoin( - const CTransaction& txIn, + const CMerkleTx& txIn, const COutPoint& utxoIn, uint256 blockHashIn ): tx(&txIn) diff --git a/divi/src/kernel.cpp b/divi/src/kernel.cpp index b59a1f14c..5b2275ca7 100644 --- a/divi/src/kernel.cpp +++ b/divi/src/kernel.cpp @@ -254,7 +254,7 @@ bool CheckProofOfStakeContextAndRecoverStakingData( uint256 hashBlock; CTransaction txPrev; if (!GetTransaction(txin.prevout.hash, txPrev, hashBlock, true)) - return error("CheckProofOfStake() : INFO: read txPrev failed"); + return error("CheckProofOfStake() : INFO: read txPrev failed for %s", txin.prevout.hash.GetHex()); const CScript &kernelScript = txPrev.vout[txin.prevout.n].scriptPubKey; diff --git a/divi/src/primitives/transaction.h b/divi/src/primitives/transaction.h index 5d0e5095a..649460aec 100644 --- a/divi/src/primitives/transaction.h +++ b/divi/src/primitives/transaction.h @@ -139,6 +139,8 @@ class CTransaction CTransaction& operator=(const CTransaction& tx); + virtual ~CTransaction() = default; + ADD_SERIALIZE_METHODS; template diff --git a/divi/src/wallet.cpp b/divi/src/wallet.cpp index 3260bfc83..cb77df254 100644 --- a/divi/src/wallet.cpp +++ b/divi/src/wallet.cpp @@ -180,28 +180,52 @@ bool WriteTxToDisk(const CWallet* walletPtr, const CWalletTx& transactionToWrite namespace { -/** Dummy UTXO hasher for the wallet. For now, this just always returns - * the normal txid, but we will later change it to return the proper hash - * for a WalletTx. */ +/** UTXO hasher for wallet transactions. It uses the transaction's known block + * hash (from CMerkleTx) to determine the activation state of segwit light. */ class WalletUtxoHasher : public TransactionUtxoHasher { +private: + + const CChain& chainActive_; + public: + WalletUtxoHasher(const CChain& chain) + : chainActive_(chain) + {} + OutputHash GetUtxoHash(const CTransaction& tx) const override { - return OutputHash(tx.GetHash()); + const CMerkleTx* mtx = dynamic_cast(&tx); + assert(mtx != nullptr); + + const CBlockIndex* pindexBlock = nullptr; + const int depth = mtx->GetNumberOfBlockConfirmations(pindexBlock); + + /* If the transaction is not yet confirmed in a block, we use the current + tip to determine the segwit-light activation status. This is not + perfect around the activation time, but there is nothing we can do + in that case anyway. Mempool and wallet discourage spending unconfirmed + outputs around the segwit-light fork anyway. */ + if (depth <= 0) + pindexBlock = chainActive_.Tip(); + + assert(pindexBlock != nullptr); + const ActivationState as(pindexBlock); + + return OutputHash(as.IsActive(Fork::SegwitLight) ? mtx->GetBareTxid() : mtx->GetHash()); } }; -} // anonymous namespace +} CWallet::CWallet(const CChain& chain, const BlockMap& blockMap ): cs_wallet() , transactionRecord_(new WalletTransactionRecord(cs_wallet,strWalletFile) ) , outputTracker_( new SpentOutputTracker(*transactionRecord_) ) - , utxoHasher(new WalletUtxoHasher() ) + , utxoHasher(new WalletUtxoHasher(chain) ) , chainActive_(chain) , mapBlockIndex_(blockMap) , orderedTransactionIndex()