// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2011 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
case OP_ABS: if (bn < bnZero) bn = -bn; break;
case OP_NOT: bn = (bn == bnZero); break;
case OP_0NOTEQUAL: bn = (bn != bnZero); break;
+ default: assert(!"invalid opcode"); break;
}
popstack(stack);
stack.push_back(bn.getvch());
case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break;
case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break;
+ default: assert(!"invalid opcode"); break;
}
popstack(stack);
popstack(stack);
}
-bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
+bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
{
scriptSigRet.clear();
return false;
// Compile solution
- CRITICAL_BLOCK(cs_mapKeys)
+ CRITICAL_BLOCK(keystore.cs_KeyStore)
{
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
{
// Sign
const valtype& vchPubKey = item.second;
- if (!mapKeys.count(vchPubKey))
+ CKey key;
+ if (!keystore.GetKey(Hash160(vchPubKey), key))
+ return false;
+ if (key.GetPubKey() != vchPubKey)
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
- if (!CKey::Sign(mapKeys[vchPubKey], hash, 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
- map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
- if (mi == mapPubKeys.end())
- return false;
- const vector<unsigned char>& vchPubKey = (*mi).second;
- if (!mapKeys.count(vchPubKey))
+ CKey key;
+ if (!keystore.GetKey(uint160(item.second), key))
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
- if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
+ if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
- scriptSigRet << vchSig << vchPubKey;
+ scriptSigRet << vchSig << key.GetPubKey();
}
}
else
}
-bool IsMine(const CScript& scriptPubKey)
-{
- CScript scriptSig;
- return Solver(scriptPubKey, 0, 0, scriptSig);
-}
-
-
-bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet)
+bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
{
- vchPubKeyRet.clear();
-
vector<pair<opcodetype, valtype> > vSolution;
if (!Solver(scriptPubKey, vSolution))
return false;
- CRITICAL_BLOCK(cs_mapKeys)
+ // Compile solution
+ CRITICAL_BLOCK(keystore.cs_KeyStore)
{
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
- valtype vchPubKey;
if (item.first == OP_PUBKEY)
{
- vchPubKey = item.second;
+ 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)
{
- map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
- if (mi == mapPubKeys.end())
- continue;
- vchPubKey = (*mi).second;
+ if (!keystore.HaveKey(uint160(item.second)))
+ return false;
}
- if (!fMineOnly || mapKeys.count(vchPubKey))
+ else
{
- vchPubKeyRet = vchPubKey;
- return true;
+ return false;
}
}
}
- return false;
-}
+ return true;
+}
-bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret)
+// requires either keystore==0, or a lock on keystore->cs_KeyStore
+bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
{
- hash160Ret = 0;
-
vector<pair<opcodetype, valtype> > vSolution;
if (!Solver(scriptPubKey, vSolution))
return false;
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
- if (item.first == OP_PUBKEYHASH)
- {
- hash160Ret = uint160(item.second);
+ if (item.first == OP_PUBKEY)
+ addressRet.SetPubKey(item.second);
+ else if (item.first == OP_PUBKEYHASH)
+ addressRet.SetHash160((uint160)item.second);
+ if (keystore == NULL || keystore->HaveKey(addressRet))
return true;
- }
}
+
+ return false;
+}
+
+
+bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
+{
+ if (keystore)
+ CRITICAL_BLOCK(keystore->cs_KeyStore)
+ return ExtractAddressInner(scriptPubKey, keystore, addressRet);
+ else
+ return ExtractAddressInner(scriptPubKey, NULL, addressRet);
return false;
}
}
-bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
+bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
// The checksig op will also drop the signatures from its hash.
uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType);
- if (!Solver(txout.scriptPubKey, hash, nHashType, txin.scriptSig))
+ if (!Solver(keystore, txout.scriptPubKey, hash, nHashType, txin.scriptSig))
return false;
txin.scriptSig = scriptPrereq + txin.scriptSig;
if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType))
return false;
- // Anytime a signature is successfully verified, it's proof the outpoint is spent,
- // so lets update the wallet spent flag if it doesn't know due to wallet.dat being
- // restored from backup or the user making copies of wallet.dat.
- WalletUpdateSpent(txin.prevout);
-
return true;
}