Browse Source

Merge pull request #4309

d38da59 Code simplifications after CTransaction::GetHash() caching (Pieter Wuille)
4949004 Add CMutableTransaction and make CTransaction immutable. (Pieter Wuille)
0.10
Pieter Wuille 11 years ago
parent
commit
d4e4e05435
No known key found for this signature in database
GPG Key ID: 8F653255C87992E0
  1. 3
      src/bloom.cpp
  2. 2
      src/bloom.h
  3. 2
      src/chainparams.cpp
  4. 25
      src/core.cpp
  5. 99
      src/core.h
  6. 59
      src/main.cpp
  7. 6
      src/main.h
  8. 22
      src/miner.cpp
  9. 10
      src/net.cpp
  10. 4
      src/net.h
  11. 2
      src/qt/coincontroldialog.cpp
  12. 16
      src/rpcrawtransaction.cpp
  13. 6
      src/script.cpp
  14. 5
      src/script.h
  15. 12
      src/test/DoS_tests.cpp
  16. 12
      src/test/accounting_tests.cpp
  17. 26
      src/test/bloom_tests.cpp
  18. 12
      src/test/miner_tests.cpp
  19. 8
      src/test/multisig_tests.cpp
  20. 4
      src/test/pmt_tests.cpp
  21. 18
      src/test/script_P2SH_tests.cpp
  22. 12
      src/test/script_tests.cpp
  23. 6
      src/test/sighash_tests.cpp
  24. 14
      src/test/transaction_tests.cpp
  25. 10
      src/test/wallet_tests.cpp
  26. 33
      src/wallet.cpp
  27. 4
      src/wallet.h

3
src/bloom.cpp

@ -99,7 +99,7 @@ bool CBloomFilter::IsWithinSizeConstraints() const @@ -99,7 +99,7 @@ bool CBloomFilter::IsWithinSizeConstraints() const
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
}
bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash)
bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
{
bool fFound = false;
// Match if the filter contains the hash of tx
@ -108,6 +108,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha @@ -108,6 +108,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha
return true;
if (isEmpty)
return false;
const uint256& hash = tx.GetHash();
if (contains(hash))
fFound = true;

2
src/bloom.h

@ -83,7 +83,7 @@ public: @@ -83,7 +83,7 @@ public:
bool IsWithinSizeConstraints() const;
// Also adds any outputs which match the filter to the filter (to match their spending txes)
bool IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash);
bool IsRelevantAndUpdate(const CTransaction& tx);
// Checks for empty and full filters to avoid wasting cpu
void UpdateEmptyFull();

2
src/chainparams.cpp

@ -127,7 +127,7 @@ public: @@ -127,7 +127,7 @@ public:
// CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
// vMerkleTree: 4a5e1e
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
CTransaction txNew;
CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));

25
src/core.cpp

