Comparing sensitive data, confidential files or internal emails?

Most legal and privacy policies prohibit uploading sensitive data online. Diffchecker Desktop ensures your confidential information never leaves your computer. Work offline and compare documents securely.

Untitled diff

Created Diff never expires
337 removals
807 lines
330 additions
804 lines
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// file COPYING or http://www.opensource.org/licenses/mit-license.php.


#include "alert.h"
#include "alert.h"
#include "checkpoints.h"
#include "checkpoints.h"
#include "db.h"
#include "db.h"
#include "txdb.h"
#include "net.h"
#include "net.h"
#include "init.h"
#include "init.h"
#include "ui_interface.h"
#include "ui_interface.h"
#include "kernel.h"
#include "kernel.h"
#include "scrypt_mine.h"
#include "scrypt_mine.h"
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>


using namespace std;
using namespace std;
using namespace boost;
using namespace boost;


//
//
// Global state
// Global state
//
//




CCriticalSection cs_setpwalletRegistered;
CCriticalSection cs_setpwalletRegistered;
set<CWallet*> setpwalletRegistered;
set<CWallet*> setpwalletRegistered;


CCriticalSection cs_main;
CCriticalSection cs_main;


CTxMemPool mempool;
CTxMemPool mempool;
unsigned int nTransactionsUpdated = 0;
unsigned int nTransactionsUpdated = 0;


map<uint256, CBlockIndex*> mapBlockIndex;
map<uint256, CBlockIndex*> mapBlockIndex;
set<pair<COutPoint, unsigned int> > setStakeSeen;
set<pair<COutPoint, unsigned int> > setStakeSeen;
uint256 hashGenesisBlock = hashGenesisBlockOfficial;
uint256 hashGenesisBlock = hashGenesisBlockOfficial;
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 20);
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 20);
static CBigNum bnProofOfStakeLimit(~uint256(0) >> 24);
static CBigNum bnProofOfStakeLimit(~uint256(0) >> 20);
static CBigNum bnProofOfStakeHardLimit(~uint256(0) >> 30);



static CBigNum bnProofOfWorkLimitTestNet(~uint256(0) >> 16);
static CBigNum bnProofOfWorkLimitTestNet(~uint256(0) >> 20);
static CBigNum bnProofOfStakeLimitTestNet(~uint256(0) >> 20);
static CBigNum bnProofOfStakeLimitTestNet(~uint256(0) >> 20);


unsigned int nStakeMinAge = 60 * 60 * 24 * 10; // minimum age for coin age - 10 days
unsigned int nStakeMinAge = 60 * 60 * 8; // time at which weight begins to build
unsigned int nStakeMaxAge = 60 * 60 * 24 * 30; // stake age of full weight - 30 days
unsigned int nStakeMinAgeV2 = 60 * 60 * 24 * 88 / 10; // functionally the minimum age is 8.8 days
unsigned int nStakeTargetSpacing = 1 * 30; // 1-minute block spacing
unsigned int nStakeMaxAge = 60 * 60 * 24 * 30; // stake age of full weight: -1
int64_t nChainStartTime = 1371910049;
unsigned int nStakeTargetSpacing = 90; // 90 sec block spacing
int nCoinbaseMaturity = 5;

int64 nChainStartTime = 1399495660;
int nCoinbaseMaturity = 10;
CBlockIndex* pindexGenesisBlock = NULL;
CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
int nBestHeight = -1;
uint256 nBestChainTrust = 0;
CBigNum bnBestChainTrust = 0;
uint256 nBestInvalidTrust = 0;
CBigNum bnBestInvalidTrust = 0;
uint256 hashBestChain = 0;
uint256 hashBestChain = 0;
CBlockIndex* pindexBest = NULL;
CBlockIndex* pindexBest = NULL;
int64_t nTimeBestReceived = 0;
int64 nTimeBestReceived = 0;
bool fHaveGUI = false;
bool fHaveGUI = false;
bool fImporting = false; //Tranz need to fix this 66b02c93
bool fReindex = false; // Tranz need to fix this 7fea4846


CMedianFilter<int> cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have
CMedianFilter<int> cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have


map<uint256, CBlock*> mapOrphanBlocks;
map<uint256, CBlock*> mapOrphanBlocks;
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
set<pair<COutPoint, unsigned int> > setStakeSeenOrphan;
set<pair<COutPoint, unsigned int> > setStakeSeenOrphan;

map<uint256, uint256> mapProofOfStake;


map<uint256, CTransaction> mapOrphanTransactions;
map<uint256, CDataStream*> mapOrphanTransactions;
map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
map<uint256, map<uint256, CDataStream*> > mapOrphanTransactionsByPrev;
map<unsigned int, unsigned int> mapHashedBlocks;
map<std::string, std::pair<int, int> > mapGetBlocksRequests;
std::map <std::string, int> mapPeerRejectedBlocks;
bool fStrictProtocol = false;
bool fStrictIncoming = false;


