Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

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 
14 typedef std::vector<unsigned char> valtype;
15 
18 
19 CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
20 
22 {
23  switch (t)
24  {
25  case TX_NONSTANDARD: return "nonstandard";
26  case TX_PUBKEY: return "pubkey";
27  case TX_PUBKEYHASH: return "pubkeyhash";
28  case TX_SCRIPTHASH: return "scripthash";
29  case TX_MULTISIG: return "multisig";
30  case TX_NULL_DATA: return "nulldata";
31  }
32  return nullptr;
33 }
34 
35 bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
36 {
37  // Templates
38  static std::multimap<txnouttype, CScript> mTemplates;
39  if (mTemplates.empty())
40  {
41  // Standard tx, sender provides pubkey, receiver adds signature
42  mTemplates.insert(std::make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
43 
44  // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
45  mTemplates.insert(std::make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
46 
47  // Sender provides N pubkeys, receivers provides M signatures
48  mTemplates.insert(std::make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
49  }
50 
51  vSolutionsRet.clear();
52 
53  // Shortcut for pay-to-script-hash, which are more constrained than the other types:
54  // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
55  if (scriptPubKey.IsPayToScriptHash())
56  {
57  typeRet = TX_SCRIPTHASH;
58  std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
59  vSolutionsRet.push_back(hashBytes);
60  return true;
61  }
62 
63  // Provably prunable, data-carrying output
64  //
65  // So long as script passes the IsUnspendable() test and all but the first
66  // byte passes the IsPushOnly() test we don't care what exactly is in the
67  // script.
68  if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
69  typeRet = TX_NULL_DATA;
70  return true;
71  }
72 
73  // Scan templates
74  const CScript& script1 = scriptPubKey;
75  for (const std::pair<txnouttype, CScript>& tplate : mTemplates)
76  {
77  const CScript& script2 = tplate.second;
78  vSolutionsRet.clear();
79 
80  opcodetype opcode1, opcode2;
81  std::vector<unsigned char> vch1, vch2;
82 
83  // Compare
84  CScript::const_iterator pc1 = script1.begin();
85  CScript::const_iterator pc2 = script2.begin();
86  while (true)
87  {
88  if (pc1 == script1.end() && pc2 == script2.end())
89  {
90  // Found a match
91  typeRet = tplate.first;
92  if (typeRet == TX_MULTISIG)
93  {
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  {
110  while (vch1.size() >= 33 && vch1.size() <= 65)
111  {
112  vSolutionsRet.push_back(vch1);
113  if (!script1.GetOp(pc1, opcode1, vch1))
114  break;
115  }
116  if (!script2.GetOp(pc2, opcode2, vch2))
117  break;
118  // Normal situation is to fall through
119  // to other if/else statements
120  }
121 
122  if (opcode2 == OP_PUBKEY)
123  {
124  if (vch1.size() < 33 || vch1.size() > 65)
125  break;
126  vSolutionsRet.push_back(vch1);
127  }
128  else if (opcode2 == OP_PUBKEYHASH)
129  {
130  if (vch1.size() != sizeof(uint160))
131  break;
132  vSolutionsRet.push_back(vch1);
133  }
134  else if (opcode2 == OP_SMALLINTEGER)
135  { // Single-byte small integer pushed onto vSolutions
136  if (opcode1 == OP_0 ||
137  (opcode1 >= OP_1 && opcode1 <= OP_16))
138  {
139  char n = (char)CScript::DecodeOP_N(opcode1);
140  vSolutionsRet.push_back(valtype(1, n));
141  }
142  else
143  break;
144  }
145  else if (opcode1 != opcode2 || vch1 != vch2)
146  {
147  // Others must match exactly
148  break;
149  }
150  }
151  }
152 
153  vSolutionsRet.clear();
154  typeRet = TX_NONSTANDARD;
155  return false;
156 }
157 
158 bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
159 {
160  std::vector<valtype> vSolutions;
161  txnouttype whichType;
162  if (!Solver(scriptPubKey, whichType, vSolutions))
163  return false;
164 
165  if (whichType == TX_PUBKEY)
166  {
167  CPubKey pubKey(vSolutions[0]);
168  if (!pubKey.IsValid())
169  return false;
170 
171  addressRet = pubKey.GetID();
172  return true;
173  }
174  else if (whichType == TX_PUBKEYHASH)
175  {
176  addressRet = CKeyID(uint160(vSolutions[0]));
177  return true;
178  }
179  else if (whichType == TX_SCRIPTHASH)
180  {
181  addressRet = CScriptID(uint160(vSolutions[0]));
182  return true;
183  }
184  // Multisig txns have more than one address...
185  return false;
186 }
187 
188 bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
189 {
190  addressRet.clear();
191  typeRet = TX_NONSTANDARD;
192  std::vector<valtype> vSolutions;
193  if (!Solver(scriptPubKey, typeRet, vSolutions))
194  return false;
195  if (typeRet == TX_NULL_DATA){
196  // This is data, not addresses
197  return false;
198  }
199 
200  if (typeRet == TX_MULTISIG)
201  {
202  nRequiredRet = vSolutions.front()[0];
203  for (unsigned int i = 1; i < vSolutions.size()-1; i++)
204  {
205  CPubKey pubKey(vSolutions[i]);
206  if (!pubKey.IsValid())
207  continue;
208 
209  CTxDestination address = pubKey.GetID();
210  addressRet.push_back(address);
211  }
212 
213  if (addressRet.empty())
214  return false;
215  }
216  else
217  {
218  nRequiredRet = 1;
219  CTxDestination address;
220  if (!ExtractDestination(scriptPubKey, address))
221  return false;
222  addressRet.push_back(address);
223  }
224 
225  return true;
226 }
227 
228 namespace
229 {
230 class CScriptVisitor : public boost::static_visitor<bool>
231 {
232 private:
233  CScript *script;
234 public:
235  explicit CScriptVisitor(CScript *scriptin) { script = scriptin; }
236 
237  bool operator()(const CNoDestination &dest) const {
238  script->clear();
239  return false;
240  }
241 
242  bool operator()(const CKeyID &keyID) const {
243  script->clear();
244  *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
245  return true;
246  }
247 
248  bool operator()(const CScriptID &scriptID) const {
249  script->clear();
250  *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
251  return true;
252  }
253 };
254 } // namespace
255 
257 {
258  CScript script;
259 
260  boost::apply_visitor(CScriptVisitor(&script), dest);
261  return script;
262 }
263 
265 {
266  return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
267 }
268 
269 CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
270 {
271  CScript script;
272 
273  script << CScript::EncodeOP_N(nRequired);
274  for (const CPubKey& key : keys)
275  script << ToByteVector(key);
276  script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
277  return script;
278 }
279 
280 
282  return dest.which() != 0;
283 }
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
static int DecodeOP_N(opcodetype opcode)
Encode/decode small integers:
Definition: script.h:576
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
unspendable OP_RETURN script that carries data
Definition: standard.h:64
static const unsigned int MAX_OP_RETURN_RELAY
Default setting for nMaxDatacarrierBytes.
Definition: standard.h:34
bool IsPayToScriptHash() const
Definition: script.cpp:212
static const bool DEFAULT_ACCEPT_DATACARRIER
Definition: standard.h:16
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:281
bool fAcceptDatacarrier
A data carrying output is an unspendable output containing data.
Definition: standard.cpp:16
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:264
uint160 Hash160(const T1 pbegin, const T1 pend)
Compute the 160-bit hash an object.
Definition: hash.h:161
CScriptID()
Definition: standard.h:25
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:149
const unsigned char * begin() const
Definition: pubkey.h:105
Definition: script.h:74
bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< CTxDestination > &addressRet, int &nRequiredRet)
Parse a standard scriptPubKey with one or more destination addresses.
Definition: standard.cpp:188
iterator end()
Definition: prevector.h:320
opcodetype
Script opcodes.
Definition: script.h:48
const unsigned char * end() const
Definition: pubkey.h:106
bool IsPushOnly(const_iterator pc) const
Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
Definition: script.cpp:236
bool IsValid() const
Definition: pubkey.h:165
An encapsulated public key.
Definition: pubkey.h:30
Definition: script.h:58
std::vector< unsigned char > valtype
Definition: standard.cpp:14
const char * GetTxnOutputType(txnouttype t)
Get the name of a txnouttype as a C string, or nullptr if unknown.
Definition: standard.cpp:21
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:256
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:35
txnouttype
Definition: standard.h:56
static opcodetype EncodeOP_N(int n)
Definition: script.h:583
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:389
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
160-bit opaque blob.
Definition: uint256.h:112
iterator begin()
Definition: prevector.h:318
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:22
size_type size() const
Definition: prevector.h:310
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:269
bool GetOp(iterator &pc, opcodetype &opcodeRet, std::vector< unsigned char > &vchRet)
Definition: script.h:496
Definition: script.h:51
void clear()
Definition: script.h:664
unsigned nMaxDatacarrierBytes
Maximum size of TX_NULL_DATA scripts that this node considers standard.
Definition: standard.cpp:17
Definition: script.h:100
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:42
Released under the MIT license