@ -724,35 +724,6 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
return false ;
return false ;
}
}
// Check for conflicts with in-memory transactions
CTransaction * ptxOld = NULL ;
/*
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + )
{
COutPoint outpoint = tx . vin [ i ] . prevout ;
if ( mapNextTx . count ( outpoint ) )
{
// Disable replacement feature for now
return false ;
// Allow replacing with a newer version of the same transaction
if ( i ! = 0 )
return false ;
ptxOld = mapNextTx [ outpoint ] . ptx ;
if ( IsFinalTx ( * ptxOld ) )
return false ;
if ( ! tx . IsNewerThan ( * ptxOld ) )
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 ;
}
}
*/
{
{
CCoinsView dummy ;
CCoinsView dummy ;
CCoinsViewCache view ( dummy ) ;
CCoinsViewCache view ( dummy ) ;
@ -763,25 +734,10 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
view . SetBackend ( viewMemPool ) ;
view . SetBackend ( viewMemPool ) ;
// do we already have it?
// do we already have it?
// [MF] TODO: use hash(tx.userName)
if ( view . HaveCoins ( hash ) )
if ( view . HaveCoins ( hash ) )
return false ;
return false ;
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
// only helps filling in pfMissingInputs (to determine missing vs spent).
/*
BOOST_FOREACH ( const CTxIn txin , tx . vin ) {
if ( ! view . HaveCoins ( txin . prevout . hash ) ) {
if ( pfMissingInputs )
* pfMissingInputs = true ;
return false ;
}
}
*/
// are the actual inputs available?
if ( ! view . HaveInputs ( tx ) )
return state . Invalid ( error ( " CTxMemPool::accept() : inputs already spent " ) ) ;
// Bring the best block into scope
// Bring the best block into scope
view . GetBestBlock ( ) ;
view . GetBestBlock ( ) ;
@ -789,14 +745,6 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
view . SetBackend ( dummy ) ;
view . SetBackend ( dummy ) ;
}
}
// Check for non-standard pay-to-script-hash in inputs
if ( ! TestNet ( ) & & ! AreInputsStandard ( tx , view ) )
return error ( " CTxMemPool::accept() : nonstandard transaction input " ) ;
// Note: if you modify this code to accept non-standard transactions, then
// you should add code here to check that the transaction does a
// reasonable number of ECDSA signature verifications.
unsigned int nSize = : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) ;
unsigned int nSize = : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) ;
// Continuously rate-limit free transactions
// Continuously rate-limit free transactions
@ -821,30 +769,15 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
printf ( " Rate limit dFreeCount: %g => %g \n " , dFreeCount , dFreeCount + nSize ) ;
printf ( " Rate limit dFreeCount: %g => %g \n " , dFreeCount , dFreeCount + nSize ) ;
dFreeCount + = nSize ;
dFreeCount + = nSize ;
}
}
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if ( ! CheckInputs ( tx , state , view , true , SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC ) )
{
return error ( " CTxMemPool::accept() : ConnectInputs failed % s " , hash.ToString().c_str()) ;
}
}
}
// Store transaction in memory
// Store transaction in memory
{
{
LOCK ( cs ) ;
LOCK ( cs ) ;
if ( ptxOld )
{
printf ( " CTxMemPool::accept() : replacing tx %s with new version \n " , ptxOld - > GetHash ( ) . ToString ( ) . c_str ( ) ) ;
remove ( * ptxOld ) ;
}
addUnchecked ( hash , tx ) ;
addUnchecked ( hash , tx ) ;
}
}
///// are we sure this is ok when loading transactions or restoring block txes
///// 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 ( ) ) ;
SyncWithWallets ( hash , tx , NULL , true ) ;
SyncWithWallets ( hash , tx , NULL , true ) ;
printf ( " CTxMemPool::accept() : accepted %s (poolsz % " PRIszu " ) \n " ,
printf ( " CTxMemPool::accept() : accepted %s (poolsz % " PRIszu " ) \n " ,
@ -1428,24 +1361,6 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
bool CCoinsViewCache : : HaveInputs ( const CTransaction & tx )
bool CCoinsViewCache : : HaveInputs ( const CTransaction & tx )
{
{
if ( ! tx . IsSpamMessage ( ) ) {
/* [MF]
// first check whether information about the prevout hash is available
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
const COutPoint & prevout = tx . vin [ i ] . prevout ;
if ( ! HaveCoins ( prevout . hash ) )
return false ;
}
// then check whether the actual outputs are available
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
const COutPoint & prevout = tx . vin [ i ] . prevout ;
const CCoins & coins = GetCoins ( prevout . hash ) ;
if ( ! coins . IsAvailable ( prevout . n ) )
return false ;
}
*/
}
return true ;
return true ;
}
}
@ -1466,90 +1381,6 @@ bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned in
return true ;
return true ;
}
}
bool CheckInputs ( const CTransaction & tx , CValidationState & state , CCoinsViewCache & inputs , bool fScriptChecks , unsigned int flags , std : : vector < CScriptCheck > * pvChecks )
{
if ( ! tx . IsSpamMessage ( ) )
{
/* [MF]
if ( pvChecks )
pvChecks - > reserve ( tx . vin . size ( ) ) ;
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
// for an attacker to attempt to split the network.
if ( ! inputs . HaveInputs ( tx ) )
return state . Invalid ( error ( " CheckInputs() : %s inputs unavailable " , tx . GetHash ( ) . ToString ( ) . c_str ( ) ) ) ;
// While checking, GetBestBlock() refers to the parent block.
// This is also true for mempool checks.
int nSpendHeight = inputs . GetBestBlock ( ) - > nHeight + 1 ;
int64 nValueIn = 0 ;
int64 nFees = 0 ;
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + )
{
const COutPoint & prevout = tx . vin [ i ] . prevout ;
const CCoins & coins = inputs . GetCoins ( prevout . hash ) ;
// If prev is coinbase, check that it's matured
if ( coins . IsCoinBase ( ) ) {
if ( nSpendHeight - coins . nHeight < COINBASE_MATURITY )
return state . Invalid ( error ( " CheckInputs() : tried to spend coinbase at depth %d " , nSpendHeight - coins . nHeight ) ) ;
}
// Check for negative or overflow input values
nValueIn + = coins . vout [ prevout . n ] . nValue ;
if ( ! MoneyRange ( coins . vout [ prevout . n ] . nValue ) | | ! MoneyRange ( nValueIn ) )
return state . DoS ( 100 , error ( " CheckInputs() : txin values out of range " ) ) ;
}
if ( nValueIn < GetValueOut ( tx ) )
return state . DoS ( 100 , error ( " CheckInputs() : %s value in < value out " , tx . GetHash ( ) . ToString ( ) . c_str ( ) ) ) ;
// Tally transaction fees
int64 nTxFee = nValueIn - GetValueOut ( tx ) ;
if ( nTxFee < 0 )
return state . DoS ( 100 , error ( " CheckInputs() : %s nTxFee < 0 " , tx . GetHash ( ) . ToString ( ) . c_str ( ) ) ) ;
nFees + = nTxFee ;
if ( ! MoneyRange ( nFees ) )
return state . DoS ( 100 , error ( " CheckInputs() : nFees out of range " ) ) ;
// The first loop above does all the inexpensive checks.
// Only if ALL inputs pass do we perform expensive ECDSA signature checks.
// Helps prevent CPU exhaustion attacks.
// Skip ECDSA signature verification when connecting blocks
// before the last block chain checkpoint. This is safe because block merkle hashes are
// still computed and checked, and any change will be caught at the next checkpoint.
if ( fScriptChecks ) {
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
const COutPoint & prevout = tx . vin [ i ] . prevout ;
const CCoins & coins = inputs . GetCoins ( prevout . hash ) ;
// Verify signature
CScriptCheck check ( coins , tx , i , flags , 0 ) ;
if ( pvChecks ) {
pvChecks - > push_back ( CScriptCheck ( ) ) ;
check . swap ( pvChecks - > back ( ) ) ;
} else if ( ! check ( ) ) {
if ( flags & SCRIPT_VERIFY_STRICTENC ) {
// For now, check whether the failure was caused by non-canonical
// encodings or not; if so, don't trigger DoS protection.
CScriptCheck check ( coins , tx , i , flags & ( ~ SCRIPT_VERIFY_STRICTENC ) , 0 ) ;
if ( check ( ) )
return state . Invalid ( ) ;
}
return state . DoS ( 100 , false ) ;
}
}
}
*/
}
return true ;
}
bool DisconnectBlock ( CBlock & block , CValidationState & state , CBlockIndex * pindex , CCoinsViewCache & view , bool * pfClean )
bool DisconnectBlock ( CBlock & block , CValidationState & state , CBlockIndex * pindex , CCoinsViewCache & view , bool * pfClean )
{
{
assert ( pindex = = view . GetBestBlock ( ) ) ;
assert ( pindex = = view . GetBestBlock ( ) ) ;
@ -1683,81 +1514,23 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return true ;
return true ;
}
}
bool fScriptChecks = pindex - > nHeight > = Checkpoints : : GetTotalBlocksEstimate ( ) ;
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// unless those are already completely spent.
// If such overwrites are allowed, coinbases and transactions depending upon those
// can be duplicated to remove the ability to spend the first instance -- even after
// being sent to another address.
// See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information.
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
// already refuses previously-known transaction ids entirely.
// This rule was originally applied all blocks whose timestamp was after March 15, 2012, 0:00 UTC.
// Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the
// two in the chain that violate it. This prevents exploiting the issue against nodes in their
// initial block download.
bool fEnforceBIP30 = ( ! pindex - > phashBlock ) | | // Enforce on CreateNewBlock invocations which don't have a hash.
! ( ( 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 + + ) {
for ( unsigned int i = 0 ; i < block . vtx . size ( ) ; i + + ) {
uint256 hash = block . GetTxHash ( i ) ;
uint256 hash = block . GetTxHash ( i ) ;
if ( view . HaveCoins ( hash ) & & ! view . GetCoins ( hash ) . IsPruned ( ) )
if ( view . HaveCoins ( hash ) )
return state . DoS ( 100 , error ( " ConnectBlock() : tried to overwrite transaction " ) ) ;
return state . DoS ( 100 , error ( " ConnectBlock() : tried to overwrite transaction " ) ) ;
}
}
}
// BIP16 didn't become active until Apr 1 2012
int64 nBIP16SwitchTime = 1333238400 ;
bool fStrictPayToScriptHash = ( pindex - > nTime > = nBIP16SwitchTime ) ;
unsigned int flags = SCRIPT_VERIFY_NOCACHE |
( fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE ) ;
CBlockUndo blockundo ;
CBlockUndo blockundo ;
CCheckQueueControl < CScriptCheck > control ( fScriptChecks & & nScriptCheckThreads ? & scriptcheckqueue : NULL ) ;
int64 nStart = GetTimeMicros ( ) ;
int64 nStart = GetTimeMicros ( ) ;
int64 nFees = 0 ;
int nInputs = 0 ;
unsigned int nSigOps = 0 ;
CDiskTxPos pos ( pindex - > GetBlockPos ( ) , GetSizeOfCompactSize ( block . vtx . size ( ) ) ) ;
CDiskTxPos pos ( pindex - > GetBlockPos ( ) , GetSizeOfCompactSize ( block . vtx . size ( ) ) ) ;
std : : vector < std : : pair < uint256 , CDiskTxPos > > vPos ;
std : : vector < std : : pair < uint256 , CDiskTxPos > > vPos ;
vPos . reserve ( block . vtx . size ( ) ) ;
vPos . reserve ( block . vtx . size ( ) ) ;
for ( unsigned int i = 0 ; i < block . vtx . size ( ) ; i + + )
for ( unsigned int i = 0 ; i < block . vtx . size ( ) ; i + + )
{
{
const CTransaction & tx = block . vtx [ i ] ;
const CTransaction & tx = block . vtx [ i ] ;
/* [MF]
nInputs + = tx . vin . size ( ) ;
nSigOps + = GetLegacySigOpCount ( tx ) ;
if ( nSigOps > MAX_BLOCK_SIGOPS )
return state . DoS ( 100 , error ( " ConnectBlock() : too many sigops " ) ) ;
if ( ! tx . IsCoinBase ( ) )
{
if ( ! view . HaveInputs ( tx ) )
return state . DoS ( 100 , error ( " ConnectBlock() : inputs missing/spent " ) ) ;
if ( fStrictPayToScriptHash )
{
// Add in sigops done by pay-to-script-hash inputs;
// this is to prevent a "rogue miner" from creating
// an incredibly-expensive-to-validate block.
nSigOps + = GetP2SHSigOpCount ( tx , view ) ;
if ( nSigOps > MAX_BLOCK_SIGOPS )
return state . DoS ( 100 , error ( " ConnectBlock() : too many sigops " ) ) ;
}
nFees + = view . GetValueIn ( tx ) - GetValueOut ( tx ) ;
std : : vector < CScriptCheck > vChecks ;
if ( ! CheckInputs ( tx , state , view , fScriptChecks , flags , nScriptCheckThreads ? & vChecks : NULL ) )
return false ;
control . Add ( vChecks ) ;
}
*/
CTxUndo txundo ;
CTxUndo txundo ;
UpdateCoins ( tx , state , view , txundo , pindex - > nHeight , block . GetTxHash ( i ) ) ;
UpdateCoins ( tx , state , view , txundo , pindex - > nHeight , block . GetTxHash ( i ) ) ;
if ( ! tx . IsSpamMessage ( ) )
if ( ! tx . IsSpamMessage ( ) )
@ -1768,16 +1541,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
}
}
int64 nTime = GetTimeMicros ( ) - nStart ;
int64 nTime = GetTimeMicros ( ) - nStart ;
if ( fBenchmark )
if ( fBenchmark )
printf ( " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) \n " , ( unsigned ) block . vtx . size ( ) , 0.001 * nTime , 0.001 * nTime / block . vtx . size ( ) , nInputs < = 1 ? 0 : 0.001 * nTime / ( nInputs - 1 ) ) ;
printf ( " - Connect %u transactions: %.2fms (%.3fms/tx) \n " , ( unsigned ) block . vtx . size ( ) , 0.001 * nTime , 0.001 * nTime / block . vtx . size ( ) ) ;
if ( GetValueOut ( block . vtx [ 0 ] ) > GetBlockValue ( pindex - > nHeight , nFees ) )
return state . DoS ( 100 , error ( " ConnectBlock() : coinbase pays too much (actual=% " PRI64d " vs limit=% " PRI64d " ) " , GetValueOut ( block . vtx [ 0 ] ) , GetBlockValue ( pindex - > nHeight , nFees ) ) ) ;
if ( ! control . Wait ( ) )
return state . DoS ( 100 , false ) ;
int64 nTime2 = GetTimeMicros ( ) - nStart ;
if ( fBenchmark )
printf ( " - Verify %u txins: %.2fms (%.3fms/txin) \n " , nInputs - 1 , 0.001 * nTime2 , nInputs < = 1 ? 0 : 0.001 * nTime2 / ( nInputs - 1 ) ) ;
if ( fJustCheck )
if ( fJustCheck )
return true ;
return true ;
@ -2180,14 +1944,6 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
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 " ) ) ;
unsigned int nSigOps = 0 ;
BOOST_FOREACH ( const CTransaction & tx , block . vtx )
{
nSigOps + = GetLegacySigOpCount ( tx ) ;
}
if ( nSigOps > MAX_BLOCK_SIGOPS )
return state . DoS ( 100 , error ( " CheckBlock() : out-of-bounds SigOpCount " ) ) ;
// Check merkle root
// Check merkle root
if ( fCheckMerkleRoot & & block . hashMerkleRoot ! = block . BuildMerkleTree ( ) )
if ( fCheckMerkleRoot & & block . hashMerkleRoot ! = block . BuildMerkleTree ( ) )
return state . DoS ( 100 , error ( " CheckBlock() : hashMerkleRoot mismatch " ) ) ;
return state . DoS ( 100 , error ( " CheckBlock() : hashMerkleRoot mismatch " ) ) ;
@ -4186,6 +3942,8 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
return NULL ;
return NULL ;
txNew . pubKey < < pubkey < < OP_CHECKSIG ;
txNew . pubKey < < pubkey < < OP_CHECKSIG ;
// [MF] TODO: fix nNonce
// Add our coinbase tx as first transaction
// Add our coinbase tx as first transaction
pblock - > vtx . push_back ( txNew ) ;
pblock - > vtx . push_back ( txNew ) ;
pblocktemplate - > vTxFees . push_back ( - 1 ) ; // updated at end
pblocktemplate - > vTxFees . push_back ( - 1 ) ; // updated at end
@ -4207,7 +3965,6 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
nBlockMinSize = std : : min ( nBlockMaxSize , nBlockMinSize ) ;
nBlockMinSize = std : : min ( nBlockMaxSize , nBlockMinSize ) ;
// Collect memory pool transactions into the block
// Collect memory pool transactions into the block
int64 nFees = 0 ;
{
{
LOCK2 ( cs_main , mempool . cs ) ;
LOCK2 ( cs_main , mempool . cs ) ;
CBlockIndex * pindexPrev = pindexBest ;
CBlockIndex * pindexPrev = pindexBest ;
@ -4216,193 +3973,49 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Priority order to process transactions
// Priority order to process transactions
list < COrphan > vOrphan ; // list memory doesn't move
list < COrphan > vOrphan ; // list memory doesn't move
map < uint256 , vector < COrphan * > > mapDependers ;
map < uint256 , vector < COrphan * > > mapDependers ;
bool fPrintPriority = GetBoolArg ( " -printpriority " , false ) ;
// This vector will be sorted into a priority queue:
// Collect transactions into block
vector < TxPriority > vecPriority ;
uint64 nBlockSize = 1000 ;
vecPriority . reserve ( mempool . mapTx . size ( ) ) ;
uint64 nBlockTx = 0 ;
for ( map < uint256 , CTransaction > : : iterator mi = mempool . mapTx . begin ( ) ; mi ! = mempool . mapTx . end ( ) ; + + mi )
for ( map < uint256 , CTransaction > : : iterator mi = mempool . mapTx . begin ( ) ; mi ! = mempool . mapTx . end ( ) ; + + mi )
{
{
CTransaction & tx = ( * mi ) . second ;
CTransaction & tx = ( * mi ) . second ;
if ( tx . IsSpamMessage ( ) )
if ( tx . IsSpamMessage ( ) )
continue ;
continue ;
COrphan * porphan = NULL ;
// This should never happen; all transactions in the memory are new
double dPriority = 0 ;
if ( view . HaveCoins ( tx . GetHash ( ) ) ) {
int64 nTotalIn = 0 ;
printf ( " ERROR: mempool transaction already exists \n " ) ;
bool fMissingInputs = false ;
if ( fDebug ) assert ( " mempool transaction already exists " = = 0 ) ;
/* [MF]
BOOST_FOREACH ( const CTxIn & txin , tx . vin )
{
// Read prev transaction
if ( ! view . HaveCoins ( txin . prevout . hash ) )
{
// This should never happen; all transactions in the memory
// pool should connect to either transactions in the chain
// or other transactions in the memory pool.
if ( ! mempool . mapTx . count ( txin . prevout . hash ) )
{
printf ( " ERROR: mempool transaction missing input \n " ) ;
if ( fDebug ) assert ( " mempool transaction missing input " = = 0 ) ;
fMissingInputs = true ;
if ( porphan )
vOrphan . pop_back ( ) ;
break ;
}
// Has to wait for dependencies
if ( ! porphan )
{
// Use list for automatic deletion
vOrphan . push_back ( COrphan ( & tx ) ) ;
porphan = & vOrphan . back ( ) ;
}
mapDependers [ txin . prevout . hash ] . push_back ( porphan ) ;
porphan - > setDependsOn . insert ( txin . prevout . hash ) ;
nTotalIn + = mempool . mapTx [ txin . prevout . hash ] . vout [ txin . prevout . n ] . nValue ;
continue ;
}
const CCoins & coins = view . GetCoins ( txin . prevout . hash ) ;
int64 nValueIn = coins . vout [ txin . prevout . n ] . nValue ;
nTotalIn + = nValueIn ;
int nConf = pindexPrev - > nHeight - coins . nHeight + 1 ;
dPriority + = ( double ) nValueIn * nConf ;
}
}
*/
if ( fMissingInputs ) continue ;
// Priority is sum(valuein * age) / txsize
unsigned int nTxSize = : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) ;
dPriority / = nTxSize ;
// This is a more accurate fee-per-kilobyte than is used by the client code, because the
// client code rounds up the size to the nearest 1K. That's good, because it gives an
// incentive to create smaller transactions.
double dFeePerKb = double ( nTotalIn - GetValueOut ( tx ) ) / ( double ( nTxSize ) / 1000.0 ) ;
if ( porphan )
{
porphan - > dPriority = dPriority ;
porphan - > dFeePerKb = dFeePerKb ;
}
else
vecPriority . push_back ( TxPriority ( dPriority , dFeePerKb , & ( * mi ) . second ) ) ;
}
// Collect transactions into block
uint64 nBlockSize = 1000 ;
uint64 nBlockTx = 0 ;
int nBlockSigOps = 100 ;
bool fSortedByFee = ( nBlockPrioritySize < = 0 ) ;
TxPriorityCompare comparer ( fSortedByFee ) ;
std : : make_heap ( vecPriority . begin ( ) , vecPriority . end ( ) , comparer ) ;
while ( ! vecPriority . empty ( ) )
{
// Take highest priority transaction off the priority queue:
double dPriority = vecPriority . front ( ) . get < 0 > ( ) ;
double dFeePerKb = vecPriority . front ( ) . get < 1 > ( ) ;
CTransaction & tx = * ( vecPriority . front ( ) . get < 2 > ( ) ) ;
std : : pop_heap ( vecPriority . begin ( ) , vecPriority . end ( ) , comparer ) ;
vecPriority . pop_back ( ) ;
// Size limits
// Size limits
unsigned int nTxSize = : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) ;
unsigned int nTxSize = : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) ;
if ( nBlockSize + nTxSize > = nBlockMaxSize )
if ( nBlockSize + nTxSize > = nBlockMaxSize )
continue ;
continue ;
// Legacy limits on sigOps:
unsigned int nTxSigOps = GetLegacySigOpCount ( tx ) ;
if ( nBlockSigOps + nTxSigOps > = MAX_BLOCK_SIGOPS )
continue ;
// Skip free transactions if we're past the minimum block size:
if ( fSortedByFee & & ( nBlockSize + nTxSize > = nBlockMinSize ) )
continue ;
// Prioritize by fee once past the priority size or we run out of high-priority
// transactions:
if ( ! fSortedByFee & &
( ( nBlockSize + nTxSize > = nBlockPrioritySize ) | | ! AllowFree ( dPriority ) ) )
{
fSortedByFee = true ;
comparer = TxPriorityCompare ( fSortedByFee ) ;
std : : make_heap ( vecPriority . begin ( ) , vecPriority . end ( ) , comparer ) ;
}
if ( ! view . HaveInputs ( tx ) )
continue ;
int64 nTxFees = view . GetValueIn ( tx ) - GetValueOut ( tx ) ;
nTxSigOps + = GetP2SHSigOpCount ( tx , view ) ;
if ( nBlockSigOps + nTxSigOps > = MAX_BLOCK_SIGOPS )
continue ;
CValidationState state ;
CValidationState state ;
if ( ! CheckInputs ( tx , state , view , true , SCRIPT_VERIFY_P2SH ) )
continue ;
CTxUndo txundo ;
CTxUndo txundo ;
uint256 hash = tx . GetHash ( ) ;
uint256 hash = tx . GetHash ( ) ;
UpdateCoins ( tx , state , view , txundo , pindexPrev - > nHeight + 1 , hash ) ;
UpdateCoins ( tx , state , view , txundo , pindexPrev - > nHeight + 1 , hash ) ;
// Added
// Added
pblock - > vtx . push_back ( tx ) ;
pblock - > vtx . push_back ( tx ) ;
pblocktemplate - > vTxFees . push_back ( nTxFees ) ;
pblocktemplate - > vTxSigOps . push_back ( nTxSigOps ) ;
nBlockSize + = nTxSize ;
nBlockSize + = nTxSize ;
+ + nBlockTx ;
+ + nBlockTx ;
nBlockSigOps + = nTxSigOps ;
nFees + = nTxFees ;
if ( fPrintPriority )
{
printf ( " priority %.1f feeperkb %.1f txid %s \n " ,
dPriority , dFeePerKb , tx . GetHash ( ) . ToString ( ) . c_str ( ) ) ;
}
// Add transactions that depend on this one to the priority queue
if ( mapDependers . count ( hash ) )
{
BOOST_FOREACH ( COrphan * porphan , mapDependers [ hash ] )
{
if ( ! porphan - > setDependsOn . empty ( ) )
{
porphan - > setDependsOn . erase ( hash ) ;
if ( porphan - > setDependsOn . empty ( ) )
{
vecPriority . push_back ( TxPriority ( porphan - > dPriority , porphan - > dFeePerKb , porphan - > ptx ) ) ;
std : : push_heap ( vecPriority . begin ( ) , vecPriority . end ( ) , comparer ) ;
}
}
}
}
}
}
nLastBlockTx = nBlockTx ;
nLastBlockTx = nBlockTx ;
nLastBlockSize = nBlockSize ;
nLastBlockSize = nBlockSize ;
printf ( " CreateNewBlock(): total size % " PRI64u " \n " , nBlockSize ) ;
printf ( " CreateNewBlock(): total size % " PRI64u " \n " , nBlockSize ) ;
/* [MF]
pblock - > vtx [ 0 ] . vout [ 0 ] . nValue = GetBlockValue ( pindexPrev - > nHeight + 1 , nFees ) ;
*/
pblocktemplate - > vTxFees [ 0 ] = - nFees ;
// Fill in header
// Fill in header
pblock - > hashPrevBlock = pindexPrev - > GetBlockHash ( ) ;
pblock - > hashPrevBlock = pindexPrev - > GetBlockHash ( ) ;
pblock - > nHeight = pindexPrev - > nHeight + 1 ;
UpdateTime ( * pblock , pindexPrev ) ;
UpdateTime ( * pblock , pindexPrev ) ;
pblock - > nBits = GetNextWorkRequired ( pindexPrev , pblock ) ;
pblock - > nBits = GetNextWorkRequired ( pindexPrev , pblock ) ;
pblock - > nNonce = 0 ;
pblock - > nNonce = 0 ;
/* [MF]
pblock - > vtx [ 0 ] . vin [ 0 ] . scriptSig = CScript ( ) < < OP_0 < < OP_0 ;
*/
pblocktemplate - > vTxSigOps [ 0 ] = GetLegacySigOpCount ( pblock - > vtx [ 0 ] ) ;
CBlockIndex indexDummy ( * pblock ) ;
CBlockIndex indexDummy ( * pblock ) ;
indexDummy . pprev = pindexPrev ;
indexDummy . pprev = pindexPrev ;