Merge #7453: [0.13] Missing patches from 0.12

1e05727 Decide eviction group ties based on time. (Gregory Maxwell)
1e9613a Do not absolutely protect local peers from eviction. (Gregory Maxwell)
5d74309 Get rid of inaccurate ScriptSigArgsExpected (Pieter Wuille)
This commit is contained in:
Wladimir J. van der Laan 2016-02-02 12:53:57 +01:00
commit 3dc3149e63
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
6 changed files with 16 additions and 78 deletions

View File

@ -899,8 +899,6 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
continue;
if (node->fDisconnect)
continue;
if (node->addr.IsLocal())
continue;
vEvictionCandidates.push_back(CNodeRef(node));
}
}
@ -931,15 +929,20 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
if (vEvictionCandidates.empty()) return false;
// Identify the network group with the most connections
// Identify the network group with the most connections and youngest member.
// (vEvictionCandidates is already sorted by reverse connect time)
std::vector<unsigned char> naMostConnections;
unsigned int nMostConnections = 0;
int64_t nMostConnectionsTime = 0;
std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
mapAddrCounts[node->addr.GetGroup()].push_back(node);
int64_t grouptime = mapAddrCounts[node->addr.GetGroup()][0]->nTimeConnected;
size_t groupsize = mapAddrCounts[node->addr.GetGroup()].size();
if (mapAddrCounts[node->addr.GetGroup()].size() > nMostConnections) {
nMostConnections = mapAddrCounts[node->addr.GetGroup()].size();
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
nMostConnections = groupsize;
nMostConnectionsTime = grouptime;
naMostConnections = node->addr.GetGroup();
}
}
@ -947,14 +950,13 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
// Reduce to the network group with the most connections
vEvictionCandidates = mapAddrCounts[naMostConnections];
// Do not disconnect peers if there is only 1 connection from their network group
// Do not disconnect peers if there is only one unprotected connection from their network group.
if (vEvictionCandidates.size() <= 1)
// unless we prefer the new connection (for whitelisted peers)
if (!fPreferNewConnection)
return false;
// Disconnect the most recent connection from the network group with the most connections
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
// Disconnect from the network group with the most connections
vEvictionCandidates[0]->fDisconnect = true;
return true;

View File

@ -132,45 +132,20 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
const CScript& prevScript = prev.scriptPubKey;
if (!Solver(prevScript, whichType, vSolutions))
return false;
int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
if (nArgsExpected < 0)
return false;
// Transactions with extra stuff in their scriptSigs are
// non-standard. Note that this EvalScript() call will
// be quick, because if there are any operations
// beside "push data" in the scriptSig
// IsStandardTx() will have already returned false
// and this method isn't called.
std::vector<std::vector<unsigned char> > stack;
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
return false;
if (whichType == TX_SCRIPTHASH)
{
std::vector<std::vector<unsigned char> > stack;
// convert the scriptSig into a stack, so we can inspect the redeemScript
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
return false;
if (stack.empty())
return false;
CScript subscript(stack.back().begin(), stack.back().end());
std::vector<std::vector<unsigned char> > vSolutions2;
txnouttype whichType2;
if (Solver(subscript, whichType2, vSolutions2))
{
int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2);
if (tmpExpected < 0)
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
return false;
nArgsExpected += tmpExpected;
}
else
{
// Any other Script with less than 15 sigops OK:
unsigned int sigops = subscript.GetSigOpCount(true);
// ... extra data left on the stack after execution is OK, too:
return (sigops <= MAX_P2SH_SIGOPS);
}
}
if (stack.size() != (unsigned int)nArgsExpected)
return false;
}
return true;

View File

@ -161,27 +161,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
return false;
}
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
{
switch (t)
{
case TX_NONSTANDARD:
case TX_NULL_DATA:
return -1;
case TX_PUBKEY:
return 1;
case TX_PUBKEYHASH:
return 2;
case TX_MULTISIG:
if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
return -1;
return vSolutions[0][0] + 1;
case TX_SCRIPTHASH:
return 1; // doesn't include args needed by the script
}
return -1;
}
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
vector<valtype> vSolutions;

View File

@ -71,7 +71,6 @@ typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
const char* GetTxnOutputType(txnouttype t);
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);

View File

@ -346,15 +346,6 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
// 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U);
// Make sure adding crap to the scriptSigs makes them non-standard:
for (int i = 0; i < 3; i++)
{
CScript t = txTo.vin[i].scriptSig;
txTo.vin[i].scriptSig = (CScript() << 11) + t;
BOOST_CHECK(!::AreInputsStandard(txTo, coins));
txTo.vin[i].scriptSig = t;
}
CMutableTransaction txToNonStd1;
txToNonStd1.vout.resize(1);
txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());

View File

@ -310,14 +310,6 @@ BOOST_AUTO_TEST_CASE(test_Get)
BOOST_CHECK(AreInputsStandard(t1, coins));
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
// Adding extra junk to the scriptSig should make it non-standard:
t1.vin[0].scriptSig << OP_11;
BOOST_CHECK(!AreInputsStandard(t1, coins));
// ... as should not having enough:
t1.vin[0].scriptSig = CScript();
BOOST_CHECK(!AreInputsStandard(t1, coins));
}
BOOST_AUTO_TEST_CASE(test_IsStandard)