@ -91,11 +91,34 @@ std::string CFeeRate::ToString() const @@ -91,11 +91,34 @@ std::string CFeeRate::ToString() const
return result;
}
uint256 CTransaction::GetHash() const
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
uint256 CMutableTransaction::GetHash() const
{
return SerializeHash(*this);
}
void CTransaction::UpdateHash() const
{
*const_cast<uint256*>(&hash) = SerializeHash(*this);
}
CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
UpdateHash();
}
CTransaction& CTransaction::operator=(const CTransaction &tx) {
*const_cast<int*>(&nVersion) = tx.nVersion;
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
*const_cast<uint256*>(&hash) = tx.hash;
return *this;
}
int64_t CTransaction::GetValueOut() const
{
int64_t nValueOut = 0;

99
src/core.h

@ -203,49 +203,59 @@ public: @@ -203,49 +203,59 @@ public:
};
struct CMutableTransaction;
/** The basic transaction that is broadcasted on the network and contained in
* blocks. A transaction can contain multiple inputs and outputs.
*/
class CTransaction
{
private:
/** Memory only. */
const uint256 hash;
void UpdateHash() const;
public:
static CFeeRate minTxFee;
static CFeeRate minRelayTxFee;
static const int CURRENT_VERSION=1;
int nVersion;
std::vector<CTxIn> vin;
std::vector<CTxOut> vout;
unsigned int nLockTime;
CTransaction()
{
SetNull();
}
// The local variables are made const to prevent unintended modification
// without updating the cached hash value. However, CTransaction is not
// actually immutable; deserialization and assignment are implemented,
// and bypass the constness. This is safe, as they update the entire
// structure, including the hash.
const int nVersion;
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
const unsigned int nLockTime;
IMPLEMENT_SERIALIZE
(
READWRITE(this->nVersion);
/** Construct a CTransaction that qualifies as IsNull() */
CTransaction();
/** Convert a CMutableTransaction into a CTransaction. */
CTransaction(const CMutableTransaction &tx);
CTransaction& operator=(const CTransaction& tx);
IMPLEMENT_SERIALIZE(
READWRITE(*const_cast<int*>(&this->nVersion));
nVersion = this->nVersion;
READWRITE(vin);
READWRITE(vout);
READWRITE(nLockTime);
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
READWRITE(*const_cast<unsigned int*>(&nLockTime));
if (fRead)
UpdateHash();
)
void SetNull()
{
nVersion = CTransaction::CURRENT_VERSION;
vin.clear();
vout.clear();
nLockTime = 0;
bool IsNull() const {
return vin.empty() && vout.empty();
}
bool IsNull() const
{
return (vin.empty() && vout.empty());
const uint256& GetHash() const {
return hash;
}
uint256 GetHash() const;
// Return sum of txouts.
int64_t GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
@ -261,22 +271,43 @@ public: @@ -261,22 +271,43 @@ public:
friend bool operator==(const CTransaction& a, const CTransaction& b)
{
return (a.nVersion == b.nVersion &&
a.vin == b.vin &&
a.vout == b.vout &&
a.nLockTime == b.nLockTime);
return a.hash == b.hash;
}
friend bool operator!=(const CTransaction& a, const CTransaction& b)
{
return !(a == b);
return a.hash != b.hash;
}
std::string ToString() const;
void print() const;
};
/** A mutable version of CTransaction. */
struct CMutableTransaction
{
int nVersion;
std::vector<CTxIn> vin;
std::vector<CTxOut> vout;
unsigned int nLockTime;
CMutableTransaction();
CMutableTransaction(const CTransaction& tx);
IMPLEMENT_SERIALIZE(
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(vin);
READWRITE(vout);
READWRITE(nLockTime);
)
/** Compute the hash of this CMutableTransaction. This is computed on the
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
*/
uint256 GetHash() const;
};
/** wrapper for CTxOut that provides a more compact serialization */
class CTxOutCompressor
{
@ -465,12 +496,6 @@ public: @@ -465,12 +496,6 @@ public:
uint256 BuildMerkleTree() const;
const uint256 &GetTxHash(unsigned int nIndex) const {
assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
assert(nIndex < vtx.size());
return vMerkleTree[nIndex];
}
std::vector<uint256> GetMerkleBranch(int nIndex) const;
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
void print() const;

59
src/main.cpp

@ -130,8 +130,8 @@ namespace { @@ -130,8 +130,8 @@ namespace {
namespace {
struct CMainSignals {
// Notifies listeners of updated transaction data (passing hash, transaction, and optionally the block it is found in.
boost::signals2::signal<void (const uint256 &, const CTransaction &, const CBlock *)> SyncTransaction;
// Notifies listeners of updated transaction data (transaction, and optionally the block it is found in.
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
// Notifies listeners of an erased transaction (currently disabled, requires transaction replacement).
boost::signals2::signal<void (const uint256 &)> EraseTransaction;
// Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible).
@ -146,7 +146,7 @@ struct CMainSignals { @@ -146,7 +146,7 @@ struct CMainSignals {
}
void RegisterWallet(CWalletInterface* pwalletIn) {
g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3));
g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2));
g_signals.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
g_signals.UpdatedTransaction.connect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.SetBestChain.connect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
@ -160,7 +160,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn) { @@ -160,7 +160,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn) {
g_signals.SetBestChain.disconnect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
g_signals.UpdatedTransaction.disconnect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.EraseTransaction.disconnect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
g_signals.SyncTransaction.disconnect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3));
g_signals.SyncTransaction.disconnect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2));
}
void UnregisterAllWallets() {
@ -172,8 +172,8 @@ void UnregisterAllWallets() { @@ -172,8 +172,8 @@ void UnregisterAllWallets() {
g_signals.SyncTransaction.disconnect_all_slots();
}
void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) {
g_signals.SyncTransaction(hash, tx, pblock);
void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) {
g_signals.SyncTransaction(tx, pblock);
}
//////////////////////////////////////////////////////////////////////////////
@ -952,7 +952,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa @@ -952,7 +952,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
pool.addUnchecked(hash, entry);
}
g_signals.SyncTransaction(hash, tx, NULL);
g_signals.SyncTransaction(tx, NULL);
return true;
}
@ -1479,7 +1479,7 @@ void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev) @@ -1479,7 +1479,7 @@ void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev)
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash)
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight)
{
bool ret;
// mark inputs spent
@ -1494,7 +1494,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach @@ -1494,7 +1494,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
}
// add outputs
ret = inputs.SetCoins(txhash, CCoins(tx, nHeight));
ret = inputs.SetCoins(tx.GetHash(), CCoins(tx, nHeight));
assert(ret);
}
@ -1767,8 +1767,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C @@ -1767,8 +1767,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
if (fEnforceBIP30) {
for (unsigned int i = 0; i < block.vtx.size(); i++) {
uint256 hash = block.GetTxHash(i);
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
const uint256& hash = tx.GetHash();
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
REJECT_INVALID, "bad-txns-BIP30");
@ -1829,11 +1829,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C @@ -1829,11 +1829,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
}
CTxUndo txundo;
UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i));
UpdateCoins(tx, state, view, txundo, pindex->nHeight);
if (!tx.IsCoinBase())
blockundo.vtxundo.push_back(txundo);
vPos.push_back(std::make_pair(block.GetTxHash(i), pos));
vPos.push_back(std::make_pair(tx.GetHash(), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
int64_t nTime = GetTimeMicros() - nStart;
@ -1892,13 +1892,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C @@ -1892,13 +1892,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
assert(ret);
// Watch for transactions paying to me
for (unsigned int i = 0; i < block.vtx.size(); i++)
g_signals.SyncTransaction(block.GetTxHash(i), block.vtx[i], &block);
BOOST_FOREACH(const CTransaction& tx, block.vtx)
g_signals.SyncTransaction(tx, &block);
// Watch for changes to the previous coinbase transaction.
static uint256 hashPrevBestCoinBase;
g_signals.UpdatedTransaction(hashPrevBestCoinBase);
hashPrevBestCoinBase = block.GetTxHash(0);
hashPrevBestCoinBase = block.vtx[0].GetHash();
return true;
}
@ -1996,7 +1996,7 @@ bool static DisconnectTip(CValidationState &state) { @@ -1996,7 +1996,7 @@ bool static DisconnectTip(CValidationState &state) {
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
SyncWithWallets(tx.GetHash(), tx, NULL);
SyncWithWallets(tx, NULL);
}
return true;
}
@ -2036,11 +2036,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) { @@ -2036,11 +2036,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
// Tell wallet about transactions that went from mempool
// to conflicted:
BOOST_FOREACH(const CTransaction &tx, txConflicted) {
SyncWithWallets(tx.GetHash(), tx, NULL);
SyncWithWallets(tx, NULL);
}
// ... and about transactions that got confirmed:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
SyncWithWallets(tx.GetHash(), tx, &block);
SyncWithWallets(tx, &block);
}
return true;
}
@ -2381,16 +2381,11 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo @@ -2381,16 +2381,11 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
if (!CheckTransaction(tx, state))
return error("CheckBlock() : CheckTransaction failed");
// Build the merkle tree already. We need it anyway later, and it makes the
// block cache the transaction hashes, which means they don't need to be
// recalculated many times during this block's validation.
block.BuildMerkleTree();
// Check for duplicate txids. This is caught by ConnectInputs(),
// but catching it earlier avoids a potential DoS attack:
set<uint256> uniqueTx;
for (unsigned int i = 0; i < block.vtx.size(); i++) {
uniqueTx.insert(block.GetTxHash(i));
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
uniqueTx.insert(tx.GetHash());
}
if (uniqueTx.size() != block.vtx.size())
return state.DoS(100, error("CheckBlock() : duplicate transaction"),
@ -2406,7 +2401,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo @@ -2406,7 +2401,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
REJECT_INVALID, "bad-blk-sigops", true);
// Check merkle root
if (fCheckMerkleRoot && block.hashMerkleRoot != block.vMerkleTree.back())
if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree())
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"),
REJECT_INVALID, "bad-txnmrklroot", true);
@ -2682,8 +2677,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter) @@ -2682,8 +2677,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
uint256 hash = block.vtx[i].GetHash();
if (filter.IsRelevantAndUpdate(block.vtx[i], hash))
const uint256& hash = block.vtx[i].GetHash();
if (filter.IsRelevantAndUpdate(block.vtx[i]))
{
vMatch.push_back(true);
vMatchedTxn.push_back(make_pair(i, hash));
@ -3832,7 +3827,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -3832,7 +3827,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
{
mempool.check(pcoinsTip);
RelayTransaction(tx, inv.hash);
RelayTransaction(tx);
mapAlreadyAskedFor.erase(inv);
vWorkQueue.push_back(inv.hash);
vEraseQueue.push_back(inv.hash);
@ -3862,7 +3857,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -3862,7 +3857,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2))
{
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx, orphanHash);
RelayTransaction(orphanTx);
mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash));
vWorkQueue.push_back(orphanHash);
vEraseQueue.push_back(orphanHash);
@ -3947,7 +3942,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -3947,7 +3942,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CTransaction tx;
bool fInMemPool = mempool.lookup(hash, tx);
if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx, hash)) ||
if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx)) ||
(!pfrom->pfilter))
vInv.push_back(inv);
if (vInv.size() == MAX_INV_SZ) {

6
src/main.h

@ -113,7 +113,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn); @@ -113,7 +113,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn);
/** Unregister all wallets from core */
void UnregisterAllWallets();
/** Push an updated transaction to all registered wallets */
void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL);
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL);
/** Register with a network node to receive its signals */
void RegisterNodeSignals(CNodeSignals& nodeSignals);
@ -294,7 +294,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach @@ -294,7 +294,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
std::vector<CScriptCheck> *pvChecks = NULL);
// Apply the effects of this transaction on the UTXO set represented by view
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash);
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight);
// Context-independent validity checks
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
@ -1129,7 +1129,7 @@ public: @@ -1129,7 +1129,7 @@ public:
class CWalletInterface {
protected:
virtual void SyncTransaction(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) =0;
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) =0;
virtual void EraseFromWallet(const uint256 &hash) =0;
virtual void SetBestChain(const CBlockLocator &locator) =0;
virtual void UpdatedTransaction(const uint256 &hash) =0;

