Fix rpc-hanging deadlocks

Collapsed multiple wallet mutexes to a single cs_wallet, to avoid deadlocks with wallet methods that acquired locks in different order.
Also change master RPC call handler to acquire cs_main and cs_wallet locks before executing RPC calls; requiring each RPC call to acquire the right set of locks in the right order was too error-prone.
This commit is contained in:
Gavin Andresen
2011-08-26 14:37:23 -04:00
parent b0243da77c
commit 6cc4a62c0e
9 changed files with 481 additions and 570 deletions

View File

@@ -1033,48 +1033,45 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
return false;
// Compile solution
CRITICAL_BLOCK(keystore.cs_KeyStore)
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
if (item.first == OP_PUBKEY)
{
if (item.first == OP_PUBKEY)
{
// Sign
const valtype& vchPubKey = item.second;
CKey key;
if (!keystore.GetKey(Hash160(vchPubKey), key))
return false;
if (key.GetPubKey() != vchPubKey)
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig;
}
}
else if (item.first == OP_PUBKEYHASH)
{
// Sign and give pubkey
CKey key;
if (!keystore.GetKey(uint160(item.second), key))
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig << key.GetPubKey();
}
}
else
{
// Sign
const valtype& vchPubKey = item.second;
CKey key;
if (!keystore.GetKey(Hash160(vchPubKey), key))
return false;
if (key.GetPubKey() != vchPubKey)
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig;
}
}
else if (item.first == OP_PUBKEYHASH)
{
// Sign and give pubkey
CKey key;
if (!keystore.GetKey(uint160(item.second), key))
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig << key.GetPubKey();
}
}
else
{
return false;
}
}
return true;
@@ -1095,35 +1092,31 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
return false;
// Compile solution
CRITICAL_BLOCK(keystore.cs_KeyStore)
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
if (item.first == OP_PUBKEY)
{
if (item.first == OP_PUBKEY)
{
const valtype& vchPubKey = item.second;
vector<unsigned char> vchPubKeyFound;
if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
return false;
if (vchPubKeyFound != vchPubKey)
return false;
}
else if (item.first == OP_PUBKEYHASH)
{
if (!keystore.HaveKey(uint160(item.second)))
return false;
}
else
{
const valtype& vchPubKey = item.second;
vector<unsigned char> vchPubKeyFound;
if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
return false;
}
if (vchPubKeyFound != vchPubKey)
return false;
}
else if (item.first == OP_PUBKEYHASH)
{
if (!keystore.HaveKey(uint160(item.second)))
return false;
}
else
{
return false;
}
}
return true;
}
// requires either keystore==0, or a lock on keystore->cs_KeyStore
bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
{
vector<pair<opcodetype, valtype> > vSolution;
@@ -1146,8 +1139,7 @@ bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* ke
bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
{
if (keystore)
CRITICAL_BLOCK(keystore->cs_KeyStore)
return ExtractAddressInner(scriptPubKey, keystore, addressRet);
return ExtractAddressInner(scriptPubKey, keystore, addressRet);
else
return ExtractAddressInner(scriptPubKey, NULL, addressRet);
return false;