// Constant stuff for coinbase transactions we create:
// Constant stuff for coinbase transactions we create:
CScript COINBASE_FLAGS;
CScript COINBASE_FLAGS;


const string strMessageMagic = "HoboNickels Signed Message:\n";
const string strMessageMagic = "HyperStake Signed Message:\n";


double dHashesPerSec;
double dHashesPerSec;
int64_t nHPSTimerStart;
int64 nHPSTimerStart;


// Settings
// Settings
int64_t nTransactionFee = MIN_TX_FEE;
int64 nTransactionFee = MIN_TX_FEE;
int64_t nMinimumInputValue = MIN_TX_FEE;
int64_t nSplitThreshold = GetProofOfWorkReward();
int64_t nCombineThreshold = GetProofOfWorkReward() * 2;
extern enum Checkpoints::CPMode CheckpointsMode;




//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
// dispatching functions
// dispatching functions
//
//


// These functions dispatch to one or all registered wallets
// These functions dispatch to one or all registered wallets




void RegisterWallet(CWallet* pwalletIn)
void RegisterWallet(CWallet* pwalletIn)
{
{
{
{
LOCK(cs_setpwalletRegistered);
LOCK(cs_setpwalletRegistered);
setpwalletRegistered.insert(pwalletIn);
setpwalletRegistered.insert(pwalletIn);
}
}
}
}


void UnregisterWallet(CWallet* pwalletIn)
void UnregisterWallet(CWallet* pwalletIn)
{
{
{
{
LOCK(cs_setpwalletRegistered);
LOCK(cs_setpwalletRegistered);
setpwalletRegistered.erase(pwalletIn);
setpwalletRegistered.erase(pwalletIn);
}
}
}
}


void UnregisterAllWallets()
{
{
LOCK(cs_setpwalletRegistered);
setpwalletRegistered.clear();
Text moved to lines 798-800
}
}

// check whether the passed transaction is from us
// check whether the passed transaction is from us
bool static IsFromMe(CTransaction& tx)
bool static IsFromMe(CTransaction& tx)
{
{
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
LOCK(cs_setpwalletRegistered);
if (pwallet->IsFromMe(tx))
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
return true;
if (pwallet->IsFromMe(tx))
return false;
return true;
}
return false;
}
}


// get the wallet transaction with the given hash (if it exists)
// get the wallet transaction with the given hash (if it exists)
bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
{
{
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
LOCK(cs_setpwalletRegistered);
if (pwallet->GetTransaction(hashTx,wtx))
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
return true;
if (pwallet->GetTransaction(hashTx,wtx))
return false;
return true;
}
return false;

}
// erases transaction with the given hash from all wallets
void static EraseFromWallets(uint256 hash)
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->EraseFromWallet(hash);
}
}


// make sure all wallets know about the given transaction, in the given block
// make sure all wallets know about the given transaction, in the given block
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fConnect)
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fConnect)
{
{
if (!fConnect)
if (!fConnect)
{
{
// ppcoin: wallets need to refund inputs when disconnecting coinstake
// ppcoin: wallets need to refund inputs when disconnecting coinstake
if (tx.IsCoinStake())
if (tx.IsCoinStake())
{
{
LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
if (pwallet->IsFromMe(tx))
if (pwallet->IsFromMe(tx))
pwallet->DisableTransaction(tx);
pwallet->DisableTransaction(tx);
}
}
return;
return;
}
}


{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
LOCK(cs_setpwalletRegistered);
pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
}
}

// Add wallet transactions that aren't already in a block to mapTransactions
void ReacceptWalletTransactions()
{
{
LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->ReacceptWalletTransactions();
}
}
}


// notify wallets about a new best chain
// notify wallets about a new best chain
void static SetBestChain(const CBlockLocator& loc)
void static SetBestChain(const CBlockLocator& loc)
{
{
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
LOCK(cs_setpwalletRegistered);
pwallet->SetBestChain(loc);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->SetBestChain(loc);
}
}
}


// notify wallets about an updated transaction
// notify wallets about an updated transaction
void static UpdatedTransaction(const uint256& hashTx)
void static UpdatedTransaction(const uint256& hashTx)
{
{
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
LOCK(cs_setpwalletRegistered);
pwallet->UpdatedTransaction(hashTx);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->UpdatedTransaction(hashTx);
}

}
}


// dump all wallets
// dump all wallets
void static PrintWallets(const CBlock& block)
void static PrintWallets(const CBlock& block)
{
{
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
LOCK(cs_setpwalletRegistered);
pwallet->PrintWallet(block);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->PrintWallet(block);
}

}
}


// notify wallets about an incoming inventory (for request counts)
// notify wallets about an incoming inventory (for request counts)
void static Inventory(const uint256& hash)
void static Inventory(const uint256& hash)
{
{
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
LOCK(cs_setpwalletRegistered);
pwallet->Inventory(hash);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->Inventory(hash);
}

}
}


