Raven Core  3.0.0
P2P Digital Currency
standard.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Copyright (c) 2017-2019 The Raven Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include <base58.h>
8 #include <assets/assets.h>
9 #include <validation.h>
10 #include "script/standard.h"
11 
12 #include "pubkey.h"
13 #include "script/script.h"
14 #include "util.h"
15 #include "utilstrencodings.h"
16 
17 typedef std::vector<unsigned char> valtype;
18 
19 bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
20 unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
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  case TX_RESTRICTED_ASSET_DATA: return "nullassetdata";
35  case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
36  case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
37 
39  case TX_NEW_ASSET: return ASSET_NEW_STRING;
43  }
44  return nullptr;
45 }
46 
47 bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
48 {
49  // Templates
50  static std::multimap<txnouttype, CScript> mTemplates;
51  if (mTemplates.empty())
52  {
53  // Standard tx, sender provides pubkey, receiver adds signature
54  mTemplates.insert(std::make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
55 
56  // Raven address tx, sender provides hash of pubkey, receiver provides signature and pubkey
57  mTemplates.insert(std::make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
58 
59  // Sender provides N pubkeys, receivers provides M signatures
60  mTemplates.insert(std::make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
61  }
62 
63  vSolutionsRet.clear();
64 
65  // Shortcut for pay-to-script-hash, which are more constrained than the other types:
66  // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
67  if (scriptPubKey.IsPayToScriptHash())
68  {
69  typeRet = TX_SCRIPTHASH;
70  std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
71  vSolutionsRet.push_back(hashBytes);
72  return true;
73  }
75  int nType = 0;
76  bool fIsOwner = false;
77  if (scriptPubKey.IsAssetScript(nType, fIsOwner)) {
78  typeRet = (txnouttype)nType;
79  std::vector<unsigned char> hashBytes(scriptPubKey.begin()+3, scriptPubKey.begin()+23);
80  vSolutionsRet.push_back(hashBytes);
81  return true;
82  }
85  int witnessversion;
86  std::vector<unsigned char> witnessprogram;
87  if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
88  if (witnessversion == 0 && witnessprogram.size() == 20) {
89  typeRet = TX_WITNESS_V0_KEYHASH;
90  vSolutionsRet.push_back(witnessprogram);
91  return true;
92  }
93  if (witnessversion == 0 && witnessprogram.size() == 32) {
94  typeRet = TX_WITNESS_V0_SCRIPTHASH;
95  vSolutionsRet.push_back(witnessprogram);
96  return true;
97  }
98  return false;
99  }
100 
101  // Provably prunable, data-carrying output
102  //
103  // So long as script passes the IsUnspendable() test and all but the first
104  // byte passes the IsPushOnly() test we don't care what exactly is in the
105  // script.
106  if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
107  typeRet = TX_NULL_DATA;
108  return true;
109  }
110 
111  // Provably prunable, asset data-carrying output
112  //
113  // So long as script passes the IsUnspendable() test and all but the first three
114  // byte passes the IsPushOnly()
115  if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RVN_ASSET && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
116  typeRet = TX_RESTRICTED_ASSET_DATA;
117 
118  if (scriptPubKey.size() >= 23 && scriptPubKey[1] != OP_RESERVED) {
119  std::vector<unsigned char> hashBytes(scriptPubKey.begin() + 2, scriptPubKey.begin() + 22);
120  vSolutionsRet.push_back(hashBytes);
121  }
122  return true;
123  }
124 
125  // Scan templates
126  const CScript& script1 = scriptPubKey;
127  for (const std::pair<txnouttype, CScript>& tplate : mTemplates)
128  {
129  const CScript& script2 = tplate.second;
130  vSolutionsRet.clear();
131 
132  opcodetype opcode1, opcode2;
133  std::vector<unsigned char> vch1, vch2;
134 
135  // Compare
136  CScript::const_iterator pc1 = script1.begin();
137  CScript::const_iterator pc2 = script2.begin();
138  while (true)
139  {
140  if (pc1 == script1.end() && pc2 == script2.end())
141  {
142  // Found a match
143  typeRet = tplate.first;
144  if (typeRet == TX_MULTISIG)
145  {
146  // Additional checks for TX_MULTISIG:
147  unsigned char m = vSolutionsRet.front()[0];
148  unsigned char n = vSolutionsRet.back()[0];
149  if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
150  return false;
151  }
152  return true;
153  }
154  if (!script1.GetOp(pc1, opcode1, vch1))
155  break;
156  if (!script2.GetOp(pc2, opcode2, vch2))
157  break;
158 
159  // Template matching opcodes:
160  if (opcode2 == OP_PUBKEYS)
161  {
162  while (vch1.size() >= 33 && vch1.size() <= 65)
163  {
164  vSolutionsRet.push_back(vch1);
165  if (!script1.GetOp(pc1, opcode1, vch1))
166  break;
167  }
168  if (!script2.GetOp(pc2, opcode2, vch2))
169  break;
170  // Normal situation is to fall through
171  // to other if/else statements
172  }
173 
174  if (opcode2 == OP_PUBKEY)
175  {
176  if (vch1.size() < 33 || vch1.size() > 65)
177  break;
178  vSolutionsRet.push_back(vch1);
179  }
180  else if (opcode2 == OP_PUBKEYHASH)
181  {
182  if (vch1.size() != sizeof(uint160))
183  break;
184  vSolutionsRet.push_back(vch1);
185  }
186  else if (opcode2 == OP_SMALLINTEGER)
187  { // Single-byte small integer pushed onto vSolutions
188  if (opcode1 == OP_0 ||
189  (opcode1 >= OP_1 && opcode1 <= OP_16))
190  {
191  char n = (char)CScript::DecodeOP_N(opcode1);
192  vSolutionsRet.push_back(valtype(1, n));
193  }
194  else
195  break;
196  }
197  else if (opcode1 != opcode2 || vch1 != vch2)
198  {
199  // Others must match exactly
200  break;
201  }
202  }
203  }
204 
205  vSolutionsRet.clear();
206  typeRet = TX_NONSTANDARD;
207  return false;
208 }
209 
210 bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
211 {
212  std::vector<valtype> vSolutions;
213  txnouttype whichType;
214  if (!Solver(scriptPubKey, whichType, vSolutions)) {
215  return false;
216  }
217 
218  if (whichType == TX_PUBKEY)
219  {
220  CPubKey pubKey(vSolutions[0]);
221  if (!pubKey.IsValid())
222  return false;
223 
224  addressRet = pubKey.GetID();
225  return true;
226  }
227  else if (whichType == TX_PUBKEYHASH)
228  {
229  addressRet = CKeyID(uint160(vSolutions[0]));
230  return true;
231  }
232  else if (whichType == TX_SCRIPTHASH)
233  {
234  addressRet = CScriptID(uint160(vSolutions[0]));
235  return true;
237  } else if (whichType == TX_NEW_ASSET || whichType == TX_REISSUE_ASSET || whichType == TX_TRANSFER_ASSET) {
238  addressRet = CKeyID(uint160(vSolutions[0]));
239  return true;
240  } else if (whichType == TX_RESTRICTED_ASSET_DATA) {
241  if (vSolutions.size()) {
242  addressRet = CKeyID(uint160(vSolutions[0]));
243  return true;
244  }
245  }
247  // Multisig txns have more than one address...
248  return false;
249 }
250 
251 bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
252 {
253  addressRet.clear();
254  typeRet = TX_NONSTANDARD;
255  std::vector<valtype> vSolutions;
256  if (!Solver(scriptPubKey, typeRet, vSolutions))
257  return false;
258  if (typeRet == TX_NULL_DATA) {
259  // This is data, not addresses
260  return false;
261  }
262 
263  if (typeRet == TX_MULTISIG)
264  {
265  nRequiredRet = vSolutions.front()[0];
266  for (unsigned int i = 1; i < vSolutions.size()-1; i++)
267  {
268  CPubKey pubKey(vSolutions[i]);
269  if (!pubKey.IsValid())
270  continue;
271 
272  CTxDestination address = pubKey.GetID();
273  addressRet.push_back(address);
274  }
275 
276  if (addressRet.empty())
277  return false;
278  }
279  else
280  {
281  nRequiredRet = 1;
282  CTxDestination address;
283  if (!ExtractDestination(scriptPubKey, address))
284  return false;
285  addressRet.push_back(address);
286  }
287 
288  return true;
289 }
290 
291 namespace
292 {
293 class CScriptVisitor : public boost::static_visitor<bool>
294 {
295 private:
296  CScript *script;
297 public:
298  explicit CScriptVisitor(CScript *scriptin) { script = scriptin; }
299 
300  bool operator()(const CNoDestination &dest) const {
301  script->clear();
302  return false;
303  }
304 
305  bool operator()(const CKeyID &keyID) const {
306  script->clear();
307  *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
308  return true;
309  }
310 
311  bool operator()(const CScriptID &scriptID) const {
312  script->clear();
313  *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
314  return true;
315  }
316 };
317 } // namespace
318 
319 namespace
320 {
321  class CNullAssetScriptVisitor : public boost::static_visitor<bool>
322  {
323  private:
324  CScript *script;
325  public:
326  explicit CNullAssetScriptVisitor(CScript *scriptin) { script = scriptin; }
327 
328  bool operator()(const CNoDestination &dest) const {
329  script->clear();
330  return false;
331  }
332 
333  bool operator()(const CKeyID &keyID) const {
334  script->clear();
335  *script << OP_RVN_ASSET << ToByteVector(keyID);
336  return true;
337  }
338 
339  bool operator()(const CScriptID &scriptID) const {
340  script->clear();
341  *script << OP_RVN_ASSET << ToByteVector(scriptID);
342  return true;
343  }
344  };
345 } // namespace
346 
348 {
349  CScript script;
350 
351  boost::apply_visitor(CScriptVisitor(&script), dest);
352  return script;
353 }
354 
356 {
357  CScript script;
358 
359  boost::apply_visitor(CNullAssetScriptVisitor(&script), dest);
360  return script;
361 }
362 
364 {
365  return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
366 }
367 
368 CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
369 {
370  CScript script;
371 
372  script << CScript::EncodeOP_N(nRequired);
373  for (const CPubKey& key : keys)
374  script << ToByteVector(key);
375  script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
376  return script;
377 }
378 
379 CScript GetScriptForWitness(const CScript& redeemscript)
380 {
381  CScript ret;
382 
383  txnouttype typ;
384  std::vector<std::vector<unsigned char> > vSolutions;
385  if (Solver(redeemscript, typ, vSolutions)) {
386  if (typ == TX_PUBKEY) {
387  unsigned char h160[20];
388  CHash160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160);
389  ret << OP_0 << std::vector<unsigned char>(&h160[0], &h160[20]);
390  return ret;
391  } else if (typ == TX_PUBKEYHASH) {
392  ret << OP_0 << vSolutions[0];
393  return ret;
394  }
395  }
396  uint256 hash;
397  CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin());
398  ret << OP_0 << ToByteVector(hash);
399  return ret;
400 }
401 
403  return dest.which() != 0;
404 }
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:202
RVN START.
Definition: script.h:188
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:89
static int DecodeOP_N(opcodetype opcode)
Encode/decode small integers:
Definition: script.h:583
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:210
unspendable OP_RETURN script that carries data
Definition: standard.h:65
bool IsPayToScriptHash() const
Definition: script.cpp:221
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:402
bool fAcceptDatacarrier
A data carrying output is an unspendable output containing data.
Definition: standard.cpp:19
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:363
bool IsWitnessProgram(int &version, std::vector< unsigned char > &program) const
Definition: script.cpp:368
uint160 Hash160(const T1 pbegin, const T1 pend)
Compute the 160-bit hash an object.
Definition: hash.h:208
CScriptID()
Definition: standard.h:26
uint160()
Definition: uint256.h:114
unsigned char * begin()
Definition: uint256.h:57
#define ASSET_TRANSFER_STRING
Definition: assets.h:47
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:143
const unsigned char * begin() const
Definition: pubkey.h:99
Definition: script.h:77
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:251
iterator end()
Definition: prevector.h:293
opcodetype
Script opcodes.
Definition: script.h:51
const unsigned char * end() const
Definition: pubkey.h:100
bool IsPushOnly(const_iterator pc) const
Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
Definition: script.cpp:400
bool IsValid() const
Definition: pubkey.h:159
An encapsulated public key.
Definition: pubkey.h:40
RVN END.
Definition: script.h:193
Definition: script.h:61
std::vector< unsigned char > valtype
Definition: standard.cpp:17
CHash160 & Write(const unsigned char *data, size_t len)
Definition: hash.h:112
const char * GetTxnOutputType(txnouttype t)
Get the name of a txnouttype as a C string, or nullptr if unknown.
Definition: standard.cpp:24
unsigned int size() const
Definition: uint256.h:77
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Raven scriptPubKey for the given CTxDestination.
Definition: standard.cpp:347
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:47
txnouttype
Definition: standard.h:57
256-bit opaque blob.
Definition: uint256.h:123
static opcodetype EncodeOP_N(int n)
Definition: script.h:590
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:396
RVN START.
Definition: standard.h:69
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: hash.h:106
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:30
#define ASSET_REISSUE_STRING
Definition: assets.h:49
160-bit opaque blob.
Definition: uint256.h:112
iterator begin()
Definition: prevector.h:291
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:23
size_type size() const
Definition: prevector.h:283
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:368
bool GetOp(iterator &pc, opcodetype &opcodeRet, std::vector< unsigned char > &vchRet)
Definition: script.h:503
#define ASSET_NEW_STRING
Definition: assets.h:48
A hasher class for Raven&#39;s 160-bit hash (SHA-256 + RIPEMD-160).
Definition: hash.h:100
A hasher class for SHA-256.
Definition: sha256.h:14
Definition: script.h:54
void clear()
Definition: script.h:689
CScript GetScriptForWitness(const CScript &redeemscript)
Generate a pay-to-witness script for the given redeem script.
Definition: standard.cpp:379
unsigned nMaxDatacarrierBytes
Maximum size of TX_NULL_DATA scripts that this node considers standard.
Definition: standard.cpp:20
unspendable OP_RAVEN_ASSET script that carries data
Definition: standard.h:72
CScript GetScriptForNullAssetDataDestination(const CTxDestination &dest)
Generate a script that contains an address used for qualifier, and restricted assets data transaction...
Definition: standard.cpp:355
Definition: script.h:103
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:45
bool IsAssetScript(int &nType, bool &fIsOwner, int &nStartingIndex) const
Definition: script.cpp:245