22
src/miner.cpp

@ -86,14 +86,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -86,14 +86,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
// Create coinbase tx
CTransaction txNew;
CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
// Add our coinbase tx as first transaction
pblock->vtx.push_back(txNew);
// Add dummy coinbase tx as first transaction
pblock->vtx.push_back(CTransaction());
pblocktemplate->vTxFees.push_back(-1); // updated at end
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
@ -254,8 +254,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -254,8 +254,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
continue;
CTxUndo txundo;
uint256 hash = tx.GetHash();
UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
const uint256& hash = tx.GetHash();
UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1);
// Added
pblock->vtx.push_back(tx);
@ -294,7 +294,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -294,7 +294,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
nLastBlockSize = nBlockSize;
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
// Compute final coinbase transaction.
txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0;
pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
// Fill in header
@ -302,7 +305,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -302,7 +305,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(*pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0;
pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
CBlockIndex indexDummy(*pblock);
@ -328,9 +330,11 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& @@ -328,9 +330,11 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
CMutableTransaction txCoinbase(pblock->vtx[0]);
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
pblock->vtx[0] = txCoinbase;
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
}

10
src/net.cpp

@ -1812,17 +1812,17 @@ instance_of_cnetcleanup; @@ -1812,17 +1812,17 @@ instance_of_cnetcleanup;
void RelayTransaction(const CTransaction& tx, const uint256& hash)
void RelayTransaction(const CTransaction& tx)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(10000);
ss << tx;
RelayTransaction(tx, hash, ss);
RelayTransaction(tx, ss);
}
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
{
CInv inv(MSG_TX, hash);
CInv inv(MSG_TX, tx.GetHash());
{
LOCK(cs_mapRelay);
// Expire old relay messages
@ -1844,7 +1844,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt @@ -1844,7 +1844,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
LOCK(pnode->cs_filter);
if (pnode->pfilter)
{
if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
if (pnode->pfilter->IsRelevantAndUpdate(tx))
pnode->PushInventory(inv);
} else
pnode->PushInventory(inv);

4
src/net.h

@ -726,8 +726,8 @@ public: @@ -726,8 +726,8 @@ public:
class CTransaction;
void RelayTransaction(const CTransaction& tx, const uint256& hash);
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss);
void RelayTransaction(const CTransaction& tx);
void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
/** Access to the (IP) address database (peers.dat) */
class CAddrDB

2
src/qt/coincontroldialog.cpp

@ -440,7 +440,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) @@ -440,7 +440,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// nPayAmount
qint64 nPayAmount = 0;
bool fDust = false;
CTransaction txDummy;
CMutableTransaction txDummy;
foreach(const qint64 &amount, CoinControlDialog::payAmounts)
{
nPayAmount += amount;

16
src/rpcrawtransaction.cpp

@ -349,7 +349,7 @@ Value createrawtransaction(const Array& params, bool fHelp) @@ -349,7 +349,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
Array inputs = params[0].get_array();
Object sendTo = params[1].get_obj();
CTransaction rawTx;
CMutableTransaction rawTx;
BOOST_FOREACH(const Value& input, inputs)
{
@ -554,11 +554,11 @@ Value signrawtransaction(const Array& params, bool fHelp) @@ -554,11 +554,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
vector<CTransaction> txVariants;
vector<CMutableTransaction> txVariants;
while (!ssData.empty())
{
try {
CTransaction tx;
CMutableTransaction tx;
ssData >> tx;
txVariants.push_back(tx);
}
@ -572,7 +572,7 @@ Value signrawtransaction(const Array& params, bool fHelp) @@ -572,7 +572,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
// mergedTx will end up with all the signatures; it
// starts as a clone of the rawtx:
CTransaction mergedTx(txVariants[0]);
CMutableTransaction mergedTx(txVariants[0]);
bool fComplete = true;
// Fetch previous transactions (inputs):
@ -713,7 +713,7 @@ Value signrawtransaction(const Array& params, bool fHelp) @@ -713,7 +713,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
// ... and merge in other signatures:
BOOST_FOREACH(const CTransaction& txv, txVariants)
BOOST_FOREACH(const CMutableTransaction& txv, txVariants)
{
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
@ -770,7 +770,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) @@ -770,7 +770,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
catch (std::exception &e) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
}
uint256 hashTx = tx.GetHash();
const uint256 &hashTx = tx.GetHash();
CCoinsViewCache &view = *pcoinsTip;
CCoins existingCoins;
@ -780,7 +780,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) @@ -780,7 +780,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
// push to local node and sync with wallets
CValidationState state;
if (AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees))
SyncWithWallets(hashTx, tx, NULL);
SyncWithWallets(tx, NULL);
else {
if(state.IsInvalid())
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
@ -790,7 +790,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) @@ -790,7 +790,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}
RelayTransaction(tx, hashTx);
RelayTransaction(tx);
return hashTx.GetHex();
}