// ask wallets to resend their transactions
// ask wallets to resend their transactions
void ResendWalletTransactions(bool fForce)
void ResendWalletTransactions()
{
{
LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->ResendWalletTransactions(fForce);
}
Text moved with changes to lines 712-717 (84.2% similarity)
}


//////////////////////////////////////////////////////////////////////////////
//
// Registration of network node signals.
//

namespace {
// Maintain validation-specific state about nodes, protected by cs_main, instead
// by CNode's own locks. This simplifies asynchronous operation, where
// processing of incoming data is done after the ProcessMessage call returns,
// and we're no longer holding the node's locks.
struct CNodeState {
// Accumulated misbehaviour score for this peer.
int nMisbehavior;
// Whether this peer should be disconnected and banned.
bool fShouldBan;
// String name of this peer (debugging/logging purposes).
std::string name;

CNodeState() {
nMisbehavior = 0;
fShouldBan = false;
}
};

map<NodeId, CNodeState> mapNodeState;

// Requires cs_main. (Tranz Locks removed for now due to deadlock)
CNodeState *State(NodeId pnode) {
map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode);
if (it == mapNodeState.end())
return NULL;
return &it->second;
}

int GetHeight()
{
return nBestHeight;
}

void InitializeNode(NodeId nodeid, const CNode *pnode) {
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
state.name = pnode->addrName;
}

void FinalizeNode(NodeId nodeid) {
mapNodeState.erase(nodeid);
}
}

bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
CNodeState *state = State(nodeid);
if (state == NULL)
return false;
stats.nMisbehavior = state->nMisbehavior;
Text moved to lines 693-695
return true;
}

void RegisterNodeSignals(CNodeSignals& nodeSignals)
{
nodeSignals.GetHeight.connect(&GetHeight);
nodeSignals.ProcessMessages.connect(&ProcessMessages);
nodeSignals.SendMessages.connect(&SendMessages);
nodeSignals.InitializeNode.connect(&InitializeNode);
nodeSignals.FinalizeNode.connect(&FinalizeNode);
}

void UnregisterNodeSignals(CNodeSignals& nodeSignals)
{
{
nodeSignals.GetHeight.disconnect(&GetHeight);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
pwallet->ResendWalletTransactions();
nodeSignals.SendMessages.disconnect(&SendMessages);
nodeSignals.InitializeNode.disconnect(&InitializeNode);
nodeSignals.FinalizeNode.disconnect(&FinalizeNode);
}
}






//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
// mapOrphanTransactions
// mapOrphanTransactions
//
//


bool AddOrphanTx(const CTransaction& tx)
bool AddOrphanTx(const CDataStream& vMsg)
{
{
CTransaction tx;
CDataStream(vMsg) >> tx;
uint256 hash = tx.GetHash();
uint256 hash = tx.GetHash();
if (mapOrphanTransactions.count(hash))
if (mapOrphanTransactions.count(hash))
return false;
return false;


CDataStream* pvMsg = new CDataStream(vMsg);

// Ignore big transactions, to avoid a
// Ignore big transactions, to avoid a
// send-big-orphans memory exhaustion attack. If a peer has a legitimate
// send-big-orphans memory exhaustion attack. If a peer has a legitimate
// large transaction with a missing parent then we assume
// large transaction with a missing parent then we assume
// it will rebroadcast it later, after the parent transaction(s)
// it will rebroadcast it later, after the parent transaction(s)
// have been mined or received.
// have been mined or received.
// 10,000 orphans, each of which is at most 5,000 bytes big is
// 10,000 orphans, each of which is at most 5,000 bytes big is
// at most 500 megabytes of orphans:
// at most 500 megabytes of orphans:

if (pvMsg->size() > 5000)
size_t nSize = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);

if (nSize > 5000)
{
{
LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", nSize, hash.ToString().substr(0,10));
printf("ignoring large orphan tx (size: %"PRIszu", hash: %s)\n", pvMsg->size(), hash.ToString().substr(0,10).c_str());
delete pvMsg;
return false;
return false;
}
}


mapOrphanTransactions[hash] = tx;
mapOrphanTransactions[hash] = pvMsg;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(make_pair(hash, pvMsg));


LogPrint("mempool", "stored orphan tx %s (mapsz %u)\n", hash.ToString().substr(0,10),
printf("stored orphan tx %s (mapsz %"PRIszu")\n", hash.ToString().substr(0,10).c_str(),
mapOrphanTransactions.size());
mapOrphanTransactions.size());
return true;
return true;
}
}


void static EraseOrphanTx(uint256 hash)
void static EraseOrphanTx(uint256 hash)
{
{
if (!mapOrphanTransactions.count(hash))
if (!mapOrphanTransactions.count(hash))
return;
return;
const CTransaction& tx = mapOrphanTransactions[hash];
const CDataStream* pvMsg = mapOrphanTransactions[hash];
CTransaction tx;
CDataStream(*pvMsg) >> tx;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
{
mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash);
mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash);
if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty())
if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty())
mapOrphanTransactionsByPrev.erase(txin.prevout.hash);
mapOrphanTransactionsByPrev.erase(txin.prevout.hash);
}
}

