aboutsummaryrefslogtreecommitdiff
path: root/src/script/standard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/standard.cpp')
-rw-r--r--src/script/standard.cpp151
1 files changed, 107 insertions, 44 deletions
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 4863b9639..f57f1f61b 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,11 +10,8 @@
#include "util.h"
#include "utilstrencodings.h"
-#include <boost/foreach.hpp>
-using namespace std;
-
-typedef vector<unsigned char> valtype;
+typedef std::vector<unsigned char> valtype;
bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
@@ -31,27 +28,27 @@ const char* GetTxnOutputType(txnouttype t)
case TX_SCRIPTHASH: return "scripthash";
case TX_MULTISIG: return "multisig";
case TX_NULL_DATA: return "nulldata";
+ case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
+ case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
+ case TX_WITNESS_UNKNOWN: return "witness_unknown";
}
- return NULL;
+ return nullptr;
}
-/**
- * Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
- */
-bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
+bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
{
// Templates
- static multimap<txnouttype, CScript> mTemplates;
+ static std::multimap<txnouttype, CScript> mTemplates;
if (mTemplates.empty())
{
// Standard tx, sender provides pubkey, receiver adds signature
- mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
+ mTemplates.insert(std::make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << 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(std::make_pair(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(std::make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
}
vSolutionsRet.clear();
@@ -61,11 +58,33 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
if (scriptPubKey.IsPayToScriptHash())
{
typeRet = TX_SCRIPTHASH;
- vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
+ std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
vSolutionsRet.push_back(hashBytes);
return true;
}
+ int witnessversion;
+ std::vector<unsigned char> witnessprogram;
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ if (witnessversion == 0 && witnessprogram.size() == 20) {
+ typeRet = TX_WITNESS_V0_KEYHASH;
+ vSolutionsRet.push_back(witnessprogram);
+ return true;
+ }
+ if (witnessversion == 0 && witnessprogram.size() == 32) {
+ typeRet = TX_WITNESS_V0_SCRIPTHASH;
+ vSolutionsRet.push_back(witnessprogram);
+ return true;
+ }
+ if (witnessversion != 0) {
+ typeRet = TX_WITNESS_UNKNOWN;
+ vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
+ vSolutionsRet.push_back(std::move(witnessprogram));
+ return true;
+ }
+ return false;
+ }
+
// Provably prunable, data-carrying output
//
// So long as script passes the IsUnspendable() test and all but the first
@@ -78,13 +97,13 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
// Scan templates
const CScript& script1 = scriptPubKey;
- BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
+ for (const std::pair<txnouttype, CScript>& tplate : mTemplates)
{
const CScript& script2 = tplate.second;
vSolutionsRet.clear();
opcodetype opcode1, opcode2;
- vector<unsigned char> vch1, vch2;
+ std::vector<unsigned char> vch1, vch2;
// Compare
CScript::const_iterator pc1 = script1.begin();
@@ -161,30 +180,9 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
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)
{
- vector<valtype> vSolutions;
+ std::vector<valtype> vSolutions;
txnouttype whichType;
if (!Solver(scriptPubKey, whichType, vSolutions))
return false;
@@ -207,16 +205,33 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
addressRet = CScriptID(uint160(vSolutions[0]));
return true;
+ } else if (whichType == TX_WITNESS_V0_KEYHASH) {
+ WitnessV0KeyHash hash;
+ std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
+ addressRet = hash;
+ return true;
+ } else if (whichType == TX_WITNESS_V0_SCRIPTHASH) {
+ WitnessV0ScriptHash hash;
+ std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
+ addressRet = hash;
+ return true;
+ } else if (whichType == TX_WITNESS_UNKNOWN) {
+ WitnessUnknown unk;
+ unk.version = vSolutions[0][0];
+ std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
+ unk.length = vSolutions[1].size();
+ addressRet = unk;
+ return true;
}
// Multisig txns have more than one address...
return false;
}
-bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
+bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
{
addressRet.clear();
typeRet = TX_NONSTANDARD;
- vector<valtype> vSolutions;
+ std::vector<valtype> vSolutions;
if (!Solver(scriptPubKey, typeRet, vSolutions))
return false;
if (typeRet == TX_NULL_DATA){
@@ -259,7 +274,7 @@ class CScriptVisitor : public boost::static_visitor<bool>
private:
CScript *script;
public:
- CScriptVisitor(CScript *scriptin) { script = scriptin; }
+ explicit CScriptVisitor(CScript *scriptin) { script = scriptin; }
bool operator()(const CNoDestination &dest) const {
script->clear();
@@ -277,8 +292,29 @@ public:
*script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
return true;
}
+
+ bool operator()(const WitnessV0KeyHash& id) const
+ {
+ script->clear();
+ *script << OP_0 << ToByteVector(id);
+ return true;
+ }
+
+ bool operator()(const WitnessV0ScriptHash& id) const
+ {
+ script->clear();
+ *script << OP_0 << ToByteVector(id);
+ return true;
+ }
+
+ bool operator()(const WitnessUnknown& id) const
+ {
+ script->clear();
+ *script << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
+ return true;
+ }
};
-}
+} // namespace
CScript GetScriptForDestination(const CTxDestination& dest)
{
@@ -298,8 +334,35 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
CScript script;
script << CScript::EncodeOP_N(nRequired);
- BOOST_FOREACH(const CPubKey& key, keys)
+ for (const CPubKey& key : keys)
script << ToByteVector(key);
script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
return script;
}
+
+CScript GetScriptForWitness(const CScript& redeemscript)
+{
+ CScript ret;
+
+ txnouttype typ;
+ std::vector<std::vector<unsigned char> > vSolutions;
+ if (Solver(redeemscript, typ, vSolutions)) {
+ if (typ == TX_PUBKEY) {
+ unsigned char h160[20];
+ CHash160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160);
+ ret << OP_0 << std::vector<unsigned char>(&h160[0], &h160[20]);
+ return ret;
+ } else if (typ == TX_PUBKEYHASH) {
+ ret << OP_0 << vSolutions[0];
+ return ret;
+ }
+ }
+ uint256 hash;
+ CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin());
+ ret << OP_0 << ToByteVector(hash);
+ return ret;
+}
+
+bool IsValidDestination(const CTxDestination& dest) {
+ return dest.which() != 0;
+}