@ -277,6 +277,34 @@ void EraseOrphanTx(uint256 hash)
// CTransaction
// CTransaction
//
//
bool CTransaction : : ReadFromDisk ( CTxDB & txdb , COutPoint prevout , CTxIndex & txindexRet )
{
SetNull ( ) ;
if ( ! txdb . ReadTxIndex ( prevout . hash , txindexRet ) )
return false ;
if ( ! ReadFromDisk ( txindexRet . pos ) )
return false ;
if ( prevout . n > = vout . size ( ) )
{
SetNull ( ) ;
return false ;
}
return true ;
}
bool CTransaction : : ReadFromDisk ( CTxDB & txdb , COutPoint prevout )
{
CTxIndex txindex ;
return ReadFromDisk ( txdb , prevout , txindex ) ;
}
bool CTransaction : : ReadFromDisk ( COutPoint prevout )
{
CTxDB txdb ( " r " ) ;
CTxIndex txindex ;
return ReadFromDisk ( txdb , prevout , txindex ) ;
}
bool CTxIn : : IsMine ( ) const
bool CTxIn : : IsMine ( ) const
{
{
CRITICAL_BLOCK ( cs_mapWallet )
CRITICAL_BLOCK ( cs_mapWallet )
@ -2882,7 +2910,7 @@ void CallCPUID(int in, int& aret, int& cret)
" mov %2, %%eax; " // in into eax
" mov %2, %%eax; " // in into eax
" cpuid; "
" cpuid; "
" mov %%eax, %0; " // eax into a
" mov %%eax, %0; " // eax into a
" mov %%ecx, %1; " // ea x into c
" mov %%ecx, %1; " // ec x into c
: " =r " ( a ) , " =r " ( c ) /* output */
: " =r " ( a ) , " =r " ( c ) /* output */
: " r " ( in ) /* input */
: " r " ( in ) /* input */
: " %eax " , " %ecx " /* clobbered register */
: " %eax " , " %ecx " /* clobbered register */
@ -3068,42 +3096,97 @@ void BitcoinMiner()
CRITICAL_BLOCK ( cs_mapTransactions )
CRITICAL_BLOCK ( cs_mapTransactions )
{
{
CTxDB txdb ( " r " ) ;
CTxDB txdb ( " r " ) ;
// Priority order to process transactions
multimap < double , CTransaction * > mapPriority ;
for ( map < uint256 , CTransaction > : : iterator mi = mapTransactions . begin ( ) ; mi ! = mapTransactions . end ( ) ; + + mi )
{
CTransaction & tx = ( * mi ) . second ;
if ( tx . IsCoinBase ( ) | | ! tx . IsFinal ( ) )
continue ;
double dPriority = 0 ;
foreach ( const CTxIn & txin , tx . vin )
{
// Read prev transaction
CTransaction txPrev ;
CTxIndex txindex ;
if ( ! txPrev . ReadFromDisk ( txdb , txin . prevout , txindex ) )
continue ;
int64 nValueIn = txPrev . vout [ txin . prevout . n ] . nValue ;
// Read block header
int nConf = 0 ;
CBlock block ;
if ( block . ReadFromDisk ( txindex . pos . nFile , txindex . pos . nBlockPos , false ) )
{
map < uint256 , CBlockIndex * > : : iterator it = mapBlockIndex . find ( block . GetHash ( ) ) ;
if ( it ! = mapBlockIndex . end ( ) )
{
CBlockIndex * pindex = ( * it ) . second ;
if ( pindex - > IsInMainChain ( ) )
nConf = 1 + nBestHeight - pindex - > nHeight ;
}
}
dPriority + = ( double ) nValueIn * nConf ;
if ( fDebug & & mapArgs . count ( " -printpriority " ) )
printf ( " priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f \n " , nValueIn , nConf , dPriority ) ;
}
// Priority is sum(valuein * age) / txsize
dPriority / = : : GetSerializeSize ( tx , SER_NETWORK ) ;
mapPriority . insert ( make_pair ( - dPriority , & ( * mi ) . second ) ) ;
if ( fDebug & & mapArgs . count ( " -printpriority " ) )
printf ( " priority %-20.1f %s \n %s \n " , dPriority , tx . GetHash ( ) . ToString ( ) . substr ( 0 , 10 ) . c_str ( ) , tx . ToString ( ) . c_str ( ) ) ;
}
// Collect transactions into block
map < uint256 , CTxIndex > mapTestPool ;
map < uint256 , CTxIndex > mapTestPool ;
vector < char > vfAlreadyAdded ( mapTransactions . size ( ) ) ;
uint64 nBlockSize = 1000 ;
uint64 nBlockSize = 1000 ;
int nBlockSigOps = 100 ;
int nBlockSigOps = 100 ;
bool fFoundSomething = true ;
bool fFoundSomething = true ;
while ( fFoundSomething )
while ( fFoundSomething )
{
{
fFoundSomething = false ;
fFoundSomething = false ;
unsigned int n = 0 ;
for ( multimap < double , CTransaction * > : : iterator mi = mapPriority . begin ( ) ; mi ! = mapPriority . end ( ) ; )
for ( map < uint256 , CTransaction > : : iterator mi = mapTransactions . begin ( ) ; mi ! = mapTransactions . end ( ) ; + + mi , + + n )
{
{
if ( vfAlreadyAdded [ n ] )
CTransaction & tx = * ( * mi ) . second ;
continue ;
CTransaction & tx = ( * mi ) . second ;
if ( tx . IsCoinBase ( ) | | ! tx . IsFinal ( ) )
continue ;
unsigned int nTxSize = : : GetSerializeSize ( tx , SER_NETWORK ) ;
unsigned int nTxSize = : : GetSerializeSize ( tx , SER_NETWORK ) ;
if ( nBlockSize + nTxSize > = MAX_BLOCK_SIZE_GEN )
if ( nBlockSize + nTxSize > = MAX_BLOCK_SIZE_GEN )
{
mapPriority . erase ( mi + + ) ;
continue ;
continue ;
}
int nTxSigOps = tx . GetSigOpCount ( ) ;
int nTxSigOps = tx . GetSigOpCount ( ) ;
if ( nBlockSigOps + nTxSigOps > = MAX_BLOCK_SIGOPS )
if ( nBlockSigOps + nTxSigOps > = MAX_BLOCK_SIGOPS )
{
mapPriority . erase ( mi + + ) ;
continue ;
continue ;
}
// Transaction fee based on block size
// Transaction fee based on block size
int64 nMinFee = tx . GetMinFee ( nBlockSize ) ;
int64 nMinFee = tx . GetMinFee ( nBlockSize ) ;
// Connecting can fail due to dependency on other memory pool transactions
// that aren't in the block yet, so keep trying in later passes
map < uint256 , CTxIndex > mapTestPoolTmp ( mapTestPool ) ;
map < uint256 , CTxIndex > mapTestPoolTmp ( mapTestPool ) ;
if ( ! tx . ConnectInputs ( txdb , mapTestPoolTmp , CDiskTxPos ( 1 , 1 , 1 ) , pindexPrev , nFees , false , true , nMinFee ) )
if ( ! tx . ConnectInputs ( txdb , mapTestPoolTmp , CDiskTxPos ( 1 , 1 , 1 ) , pindexPrev , nFees , false , true , nMinFee ) )
{
mi + + ;
continue ;
continue ;
}
swap ( mapTestPool , mapTestPoolTmp ) ;
swap ( mapTestPool , mapTestPoolTmp ) ;
// Added
pblock - > vtx . push_back ( tx ) ;
pblock - > vtx . push_back ( tx ) ;
nBlockSize + = nTxSize ;
nBlockSize + = nTxSize ;
nBlockSigOps + = nTxSigOps ;
nBlockSigOps + = nTxSigOps ;
vfAlreadyAdded [ n ] = true ;
fFoundSomething = true ;
fFoundSomething = true ;
mapPriority . erase ( mi + + ) ;
}
}
}
}
}
}
@ -3426,16 +3509,15 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
bool CreateTransaction ( CScript scriptPubKey , int64 nValue , CWalletTx & wtxNew , CReserveKey & reservekey , int64 & nFeeRequiredRe t )
bool CreateTransaction ( CScript scriptPubKey , int64 nValue , CWalletTx & wtxNew , CReserveKey & reservekey , int64 & nFeeRet )
{
{
nFeeRequiredRet = 0 ;
CRITICAL_BLOCK ( cs_main )
CRITICAL_BLOCK ( cs_main )
{
{
// txdb must be opened before the mapWallet lock
// txdb must be opened before the mapWallet lock
CTxDB txdb ( " r " ) ;
CTxDB txdb ( " r " ) ;
CRITICAL_BLOCK ( cs_mapWallet )
CRITICAL_BLOCK ( cs_mapWallet )
{
{
int64 nFee = nTransactionFee ;
nFeeRet = nTransactionFee ;
loop
loop
{
{
wtxNew . vin . clear ( ) ;
wtxNew . vin . clear ( ) ;
@ -3444,7 +3526,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR
if ( nValue < 0 )
if ( nValue < 0 )
return false ;
return false ;
int64 nValueOut = nValue ;
int64 nValueOut = nValue ;
int64 nTotalValue = nValue + nFee ;
int64 nTotalValue = nValue + nFeeRet ;
// Choose coins to use
// Choose coins to use
set < CWalletTx * > setCoins ;
set < CWalletTx * > setCoins ;
@ -3504,13 +3586,16 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR
return false ;
return false ;
// Limit size
// Limit size
if ( : : GetSerializeSize ( * ( CTransaction * ) & wtxNew , SER_NETWORK ) > = MAX_BLOCK_SIZE_GEN / 5 )
unsigned int nBytes = : : GetSerializeSize ( * ( CTransaction * ) & wtxNew , SER_NETWORK ) ;
if ( nBytes > = MAX_BLOCK_SIZE_GEN / 5 )
return false ;
return false ;
// Check that enough fee is included
// Check that enough fee is included
if ( nFee < wtxNew . GetMinFee ( ) )
int64 nPayFee = nTransactionFee * ( 1 + ( int64 ) nBytes / 1000 ) ;
int64 nMinFee = wtxNew . GetMinFee ( ) ;
if ( nFeeRet < max ( nPayFee , nMinFee ) )
{
{
nFee = nFeeRequiredRet = wtxNew . GetMinFee ( ) ;
nFeeRet = max ( nPayFee , nMinFee ) ;
continue ;
continue ;
}
}