Dash Core  0.12.2.1
P2P Digital Currency
standard.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "script/standard.h"
7 
8 #include "pubkey.h"
9 #include "script/script.h"
10 #include "util.h"
11 #include "utilstrencodings.h"
12 
13 #include <boost/foreach.hpp>
14 
15 using namespace std;
16 
17 typedef vector<unsigned char> valtype;
18 
21 
22 CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
23 
25 {
26  switch (t)
27  {
28  case TX_NONSTANDARD: return "nonstandard";
29  case TX_PUBKEY: return "pubkey";
30  case TX_PUBKEYHASH: return "pubkeyhash";
31  case TX_SCRIPTHASH: return "scripthash";
32  case TX_MULTISIG: return "multisig";
33  case TX_NULL_DATA: return "nulldata";
34  }
35  return NULL;
36 }
37 
41 bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
42 {
43  // Templates
44  static multimap<txnouttype, CScript> mTemplates;
45  if (mTemplates.empty())
46  {
47  // Standard tx, sender provides pubkey, receiver adds signature
48  mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
49 
50  // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
51  mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
52 
53  // Sender provides N pubkeys, receivers provides M signatures
54  mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
55  }
56 
57  vSolutionsRet.clear();
58 
59  // Shortcut for pay-to-script-hash, which are more constrained than the other types:
60  // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
61  if (scriptPubKey.IsPayToScriptHash())
62  {
63  typeRet = TX_SCRIPTHASH;
64  vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
65  vSolutionsRet.push_back(hashBytes);
66  return true;
67  }
68 
69  // Provably prunable, data-carrying output
70  //
71  // So long as script passes the IsUnspendable() test and all but the first
72  // byte passes the IsPushOnly() test we don't care what exactly is in the
73  // script.
74  if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
75  typeRet = TX_NULL_DATA;
76  return true;
77  }
78 
79  // Scan templates
80  const CScript& script1 = scriptPubKey;
81  BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
82  {
83  const CScript& script2 = tplate.second;
84  vSolutionsRet.clear();
85 
86  opcodetype opcode1, opcode2;
87  vector<unsigned char> vch1, vch2;
88 
89  // Compare
90  CScript::const_iterator pc1 = script1.begin();
91  CScript::const_iterator pc2 = script2.begin();
92  while (true)
93  {
94  if (pc1 == script1.end() && pc2 == script2.end())
95  {
96  // Found a match
97  typeRet = tplate.first;
98  if (typeRet == TX_MULTISIG)
99  {
100  // Additional checks for TX_MULTISIG:
101  unsigned char m = vSolutionsRet.front()[0];
102  unsigned char n = vSolutionsRet.back()[0];
103  if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
104  return false;
105  }
106  return true;
107  }
108  if (!script1.GetOp(pc1, opcode1, vch1))
109  break;
110  if (!script2.GetOp(pc2, opcode2, vch2))
111  break;
112 
113  // Template matching opcodes:
114  if (opcode2 == OP_PUBKEYS)
115  {
116  while (vch1.size() >= 33 && vch1.size() <= 65)
117  {
118  vSolutionsRet.push_back(vch1);
119  if (!script1.GetOp(pc1, opcode1, vch1))
120  break;
121  }
122  if (!script2.GetOp(pc2, opcode2, vch2))
123  break;
124  // Normal situation is to fall through
125  // to other if/else statements
126  }
127 
128  if (opcode2 == OP_PUBKEY)
129  {
130  if (vch1.size() < 33 || vch1.size() > 65)
131  break;
132  vSolutionsRet.push_back(vch1);
133  }
134  else if (opcode2 == OP_PUBKEYHASH)
135  {
136  if (vch1.size() != sizeof(uint160))
137  break;
138  vSolutionsRet.push_back(vch1);
139  }
140  else if (opcode2 == OP_SMALLINTEGER)
141  { // Single-byte small integer pushed onto vSolutions
142  if (opcode1 == OP_0 ||
143  (opcode1 >= OP_1 && opcode1 <= OP_16))
144  {
145  char n = (char)CScript::DecodeOP_N(opcode1);
146  vSolutionsRet.push_back(valtype(1, n));
147  }
148  else
149  break;
150  }
151  else if (opcode1 != opcode2 || vch1 != vch2)
152  {
153  // Others must match exactly
154  break;
155  }
156  }
157  }
158 
159  vSolutionsRet.clear();
160  typeRet = TX_NONSTANDARD;
161  return false;
162 }
163 
164 bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
165 {
166  vector<valtype> vSolutions;
167  txnouttype whichType;
168  if (!Solver(scriptPubKey, whichType, vSolutions))
169  return false;
170 
171  if (whichType == TX_PUBKEY)
172  {
173  CPubKey pubKey(vSolutions[0]);
174  if (!pubKey.IsValid())
175  return false;
176 
177  addressRet = pubKey.GetID();
178  return true;
179  }
180  else if (whichType == TX_PUBKEYHASH)
181  {
182  addressRet = CKeyID(uint160(vSolutions[0]));
183  return true;
184  }
185  else if (whichType == TX_SCRIPTHASH)
186  {
187  addressRet = CScriptID(uint160(vSolutions[0]));
188  return true;
189  }
190  // Multisig txns have more than one address...
191  return false;
192 }
193 
194 bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
195 {
196  addressRet.clear();
197  typeRet = TX_NONSTANDARD;
198  vector<valtype> vSolutions;
199  if (!Solver(scriptPubKey, typeRet, vSolutions))
200  return false;
201  if (typeRet == TX_NULL_DATA){
202  // This is data, not addresses
203  return false;
204  }
205 
206  if (typeRet == TX_MULTISIG)
207  {
208  nRequiredRet = vSolutions.front()[0];
209  for (unsigned int i = 1; i < vSolutions.size()-1; i++)
210  {
211  CPubKey pubKey(vSolutions[i]);
212  if (!pubKey.IsValid())
213  continue;
214 
215  CTxDestination address = pubKey.GetID();
216  addressRet.push_back(address);
217  }
218 
219  if (addressRet.empty())
220  return false;
221  }
222  else
223  {
224  nRequiredRet = 1;
225  CTxDestination address;
226  if (!ExtractDestination(scriptPubKey, address))
227  return false;
228  addressRet.push_back(address);
229  }
230 
231  return true;
232 }
233 
234 namespace
235 {
236 class CScriptVisitor : public boost::static_visitor<bool>
237 {
238 private:
239  CScript *script;
240 public:
241  CScriptVisitor(CScript *scriptin) { script = scriptin; }
242 
243  bool operator()(const CNoDestination &dest) const {
244  script->clear();
245  return false;
246  }
247 
248  bool operator()(const CKeyID &keyID) const {
249  script->clear();
250  *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
251  return true;
252  }
253 
254  bool operator()(const CScriptID &scriptID) const {
255  script->clear();
256  *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
257  return true;
258  }
259 };
260 }
261 
263 {
264  CScript script;
265 
266  boost::apply_visitor(CScriptVisitor(&script), dest);
267  return script;
268 }
269 
271 {
272  return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
273 }
274 
275 CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
276 {
277  CScript script;
278 
279  script << CScript::EncodeOP_N(nRequired);
280  BOOST_FOREACH(const CPubKey& key, keys)
281  script << ToByteVector(key);
282  script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
283  return script;
284 }
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
Definition: standard.h:69
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: standard.cpp:164
vector< unsigned char > valtype
Definition: standard.cpp:17
static const unsigned int MAX_OP_RETURN_RELAY
Definition: standard.h:30
static const bool DEFAULT_ACCEPT_DATACARRIER
Definition: standard.h:16
bool fAcceptDatacarrier
bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
Definition: standard.cpp:19
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Definition: standard.cpp:270
Definition: pubkey.h:27
bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, vector< CTxDestination > &addressRet, int &nRequiredRet)
Definition: standard.cpp:194
uint160 Hash160(const T1 pbegin, const T1 pend)
Definition: hash.h:214
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:144
Definition: script.h:67
bool GetOp(iterator &pc, opcodetype &opcodeRet, std::vector< unsigned char > &vchRet)
Definition: script.h:473
iterator end()
Definition: prevector.h:272
opcodetype
Definition: script.h:41
const unsigned char * begin() const
Definition: pubkey.h:96
CScriptID()
Definition: standard.h:25
Definition: script.h:51
const char * GetTxnOutputType(txnouttype t)
Definition: standard.cpp:24
bool IsPayToScriptHash() const
Definition: script.cpp:238
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:262
const unsigned char * end() const
Definition: pubkey.h:97
txnouttype
Definition: standard.h:45
bool IsPushOnly(const_iterator pc) const
Definition: script.cpp:247
bool IsValid() const
Definition: pubkey.h:160
iterator begin()
Definition: prevector.h:270
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, vector< vector< unsigned char > > &vSolutionsRet)
Definition: standard.cpp:41
Definition: pubkey.h:37
size_type size() const
Definition: prevector.h:262
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Definition: standard.cpp:275
void clear()
Definition: script.h:639
static int DecodeOP_N(opcodetype opcode)
Definition: script.h:553
Definition: script.h:44
#define PAIRTYPE(t1, t2)
static opcodetype EncodeOP_N(int n)
Definition: script.h:560
unsigned nMaxDatacarrierBytes
Definition: standard.cpp:20
Definition: script.h:93
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:35