Code simplifications after CTransaction::GetHash() caching
This commit is contained in:
parent
4949004d68
commit
d38da59bf6
@ -99,7 +99,7 @@ bool CBloomFilter::IsWithinSizeConstraints() const
|
|||||||
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
|
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;
|
bool fFound = false;
|
||||||
// Match if the filter contains the hash of tx
|
// Match if the filter contains the hash of tx
|
||||||
@ -108,6 +108,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha
|
|||||||
return true;
|
return true;
|
||||||
if (isEmpty)
|
if (isEmpty)
|
||||||
return false;
|
return false;
|
||||||
|
const uint256& hash = tx.GetHash();
|
||||||
if (contains(hash))
|
if (contains(hash))
|
||||||
fFound = true;
|
fFound = true;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ public:
|
|||||||
bool IsWithinSizeConstraints() const;
|
bool IsWithinSizeConstraints() const;
|
||||||
|
|
||||||
// Also adds any outputs which match the filter to the filter (to match their spending txes)
|
// 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
|
// Checks for empty and full filters to avoid wasting cpu
|
||||||
void UpdateEmptyFull();
|
void UpdateEmptyFull();
|
||||||
|
@ -496,12 +496,6 @@ public:
|
|||||||
|
|
||||||
uint256 BuildMerkleTree() const;
|
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;
|
std::vector<uint256> GetMerkleBranch(int nIndex) const;
|
||||||
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
|
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
|
||||||
void print() const;
|
void print() const;
|
||||||
|
59
src/main.cpp
59
src/main.cpp
@ -130,8 +130,8 @@ namespace {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct CMainSignals {
|
struct CMainSignals {
|
||||||
// Notifies listeners of updated transaction data (passing hash, transaction, and optionally the block it is found in.
|
// Notifies listeners of updated transaction data (transaction, and optionally the block it is found in.
|
||||||
boost::signals2::signal<void (const uint256 &, const CTransaction &, const CBlock *)> SyncTransaction;
|
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
|
||||||
// Notifies listeners of an erased transaction (currently disabled, requires transaction replacement).
|
// Notifies listeners of an erased transaction (currently disabled, requires transaction replacement).
|
||||||
boost::signals2::signal<void (const uint256 &)> EraseTransaction;
|
boost::signals2::signal<void (const uint256 &)> EraseTransaction;
|
||||||
// Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible).
|
// Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible).
|
||||||
@ -146,7 +146,7 @@ struct CMainSignals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RegisterWallet(CWalletInterface* pwalletIn) {
|
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.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
|
||||||
g_signals.UpdatedTransaction.connect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
|
g_signals.UpdatedTransaction.connect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
|
||||||
g_signals.SetBestChain.connect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
|
g_signals.SetBestChain.connect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
|
||||||
@ -160,7 +160,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn) {
|
|||||||
g_signals.SetBestChain.disconnect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
|
g_signals.SetBestChain.disconnect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
|
||||||
g_signals.UpdatedTransaction.disconnect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
|
g_signals.UpdatedTransaction.disconnect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
|
||||||
g_signals.EraseTransaction.disconnect(boost::bind(&CWalletInterface::EraseFromWallet, 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() {
|
void UnregisterAllWallets() {
|
||||||
@ -172,8 +172,8 @@ void UnregisterAllWallets() {
|
|||||||
g_signals.SyncTransaction.disconnect_all_slots();
|
g_signals.SyncTransaction.disconnect_all_slots();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) {
|
void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) {
|
||||||
g_signals.SyncTransaction(hash, tx, pblock);
|
g_signals.SyncTransaction(tx, pblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -952,7 +952,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
pool.addUnchecked(hash, entry);
|
pool.addUnchecked(hash, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_signals.SyncTransaction(hash, tx, NULL);
|
g_signals.SyncTransaction(tx, NULL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -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;
|
bool ret;
|
||||||
// mark inputs spent
|
// mark inputs spent
|
||||||
@ -1494,7 +1494,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add outputs
|
// add outputs
|
||||||
ret = inputs.SetCoins(txhash, CCoins(tx, nHeight));
|
ret = inputs.SetCoins(tx.GetHash(), CCoins(tx, nHeight));
|
||||||
assert(ret);
|
assert(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1767,8 +1767,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
|||||||
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
|
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
|
||||||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
|
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
|
||||||
if (fEnforceBIP30) {
|
if (fEnforceBIP30) {
|
||||||
for (unsigned int i = 0; i < block.vtx.size(); i++) {
|
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
|
||||||
uint256 hash = block.GetTxHash(i);
|
const uint256& hash = tx.GetHash();
|
||||||
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
|
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
|
||||||
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
|
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
|
||||||
REJECT_INVALID, "bad-txns-BIP30");
|
REJECT_INVALID, "bad-txns-BIP30");
|
||||||
@ -1829,11 +1829,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
|||||||
}
|
}
|
||||||
|
|
||||||
CTxUndo txundo;
|
CTxUndo txundo;
|
||||||
UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i));
|
UpdateCoins(tx, state, view, txundo, pindex->nHeight);
|
||||||
if (!tx.IsCoinBase())
|
if (!tx.IsCoinBase())
|
||||||
blockundo.vtxundo.push_back(txundo);
|
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);
|
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
|
||||||
}
|
}
|
||||||
int64_t nTime = GetTimeMicros() - nStart;
|
int64_t nTime = GetTimeMicros() - nStart;
|
||||||
@ -1892,13 +1892,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
|||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
// Watch for transactions paying to me
|
// Watch for transactions paying to me
|
||||||
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
BOOST_FOREACH(const CTransaction& tx, block.vtx)
|
||||||
g_signals.SyncTransaction(block.GetTxHash(i), block.vtx[i], &block);
|
g_signals.SyncTransaction(tx, &block);
|
||||||
|
|
||||||
// Watch for changes to the previous coinbase transaction.
|
// Watch for changes to the previous coinbase transaction.
|
||||||
static uint256 hashPrevBestCoinBase;
|
static uint256 hashPrevBestCoinBase;
|
||||||
g_signals.UpdatedTransaction(hashPrevBestCoinBase);
|
g_signals.UpdatedTransaction(hashPrevBestCoinBase);
|
||||||
hashPrevBestCoinBase = block.GetTxHash(0);
|
hashPrevBestCoinBase = block.vtx[0].GetHash();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1996,7 +1996,7 @@ bool static DisconnectTip(CValidationState &state) {
|
|||||||
// Let wallets know transactions went from 1-confirmed to
|
// Let wallets know transactions went from 1-confirmed to
|
||||||
// 0-confirmed or conflicted:
|
// 0-confirmed or conflicted:
|
||||||
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
|
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
|
||||||
SyncWithWallets(tx.GetHash(), tx, NULL);
|
SyncWithWallets(tx, NULL);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2036,11 +2036,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
|
|||||||
// Tell wallet about transactions that went from mempool
|
// Tell wallet about transactions that went from mempool
|
||||||
// to conflicted:
|
// to conflicted:
|
||||||
BOOST_FOREACH(const CTransaction &tx, txConflicted) {
|
BOOST_FOREACH(const CTransaction &tx, txConflicted) {
|
||||||
SyncWithWallets(tx.GetHash(), tx, NULL);
|
SyncWithWallets(tx, NULL);
|
||||||
}
|
}
|
||||||
// ... and about transactions that got confirmed:
|
// ... and about transactions that got confirmed:
|
||||||
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
|
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
|
||||||
SyncWithWallets(tx.GetHash(), tx, &block);
|
SyncWithWallets(tx, &block);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2381,16 +2381,11 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
|
|||||||
if (!CheckTransaction(tx, state))
|
if (!CheckTransaction(tx, state))
|
||||||
return error("CheckBlock() : CheckTransaction failed");
|
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(),
|
// Check for duplicate txids. This is caught by ConnectInputs(),
|
||||||
// but catching it earlier avoids a potential DoS attack:
|
// but catching it earlier avoids a potential DoS attack:
|
||||||
set<uint256> uniqueTx;
|
set<uint256> uniqueTx;
|
||||||
for (unsigned int i = 0; i < block.vtx.size(); i++) {
|
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
|
||||||
uniqueTx.insert(block.GetTxHash(i));
|
uniqueTx.insert(tx.GetHash());
|
||||||
}
|
}
|
||||||
if (uniqueTx.size() != block.vtx.size())
|
if (uniqueTx.size() != block.vtx.size())
|
||||||
return state.DoS(100, error("CheckBlock() : duplicate transaction"),
|
return state.DoS(100, error("CheckBlock() : duplicate transaction"),
|
||||||
@ -2406,7 +2401,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
|
|||||||
REJECT_INVALID, "bad-blk-sigops", true);
|
REJECT_INVALID, "bad-blk-sigops", true);
|
||||||
|
|
||||||
// Check merkle root
|
// Check merkle root
|
||||||
if (fCheckMerkleRoot && block.hashMerkleRoot != block.vMerkleTree.back())
|
if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree())
|
||||||
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"),
|
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"),
|
||||||
REJECT_INVALID, "bad-txnmrklroot", true);
|
REJECT_INVALID, "bad-txnmrklroot", true);
|
||||||
|
|
||||||
@ -2682,8 +2677,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
||||||
{
|
{
|
||||||
uint256 hash = block.vtx[i].GetHash();
|
const uint256& hash = block.vtx[i].GetHash();
|
||||||
if (filter.IsRelevantAndUpdate(block.vtx[i], hash))
|
if (filter.IsRelevantAndUpdate(block.vtx[i]))
|
||||||
{
|
{
|
||||||
vMatch.push_back(true);
|
vMatch.push_back(true);
|
||||||
vMatchedTxn.push_back(make_pair(i, hash));
|
vMatchedTxn.push_back(make_pair(i, hash));
|
||||||
@ -3832,7 +3827,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
|
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
|
||||||
{
|
{
|
||||||
mempool.check(pcoinsTip);
|
mempool.check(pcoinsTip);
|
||||||
RelayTransaction(tx, inv.hash);
|
RelayTransaction(tx);
|
||||||
mapAlreadyAskedFor.erase(inv);
|
mapAlreadyAskedFor.erase(inv);
|
||||||
vWorkQueue.push_back(inv.hash);
|
vWorkQueue.push_back(inv.hash);
|
||||||
vEraseQueue.push_back(inv.hash);
|
vEraseQueue.push_back(inv.hash);
|
||||||
@ -3862,7 +3857,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2))
|
if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2))
|
||||||
{
|
{
|
||||||
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
|
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
|
||||||
RelayTransaction(orphanTx, orphanHash);
|
RelayTransaction(orphanTx);
|
||||||
mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash));
|
mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash));
|
||||||
vWorkQueue.push_back(orphanHash);
|
vWorkQueue.push_back(orphanHash);
|
||||||
vEraseQueue.push_back(orphanHash);
|
vEraseQueue.push_back(orphanHash);
|
||||||
@ -3947,7 +3942,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
CTransaction tx;
|
CTransaction tx;
|
||||||
bool fInMemPool = mempool.lookup(hash, tx);
|
bool fInMemPool = mempool.lookup(hash, tx);
|
||||||
if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
|
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))
|
(!pfrom->pfilter))
|
||||||
vInv.push_back(inv);
|
vInv.push_back(inv);
|
||||||
if (vInv.size() == MAX_INV_SZ) {
|
if (vInv.size() == MAX_INV_SZ) {
|
||||||
|
@ -113,7 +113,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn);
|
|||||||
/** Unregister all wallets from core */
|
/** Unregister all wallets from core */
|
||||||
void UnregisterAllWallets();
|
void UnregisterAllWallets();
|
||||||
/** Push an updated transaction to all registered wallets */
|
/** 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 */
|
/** Register with a network node to receive its signals */
|
||||||
void RegisterNodeSignals(CNodeSignals& nodeSignals);
|
void RegisterNodeSignals(CNodeSignals& nodeSignals);
|
||||||
@ -294,7 +294,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
|
|||||||
std::vector<CScriptCheck> *pvChecks = NULL);
|
std::vector<CScriptCheck> *pvChecks = NULL);
|
||||||
|
|
||||||
// Apply the effects of this transaction on the UTXO set represented by view
|
// 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
|
// Context-independent validity checks
|
||||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
||||||
@ -1129,7 +1129,7 @@ public:
|
|||||||
|
|
||||||
class CWalletInterface {
|
class CWalletInterface {
|
||||||
protected:
|
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 EraseFromWallet(const uint256 &hash) =0;
|
||||||
virtual void SetBestChain(const CBlockLocator &locator) =0;
|
virtual void SetBestChain(const CBlockLocator &locator) =0;
|
||||||
virtual void UpdatedTransaction(const uint256 &hash) =0;
|
virtual void UpdatedTransaction(const uint256 &hash) =0;
|
||||||
|
@ -254,8 +254,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
CTxUndo txundo;
|
CTxUndo txundo;
|
||||||
uint256 hash = tx.GetHash();
|
const uint256& hash = tx.GetHash();
|
||||||
UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
|
UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1);
|
||||||
|
|
||||||
// Added
|
// Added
|
||||||
pblock->vtx.push_back(tx);
|
pblock->vtx.push_back(tx);
|
||||||
|
10
src/net.cpp
10
src/net.cpp
@ -1808,17 +1808,17 @@ instance_of_cnetcleanup;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void RelayTransaction(const CTransaction& tx, const uint256& hash)
|
void RelayTransaction(const CTransaction& tx)
|
||||||
{
|
{
|
||||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ss.reserve(10000);
|
ss.reserve(10000);
|
||||||
ss << tx;
|
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);
|
LOCK(cs_mapRelay);
|
||||||
// Expire old relay messages
|
// Expire old relay messages
|
||||||
@ -1840,7 +1840,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
|
|||||||
LOCK(pnode->cs_filter);
|
LOCK(pnode->cs_filter);
|
||||||
if (pnode->pfilter)
|
if (pnode->pfilter)
|
||||||
{
|
{
|
||||||
if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
|
if (pnode->pfilter->IsRelevantAndUpdate(tx))
|
||||||
pnode->PushInventory(inv);
|
pnode->PushInventory(inv);
|
||||||
} else
|
} else
|
||||||
pnode->PushInventory(inv);
|
pnode->PushInventory(inv);
|
||||||
|
@ -726,8 +726,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
class CTransaction;
|
class CTransaction;
|
||||||
void RelayTransaction(const CTransaction& tx, const uint256& hash);
|
void RelayTransaction(const CTransaction& tx);
|
||||||
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss);
|
void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
|
||||||
|
|
||||||
/** Access to the (IP) address database (peers.dat) */
|
/** Access to the (IP) address database (peers.dat) */
|
||||||
class CAddrDB
|
class CAddrDB
|
||||||
|
@ -770,7 +770,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
|
|||||||
catch (std::exception &e) {
|
catch (std::exception &e) {
|
||||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
||||||
}
|
}
|
||||||
uint256 hashTx = tx.GetHash();
|
const uint256 &hashTx = tx.GetHash();
|
||||||
|
|
||||||
CCoinsViewCache &view = *pcoinsTip;
|
CCoinsViewCache &view = *pcoinsTip;
|
||||||
CCoins existingCoins;
|
CCoins existingCoins;
|
||||||
@ -780,7 +780,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
|
|||||||
// push to local node and sync with wallets
|
// push to local node and sync with wallets
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
if (AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees))
|
if (AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees))
|
||||||
SyncWithWallets(hashTx, tx, NULL);
|
SyncWithWallets(tx, NULL);
|
||||||
else {
|
else {
|
||||||
if(state.IsInvalid())
|
if(state.IsInvalid())
|
||||||
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
|
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
|
||||||
@ -790,7 +790,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
|
|||||||
} else if (fHaveChain) {
|
} else if (fHaveChain) {
|
||||||
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
|
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
|
||||||
}
|
}
|
||||||
RelayTransaction(tx, hashTx);
|
RelayTransaction(tx);
|
||||||
|
|
||||||
return hashTx.GetHex();
|
return hashTx.GetHex();
|
||||||
}
|
}
|
||||||
|
@ -118,33 +118,33 @@ BOOST_AUTO_TEST_CASE(bloom_match)
|
|||||||
|
|
||||||
CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(uint256("0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"));
|
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);
|
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
// byte-reversed tx hash
|
// byte-reversed tx hash
|
||||||
filter.insert(ParseHex("6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4"));
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(ParseHex("30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a01"));
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(ParseHex("046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339"));
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19"));
|
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(tx), "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(spendingTx), "Simple Bloom filter didn't add output");
|
||||||
|
|
||||||
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(ParseHex("a266436d2965547608b9e15d9032a7b9d64fa431"));
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
|
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);
|
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
COutPoint prevOutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0);
|
COutPoint prevOutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0);
|
||||||
@ -154,23 +154,23 @@ BOOST_AUTO_TEST_CASE(bloom_match)
|
|||||||
memcpy(&data[32], &prevOutPoint.n, sizeof(unsigned int));
|
memcpy(&data[32], &prevOutPoint.n, sizeof(unsigned int));
|
||||||
filter.insert(data);
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(uint256("00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436"));
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(ParseHex("0000006d2965547608b9e15d9032a7b9d64fa431"));
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 1));
|
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 = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||||
filter.insert(COutPoint(uint256("0x000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
|
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)
|
BOOST_AUTO_TEST_CASE(merkle_block_1)
|
||||||
|
@ -603,11 +603,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
|
|||||||
// Add a transaction to the wallet, or update it.
|
// 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.
|
// 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.
|
// 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);
|
AssertLockHeld(cs_wallet);
|
||||||
bool fExisted = mapWallet.count(hash);
|
bool fExisted = mapWallet.count(tx.GetHash());
|
||||||
if (fExisted && !fUpdate) return false;
|
if (fExisted && !fUpdate) return false;
|
||||||
if (fExisted || IsMine(tx) || IsFromMe(tx))
|
if (fExisted || IsMine(tx) || IsFromMe(tx))
|
||||||
{
|
{
|
||||||
@ -621,10 +621,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction&
|
|||||||
return false;
|
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);
|
LOCK2(cs_main, cs_wallet);
|
||||||
if (!AddToWalletIfInvolvingMe(hash, tx, pblock, true))
|
if (!AddToWalletIfInvolvingMe(tx, pblock, true))
|
||||||
return; // Not one of ours
|
return; // Not one of ours
|
||||||
|
|
||||||
// If a transaction changes 'conflicted' state, that changes the balance
|
// If a transaction changes 'conflicted' state, that changes the balance
|
||||||
@ -870,7 +870,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
|||||||
ReadBlockFromDisk(block, pindex);
|
ReadBlockFromDisk(block, pindex);
|
||||||
BOOST_FOREACH(CTransaction& tx, block.vtx)
|
BOOST_FOREACH(CTransaction& tx, block.vtx)
|
||||||
{
|
{
|
||||||
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
|
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
pindex = chainActive.Next(pindex);
|
pindex = chainActive.Next(pindex);
|
||||||
@ -909,9 +909,8 @@ void CWalletTx::RelayWalletTransaction()
|
|||||||
if (!IsCoinBase())
|
if (!IsCoinBase())
|
||||||
{
|
{
|
||||||
if (GetDepthInMainChain() == 0) {
|
if (GetDepthInMainChain() == 0) {
|
||||||
uint256 hash = GetHash();
|
LogPrintf("Relaying wtx %s\n", GetHash().ToString());
|
||||||
LogPrintf("Relaying wtx %s\n", hash.ToString());
|
RelayTransaction((CTransaction)*this);
|
||||||
RelayTransaction((CTransaction)*this, hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,8 +244,8 @@ public:
|
|||||||
|
|
||||||
void MarkDirty();
|
void MarkDirty();
|
||||||
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false);
|
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false);
|
||||||
void SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock);
|
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
|
||||||
bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate);
|
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
|
||||||
void EraseFromWallet(const uint256 &hash);
|
void EraseFromWallet(const uint256 &hash);
|
||||||
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
|
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
|
||||||
void ReacceptWalletTransactions();
|
void ReacceptWalletTransactions();
|
||||||
|
Loading…
Reference in New Issue
Block a user