6
src/script.cpp

@ -1636,7 +1636,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C @@ -1636,7 +1636,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
}
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType)
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
@ -1671,7 +1671,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransa @@ -1671,7 +1671,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransa
return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0);
}
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType)
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
@ -1689,7 +1689,7 @@ static CScript PushAll(const vector<valtype>& values) @@ -1689,7 +1689,7 @@ static CScript PushAll(const vector<valtype>& values)
return result;
}
static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn,
const vector<valtype>& vSolutions,
vector<valtype>& sigs1, vector<valtype>& sigs2)
{

5
src/script.h

@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
class CCoins;
class CKeyStore;
class CTransaction;
class CMutableTransaction;
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
@ -805,8 +806,8 @@ bool IsMine(const CKeyStore& keystore, const CTxDestination &dest); @@ -805,8 +806,8 @@ bool IsMine(const CKeyStore& keystore, const CTxDestination &dest);
void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,

12
src/test/DoS_tests.cpp

@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) @@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
// 50 orphan transactions:
for (int i = 0; i < 50; i++)
{
CTransaction tx;
CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
tx.vin[0].prevout.hash = GetRandHash();
@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) @@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
{
CTransaction txPrev = RandomOrphan();
CTransaction tx;
CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
tx.vin[0].prevout.hash = txPrev.GetHash();
@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) @@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
{
CTransaction txPrev = RandomOrphan();
CTransaction tx;
CMutableTransaction tx;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
@ -242,10 +242,10 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig) @@ -242,10 +242,10 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
// 100 orphan transactions:
static const int NPREV=100;
CTransaction orphans[NPREV];
CMutableTransaction orphans[NPREV];
for (int i = 0; i < NPREV; i++)
{
CTransaction& tx = orphans[i];
CMutableTransaction& tx = orphans[i];
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
tx.vin[0].prevout.hash = GetRandHash();
@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig) @@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
}
// Create a transaction that depends on orphans:
CTransaction tx;
CMutableTransaction tx;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());

