@ -537,7 +537,7 @@ CBlockIndex* LastCommonAncestor(CBlockIndex* pa, CBlockIndex* pb) {
/** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
/** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
* at most count entries . */
* at most count entries . */
void FindNextBlocksToDownload ( NodeId nodeid , unsigned int count , std : : vector < CBlockIndex * > & vBlocks , NodeId & nodeStaller ) {
void FindNextBlocksToDownload ( NodeId nodeid , unsigned int count , std : : vector < CBlockIndex * > & vBlocks , NodeId & nodeStaller , const Consensus : : Params & consensusParams ) {
if ( count = = 0 )
if ( count = = 0 )
return ;
return ;
@ -594,6 +594,10 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBl
// We consider the chain that this peer is on invalid.
// We consider the chain that this peer is on invalid.
return ;
return ;
}
}
if ( ! State ( nodeid ) - > fHaveWitness & & IsWitnessEnabled ( pindex - > pprev , consensusParams ) ) {
// We wouldn't download this block or its descendants from this peer.
return ;
}
if ( pindex - > nStatus & BLOCK_HAVE_DATA | | chainActive . Contains ( pindex ) ) {
if ( pindex - > nStatus & BLOCK_HAVE_DATA | | chainActive . Contains ( pindex ) ) {
if ( pindex - > nChainTx )
if ( pindex - > nChainTx )
state - > pindexLastCommonBlock = pindex ;
state - > pindexLastCommonBlock = pindex ;
@ -1497,12 +1501,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// Check against previous transactions
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if ( ! CheckInputs ( tx , state , view , true , scriptVerifyFlags , true ) ) {
PrecomputedTransactionData txdata ( tx ) ;
if ( ! CheckInputs ( tx , state , view , true , scriptVerifyFlags , true , txdata ) ) {
// SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we
// SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we
// need to turn both off, and compare against just turning off CLEANSTACK
// need to turn both off, and compare against just turning off CLEANSTACK
// to see if the failure is specifically due to witness validation.
// to see if the failure is specifically due to witness validation.
if ( CheckInputs ( tx , state , view , true , scriptVerifyFlags & ~ ( SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK ) , true ) & &
if ( CheckInputs ( tx , state , view , true , scriptVerifyFlags & ~ ( SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK ) , true , txdata ) & &
! CheckInputs ( tx , state , view , true , scriptVerifyFlags & ~ SCRIPT_VERIFY_CLEANSTACK , true ) ) {
! CheckInputs ( tx , state , view , true , scriptVerifyFlags & ~ SCRIPT_VERIFY_CLEANSTACK , true , txdata ) ) {
// Only the witness is wrong, so the transaction itself may be fine.
// Only the witness is wrong, so the transaction itself may be fine.
state . SetCorruptionPossible ( ) ;
state . SetCorruptionPossible ( ) ;
}
}
@ -1518,7 +1523,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// There is a similar check in CreateNewBlock() to prevent creating
// There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks, however allowing such transactions into the mempool
// invalid blocks, however allowing such transactions into the mempool
// can be exploited as a DoS attack.
// can be exploited as a DoS attack.
if ( ! CheckInputs ( tx , state , view , true , MANDATORY_SCRIPT_VERIFY_FLAGS , true ) )
if ( ! CheckInputs ( tx , state , view , true , MANDATORY_SCRIPT_VERIFY_FLAGS , true , txdata ) )
{
{
return error ( " %s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s " ,
return error ( " %s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s " ,
__func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
__func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
@ -1915,7 +1920,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
bool CScriptCheck : : operator ( ) ( ) {
bool CScriptCheck : : operator ( ) ( ) {
const CScript & scriptSig = ptxTo - > vin [ nIn ] . scriptSig ;
const CScript & scriptSig = ptxTo - > vin [ nIn ] . scriptSig ;
const CScriptWitness * witness = ( nIn < ptxTo - > wit . vtxinwit . size ( ) ) ? & ptxTo - > wit . vtxinwit [ nIn ] . scriptWitness : NULL ;
const CScriptWitness * witness = ( nIn < ptxTo - > wit . vtxinwit . size ( ) ) ? & ptxTo - > wit . vtxinwit [ nIn ] . scriptWitness : NULL ;
if ( ! VerifyScript ( scriptSig , scriptPubKey , witness , nFlags , CachingTransactionSignatureChecker ( ptxTo , nIn , amount , cacheStore ) , & error ) ) {
if ( ! VerifyScript ( scriptSig , scriptPubKey , witness , nFlags , CachingTransactionSignatureChecker ( ptxTo , nIn , amount , cacheStore , * txdata ) , & error ) ) {
return false ;
return false ;
}
}
return true ;
return true ;
@ -1974,7 +1979,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
}
}
} // namespace Consensus
} // namespace Consensus
bool CheckInputs ( const CTransaction & tx , CValidationState & state , const CCoinsViewCache & inputs , bool fScriptChecks , unsigned int flags , bool cacheStore , std : : vector < CScriptCheck > * pvChecks )
bool CheckInputs ( const CTransaction & tx , CValidationState & state , const CCoinsViewCache & inputs , bool fScriptChecks , unsigned int flags , bool cacheStore , PrecomputedTransactionData & txdata , std : : vector < CScriptCheck > * pvChecks )
{
{
if ( ! tx . IsCoinBase ( ) )
if ( ! tx . IsCoinBase ( ) )
{
{
@ -2001,7 +2006,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
assert ( coins ) ;
assert ( coins ) ;
// Verify signature
// Verify signature
CScriptCheck check ( * coins , tx , i , flags , cacheStore ) ;
CScriptCheck check ( * coins , tx , i , flags , cacheStore , & txdata ) ;
if ( pvChecks ) {
if ( pvChecks ) {
pvChecks - > push_back ( CScriptCheck ( ) ) ;
pvChecks - > push_back ( CScriptCheck ( ) ) ;
check . swap ( pvChecks - > back ( ) ) ;
check . swap ( pvChecks - > back ( ) ) ;
@ -2014,7 +2019,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// avoid splitting the network between upgraded and
// avoid splitting the network between upgraded and
// non-upgraded nodes.
// non-upgraded nodes.
CScriptCheck check2 ( * coins , tx , i ,
CScriptCheck check2 ( * coins , tx , i ,
flags & ~ STANDARD_NOT_MANDATORY_VERIFY_FLAGS , cacheStore ) ;
flags & ~ STANDARD_NOT_MANDATORY_VERIFY_FLAGS , cacheStore , & txdata ) ;
if ( check2 ( ) )
if ( check2 ( ) )
return state . Invalid ( false , REJECT_NONSTANDARD , strprintf ( " non-mandatory-script-verify-flag (%s) " , ScriptErrorString ( check . GetScriptError ( ) ) ) ) ;
return state . Invalid ( false , REJECT_NONSTANDARD , strprintf ( " non-mandatory-script-verify-flag (%s) " , ScriptErrorString ( check . GetScriptError ( ) ) ) ) ;
}
}
@ -2412,6 +2417,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
std : : vector < std : : pair < uint256 , CDiskTxPos > > vPos ;
std : : vector < std : : pair < uint256 , CDiskTxPos > > vPos ;
vPos . reserve ( block . vtx . size ( ) ) ;
vPos . reserve ( block . vtx . size ( ) ) ;
blockundo . vtxundo . reserve ( block . vtx . size ( ) - 1 ) ;
blockundo . vtxundo . reserve ( block . vtx . size ( ) - 1 ) ;
std : : vector < PrecomputedTransactionData > txdata ;
txdata . reserve ( block . vtx . size ( ) ) ; // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
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 ] ;
@ -2458,13 +2465,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state . DoS ( 100 , error ( " ConnectBlock(): too many sigops " ) ,
return state . DoS ( 100 , error ( " ConnectBlock(): too many sigops " ) ,
REJECT_INVALID , " bad-blk-sigops " ) ;
REJECT_INVALID , " bad-blk-sigops " ) ;
txdata . emplace_back ( tx ) ;
if ( ! tx . IsCoinBase ( ) )
if ( ! tx . IsCoinBase ( ) )
{
{
nFees + = view . GetValueIn ( tx ) - tx . GetValueOut ( ) ;
nFees + = view . GetValueIn ( tx ) - tx . GetValueOut ( ) ;
std : : vector < CScriptCheck > vChecks ;
std : : vector < CScriptCheck > vChecks ;
bool fCacheResults = fJustCheck ; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
bool fCacheResults = fJustCheck ; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
if ( ! CheckInputs ( tx , state , view , fScriptChecks , flags , fCacheResults , nScriptCheckThreads ? & vChecks : NULL ) )
if ( ! CheckInputs ( tx , state , view , fScriptChecks , flags , fCacheResults , txdata [ i ] , nScriptCheckThreads ? & vChecks : NULL ) )
return error ( " ConnectBlock(): CheckInputs on %s failed with %s " ,
return error ( " ConnectBlock(): CheckInputs on %s failed with %s " ,
tx . GetHash ( ) . ToString ( ) , FormatStateMessage ( state ) ) ;
tx . GetHash ( ) . ToString ( ) , FormatStateMessage ( state ) ) ;
control . Add ( vChecks ) ;
control . Add ( vChecks ) ;
@ -4647,6 +4655,7 @@ std::string GetWarnings(const std::string& strFor)
string strStatusBar ;
string strStatusBar ;
string strRPC ;
string strRPC ;
string strGUI ;
string strGUI ;
const string uiAlertSeperator = " <hr /> " ;
if ( ! CLIENT_VERSION_IS_RELEASE ) {
if ( ! CLIENT_VERSION_IS_RELEASE ) {
strStatusBar = " This is a pre-release test build - use at your own risk - do not use for mining or merchant applications " ;
strStatusBar = " This is a pre-release test build - use at your own risk - do not use for mining or merchant applications " ;
@ -4659,18 +4668,19 @@ std::string GetWarnings(const std::string& strFor)
// Misc warnings like out of disk space and clock is wrong
// Misc warnings like out of disk space and clock is wrong
if ( strMiscWarning ! = " " )
if ( strMiscWarning ! = " " )
{
{
strStatusBar = strGUI = strMiscWarning ;
strStatusBar = strMiscWarning ;
strGUI + = ( strGUI . empty ( ) ? " " : uiAlertSeperator ) + strMiscWarning ;
}
}
if ( fLargeWorkForkFound )
if ( fLargeWorkForkFound )
{
{
strStatusBar = strRPC = " Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. " ;
strStatusBar = strRPC = " Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. " ;
strGUI = _ ( " Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. " ) ;
strGUI + = strGUI . empty ( ) ? " " : uiAlertSeperator + _ ( " Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. " ) ;
}
}
else if ( fLargeWorkInvalidChainFound )
else if ( fLargeWorkInvalidChainFound )
{
{
strStatusBar = strRPC = " Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. " ;
strStatusBar = strRPC = " Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. " ;
strGUI = _ ( " Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. " ) ;
strGUI + = strGUI . empty ( ) ? " " : uiAlertSeperator + _ ( " Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. " ) ;
}
}
if ( strFor = = " gui " )
if ( strFor = = " gui " )
@ -4793,10 +4803,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
pfrom - > PushMessage ( NetMsgType : : BLOCK , block ) ;
pfrom - > PushMessage ( NetMsgType : : BLOCK , block ) ;
else if ( inv . type = = MSG_FILTERED_BLOCK )
else if ( inv . type = = MSG_FILTERED_BLOCK )
{
{
LOCK ( pfrom - > cs_filter ) ;
bool send = false ;
if ( pfrom - > pfilter )
CMerkleBlock merkleBlock ;
{
{
CMerkleBlock merkleBlock ( block , * pfrom - > pfilter ) ;
LOCK ( pfrom - > cs_filter ) ;
if ( pfrom - > pfilter ) {
send = true ;
merkleBlock = CMerkleBlock ( block , * pfrom - > pfilter ) ;
}
}
if ( send ) {
pfrom - > PushMessage ( NetMsgType : : MERKLEBLOCK , merkleBlock ) ;
pfrom - > PushMessage ( NetMsgType : : MERKLEBLOCK , merkleBlock ) ;
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
// This avoids hurting performance by pointlessly requiring a round-trip
// This avoids hurting performance by pointlessly requiring a round-trip
@ -4917,6 +4933,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if ( strCommand = = NetMsgType : : VERSION )
if ( strCommand = = NetMsgType : : VERSION )
{
{
// Feeler connections exist only to verify if address is online.
if ( pfrom - > fFeeler ) {
assert ( pfrom - > fInbound = = false ) ;
pfrom - > fDisconnect = true ;
}
// Each connection can only send one version message
// Each connection can only send one version message
if ( pfrom - > nVersion ! = 0 )
if ( pfrom - > nVersion ! = 0 )
{
{
@ -5035,12 +5057,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom - > fGetAddr = true ;
pfrom - > fGetAddr = true ;
}
}
addrman . Good ( pfrom - > addr ) ;
addrman . Good ( pfrom - > addr ) ;
} else {
if ( ( ( CNetAddr ) pfrom - > addr ) = = ( CNetAddr ) addrFrom )
{
addrman . Add ( addrFrom , addrFrom ) ;
addrman . Good ( addrFrom ) ;
}
}
}
pfrom - > fSuccessfullyConnected = true ;
pfrom - > fSuccessfullyConnected = true ;
@ -6058,8 +6074,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CBloomFilter filter ;
CBloomFilter filter ;
vRecv > > filter ;
vRecv > > filter ;
LOCK ( pfrom - > cs_filter ) ;
if ( ! filter . IsWithinSizeConstraints ( ) )
if ( ! filter . IsWithinSizeConstraints ( ) )
{
{
// There is no excuse for sending a too-large filter
// There is no excuse for sending a too-large filter
@ -6068,12 +6082,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
else
else
{
{
LOCK ( pfrom - > cs_filter ) ;
delete pfrom - > pfilter ;
delete pfrom - > pfilter ;
pfrom - > pfilter = new CBloomFilter ( filter ) ;
pfrom - > pfilter = new CBloomFilter ( filter ) ;
pfrom - > pfilter - > UpdateEmptyFull ( ) ;
pfrom - > pfilter - > UpdateEmptyFull ( ) ;
}
pfrom - > fRelayTxes = true ;
pfrom - > fRelayTxes = true ;
}
}
}
else if ( strCommand = = NetMsgType : : FILTERADD )
else if ( strCommand = = NetMsgType : : FILTERADD )
@ -6083,21 +6098,22 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Nodes must NEVER send a data item > 520 bytes (the max size for a script data object,
// Nodes must NEVER send a data item > 520 bytes (the max size for a script data object,
// and thus, the maximum size any matched object can have) in a filteradd message
// and thus, the maximum size any matched object can have) in a filteradd message
if ( vData . size ( ) > MAX_SCRIPT_ELEMENT_SIZE )
bool bad = false ;
{
if ( vData . size ( ) > MAX_SCRIPT_ELEMENT_SIZE ) {
LOCK ( cs_main ) ;
bad = true ;
Misbehaving ( pfrom - > GetId ( ) , 100 ) ;
} else {
} else {
LOCK ( pfrom - > cs_filter ) ;
LOCK ( pfrom - > cs_filter ) ;
if ( pfrom - > pfilter )
if ( pfrom - > pfilter ) {
pfrom - > pfilter - > insert ( vData ) ;
pfrom - > pfilter - > insert ( vData ) ;
else
} else {
{
bad = true ;
}
}
if ( bad ) {
LOCK ( cs_main ) ;
LOCK ( cs_main ) ;
Misbehaving ( pfrom - > GetId ( ) , 100 ) ;
Misbehaving ( pfrom - > GetId ( ) , 100 ) ;
}
}
}
}
}
else if ( strCommand = = NetMsgType : : FILTERCLEAR )
else if ( strCommand = = NetMsgType : : FILTERCLEAR )
@ -6714,16 +6730,14 @@ bool SendMessages(CNode* pto)
if ( ! pto - > fDisconnect & & ! pto - > fClient & & ( fFetch | | ! IsInitialBlockDownload ( ) ) & & state . nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER ) {
if ( ! pto - > fDisconnect & & ! pto - > fClient & & ( fFetch | | ! IsInitialBlockDownload ( ) ) & & state . nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER ) {
vector < CBlockIndex * > vToDownload ;
vector < CBlockIndex * > vToDownload ;
NodeId staller = - 1 ;
NodeId staller = - 1 ;
FindNextBlocksToDownload ( pto - > GetId ( ) , MAX_BLOCKS_IN_TRANSIT_PER_PEER - state . nBlocksInFlight , vToDownload , staller ) ;
FindNextBlocksToDownload ( pto - > GetId ( ) , MAX_BLOCKS_IN_TRANSIT_PER_PEER - state . nBlocksInFlight , vToDownload , staller , consensusParams ) ;
BOOST_FOREACH ( CBlockIndex * pindex , vToDownload ) {
BOOST_FOREACH ( CBlockIndex * pindex , vToDownload ) {
if ( State ( pto - > GetId ( ) ) - > fHaveWitness | | ! IsWitnessEnabled ( pindex - > pprev , consensusParams ) ) {
uint32_t nFetchFlags = GetFetchFlags ( pto , pindex - > pprev , consensusParams ) ;
uint32_t nFetchFlags = GetFetchFlags ( pto , pindex - > pprev , consensusParams ) ;
vGetData . push_back ( CInv ( MSG_BLOCK | nFetchFlags , pindex - > GetBlockHash ( ) ) ) ;
vGetData . push_back ( CInv ( MSG_BLOCK | nFetchFlags , pindex - > GetBlockHash ( ) ) ) ;
MarkBlockAsInFlight ( pto - > GetId ( ) , pindex - > GetBlockHash ( ) , consensusParams , pindex ) ;
MarkBlockAsInFlight ( pto - > GetId ( ) , pindex - > GetBlockHash ( ) , consensusParams , pindex ) ;
LogPrint ( " net " , " Requesting block %s (%d) peer=%d \n " , pindex - > GetBlockHash ( ) . ToString ( ) ,
LogPrint ( " net " , " Requesting block %s (%d) peer=%d \n " , pindex - > GetBlockHash ( ) . ToString ( ) ,
pindex - > nHeight , pto - > id ) ;
pindex - > nHeight , pto - > id ) ;
}
}
}
if ( state . nBlocksInFlight = = 0 & & staller ! = - 1 ) {
if ( state . nBlocksInFlight = = 0 & & staller ! = - 1 ) {
if ( State ( staller ) - > nStallingSince = = 0 ) {
if ( State ( staller ) - > nStallingSince = = 0 ) {
State ( staller ) - > nStallingSince = nNow ;
State ( staller ) - > nStallingSince = nNow ;