PRCYCoin  2.0.0.7rc1
P2P Digital Currency
standard.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin 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 
14 typedef std::vector<unsigned char> valtype;
15 
16 unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
17 
18 CScriptID::CScriptID(const CScript &in) : uint160(Hash160(in.begin(), in.end())) {}
19 
20 const char *GetTxnOutputType(txnouttype t) {
21  switch (t) {
22  case TX_NONSTANDARD:
23  return "nonstandard";
24  case TX_PUBKEY:
25  return "pubkey";
26  case TX_PUBKEYHASH:
27  return "pubkeyhash";
28  case TX_SCRIPTHASH:
29  return "scripthash";
30  case TX_MULTISIG:
31  return "multisig";
32  case TX_NULL_DATA:
33  return "nulldata";
34  }
35  return NULL;
36 }
37 
41 bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet) {
42  // Templates
43  static std::multimap <txnouttype, CScript> mTemplates;
44  if (mTemplates.empty()) {
45  // Standard tx, sender provides pubkey, receiver adds signature
46  mTemplates.insert(std::make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
47 
48  // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
49  mTemplates.insert(std::make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY
50  << OP_CHECKSIG));
51 
52  // Sender provides N pubkeys, receivers provides M signatures
53  mTemplates.insert(std::make_pair(TX_MULTISIG,
55  }
56 
57  // Shortcut for pay-to-script-hash, which are more constrained than the other types:
58  // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
59  if (scriptPubKey.IsPayToScriptHash()) {
60  typeRet = TX_SCRIPTHASH;
61  std::vector<unsigned char> hashBytes(scriptPubKey.begin() + 2, scriptPubKey.begin() + 22);
62  vSolutionsRet.push_back(hashBytes);
63  return true;
64  }
65 
66  // Provably prunable, data-carrying output
67  //
68  // So long as script passes the IsUnspendable() test and all but the first
69  // byte passes the IsPushOnly() test we don't care what exactly is in the
70  // script.
71  if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin() + 1)) {
72  typeRet = TX_NULL_DATA;
73  return true;
74  }
75 
76  // Scan templates
77  const CScript &script1 = scriptPubKey;
78  for (const PAIRTYPE(txnouttype, CScript)&tplate : mTemplates)
79  {
80  const CScript &script2 = tplate.second;
81  vSolutionsRet.clear();
82 
83  opcodetype opcode1, opcode2;
84  std::vector<unsigned char> vch1, vch2;
85 
86  // Compare
87  CScript::const_iterator pc1 = script1.begin();
88  CScript::const_iterator pc2 = script2.begin();
89  while (true) {
90  if (pc1 == script1.end() && pc2 == script2.end()) {
91  // Found a match
92  typeRet = tplate.first;
93  if (typeRet == TX_MULTISIG) {
94  // Additional checks for TX_MULTISIG:
95  unsigned char m = vSolutionsRet.front()[0];
96  unsigned char n = vSolutionsRet.back()[0];
97  if (m < 1 || n < 1 || m > n || vSolutionsRet.size() - 2 != n)
98  return false;
99  }
100  return true;
101  }
102  if (!script1.GetOp(pc1, opcode1, vch1))
103  break;
104  if (!script2.GetOp(pc2, opcode2, vch2))
105  break;
106 
107  // Template matching opcodes:
108  if (opcode2 == OP_PUBKEYS) {
109  while (vch1.size() >= 33 && vch1.size() <= 65) {
110  vSolutionsRet.push_back(vch1);
111  if (!script1.GetOp(pc1, opcode1, vch1))
112  break;
113  }
114  if (!script2.GetOp(pc2, opcode2, vch2))
115  break;
116  // Normal situation is to fall through
117  // to other if/else statements
118  }
119 
120  if (opcode2 == OP_PUBKEY) {
121  if (vch1.size() < 33 || vch1.size() > 65)
122  break;
123  vSolutionsRet.push_back(vch1);
124  } else if (opcode2 == OP_PUBKEYHASH) {
125  if (vch1.size() != sizeof(uint160))
126  break;
127  vSolutionsRet.push_back(vch1);
128  } else if (opcode2 == OP_SMALLINTEGER) { // Single-byte small integer pushed onto vSolutions
129  if (opcode1 == OP_0 ||
130  (opcode1 >= OP_1 && opcode1 <= OP_16)) {
131  char n = (char) CScript::DecodeOP_N(opcode1);
132  vSolutionsRet.push_back(valtype(1, n));
133  } else
134  break;
135  } else if (opcode1 != opcode2 || vch1 != vch2) {
136  // Others must match exactly
137  break;
138  }
139  }
140  }
141 
142  vSolutionsRet.clear();
143  typeRet = TX_NONSTANDARD;
144  return false;
145 }
146 
147 int ScriptSigArgsExpected(txnouttype t, const std::vector <std::vector<unsigned char>> &vSolutions) {
148  switch (t) {
149  case TX_NONSTANDARD:
150  case TX_NULL_DATA:
151  case TX_PUBKEY:
152  return 1;
153  case TX_PUBKEYHASH:
154  return 2;
155  case TX_MULTISIG:
156  if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
157  return -1;
158  return vSolutions[0][0] + 1;
159  case TX_SCRIPTHASH:
160  return 1; // doesn't include args needed by the script
161  }
162  return -1;
163 }
164 
165 bool IsStandard(const CScript &scriptPubKey, txnouttype &whichType) {
166  std::vector<valtype> vSolutions;
167  if (!Solver(scriptPubKey, whichType, vSolutions))
168  return false;
169 
170  if (whichType == TX_MULTISIG) {
171  unsigned char m = vSolutions.front()[0];
172  unsigned char n = vSolutions.back()[0];
173  // Support up to x-of-3 multisig txns as standard
174  if (n < 1 || n > 3)
175  return false;
176  if (m < 1 || m > n)
177  return false;
178  } else if (whichType == TX_NULL_DATA &&
179  (!GetBoolArg("-datacarrier", true) || scriptPubKey.size() > nMaxDatacarrierBytes))
180  return false;
181 
182  return whichType != TX_NONSTANDARD;
183 }
184 
185 bool ExtractPubKey(const CScript &scriptPubKey, CPubKey& out) {
186  std::vector<valtype> vSolutions;
187  txnouttype whichType;
188  if (!Solver(scriptPubKey, whichType, vSolutions))
189  return false;
190 
191  if (whichType == TX_PUBKEY) {
192  CPubKey pubKey(vSolutions[0]);
193  out.Set(pubKey.begin(), pubKey.end());
194  return true;
195  }
196  return false;
197 }
198 
199 bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet) {
200  std::vector<valtype> vSolutions;
201  txnouttype whichType;
202  if (!Solver(scriptPubKey, whichType, vSolutions))
203  return false;
204 
205  if (whichType == TX_PUBKEY) {
206  CPubKey pubKey(vSolutions[0]);
207  if (!pubKey.IsValid())
208  return false;
209 
210  addressRet = pubKey.GetID();
211  return true;
212  } else if (whichType == TX_PUBKEYHASH) {
213  addressRet = CKeyID(uint160(vSolutions[0]));
214  return true;
215  } else if (whichType == TX_SCRIPTHASH) {
216  addressRet = CScriptID(uint160(vSolutions[0]));
217  return true;
218  }
219  // Multisig txns have more than one address...
220  return false;
221 }
222 
223 bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, std::vector <CTxDestination> &addressRet,
224  int &nRequiredRet) {
225  addressRet.clear();
226  typeRet = TX_NONSTANDARD;
227  std::vector<valtype> vSolutions;
228  if (!Solver(scriptPubKey, typeRet, vSolutions))
229  return false;
230  if (typeRet == TX_NULL_DATA) {
231  // This is data, not addresses
232  return false;
233  }
234 
235  if (typeRet == TX_MULTISIG) {
236  nRequiredRet = vSolutions.front()[0];
237  for (unsigned int i = 1; i < vSolutions.size() - 1; i++) {
238  CPubKey pubKey(vSolutions[i]);
239  if (!pubKey.IsValid())
240  continue;
241 
242  CTxDestination address = pubKey.GetID();
243  addressRet.push_back(address);
244  }
245 
246  if (addressRet.empty())
247  return false;
248  } else {
249  nRequiredRet = 1;
250  CTxDestination address;
251  if (!ExtractDestination(scriptPubKey, address))
252  return false;
253  addressRet.push_back(address);
254  }
255 
256  return true;
257 }
258 
259 namespace {
260  class CScriptVisitor : public boost::static_visitor<bool> {
261  private:
262  CScript *script;
263  public:
264  CScriptVisitor(CScript *scriptin) { script = scriptin; }
265 
266  bool operator()(const CNoDestination &dest) const {
267  script->clear();
268  return false;
269  }
270 
271  bool operator()(const CKeyID &keyID) const {
272  script->clear();
273  *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
274  return true;
275  }
276 
277  bool operator()(const CScriptID &scriptID) const {
278  script->clear();
279  *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
280  return true;
281  }
282  };
283 }
284 
286  CScript script;
287 
288  boost::apply_visitor(CScriptVisitor(&script), dest);
289  return script;
290 }
291 
293  CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
294  //boost::apply_visitor(CScriptVisitor(&script), dest);
295  return scriptPubKey;
296 }
297 
298 CScript GetScriptForMultisig(int nRequired, const std::vector <CPubKey> &keys) {
299  CScript script;
300 
301  script << CScript::EncodeOP_N(nRequired);
302  for (const CPubKey &key : keys)
303  script << ToByteVector(key);
304  script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
305  return script;
306 }
OP_0
@ OP_0
Definition: script.h:41
OP_SMALLINTEGER
@ OP_SMALLINTEGER
Definition: script.h:174
OP_PUBKEYS
@ OP_PUBKEYS
Definition: script.h:175
prevector::const_iterator
Definition: prevector.h:97
GetScriptForDestination
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:285
CPubKey::Set
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:71
ToByteVector
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:32
OP_PUBKEY
@ OP_PUBKEY
Definition: script.h:177
Hash160
uint160 Hash160(const T1 pbegin, const T1 pend)
Compute the 160-bit hash an object.
Definition: hash.h:237
CScript::EncodeOP_N
static opcodetype EncodeOP_N(int n)
Definition: script.h:555
OP_HASH160
@ OP_HASH160
Definition: script.h:152
CScript::DecodeOP_N
static int DecodeOP_N(opcodetype opcode)
Encode/decode small integers:
Definition: script.h:548
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
TX_NONSTANDARD
@ TX_NONSTANDARD
Definition: standard.h:59
CScript::IsPayToScriptHash
bool IsPayToScriptHash() const
Definition: script.cpp:235
pubkey.h
CScript::clear
void clear()
Definition: script.h:634
CScript::IsPushOnly
bool IsPushOnly(const_iterator pc) const
Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
Definition: script.cpp:244
TX_PUBKEYHASH
@ TX_PUBKEYHASH
Definition: standard.h:62
CPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:95
prevector::end
iterator end()
Definition: prevector.h:292
TX_MULTISIG
@ TX_MULTISIG
Definition: standard.h:64
GetTxnOutputType
const char * GetTxnOutputType(txnouttype t)
Definition: standard.cpp:20
OP_RETURN
@ OP_RETURN
Definition: script.h:76
GetScriptForMultisig
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Definition: standard.cpp:298
ExtractPubKey
bool ExtractPubKey(const CScript &scriptPubKey, CPubKey &out)
Definition: standard.cpp:185
Solver
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
Definition: standard.cpp:41
IsStandard
bool IsStandard(const CScript &scriptPubKey, txnouttype &whichType)
Definition: standard.cpp:165
TX_PUBKEY
@ TX_PUBKEY
Definition: standard.h:61
CPubKey::end
const unsigned char * end() const
Definition: pubkey.h:96
TX_SCRIPTHASH
@ TX_SCRIPTHASH
Definition: standard.h:63
OP_DUP
@ OP_DUP
Definition: script.h:90
ScriptSigArgsExpected
int ScriptSigArgsExpected(txnouttype t, const std::vector< std::vector< unsigned char >> &vSolutions)
Definition: standard.cpp:147
CScript::GetOp
bool GetOp(iterator &pc, opcodetype &opcodeRet, std::vector< unsigned char > &vchRet)
Definition: script.h:468
OP_CHECKMULTISIG
@ OP_CHECKMULTISIG
Definition: script.h:157
GetBoolArg
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:255
PAIRTYPE
#define PAIRTYPE(t1, t2)
This is needed because the foreach macro can't get over the comma in pair<t1, t2>
Definition: utilstrencodings.h:24
standard.h
nMaxDatacarrierBytes
unsigned nMaxDatacarrierBytes
Definition: standard.cpp:16
TX_NULL_DATA
@ TX_NULL_DATA
Definition: standard.h:65
OP_CHECKSIG
@ OP_CHECKSIG
Definition: script.h:155
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:363
ExtractDestination
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: standard.cpp:199
CNoDestination
Definition: standard.h:68
CTxDestination
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:81
OP_16
@ OP_16
Definition: script.h:64
uint160
160-bit unsigned big integer.
Definition: uint256.h:27
CPubKey
An encapsulated public key.
Definition: pubkey.h:37
key
CKey key
Definition: bip38tooldialog.cpp:173
prevector::size
size_type size() const
Definition: prevector.h:282
OP_EQUAL
@ OP_EQUAL
Definition: script.h:111
prevector::begin
iterator begin()
Definition: prevector.h:290
OP_PUBKEYHASH
@ OP_PUBKEYHASH
Definition: script.h:176
script.h
utilstrencodings.h
txnouttype
txnouttype
Definition: standard.h:57
CPubKey::IsValid
bool IsValid() const
Definition: pubkey.h:159
ExtractDestinations
bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< CTxDestination > &addressRet, int &nRequiredRet)
Definition: standard.cpp:223
CScriptID
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:20
CScriptID::CScriptID
CScriptID()
Definition: standard.h:23
OP_EQUALVERIFY
@ OP_EQUALVERIFY
Definition: script.h:112
OP_1
@ OP_1
Definition: script.h:48
valtype
std::vector< unsigned char > valtype
Definition: standard.cpp:14
opcodetype
opcodetype
Script opcodes.
Definition: script.h:38
CPubKey::GetID
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:143