// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <boost/tuple/tuple.hpp>
-
-using namespace std;
-using namespace boost;
#include "script.h"
#include "keystore.h"
#include "sync.h"
#include "util.h"
+using namespace std;
+
bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
static const valtype vchFalse(0);
}
-
//
// Script is a stack machine (like Forth) that evaluates a predicate
// returning a bool indicating valid or not. There are no loops.
//
#define stacktop(i) (stack.at(stack.size()+(i)))
+
+//static inline valtype stacktop(vector<valtype>& st, int nDepth)
+//{
+// return st.at(st.size()+nDepth);
+//}
+
#define altstacktop(i) (altstack.at(altstack.size()+(i)))
+
static inline void popstack(vector<valtype>& stack)
{
if (stack.empty())
return true;
}
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType)
+bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, uint32_t nIn, unsigned int flags, int nHashType)
{
CAutoBN_CTX pctx;
auto pc = script.begin();
opcode == OP_RSHIFT)
return false; // Disabled opcodes.
- if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4)
+ if (fExec && opcode <= OP_PUSHDATA4)
stack.push_back(vchPushValue);
else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
switch (opcode)
case OP_16:
{
// ( -- value)
- CBigNum bn((int)opcode - (int)(OP_1 - 1));
+ CBigNum bn(opcode - (OP_1 - 1));
stack.push_back(bn.getvch());
}
break;
// (x1 x2 x3 x4 -- x3 x4 x1 x2)
if (stack.size() < 4)
return false;
- swap(stacktop(-4), stacktop(-2));
- swap(stacktop(-3), stacktop(-1));
+ swap(*(stack.end()-4),*(stack.end()-2));
+ swap(*(stack.end()-3),*(stack.end()-1));
}
break;
// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
if (stack.size() < 2)
return false;
- int n = CastToBigNum(stacktop(-1)).getint32();
+ int n = CastToBigNum(stack.back()).getint32();
popstack(stack);
if (n < 0 || n >= (int)stack.size())
return false;
// x2 x3 x1 after second swap
if (stack.size() < 3)
return false;
- swap(stacktop(-3), stacktop(-2));
- swap(stacktop(-2), stacktop(-1));
+ swap(*(stack.end()-3), *(stack.end()-2));
+ swap(*(stack.end()-2), *(stack.end()-1));
}
break;
// (x1 x2 -- x2 x1)
if (stack.size() < 2)
return false;
- swap(stacktop(-2), stacktop(-1));
+ swap(*(stack.end()-2),*(stack.end()-1));
}
break;
// (in -- in size)
if (stack.size() < 1)
return false;
- CBigNum bn((uint16_t) stacktop(-1).size());
+ CBigNum bn((uint16_t) (stack.back()).size());
stack.push_back(bn.getvch());
}
break;
-uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, uint32_t nIn, int nHashType)
{
if (nIn >= txTo.vin.size())
{
- printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ printf("ERROR: SignatureHash() : nIn=%" PRIu32 " out of range\n", nIn);
return 1;
}
CTransaction txTmp(txTo);
else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
{
// Only lock-in the txout payee at same index as txin
- unsigned int nOut = nIn;
+ uint32_t nOut = nIn;
if (nOut >= txTmp.vout.size())
{
- printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
+ printf("ERROR: SignatureHash() : nOut=%" PRIu32 " out of range\n", nOut);
return 1;
}
txTmp.vout.resize(nOut+1);
{
private:
// sigdata_type is (signature hash, signature, public key):
- typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey > sigdata_type;
- std::set< sigdata_type> setValid;
+ typedef tuple<uint256, vector<unsigned char>, CPubKey > sigdata_type;
+ set< sigdata_type> setValid;
boost::shared_mutex cs_sigcache;
public:
bool
- Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
+ Get(const uint256 &hash, const vector<unsigned char>& vchSig, const CPubKey& pubKey)
{
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
sigdata_type k(hash, vchSig, pubKey);
- std::set<sigdata_type>::iterator mi = setValid.find(k);
+ auto mi = setValid.find(k);
if (mi != setValid.end())
return true;
return false;
}
- void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
+ void Set(const uint256 &hash, const vector<unsigned char>& vchSig, const CPubKey& pubKey)
{
// DoS prevention: limit cache size to less than 10MB
// (~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_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
+ size_t nMaxCacheSize = GetArgUInt("-maxsigcachesize", 50000u);
if (nMaxCacheSize <= 0) return;
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
- while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize)
+ while (setValid.size() > nMaxCacheSize)
{
// Evict a random entry. Random because that helps
// foil would-be DoS attackers who might try to pre-generate
// and re-use a set of valid signatures just-slightly-greater
// than our cache size.
auto randomHash = GetRandHash();
- std::vector<unsigned char> unused;
- std::set<sigdata_type>::iterator it =
- setValid.lower_bound(sigdata_type(randomHash, unused, unused));
+ vector<unsigned char> unused;
+ auto it = setValid.lower_bound(sigdata_type(randomHash, unused, unused));
if (it == setValid.end())
it = setValid.begin();
setValid.erase(*it);
if (mTemplates.empty())
{
// Standard tx, sender provides pubkey, receiver adds signature
- mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
+ mTemplates.insert({ TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG });
// Malleable pubkey tx hack, sender provides generated pubkey combined with R parameter. The R parameter is dropped before checking a signature.
- mTemplates.insert(make_pair(TX_PUBKEY_DROP, CScript() << OP_PUBKEY << OP_PUBKEY << OP_DROP << OP_CHECKSIG));
+ mTemplates.insert({ TX_PUBKEY_DROP, CScript() << OP_PUBKEY << OP_PUBKEY << OP_DROP << OP_CHECKSIG });
// Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
- mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
+ mTemplates.insert({ TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG });
// Sender provides N pubkeys, receivers provides M signatures
- mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
+ mTemplates.insert({ TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG });
// Empty, provably prunable, data-carrying output
- mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA));
+ mTemplates.insert({ TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA });
}
vSolutionsRet.clear();
}
// Scan templates
- const CScript& script1 = scriptPubKey;
+ const auto& script1 = scriptPubKey;
for(const auto& tplate : mTemplates)
{
- const CScript& script2 = tplate.second;
+ const auto& script2 = tplate.second;
vSolutionsRet.clear();
opcodetype opcode1, opcode2;
if (typeRet == TX_MULTISIG)
{
// Additional checks for TX_MULTISIG:
- unsigned char m = vSolutionsRet.front()[0];
- unsigned char n = vSolutionsRet.back()[0];
+ auto m = vSolutionsRet.front()[0];
+ auto n = vSolutionsRet.back()[0];
if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
return false;
}
{
int nSigned = 0;
int nRequired = multisigdata.front()[0];
- for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
+ for (uint32_t i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
{
- const valtype& pubkey = multisigdata[i];
+ const auto& pubkey = multisigdata[i];
auto keyID = CPubKey(pubkey).GetID();
if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
++nSigned;
return false;
}
-int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
+int ScriptSigArgsExpected(txnouttype t, const vector<vector<unsigned char> >& vSolutions)
{
switch (t)
{
unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
{
- unsigned int nResult = 0;
- for(const valtype& pubkey : pubkeys)
+ uint32_t nResult = 0;
+ for(const auto& pubkey : pubkeys)
{
auto keyID = CPubKey(pubkey).GetID();
if (keystore.HaveKey(keyID))
bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); }
};
-/*
-isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
-{
- CScript script;
- script.SetDestination(dest);
- return IsMine(keystore, script);
-}*/
-
isminetype IsMine(const CKeyStore &keystore, const CBitcoinAddress& dest)
{
CScript script;
private:
const CKeyStore &keystore;
CAffectedKeysVisitor& operator=(CAffectedKeysVisitor const&);
- std::vector<CKeyID> &vKeys;
+ vector<CKeyID> &vKeys;
public:
- CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
+ CAffectedKeysVisitor(const CKeyStore &keystoreIn, vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
void Process(const CScript &script) {
txnouttype type;
- std::vector<CTxDestination> vDest;
+ vector<CTxDestination> vDest;
int nRequired;
if (ExtractDestinations(script, type, vDest, nRequired)) {
for(const CTxDestination &dest : vDest)
};
-void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys) {
+void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, vector<CKeyID> &vKeys) {
CAffectedKeysVisitor(keystore, vKeys).Process(scriptPubKey);
}
return true;
}
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
- unsigned int flags, int nHashType)
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, uint32_t nIn, unsigned int flags, int nHashType)
{
vector<vector<unsigned char> > stack, stackCopy;
if (!EvalScript(stack, scriptSig, txTo, nIn, flags, nHashType))
// an empty stack and the EvalScript above would return false.
assert(!stackCopy.empty());
- const valtype& pubKeySerialized = stackCopy.back();
+ const auto& pubKeySerialized = stackCopy.back();
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stackCopy);
return true;
}
-bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType)
+bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, uint32_t nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
auto& txin = txTo.vin[nIn];
auto hash2 = SignatureHash(subscript, txTo, nIn, nHashType);
txnouttype subType;
- bool fSolved =
- Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH;
+ bool fSolved = Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH;
// Append serialized subscript whether or not it is completely signed:
txin.scriptSig << static_cast<valtype>(subscript);
if (!fSolved) return false;
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)
+bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, uint32_t nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
auto& txin = txTo.vin[nIn];
assert(txin.prevout.n < txFrom.vout.size());
assert(txin.prevout.hash == txFrom.GetHash());
- const CTxOut& txout = txFrom.vout[txin.prevout.n];
+ const auto& txout = txFrom.vout[txin.prevout.n];
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType);
}
static CScript PushAll(const vector<valtype>& values)
{
CScript result;
- for(const valtype& v : values)
+ for(const auto& v : values)
result << v;
return result;
}
{
// Combine all the signatures we've got:
set<valtype> allsigs;
- for(const valtype& v : sigs1)
+ for(const auto& v : sigs1)
{
if (!v.empty())
allsigs.insert(v);
}
- for(const valtype& v : sigs2)
+ for(const auto& v : sigs2)
{
if (!v.empty())
allsigs.insert(v);
// Build a map of pubkey -> signature by matching sigs to pubkeys:
assert(vSolutions.size() > 1);
- unsigned int nSigsRequired = vSolutions.front()[0];
- unsigned int nPubKeys = (unsigned int)(vSolutions.size()-2);
+ auto nSigsRequired = (uint32_t)vSolutions.front()[0];
+ auto nPubKeys = (uint32_t)(vSolutions.size()-2);
+
map<valtype, valtype> sigs;
- for(const valtype& sig : allsigs)
+ for(const auto& sig : allsigs)
{
for (unsigned int i = 0; i < nPubKeys; i++)
{
- const valtype& pubkey = vSolutions[i+1];
+ const auto& pubkey = vSolutions[i+1];
if (sigs.count(pubkey))
continue; // Already got a sig for this pubkey
}
}
// Now build a merged CScript:
- unsigned int nSigsHave = 0;
+ uint32_t nSigsHave = 0;
CScript result; result << OP_0; // pop-one-too-many workaround
- for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
+ for (uint32_t i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
{
if (sigs.count(vSolutions[i+1]))
{
}
}
// Fill any missing with OP_0:
- for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
+ for (auto i = nSigsHave; i < nSigsRequired; i++)
result << OP_0;
return result;
return CScript();
}
-CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, uint32_t nIn,
const CScript& scriptSig1, const CScript& scriptSig2)
{
txnouttype txType;
return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2);
}
+//
+//CScript
+//
+
+CScript& CScript::push_int64(int64_t n)
+{
+ if (n == -1 || (n >= 1 && n <= 16))
+ {
+ push_back((uint8_t)n + (OP_1 - 1));
+ }
+ else
+ {
+ CBigNum bn(n);
+ *this << bn.getvch();
+ }
+ return *this;
+}
+
+CScript& CScript::push_uint64(uint64_t n)
+{
+ if (n >= 1 && n <= 16)
+ {
+ push_back((uint8_t)n + (OP_1 - 1));
+ }
+ else
+ {
+ CBigNum bn(n);
+ *this << bn.getvch();
+ }
+ return *this;
+}
+
+CScript& CScript::operator+=(const CScript& b)
+{
+ insert(end(), b.begin(), b.end());
+ return *this;
+}
+
+CScript& CScript::operator<<(opcodetype opcode)
+{
+ insert(end(), opcode);
+ return *this;
+}
+
+CScript& CScript::operator<<(const uint160& b)
+{
+ insert(end(), sizeof(b));
+ insert(end(), (uint8_t*)&b, (uint8_t*)&b + sizeof(b));
+ return *this;
+}
+
+CScript& CScript::operator<<(const uint256& b)
+{
+ insert(end(), sizeof(b));
+ insert(end(), (uint8_t*)&b, (uint8_t*)&b + sizeof(b));
+ return *this;
+}
+
+CScript& CScript::operator<<(const CPubKey& key)
+{
+ vector<uint8_t> vchKey(key.begin(), key.end());
+ return (*this) << vchKey;
+}
+
+CScript& CScript::operator<<(const CBigNum& b)
+{
+ *this << b.getvch();
+ return *this;
+}
+
+CScript& CScript::operator<<(const vector<uint8_t>& b)
+{
+ if (b.size() < OP_PUSHDATA1)
+ {
+ insert(end(), (uint8_t)b.size());
+ }
+ else if (b.size() <= 0xff)
+ {
+ insert(end(), OP_PUSHDATA1);
+ insert(end(), (uint8_t)b.size());
+ }
+ else if (b.size() <= 0xffff)
+ {
+ insert(end(), OP_PUSHDATA2);
+ uint16_t nSize = (uint16_t) b.size();
+ insert(end(), (uint8_t*)&nSize, (uint8_t*)&nSize + sizeof(nSize));
+ }
+ else
+ {
+ insert(end(), OP_PUSHDATA4);
+ uint32_t nSize = (uint32_t) b.size();
+ insert(end(), (uint8_t*)&nSize, (uint8_t*)&nSize + sizeof(nSize));
+ }
+ insert(end(), b.begin(), b.end());
+ return *this;
+}
+
+CScript& CScript::operator<<(const CScript& b)
+{
+ // I'm not sure if this should push the script or concatenate scripts.
+ // If there's ever a use for pushing a script onto a script, delete this member fn
+ assert(!"Warning: Pushing a CScript onto a CScript with << is probably not intended, use + to concatenate!");
+ return *this;
+}
+
+bool CScript::GetOp(iterator& pc, opcodetype& opcodeRet, vector<uint8_t>& vchRet)
+{
+ // Wrapper so it can be called with either iterator or const_iterator
+ const_iterator pc2 = pc;
+ bool fRet = GetOp2(pc2, opcodeRet, &vchRet);
+ pc = begin() + (pc2 - begin());
+ return fRet;
+}
+
+bool CScript::GetOp(iterator& pc, opcodetype& opcodeRet)
+{
+ const_iterator pc2 = pc;
+ bool fRet = GetOp2(pc2, opcodeRet, NULL);
+ pc = begin() + (pc2 - begin());
+ return fRet;
+}
+
+bool CScript::GetOp(const_iterator& pc, opcodetype& opcodeRet, vector<uint8_t>& vchRet) const
+{
+ return GetOp2(pc, opcodeRet, &vchRet);
+}
+
+bool CScript::GetOp(const_iterator& pc, opcodetype& opcodeRet) const
+{
+ return GetOp2(pc, opcodeRet, NULL);
+}
+
+bool CScript::GetOp2(const_iterator& pc, opcodetype& opcodeRet, vector<uint8_t>* pvchRet) const
+{
+ opcodeRet = OP_INVALIDOPCODE;
+ if (pvchRet)
+ pvchRet->clear();
+ if (pc >= end())
+ return false;
+
+ // Read instruction
+ if (end() - pc < 1)
+ return false;
+ uint32_t opcode = *pc++;
+
+ // Immediate operand
+ if (opcode <= OP_PUSHDATA4)
+ {
+ uint32_t nSize = OP_0;
+ if (opcode < OP_PUSHDATA1)
+ {
+ nSize = opcode;
+ }
+ else if (opcode == OP_PUSHDATA1)
+ {
+ if (end() - pc < 1)
+ return false;
+ nSize = *pc++;
+ }
+ else if (opcode == OP_PUSHDATA2)
+ {
+ if (end() - pc < 2)
+ return false;
+ memcpy(&nSize, &pc[0], 2);
+ pc += 2;
+ }
+ else if (opcode == OP_PUSHDATA4)
+ {
+ if (end() - pc < 4)
+ return false;
+ memcpy(&nSize, &pc[0], 4);
+ pc += 4;
+ }
+ if (end() - pc < 0 || (uint32_t)(end() - pc) < nSize)
+ return false;
+ if (pvchRet)
+ pvchRet->assign(pc, pc + nSize);
+ pc += nSize;
+ }
+
+ opcodeRet = (opcodetype)opcode;
+ return true;
+}
+
+int CScript::DecodeOP_N(opcodetype opcode)
+{
+ if (opcode == OP_0)
+ return 0;
+ assert(opcode >= OP_1 && opcode <= OP_16);
+ return (opcode - (OP_1 - 1));
+}
+
+opcodetype CScript::EncodeOP_N(int n)
+{
+ assert(n >= 0 && n <= 16);
+ if (n == 0)
+ return OP_0;
+ return (opcodetype)(OP_1+n-1);
+}
+
+int CScript::FindAndDelete(const CScript& b)
+{
+ int nFound = 0;
+ if (b.empty())
+ return nFound;
+ CScript result;
+ iterator pc = begin(), pc2 = begin();
+ opcodetype opcode;
+ do
+ {
+ result.insert(result.end(), pc2, pc);
+ while (static_cast<size_t>(end() - pc) >= b.size() && equal(b.begin(), b.end(), pc))
+ {
+ pc = pc + b.size();
+ ++nFound;
+ }
+ pc2 = pc;
+ }
+ while (GetOp(pc, opcode));
+
+ if (nFound > 0) {
+ result.insert(result.end(), pc2, end());
+ *this = result;
+ }
+ return nFound;
+}
+
+int CScript::Find(opcodetype op) const
+{
+ int nFound = 0;
+ opcodetype opcode;
+ for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);)
+ if (opcode == op)
+ ++nFound;
+ return nFound;
+}
+
unsigned int CScript::GetSigOpCount(bool fAccurate) const
{
- unsigned int n = 0;
+ uint32_t n = 0;
auto pc = begin();
- opcodetype lastOpcode = OP_INVALIDOPCODE;
+ auto lastOpcode = OP_INVALIDOPCODE;
while (pc < end())
{
opcodetype opcode;
this->at(22) == OP_EQUAL);
}
+bool CScript::IsPushOnly(const_iterator pc) const
+{
+ while (pc < end())
+ {
+ opcodetype opcode;
+ if (!GetOp(pc, opcode))
+ return false;
+ if (opcode > OP_16)
+ return false;
+ }
+ return true;
+}
+
+// Called by CTransaction::IsStandard and P2SH VerifyScript (which makes it consensus-critical).
+bool CScript::IsPushOnly() const
+{
+ return this->IsPushOnly(begin());
+}
+
bool CScript::HasCanonicalPushes() const
{
auto pc = begin();
while (pc < end())
{
opcodetype opcode;
- std::vector<unsigned char> data;
+ vector<unsigned char> data;
if (!GetOp(pc, opcode, data))
return false;
if (opcode > OP_16)
}
}
-void CScript::SetMultisig(int nRequired, const std::vector<CPubKey>& keys)
+void CScript::SetMultisig(int nRequired, const vector<CPubKey>& keys)
{
this->clear();
*this << EncodeOP_N(nRequired);
- for(const CPubKey& key : keys)
+ for(const auto& key : keys)
*this << key;
*this << EncodeOP_N((int)(keys.size())) << OP_CHECKMULTISIG;
}
+
+void CScript::PrintHex() const
+{
+ printf("CScript(%s)\n", HexStr(begin(), end(), true).c_str());
+}
+
+string CScript::ToString(bool fShort) const
+{
+ string str;
+ opcodetype opcode;
+ vector<uint8_t> vch;
+ const_iterator pc = begin();
+ while (pc < end())
+ {
+ if (!str.empty())
+ str += " ";
+ if (!GetOp(pc, opcode, vch))
+ {
+ str += "[error]";
+ return str;
+ }
+ if (opcode <= OP_PUSHDATA4)
+ str += fShort? ValueString(vch).substr(0, 10) : ValueString(vch);
+ else
+ str += GetOpName(opcode);
+ }
+ return str;
+}
+
+void CScript::print() const
+{
+ printf("%s\n", ToString().c_str());
+}
+
+CScriptID CScript::GetID() const
+{
+ return CScriptID(Hash160(*this));
+}