12
src/test/accounting_tests.cpp

@ -83,13 +83,21 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) @@ -83,13 +83,21 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
wtx.mapValue["comment"] = "y";
--wtx.nLockTime; // Just to change the hash :)
{
CMutableTransaction tx(wtx);
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
pwalletMain->AddToWallet(wtx);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
wtx.mapValue["comment"] = "x";
--wtx.nLockTime; // Just to change the hash :)
{
CMutableTransaction tx(wtx);
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
pwalletMain->AddToWallet(wtx);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;

26
src/test/bloom_tests.cpp

@ -118,33 +118,33 @@ BOOST_AUTO_TEST_CASE(bloom_match) @@ -118,33 +118,33 @@ BOOST_AUTO_TEST_CASE(bloom_match)
CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(uint256("0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"));
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match tx hash");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match tx hash");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
// byte-reversed tx hash
filter.insert(ParseHex("6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4"));
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized tx hash");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized tx hash");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a01"));
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input signature");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input signature");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339"));
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input pub key");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input pub key");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19"));
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx, spendingTx.GetHash()), "Simple Bloom filter didn't add output");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx), "Simple Bloom filter didn't add output");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("a266436d2965547608b9e15d9032a7b9d64fa431"));
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match COutPoint");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match COutPoint");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
COutPoint prevOutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0);
@ -154,23 +154,23 @@ BOOST_AUTO_TEST_CASE(bloom_match) @@ -154,23 +154,23 @@ BOOST_AUTO_TEST_CASE(bloom_match)
memcpy(&data[32], &prevOutPoint.n, sizeof(unsigned int));
filter.insert(data);
}
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized COutPoint");
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized COutPoint");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(uint256("00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436"));
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random tx hash");
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random tx hash");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("0000006d2965547608b9e15d9032a7b9d64fa431"));
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random address");
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random address");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 1));
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about");
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(COutPoint(uint256("0x000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about");
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about");
}
BOOST_AUTO_TEST_CASE(merkle_block_1)

12
src/test/miner_tests.cpp

@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) @@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
CBlockTemplate *pblocktemplate;
CTransaction tx,tx2;
CMutableTransaction tx,tx2;
CScript script;
uint256 hash;
@ -68,10 +68,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) @@ -68,10 +68,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
pblock->nVersion = 1;
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
pblock->vtx[0].vin[0].scriptSig = CScript();
pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce);
pblock->vtx[0].vin[0].scriptSig.push_back(chainActive.Height());
pblock->vtx[0].vout[0].scriptPubKey = CScript();
CMutableTransaction txCoinbase(pblock->vtx[0]);
txCoinbase.vin[0].scriptSig = CScript();
txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
txCoinbase.vout[0].scriptPubKey = CScript();
pblock->vtx[0] = CTransaction(txCoinbase);
if (txFirst.size() < 2)
txFirst.push_back(new CTransaction(pblock->vtx[0]));
pblock->hashMerkleRoot = pblock->BuildMerkleTree();