delete pvMsg;
mapOrphanTransactions.erase(hash);
mapOrphanTransactions.erase(hash);
}
}


unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
{
{
unsigned int nEvicted = 0;
unsigned int nEvicted = 0;
while (mapOrphanTransactions.size() > nMaxOrphans)
while (mapOrphanTransactions.size() > nMaxOrphans)
{
{
// Evict a random orphan:
// Evict a random orphan:
uint256 randomhash = GetRandHash();
uint256 randomhash = GetRandHash();
map<uint256, CTransaction>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
map<uint256, CDataStream*>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
if (it == mapOrphanTransactions.end())
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
it = mapOrphanTransactions.begin();
EraseOrphanTx(it->first);
EraseOrphanTx(it->first);
++nEvicted;
++nEvicted;
}
}
return nEvicted;
return nEvicted;
}
}






Text moved to lines 749-752




//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
// CTransaction and CTxIndex
// CTransaction and CTxIndex
//
//


bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet)
bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet)
{
{
SetNull();
SetNull();
if (!txdb.ReadTxIndex(prevout.hash, txindexRet))
if (!txdb.ReadTxIndex(prevout.hash, txindexRet))
return false;
return false;
if (!ReadFromDisk(txindexRet.pos))
if (!ReadFromDisk(txindexRet.pos))
return false;
return false;
if (prevout.n >= vout.size())
if (prevout.n >= vout.size())
{
{
SetNull();
SetNull();
return false;
return false;
}
}
return true;
return true;
}
}


bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout)
bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout)
{
{
CTxIndex txindex;
CTxIndex txindex;
return ReadFromDisk(txdb, prevout, txindex);
return ReadFromDisk(txdb, prevout, txindex);
}
}


bool CTransaction::ReadFromDisk(COutPoint prevout)
bool CTransaction::ReadFromDisk(COutPoint prevout)
{
{
CTxDB txdb("r");
CTxDB txdb("r");
CTxIndex txindex;
CTxIndex txindex;
return ReadFromDisk(txdb, prevout, txindex);
return ReadFromDisk(txdb, prevout, txindex);
}
}


bool IsStandardTx(const CTransaction& tx)
bool CTransaction::IsStandard() const
{
{
if (tx.nVersion > CTransaction::CURRENT_VERSION)
if (nVersion > CTransaction::CURRENT_VERSION)
return false;

// Treat non-final transactions as non-standard to prevent a specific type
// of double-spend attack, as well as DoS attacks. (if the transaction
// can't be mined, the attacker isn't expending resources broadcasting it)
// Basically we don't want to propagate transactions that can't included in
// the next block.
//
// However, IsFinalTx() is confusing... Without arguments, it uses
// chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height()
// is set to the value of nHeight in the block. However, when IsFinalTx()
// is called within CBlock::AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a transaction can
// be part of the *next* block, we need to call IsFinalTx() with one more
// than chainActive.Height().
//
// Timestamps on the other hand don't get any special treatment, because we
// can't know what timestamp the next block will have, and there aren't
// timestamp applications where it matters.

if (!IsFinalTx(tx, nBestHeight + 1)) {
return false;
}

// nTime has different purpose from nLockTime but can be used in similar attacks
if (tx.nTime > FutureDrift(GetAdjustedTime())) {
return false;
}

// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz >= MAX_STANDARD_TX_SIZE)
return false;
return false;



BOOST_FOREACH(const CTxIn& txin, vin)

BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
// ~65-byte public keys, plus a few script ops.
// ~65-byte public keys, plus a few script ops.
if (txin.scriptSig.size() > 500)
if (txin.scriptSig.size() > 500)
return false;
return false;
if (!txin.scriptSig.IsPushOnly())
if (!txin.scriptSig.IsPushOnly())
return false;
return false;
if (!txin.scriptSig.HasCanonicalPushes())
return false;
}
}

BOOST_FOREACH(const CTxOut& txout, vout) {
unsigned int nDataOut = 0;
if (!::IsStandard(txout.scriptPubKey))
txnouttype whichType;
BOOST_FOREACH(const CTxOut& txout, tx.vout) {
if (!::IsStandard(txout.scriptPubKey, whichType))
return false;
return false;
if (whichType == TX_NULL_DATA)
nDataOut++;
if (txout.nValue == 0)
if (txout.nValue == 0)
return false;
return false;
if (!txout.scriptPubKey.HasCanonicalPushes())
return false;
}

// only one OP_RETURN txout is permitted
if (nDataOut > 1) {
return false;
}
}

return true;
return true;
}
}


bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
AssertLockHeld(cs_main);
// Time based nLockTime implemented in 0.1.6
if (tx.nLockTime == 0)
return true;
if (nBlockHeight == 0)
nBlockHeight = nBestHeight;
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
return true;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
if (!txin.IsFinal())
return false;
return true;

}

//
//
// Check transaction inputs, and make sure any
// Check transaction inputs, and make sure any
// pay-to-script-hash transactions are evaluating IsStandard scripts
// pay-to-script-hash transactions are evaluating IsStandard scripts
//
//
// Why bother? To avoid denial-of-service attacks; an attacker
// Why bother? To avoid denial-of-service attacks; an attacker
// can submit a standard HASH... OP_EQUAL transaction,
// can submit a standard HASH... OP_EQUAL transaction,
// which will get accepted into blocks. The redemption
// which will get accepted into blocks. The redemption
// script can be anything; an attacker could use a very
// script can be anything; an attacker could use a very
// expensive-to-check-upon-redemption script like:
// expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
//
//
bool CTransaction::AreInputsStandard(const MapPrevTx& mapInputs) const
bool CTransaction::AreInputsStandard(const MapPrevTx& mapInputs) const
{
{
if (IsCoinBase())
if (IsCoinBase())
return true; // Coinbases don't use vin normally
return true; // Coinbases don't use vin normally


for (unsigned int i = 0; i < vin.size(); i++)
for (unsigned int i = 0; i < vin.size(); i++)
{
{
const CTxOut& prev = GetOutputFor(vin[i], mapInputs);
const CTxOut& prev = GetOutputFor(vin[i], mapInputs);


vector<vector<unsigned char> > vSolutions;
vector<vector<unsigned char> > vSolutions;
txnouttype whichType;
txnouttype whichType;
// get the scriptPubKey corresponding to this input:
// get the scriptPubKey corresponding to this input:
const CScript& prevScript = prev.scriptPubKey;
const CScript& prevScript = prev.scriptPubKey;
if (!Solver(prevScript, whichType, vSolutions))
if (!Solver(prevScript, whichType, vSolutions))
return false;
return false;
int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
if (nArgsExpected < 0)
if (nArgsExpected < 0)
return false;
return false;


// Transactions with extra stuff in their scriptSigs are
// Transactions with extra stuff in their scriptSigs are
// non-standard. Note that this EvalScript() call will
// non-standard. Note that this EvalScript() call will
// be quick, because if there are any operations
// be quick, because if there are any operations
// beside "push data" in the scriptSig the
// beside "push data" in the scriptSig the
// IsStandard() call returns false
// IsStandard() call returns false
vector<vector<unsigned char> > stack;
vector<vector<unsigned char> > stack;
if (!EvalScript(stack, vin[i].scriptSig, *this, i, 0))
if (!EvalScript(stack, vin[i].scriptSig, *this, i, 0))
return false;
return false;


if (whichType == TX_SCRIPTHASH)
if (whichType == TX_SCRIPTHASH)
{
{
if (stack.empty())
if (stack.empty())
return false;
return false;
CScript subscript(stack.back().begin(), stack.back().end());
CScript subscript(stack.back().begin(), stack.back().end());
vector<vector<unsigned char> > vSolutions2;
vector<vector<unsigned char> > vSolutions2;
txnouttype whichType2;
txnouttype whichType2;
if (!Solver(subscript, whichType2, vSolutions2))
if (!Solver(subscript, whichType2, vSolutions2))
return false;
return false;
if (whichType2 == TX_SCRIPTHASH)
if (whichType2 == TX_SCRIPTHASH)
return false;
return false;


int tmpExpected;
int tmpExpected;
tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2);
tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2);
if (tmpExpected < 0)
if (tmpExpected < 0)
return false;
return false;
nArgsExpected += tmpExpected;
nArgsExpected += tmpExpected;
}
}


if (stack.size() != (unsigned int)nArgsExpected)
if (stack.size() != (unsigned int)nArgsExpected)
return false;
return false;
}
}


return true;
return true;
}
}


