@ -126,6 +126,8 @@ void BlockAssembler::resetBlock()
std : : unique_ptr < CBlockTemplate > BlockAssembler : : CreateNewBlock ( const CScript & scriptPubKeyIn , bool fMineWitnessTx )
std : : unique_ptr < CBlockTemplate > BlockAssembler : : CreateNewBlock ( const CScript & scriptPubKeyIn , bool fMineWitnessTx )
{
{
int64_t nTimeStart = GetTimeMicros ( ) ;
resetBlock ( ) ;
resetBlock ( ) ;
pblocktemplate . reset ( new CBlockTemplate ( ) ) ;
pblocktemplate . reset ( new CBlockTemplate ( ) ) ;
@ -164,7 +166,11 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
// transaction (which in most cases can be a no-op).
// transaction (which in most cases can be a no-op).
fIncludeWitness = IsWitnessEnabled ( pindexPrev , chainparams . GetConsensus ( ) ) & & fMineWitnessTx ;
fIncludeWitness = IsWitnessEnabled ( pindexPrev , chainparams . GetConsensus ( ) ) & & fMineWitnessTx ;
addPackageTxs ( ) ;
int nPackagesSelected = 0 ;
int nDescendantsUpdated = 0 ;
addPackageTxs ( nPackagesSelected , nDescendantsUpdated ) ;
int64_t nTime1 = GetTimeMicros ( ) ;
nLastBlockTx = nBlockTx ;
nLastBlockTx = nBlockTx ;
nLastBlockSize = nBlockSize ;
nLastBlockSize = nBlockSize ;
@ -196,6 +202,9 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
if ( ! TestBlockValidity ( state , chainparams , * pblock , pindexPrev , false , false ) ) {
if ( ! TestBlockValidity ( state , chainparams , * pblock , pindexPrev , false , false ) ) {
throw std : : runtime_error ( strprintf ( " %s: TestBlockValidity failed: %s " , __func__ , FormatStateMessage ( state ) ) ) ;
throw std : : runtime_error ( strprintf ( " %s: TestBlockValidity failed: %s " , __func__ , FormatStateMessage ( state ) ) ) ;
}
}
int64_t nTime2 = GetTimeMicros ( ) ;
LogPrint ( " bench " , " CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms) \n " , 0.001 * ( nTime1 - nTimeStart ) , nPackagesSelected , nDescendantsUpdated , 0.001 * ( nTime2 - nTime1 ) , 0.001 * ( nTime2 - nTimeStart ) ) ;
return std : : move ( pblocktemplate ) ;
return std : : move ( pblocktemplate ) ;
}
}
@ -269,9 +278,10 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
}
}
}
}
void BlockAssembler : : UpdatePackagesForAdded ( const CTxMemPool : : setEntries & alreadyAdded ,
int BlockAssembler : : UpdatePackagesForAdded ( const CTxMemPool : : setEntries & alreadyAdded ,
indexed_modified_transaction_set & mapModifiedTx )
indexed_modified_transaction_set & mapModifiedTx )
{
{
int nDescendantsUpdated = 0 ;
BOOST_FOREACH ( const CTxMemPool : : txiter it , alreadyAdded ) {
BOOST_FOREACH ( const CTxMemPool : : txiter it , alreadyAdded ) {
CTxMemPool : : setEntries descendants ;
CTxMemPool : : setEntries descendants ;
mempool . CalculateDescendants ( it , descendants ) ;
mempool . CalculateDescendants ( it , descendants ) ;
@ -279,6 +289,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
BOOST_FOREACH ( CTxMemPool : : txiter desc , descendants ) {
BOOST_FOREACH ( CTxMemPool : : txiter desc , descendants ) {
if ( alreadyAdded . count ( desc ) )
if ( alreadyAdded . count ( desc ) )
continue ;
continue ;
+ + nDescendantsUpdated ;
modtxiter mit = mapModifiedTx . find ( desc ) ;
modtxiter mit = mapModifiedTx . find ( desc ) ;
if ( mit = = mapModifiedTx . end ( ) ) {
if ( mit = = mapModifiedTx . end ( ) ) {
CTxMemPoolModifiedEntry modEntry ( desc ) ;
CTxMemPoolModifiedEntry modEntry ( desc ) ;
@ -291,6 +302,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
}
}
}
}
}
}
return nDescendantsUpdated ;
}
}
// Skip entries in mapTx that are already in a block or are present
// Skip entries in mapTx that are already in a block or are present
@ -331,7 +343,7 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemP
// Each time through the loop, we compare the best transaction in
// Each time through the loop, we compare the best transaction in
// mapModifiedTxs with the next transaction in the mempool to decide what
// mapModifiedTxs with the next transaction in the mempool to decide what
// transaction package to work on next.
// transaction package to work on next.
void BlockAssembler : : addPackageTxs ( )
void BlockAssembler : : addPackageTxs ( int & nPackagesSelected , int & nDescendantsUpdated )
{
{
// mapModifiedTx will store sorted packages after they are modified
// mapModifiedTx will store sorted packages after they are modified
// because some of their txs are already in the block
// because some of their txs are already in the block
@ -345,6 +357,13 @@ void BlockAssembler::addPackageTxs()
CTxMemPool : : indexed_transaction_set : : index < ancestor_score > : : type : : iterator mi = mempool . mapTx . get < ancestor_score > ( ) . begin ( ) ;
CTxMemPool : : indexed_transaction_set : : index < ancestor_score > : : type : : iterator mi = mempool . mapTx . get < ancestor_score > ( ) . begin ( ) ;
CTxMemPool : : txiter iter ;
CTxMemPool : : txiter iter ;
// Limit the number of attempts to add transactions to the block when it is
// close to full; this is just a simple heuristic to finish quickly if the
// mempool has a lot of entries.
const int64_t MAX_CONSECUTIVE_FAILURES = 1000 ;
int64_t nConsecutiveFailed = 0 ;
while ( mi ! = mempool . mapTx . get < ancestor_score > ( ) . end ( ) | | ! mapModifiedTx . empty ( ) )
while ( mi ! = mempool . mapTx . get < ancestor_score > ( ) . end ( ) | | ! mapModifiedTx . empty ( ) )
{
{
// First try to find a new transaction in mapTx to evaluate.
// First try to find a new transaction in mapTx to evaluate.
@ -406,6 +425,14 @@ void BlockAssembler::addPackageTxs()
mapModifiedTx . get < ancestor_score > ( ) . erase ( modit ) ;
mapModifiedTx . get < ancestor_score > ( ) . erase ( modit ) ;
failedTx . insert ( iter ) ;
failedTx . insert ( iter ) ;
}
}
+ + nConsecutiveFailed ;
if ( nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES & & nBlockWeight >
nBlockMaxWeight - 4000 ) {
// Give up if we're close to full and haven't succeeded in a while
break ;
}
continue ;
continue ;
}
}
@ -426,6 +453,9 @@ void BlockAssembler::addPackageTxs()
continue ;
continue ;
}
}
// This transaction will make it in; reset the failed counter.
nConsecutiveFailed = 0 ;
// Package can be added. Sort the entries in a valid order.
// Package can be added. Sort the entries in a valid order.
std : : vector < CTxMemPool : : txiter > sortedEntries ;
std : : vector < CTxMemPool : : txiter > sortedEntries ;
SortForBlock ( ancestors , iter , sortedEntries ) ;
SortForBlock ( ancestors , iter , sortedEntries ) ;
@ -436,8 +466,10 @@ void BlockAssembler::addPackageTxs()
mapModifiedTx . erase ( sortedEntries [ i ] ) ;
mapModifiedTx . erase ( sortedEntries [ i ] ) ;
}
}
+ + nPackagesSelected ;
// Update transactions that depend on each of these
// Update transactions that depend on each of these
UpdatePackagesForAdded ( ancestors , mapModifiedTx ) ;
nDescendantsUpdated + = UpdatePackagesForAdded ( ancestors , mapModifiedTx ) ;
}
}
}
}