8
src/test/multisig_tests.cpp

@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(multisig_verify) @@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
CScript escrow;
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
CTransaction txFrom; // Funding transaction
CMutableTransaction txFrom; // Funding transaction
txFrom.vout.resize(3);
txFrom.vout[0].scriptPubKey = a_and_b;
txFrom.vout[1].scriptPubKey = a_or_b;
txFrom.vout[2].scriptPubKey = escrow;
CTransaction txTo[3]; // Spending transaction
CMutableTransaction txTo[3]; // Spending transaction
for (int i = 0; i < 3; i++)
{
txTo[i].vin.resize(1);
@ -270,13 +270,13 @@ BOOST_AUTO_TEST_CASE(multisig_Sign) @@ -270,13 +270,13 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
CScript escrow;
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
CTransaction txFrom; // Funding transaction
CMutableTransaction txFrom; // Funding transaction
txFrom.vout.resize(3);
txFrom.vout[0].scriptPubKey = a_and_b;
txFrom.vout[1].scriptPubKey = a_or_b;
txFrom.vout[2].scriptPubKey = escrow;
CTransaction txTo[3]; // Spending transaction
CMutableTransaction txTo[3]; // Spending transaction
for (int i = 0; i < 3; i++)
{
txTo[i].vin.resize(1);

4
src/test/pmt_tests.cpp

@ -36,9 +36,9 @@ BOOST_AUTO_TEST_CASE(pmt_test1) @@ -36,9 +36,9 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
// build a block with some dummy transactions
CBlock block;
for (unsigned int j=0; j<nTx; j++) {
CTransaction tx;
CMutableTransaction tx;
tx.nLockTime = rand(); // actual transaction data doesn't matter; just make the nLockTime's unique
block.vtx.push_back(tx);
block.vtx.push_back(CTransaction(tx));
}
// calculate actual merkle root and height

18
src/test/script_P2SH_tests.cpp

@ -30,11 +30,11 @@ static bool @@ -30,11 +30,11 @@ static bool
Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
{
// Create dummy to/from transactions:
CTransaction txFrom;
CMutableTransaction txFrom;
txFrom.vout.resize(1);
txFrom.vout[0].scriptPubKey = scriptPubKey;
CTransaction txTo;
CMutableTransaction txTo;
txTo.vin.resize(1);
txTo.vout.resize(1);
txTo.vin[0].prevout.n = 0;
@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(sign) @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(sign)
evalScripts[i].SetDestination(standardScripts[i].GetID());
}
CTransaction txFrom; // Funding transaction:
CMutableTransaction txFrom; // Funding transaction:
string reason;
txFrom.vout.resize(8);
for (int i = 0; i < 4; i++)
@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(sign) @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(sign)
}
BOOST_CHECK(IsStandardTx(txFrom, reason));
CTransaction txTo[8]; // Spending transactions
CMutableTransaction txTo[8]; // Spending transactions
for (int i = 0; i < 8; i++)
{
txTo[i].vin.resize(1);
@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(set) @@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(set)
keystore.AddCScript(inner[i]);
}
CTransaction txFrom; // Funding transaction:
CMutableTransaction txFrom; // Funding transaction:
string reason;
txFrom.vout.resize(4);
for (int i = 0; i < 4; i++)
@ -183,7 +183,7 @@ BOOST_AUTO_TEST_CASE(set) @@ -183,7 +183,7 @@ BOOST_AUTO_TEST_CASE(set)
}
BOOST_CHECK(IsStandardTx(txFrom, reason));
CTransaction txTo[4]; // Spending transactions
CMutableTransaction txTo[4]; // Spending transactions
for (int i = 0; i < 4; i++)
{
txTo[i].vin.resize(1);
@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) @@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
keys.push_back(key[i].GetPubKey());
}
CTransaction txFrom;
CMutableTransaction txFrom;
txFrom.vout.resize(6);
// First three are standard:
@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) @@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
coins.SetCoins(txFrom.GetHash(), CCoins(txFrom, 0));
CTransaction txTo;
CMutableTransaction txTo;
txTo.vout.resize(1);
txTo.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
@ -326,7 +326,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) @@ -326,7 +326,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[i].scriptSig = t;
}
CTransaction txToNonStd;
CMutableTransaction txToNonStd;
txToNonStd.vout.resize(1);
txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
txToNonStd.vout[0].nValue = 1000;

