return true;
}
-bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) {
- if (!(flags & SCRIPT_VERIFY_STRICTENC))
- return true;
-
+bool IsDERSignature(const valtype &vchSig, bool fWithHashType, bool fCheckLow) {
// See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
// A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
// Where R and S are not negative (their first byte has its highest bit not set), and not
return error("Non-canonical signature: too short");
if (vchSig.size() > 73)
return error("Non-canonical signature: too long");
- unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
- if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
- return error("Non-canonical signature: unknown hashtype byte");
if (vchSig[0] != 0x30)
return error("Non-canonical signature: wrong type");
- if (vchSig[1] != vchSig.size()-3)
+ if (vchSig[1] != vchSig.size() - (fWithHashType ? 3 : 2))
return error("Non-canonical signature: wrong length marker");
+ if (fWithHashType) {
+ unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
+ if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
+ return error("Non-canonical signature: unknown hashtype byte");
+ }
unsigned int nLenR = vchSig[3];
if (5 + nLenR >= vchSig.size())
return error("Non-canonical signature: S length misplaced");
unsigned int nLenS = vchSig[5+nLenR];
- if ((unsigned long)(nLenR+nLenS+7) != vchSig.size())
+ if ((unsigned long)(nLenR + nLenS + (fWithHashType ? 7 : 6)) != vchSig.size())
return error("Non-canonical signature: R+S length mismatch");
const unsigned char *R = &vchSig[4];
if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80))
return error("Non-canonical signature: S value excessively padded");
- if (flags & SCRIPT_VERIFY_LOW_S) {
+ if (fCheckLow) {
+ unsigned int nLenR = vchSig[3];
+ unsigned int nLenS = vchSig[5+nLenR];
+ const unsigned char *S = &vchSig[6+nLenR];
+ // If the S value is above the order of the curve divided by two, its
+ // complement modulo the order could have been used instead, which is
+ // one byte shorter when encoded correctly.
if (!CKey::CheckSignatureElement(S, nLenS, true))
return error("Non-canonical signature: S value is unnecessarily high");
}
return true;
}
+bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) {
+ if (!(flags & SCRIPT_VERIFY_STRICTENC))
+ return true;
+
+ return IsDERSignature(vchSig, true, (flags & SCRIPT_VERIFY_LOW_S) != 0);
+}
+
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType)
{
CAutoBN_CTX pctx;
case OP_DEPTH:
{
// -- stacksize
- CBigNum bn(stack.size());
+ CBigNum bn((uint16_t) stack.size());
stack.push_back(bn.getvch());
}
break;
// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
if (stack.size() < 2)
return false;
- int n = CastToBigNum(stacktop(-1)).getint();
+ int n = CastToBigNum(stacktop(-1)).getint32();
popstack(stack);
if (n < 0 || n >= (int)stack.size())
return false;
// (in -- in size)
if (stack.size() < 1)
return false;
- CBigNum bn(stacktop(-1).size());
+ CBigNum bn((uint16_t) stacktop(-1).size());
stack.push_back(bn.getvch());
}
break;
if ((int)stack.size() < i)
return false;
- int nKeysCount = CastToBigNum(stacktop(-i)).getint();
+ int nKeysCount = CastToBigNum(stacktop(-i)).getint32();
if (nKeysCount < 0 || nKeysCount > 20)
return false;
nOpCount += nKeysCount;
if ((int)stack.size() < i)
return false;
- int nSigsCount = CastToBigNum(stacktop(-i)).getint();
+ int nSigsCount = CastToBigNum(stacktop(-i)).getint32();
if (nSigsCount < 0 || nSigsCount > nKeysCount)
return false;
int isig = ++i;
// (~200 bytes per cache entry times 50,000 entries)
// Since there are a maximum of 20,000 signature operations per block
// 50,000 is a reasonable default.
- int64 nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
+ int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
if (nMaxCacheSize <= 0) return;
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
- while (static_cast<int64>(setValid.size()) > nMaxCacheSize)
+ while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize)
{
// Evict a random entry. Random because that helps
// foil would-be DoS attackers who might try to pre-generate
bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); }
};
-bool IsMine(const CKeyStore &keystore, const CTxDestination &dest)
+isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
{
- return boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest);
+ CScript script;
+ script.SetDestination(dest);
+ return IsMine(keystore, script);
}
-bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
+isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
{
vector<valtype> vSolutions;
txnouttype whichType;
- if (!Solver(scriptPubKey, whichType, vSolutions))
- return false;
+ if (!Solver(scriptPubKey, whichType, vSolutions)) {
+ if (keystore.HaveWatchOnly(scriptPubKey))
+ return MINE_WATCH_ONLY;
+ return MINE_NO;
+ }
CKeyID keyID;
switch (whichType)
{
case TX_NONSTANDARD:
case TX_NULL_DATA:
- return false;
+ break;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
- return keystore.HaveKey(keyID);
+ if (keystore.HaveKey(keyID))
+ return MINE_SPENDABLE;
+ break;
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
- return keystore.HaveKey(keyID);
+ if (keystore.HaveKey(keyID))
+ return MINE_SPENDABLE;
+ break;
case TX_SCRIPTHASH:
{
+ CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
CScript subscript;
- if (!keystore.GetCScript(CScriptID(uint160(vSolutions[0])), subscript))
- return false;
- return IsMine(keystore, subscript);
+ if (keystore.GetCScript(scriptID, subscript)) {
+ isminetype ret = IsMine(keystore, subscript);
+ if (ret == MINE_SPENDABLE)
+ return ret;
+ }
+ break;
}
case TX_MULTISIG:
{
// them) enable spend-out-from-under-you attacks, especially
// in shared-wallet situations.
vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
- return HaveKeys(keys, keystore) == keys.size();
+ if (HaveKeys(keys, keystore) == keys.size())
+ return MINE_SPENDABLE;
+ break;
}
}
- return false;
+
+ if (keystore.HaveWatchOnly(scriptPubKey))
+ return MINE_WATCH_ONLY;
+ return MINE_NO;
}
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
class CAffectedKeysVisitor : public boost::static_visitor<void> {
private:
const CKeyStore &keystore;
+ CAffectedKeysVisitor& operator=(CAffectedKeysVisitor const&);
std::vector<CKeyID> &vKeys;
public:
}
// Test solution
- return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0);
+ return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STRICT_FLAGS, 0);
}
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType)
// Build a map of pubkey -> signature by matching sigs to pubkeys:
assert(vSolutions.size() > 1);
unsigned int nSigsRequired = vSolutions.front()[0];
- unsigned int nPubKeys = vSolutions.size()-2;
+ unsigned int nPubKeys = (unsigned int)(vSolutions.size()-2);
map<valtype, valtype> sigs;
BOOST_FOREACH(const valtype& sig, allsigs)
{
*this << EncodeOP_N(nRequired);
BOOST_FOREACH(const CKey& key, keys)
*this << key.GetPubKey();
- *this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
+ *this << EncodeOP_N((int)(keys.size())) << OP_CHECKMULTISIG;
}