unsigned int
unsigned int
CTransaction::GetLegacySigOpCount() const
CTransaction::GetLegacySigOpCount() const
{
{
unsigned int nSigOps = 0;
unsigned int nSigOps = 0;
BOOST_FOREACH(const CTxIn& txin, vin)
BOOST_FOREACH(const CTxIn& txin, vin)
{
{
nSigOps += txin.scriptSig.GetSigOpCount(false);
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
}
BOOST_FOREACH(const CTxOut& txout, vout)
BOOST_FOREACH(const CTxOut& txout, vout)
{
{
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
}
return nSigOps;
return nSigOps;
}
}




int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
{
{
AssertLockHeld(cs_main);
if (fClient)

CBlock blockTmp;
if (pblock == NULL)
{
{
// Load the block this tx is in
if (hashBlock == 0)
CTxIndex txindex;
if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
return 0;
if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos))
return 0;
return 0;
pblock = &blockTmp;
}
}
else
{
CBlock blockTmp;
if (pblock == NULL)
{
// Load the block this tx is in
CTxIndex txindex;
if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
return 0;
if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos))
return 0;
pblock = &blockTmp;
}


// Update the tx's hashBlock
// Update the tx's hashBlock
hashBlock = pblock->GetHash();
hashBlock = pblock->GetHash();


// Locate the transaction
// Locate the transaction
for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++)
for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++)
if (pblock->vtx[nIndex] == *(CTransaction*)this)
if (pblock->vtx[nIndex] == *(CTransaction*)this)
break;
break;
if (nIndex == (int)pblock->vtx.size())
if (nIndex == (int)pblock->vtx.size())
{
{
vMerkleBranch.clear();
vMerkleBranch.clear();
nIndex = -1;
nIndex = -1;
LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
return 0;
return 0;
}

// Fill in merkle branch
vMerkleBranch = pblock->GetMerkleBranch(nIndex);
}
}


// Fill in merkle branch
vMerkleBranch = pblock->GetMerkleBranch(nIndex);

// Is the tx in a block that's in the main chain
// Is the tx in a block that's in the main chain
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
if (mi == mapBlockIndex.end())
return 0;
return 0;
CBlockIndex* pindex = (*mi).second;
CBlockIndex* pindex = (*mi).second;
if (!pindex || !pindex->IsInMainChain())
if (!pindex || !pindex->IsInMainChain())
return 0;
return 0;


return pindexBest->nHeight - pindex->nHeight + 1;
return pindexBest->nHeight - pindex->nHeight + 1;
}
}











bool CTransaction::CheckTransaction() const
bool CTransaction::CheckTransaction() const
{
{
// Basic checks that don't depend on any context
// Basic checks that don't depend on any context
if (vin.empty())
if (vin.empty())
return DoS(10, error("CTransaction::CheckTransaction() : vin empty"));
return DoS(10, error("CTransaction::CheckTransaction() : vin empty"));
if (vout.empty())
if (vout.empty())
return DoS(10, error("CTransaction::CheckTransaction() : vout empty"));
return DoS(10, error("CTransaction::CheckTransaction() : vout empty"));
// Time (prevent mempool memory exhaustion attack)
if (nTime > GetAdjustedTime() + nMaxClockDrift)
return DoS(10, error("CTransaction::CheckTransaction() : timestamp is too far into the future"));
// Size limits
// Size limits
if (::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
if (::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
return DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));


// Check for negative or overflow output values
// Check for negative or overflow output values
int64_t nValueOut = 0;
int64 nValueOut = 0;
for (unsigned int i = 0; i < vout.size(); i++)
for (unsigned int i = 0; i < vout.size(); i++)
{
{
const CTxOut& txout = vout[i];
const CTxOut& txout = vout[i];
if (txout.IsEmpty() && !IsCoinBase() && !IsCoinStake())
if (txout.IsEmpty() && !IsCoinBase() && !IsCoinStake())
return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction"));
return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction"));


// ppcoin: enforce minimum output amount
// ppcoin: enforce minimum output amount
if ((!txout.IsEmpty()) && txout.nValue < MIN_TXOUT_AMOUNT)
if ((!txout.IsEmpty()) && txout.nValue < MIN_TXOUT_AMOUNT)
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue below minimum"));
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue below minimum"));



if (txout.nValue < 0)
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue is negative"));
if (txout.nValue > MAX_MONEY)
if (txout.nValue > MAX_MONEY)
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
nValueOut += txout.nValue;
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
if (!MoneyRange(nValueOut))
return DoS(100, error("CTransaction::CheckTransaction() : txout total out of range"));
return DoS(100, error("CTransaction::CheckTransaction() : txout total out of range"));
}
}


// Check for duplicate inputs
// Check for duplicate inputs
set<COutPoint> vInOutPoints;
set<COutPoint> vInOutPoints;
BOOST_FOREACH(const CTxIn& txin, vin)
BOOST_FOREACH(const CTxIn& txin, vin)
{
{
if (vInOutPoints.count(txin.prevout))
if (vInOutPoints.count(txin.prevout))
return false;
return false;
vInOutPoints.insert(txin.prevout);
vInOutPoints.insert(txin.prevout);
}
}


if (IsCoinBase())
if (IsCoinBase())
{
{
if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)
if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)
return DoS(100, error("CTransaction::CheckTransaction() : coinbase script size"));
return DoS(100, error("CTransaction::CheckTransaction() : coinbase script size"));
}
}
else
else
{
{
BOOST_FOREACH(const CTxIn& txin, vin)
BOOST_FOREACH(const CTxIn& txin, vin)
if (txin.prevout.IsNull())
if (txin.prevout.IsNull())
return DoS(10, error("CTransaction::CheckTransaction() : prevout is null"));
return DoS(10, error("CTransaction::CheckTransaction() : prevout is null"));
}
}