12
src/test/script_tests.cpp

@ -240,11 +240,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) @@ -240,11 +240,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
CScript scriptPubKey12;
scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG;
CTransaction txFrom12;
CMutableTransaction txFrom12;
txFrom12.vout.resize(1);
txFrom12.vout[0].scriptPubKey = scriptPubKey12;
CTransaction txTo12;
CMutableTransaction txTo12;
txTo12.vin.resize(1);
txTo12.vout.resize(1);
txTo12.vin[0].prevout.n = 0;
@ -274,11 +274,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) @@ -274,11 +274,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
CScript scriptPubKey23;
scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG;
CTransaction txFrom23;
CMutableTransaction txFrom23;
txFrom23.vout.resize(1);
txFrom23.vout[0].scriptPubKey = scriptPubKey23;
CTransaction txTo23;
CMutableTransaction txTo23;
txTo23.vin.resize(1);
txTo23.vout.resize(1);
txTo23.vin[0].prevout.n = 0;
@ -345,11 +345,11 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) @@ -345,11 +345,11 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
keystore.AddKey(key);
}
CTransaction txFrom;
CMutableTransaction txFrom;
txFrom.vout.resize(1);
txFrom.vout[0].scriptPubKey.SetDestination(keys[0].GetPubKey().GetID());
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
CTransaction txTo;
CMutableTransaction txTo;
txTo.vin.resize(1);
txTo.vout.resize(1);
txTo.vin[0].prevout.n = 0;

6
src/test/sighash_tests.cpp

@ -28,7 +28,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un @@ -28,7 +28,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
return 1;
}
CTransaction txTmp(txTo);
CMutableTransaction txTmp(txTo);
// In case concatenating two scripts ends up with two codeseparators,
// or an extra one at the end, this prevents all those possible incompatibilities.
@ -90,7 +90,7 @@ void static RandomScript(CScript &script) { @@ -90,7 +90,7 @@ void static RandomScript(CScript &script) {
script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
}
void static RandomTransaction(CTransaction &tx, bool fSingle) {
void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
tx.nVersion = insecure_rand();
tx.vin.clear();
tx.vout.clear();
@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(sighash_test) @@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
#endif
for (int i=0; i<nRandomTests; i++) {
int nHashType = insecure_rand();
CTransaction txTo;
CMutableTransaction txTo;
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
CScript scriptCode;
RandomScript(scriptCode);

14
src/test/transaction_tests.cpp

@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests) @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
CTransaction tx;
CMutableTransaction tx;
stream >> tx;
CValidationState state;
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
@ -224,10 +224,10 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests) @@ -224,10 +224,10 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
// paid to a TX_PUBKEYHASH.
//
static std::vector<CTransaction>
static std::vector<CMutableTransaction>
SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsView & coinsRet)
{
std::vector<CTransaction> dummyTransactions;
std::vector<CMutableTransaction> dummyTransactions;
dummyTransactions.resize(2);
// Add some keys to the keystore:
@ -261,9 +261,9 @@ BOOST_AUTO_TEST_CASE(test_Get) @@ -261,9 +261,9 @@ BOOST_AUTO_TEST_CASE(test_Get)
CBasicKeyStore keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(coinsDummy);
std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
CTransaction t1;
CMutableTransaction t1;
t1.vin.resize(3);
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
t1.vin[0].prevout.n = 1;
@ -296,9 +296,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) @@ -296,9 +296,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
CBasicKeyStore keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(coinsDummy);
std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
CTransaction t;
CMutableTransaction t;
t.vin.resize(1);
t.vin[0].prevout.hash = dummyTransactions[0].GetHash();
t.vin[0].prevout.n = 1;

