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:
commit
3dc3149e63
6 changed files with 16 additions and 78 deletions
18
src/net.cpp
18
src/net.cpp
|
@ -899,8 +899,6 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
|
||||||
continue;
|
continue;
|
||||||
if (node->fDisconnect)
|
if (node->fDisconnect)
|
||||||
continue;
|
continue;
|
||||||
if (node->addr.IsLocal())
|
|
||||||
continue;
|
|
||||||
vEvictionCandidates.push_back(CNodeRef(node));
|
vEvictionCandidates.push_back(CNodeRef(node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -931,15 +929,20 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
|
||||||
|
|
||||||
if (vEvictionCandidates.empty()) return false;
|
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;
|
std::vector<unsigned char> naMostConnections;
|
||||||
unsigned int nMostConnections = 0;
|
unsigned int nMostConnections = 0;
|
||||||
|
int64_t nMostConnectionsTime = 0;
|
||||||
std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
|
std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
|
||||||
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
|
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
|
||||||
mapAddrCounts[node->addr.GetGroup()].push_back(node);
|
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) {
|
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
|
||||||
nMostConnections = mapAddrCounts[node->addr.GetGroup()].size();
|
nMostConnections = groupsize;
|
||||||
|
nMostConnectionsTime = grouptime;
|
||||||
naMostConnections = node->addr.GetGroup();
|
naMostConnections = node->addr.GetGroup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -947,14 +950,13 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
|
||||||
// Reduce to the network group with the most connections
|
// Reduce to the network group with the most connections
|
||||||
vEvictionCandidates = mapAddrCounts[naMostConnections];
|
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)
|
if (vEvictionCandidates.size() <= 1)
|
||||||
// unless we prefer the new connection (for whitelisted peers)
|
// unless we prefer the new connection (for whitelisted peers)
|
||||||
if (!fPreferNewConnection)
|
if (!fPreferNewConnection)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Disconnect the most recent connection from the network group with the most connections
|
// Disconnect from the network group with the most connections
|
||||||
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
|
|
||||||
vEvictionCandidates[0]->fDisconnect = true;
|
vEvictionCandidates[0]->fDisconnect = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -132,45 +132,20 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||||
const CScript& prevScript = prev.scriptPubKey;
|
const CScript& prevScript = prev.scriptPubKey;
|
||||||
if (!Solver(prevScript, whichType, vSolutions))
|
if (!Solver(prevScript, whichType, vSolutions))
|
||||||
return false;
|
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)
|
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())
|
if (stack.empty())
|
||||||
return false;
|
return false;
|
||||||
CScript subscript(stack.back().begin(), stack.back().end());
|
CScript subscript(stack.back().begin(), stack.back().end());
|
||||||
std::vector<std::vector<unsigned char> > vSolutions2;
|
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
|
||||||
txnouttype whichType2;
|
return false;
|
||||||
if (Solver(subscript, whichType2, vSolutions2))
|
|
||||||
{
|
|
||||||
int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2);
|
|
||||||
if (tmpExpected < 0)
|
|
||||||
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;
|
return true;
|
||||||
|
|
|
@ -161,27 +161,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
|
||||||
return false;
|
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)
|
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
|
||||||
{
|
{
|
||||||
vector<valtype> vSolutions;
|
vector<valtype> vSolutions;
|
||||||
|
|
|
@ -71,7 +71,6 @@ typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
|
||||||
const char* GetTxnOutputType(txnouttype t);
|
const char* GetTxnOutputType(txnouttype t);
|
||||||
|
|
||||||
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
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 ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
|
||||||
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
|
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
|
||||||
|
|
||||||
|
|
|
@ -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]
|
// 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);
|
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;
|
CMutableTransaction txToNonStd1;
|
||||||
txToNonStd1.vout.resize(1);
|
txToNonStd1.vout.resize(1);
|
||||||
txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
|
txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
|
||||||
|
|
|
@ -310,14 +310,6 @@ BOOST_AUTO_TEST_CASE(test_Get)
|
||||||
|
|
||||||
BOOST_CHECK(AreInputsStandard(t1, coins));
|
BOOST_CHECK(AreInputsStandard(t1, coins));
|
||||||
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
|
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)
|
BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||||
|
|
Loading…
Reference in a new issue