return true;
return true;
}
}


int64_t CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree,

int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree,
enum GetMinFee_mode mode, unsigned int nBytes) const
enum GetMinFee_mode mode, unsigned int nBytes) const
{
{
// Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
// Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
int64_t nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE;


unsigned int nNewBlockSize = nBlockSize + nBytes;
unsigned int nNewBlockSize = nBlockSize + nBytes;
int64_t nMinFee = (1 + (int64_t)nBytes / 1000) * nBaseFee;
int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;


// To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
// To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
if (nMinFee < nBaseFee)
if (nMinFee < nBaseFee)
{
{
BOOST_FOREACH(const CTxOut& txout, vout)
BOOST_FOREACH(const CTxOut& txout, vout)
if (txout.nValue < CENT)
if (txout.nValue < CENT)
nMinFee = nBaseFee;
nMinFee = nBaseFee;
}
}


// Raise the price as the block approaches full
// Raise the price as the block approaches full
if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
{
{
if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
return MAX_MONEY;
return MAX_MONEY;
nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
}
}


if (!MoneyRange(nMinFee))
if (!MoneyRange(nMinFee))
nMinFee = MAX_MONEY;
nMinFee = MAX_MONEY;
return nMinFee;
return max(nMinFee, MIN_TX_FEE);
}
}




bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx,
bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs,
bool* pfMissingInputs)
bool* pfMissingInputs)
{
{
AssertLockHeld(cs_main);
if (pfMissingInputs)
if (pfMissingInputs)
*pfMissingInputs = false;
*pfMissingInputs = false;


if (!tx.CheckTransaction())
if (!tx.CheckTransaction())
return error("AcceptToMemoryPool : CheckTransaction failed");
return error("CTxMemPool::accept() : CheckTransaction failed");


// Coinbase is only valid in a block, not as a loose transaction
// Coinbase is only valid in a block, not as a loose transaction
if (tx.IsCoinBase())
if (tx.IsCoinBase())
return tx.DoS(100, error("AcceptToMemoryPool : coinbase as individual tx"));
return tx.DoS(100, error("CTxMemPool::accept() : coinbase as individual tx"));


// ppcoin: coinstake is also only valid in a block, not as a loose transaction
// ppcoin: coinstake is also only valid in a block, not as a loose transaction
if (tx.IsCoinStake())
if (tx.IsCoinStake())
return tx.DoS(100, error("AcceptToMemoryPool : coinstake as individual tx"));
return tx.DoS(100, error("CTxMemPool::accept() : coinstake as individual tx"));

// To help v0.1.5 clients who would see it as a negative number
if ((int64)tx.nLockTime > std::numeric_limits<int>::max())
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");


// Rather not work on nonstandard transactions (unless -testnet)
// Rather not work on nonstandard transactions (unless -testnet)
if (!fTestNet && !IsStandardTx(tx))
if (!fTestNet && !tx.IsStandard())
return error("AcceptToMemoryPool : nonstandard transaction type");
return error("CTxMemPool::accept() : nonstandard transaction type");


// is it already in the memory pool?
// Do we already have it?
uint256 hash = tx.GetHash();
uint256 hash = tx.GetHash();

{
if (pool.exists(hash))
LOCK(cs);
return false;
if (mapTx.count(hash))
return false;
}
if (fCheckInputs)
if (txdb.ContainsTx(hash))
return false;


// Check for conflicts with in-memory transactions
// Check for conflicts with in-memory transactions
CTransaction* ptxOld = NULL;
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
{
LOCK(pool.cs); // protect pool.mapNextTx
COutPoint outpoint = tx.vin[i].prevout;
for (unsigned int i = 0; i < tx.vin.size(); i++)
if (mapNextTx.count(outpoint))
{
{
COutPoint outpoint = tx.vin[i].prevout;
// Disable replacement feature for now
if (pool.mapNextTx.count(outpoint))
return false;
{

// Disable replacement feature for now
// Allow replacing with a newer version of the same transaction
if (i != 0)
return false;
ptxOld = mapNextTx[outpoint].ptx;
if (ptxOld->IsFinal())
return false;
if (!tx.IsNewerThan(*ptxOld))
return false;
return false;
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
COutPoint outpoint = tx.vin[i].prevout;
if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
return false;
}
}
break;
}
}
}
}