10
src/test/wallet_tests.cpp

@ -31,16 +31,18 @@ static vector<COutput> vCoins; @@ -31,16 +31,18 @@ static vector<COutput> vCoins;
static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0)
{
static int nextLockTime = 0;
CTransaction tx;
CMutableTransaction tx;
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
tx.vout.resize(nInput+1);
tx.vout[nInput].nValue = nValue;
if (fIsFromMe) {
// IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
tx.vin.resize(1);
}
CWalletTx* wtx = new CWalletTx(&wallet, tx);
if (fIsFromMe)
{
// IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
wtx->vin.resize(1);
wtx->fDebitCached = true;
wtx->nDebitCached = 1;
}

33
src/wallet.cpp

@ -603,11 +603,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) @@ -603,11 +603,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
// Add a transaction to the wallet, or update it.
// pblock is optional, but should be provided if the transaction is known to be in a block.
// If fUpdate is true, existing transactions will be updated.
bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{
{
AssertLockHeld(cs_wallet);
bool fExisted = mapWallet.count(hash);
bool fExisted = mapWallet.count(tx.GetHash());
if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx) || IsFromMe(tx))
{
@ -621,10 +621,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& @@ -621,10 +621,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction&
return false;
}
void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock)
void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
{
LOCK2(cs_main, cs_wallet);
if (!AddToWalletIfInvolvingMe(hash, tx, pblock, true))
if (!AddToWalletIfInvolvingMe(tx, pblock, true))
return; // Not one of ours
// If a transaction changes 'conflicted' state, that changes the balance
@ -870,7 +870,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) @@ -870,7 +870,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ReadBlockFromDisk(block, pindex);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
ret++;
}
pindex = chainActive.Next(pindex);
@ -909,9 +909,8 @@ void CWalletTx::RelayWalletTransaction() @@ -909,9 +909,8 @@ void CWalletTx::RelayWalletTransaction()
if (!IsCoinBase())
{
if (GetDepthInMainChain() == 0) {
uint256 hash = GetHash();
LogPrintf("Relaying wtx %s\n", hash.ToString());
RelayTransaction((CTransaction)*this, hash);
LogPrintf("Relaying wtx %s\n", GetHash().ToString());
RelayTransaction((CTransaction)*this);
}
}
}
@ -1245,6 +1244,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, @@ -1245,6 +1244,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
}
wtxNew.BindWallet(this);
CMutableTransaction txNew;
{
LOCK2(cs_main, cs_wallet);
@ -1252,8 +1252,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, @@ -1252,8 +1252,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
nFeeRet = payTxFee.GetFeePerK();
while (true)
{
wtxNew.vin.clear();
wtxNew.vout.clear();
txNew.vin.clear();
txNew.vout.clear();
wtxNew.fFromMe = true;
int64_t nTotalValue = nValue + nFeeRet;
@ -1267,7 +1267,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, @@ -1267,7 +1267,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
strFailReason = _("Transaction amount too small");
return false;
}
wtxNew.vout.push_back(txout);
txNew.vout.push_back(txout);
}
// Choose coins to use
@ -1331,8 +1331,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, @@ -1331,8 +1331,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
else
{
// Insert change txn at random position:
vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
wtxNew.vout.insert(position, newTxOut);
vector<CTxOut>::iterator position = txNew.vout.begin()+GetRandInt(txNew.vout.size()+1);
txNew.vout.insert(position, newTxOut);
}
}
else
@ -1340,17 +1340,20 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, @@ -1340,17 +1340,20 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
// Fill vin
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
// Sign
int nIn = 0;
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
if (!SignSignature(*this, *coin.first, txNew, nIn++))
{
strFailReason = _("Signing transaction failed");
return false;
}
// Embed the constructed transaction data in wtxNew.
*static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
// Limit size
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= MAX_STANDARD_TX_SIZE)

4
src/wallet.h

@ -244,8 +244,8 @@ public: @@ -244,8 +244,8 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false);
void SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void EraseFromWallet(const uint256 &hash);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();

Loading…
Cancel
Save