if (fCheckInputs)
{
{
CTxDB txdb("r");
// do we already have it?
if (txdb.ContainsTx(hash))
return false;

MapPrevTx mapInputs;
MapPrevTx mapInputs;
map<uint256, CTxIndex> mapUnused;
map<uint256, CTxIndex> mapUnused;
bool fInvalid = false;
bool fInvalid = false;
if (!tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid))
if (!tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid))
{
{
if (fInvalid)
if (fInvalid)
return error("AcceptToMemoryPool : FetchInputs found invalid tx %s", hash.ToString().substr(0,10));
return error("CTxMemPool::accept() : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str());
if (pfMissingInputs)
if (pfMissingInputs)
*pfMissingInputs = true;
*pfMissingInputs = true;
return false;
return false;
}
}


// Check for non-standard pay-to-script-hash in inputs
// Check for non-standard pay-to-script-hash in inputs
if (!tx.AreInputsStandard(mapInputs) && !fTestNet)
if (!tx.AreInputsStandard(mapInputs) && !fTestNet)
return error("AcceptToMemoryPool : nonstandard transaction input");
return error("CTxMemPool::accept() : nonstandard transaction input");


// Note: if you modify this code to accept non-standard transactions, then
// Note: if you modify this code to accept non-standard transactions, then
// you should add code here to check that the transaction does a
// you should add code here to check that the transaction does a
// reasonable number of ECDSA signature verifications.
// reasonable number of ECDSA signature verifications.


int64_t nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut();
int64 nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut();
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);


// Don't accept it if it can't get into a block
// Don't accept it if it can't get into a block
int64_t txMinFee = tx.GetMinFee(1000, false, GMF_RELAY, nSize);
int64 txMinFee = tx.GetMinFee(1000, false, GMF_RELAY, nSize);
if (nFees < txMinFee)
if (nFees < txMinFee)
return error("AcceptToMemoryPool : not enough fees %s, %d < %d",
return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d,
has
hash.ToString().c_str(),
nFees, txMinFee);

// Continuously rate-limit free transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
if (nFees < MIN_RELAY_TX_FEE)
{
static CCriticalSection cs;
static double dFreeCount;
static int64 nLastTime;
int64 nNow = GetTime();

{
LOCK(cs);
// Use an exponentially decaying ~10-minute window:
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
nLastTime = nNow;
// -limitfreerelay unit is thousand-bytes-per-minute
// At default rate it would take over a month to fill 1GB
if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(tx))
return error("CTxMemPool::accept() : free transaction rejected by rate limiter");
if (fDebug)
printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
dFreeCount += nSize;
}
}

// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!tx.ConnectInputs(txdb, mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false))
{
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
}
}

// Store transaction in memory
{
LOCK(cs);
if (ptxOld)
{
printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
remove(*ptxOld);
}
addUnchecked(hash, tx);
}

///// are we sure this is ok when loading transactions or restoring block txes
// If updated, erase old tx from wallet
if (ptxOld)
EraseFromWallets(ptxOld->GetHash());

printf("CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n",
hash.ToString().substr(0,10).c_str(),
mapTx.size());
Text moved from lines 284-286
return true;
}

bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
{
return mempool.accept(txdb, *this, fCheckInputs, pfMissingInputs);
}

bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx)
{
// Add to memory pool without checking anything. Don't call this directly,
// call CTxMemPool::accept to properly check the transaction first.
{
mapTx[hash] = tx;
for (unsigned int i = 0; i < tx.vin.size(); i++)
mapNextTx[tx.vin[i].prevout] = CInPoint(&mapTx[hash], i);
nTransactionsUpdated++;
}
return true;
Text moved with changes from lines 227-232 (84.2% similarity)
}


bool CTxMemPool::remove(CTransaction &tx)
{
// Remove transaction from memory pool
{
LOCK(cs);
uint256 hash = tx.GetHash();
if (mapTx.count(hash))
{
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapNextTx.erase(txin.prevout);
mapTx.erase(hash);
nTransactionsUpdated++;
}
}
return true;
}

void CTxMemPool::clear()
{
LOCK(cs);
mapTx.clear();
mapNextTx.clear();
++nTransactionsUpdated;
}

void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
{
vtxid.clear();

LOCK(cs);
vtxid.reserve(mapTx.size());
for (map<uint256, CTransaction>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
vtxid.push_back((*mi).first);
}
Text moved from lines 376-379




int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
{
if (hashBlock == 0 || nIndex == -1)
return 0;

// Find the block it claims to be in
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
return 0;
CBlockIndex* pindex = (*mi).second;
if (!pindex || !pindex->IsInMainChain())
return 0;

// Make sure the merkle branch connects to this block
if (!fMerkleVerified)
{
if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
return 0;
fMerkleVerified = true;
}

pindexRet = pindex;
return pindexBest->nHeight - pindex->nHeight + 1;
}


int CMerkleTx::GetBlocksToMaturity() const
{
if (!(IsCoinBase() || IsCoinStake()))
return 0;
return max(0, (nCoinbaseMaturity+20) - GetDepthInMainChain());
}


bool CMerkleTx::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs)
{
if (fClient)
{
if (!IsInMainChain() && !ClientConnectInputs())
return false;
return CTransaction::AcceptToMemoryPool(txdb, false);
}
else
{
return CTransaction::AcceptToMemoryPool(txdb, fCheckInputs);
Text moved from lines 116-118
}
}

bool CMerkleTx::AcceptToMemoryPool()
{
CTxDB txdb("r");
retu