Fabcoin Core  0.16.2
P2P Digital Currency
standard.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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 #include <fasc/fascstate.h>
15 #include <fasc/fasctransaction.h>
16 #include <validation.h>
17 
18 typedef std::vector<unsigned char> valtype;
19 
20 bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
21 unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
22 
23 CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
24 
26 {
27  switch (t)
28  {
29  case TX_NONSTANDARD: return "nonstandard";
30  case TX_PUBKEY: return "pubkey";
31  case TX_PUBKEYHASH: return "pubkeyhash";
32  case TX_SCRIPTHASH: return "scripthash";
33  case TX_MULTISIG: return "multisig";
34  case TX_NULL_DATA: return "nulldata";
35  case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
36  case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
37  case TX_CREATE: return "create";
38  case TX_CALL: return "call";
39  }
40  return nullptr;
41 }
42 
46 bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet, bool contractConsensus)
47 {
48  //contractConsesus is true when evaluating if a contract tx is "standard" for consensus purposes
49  //It is false in all other cases, so to prevent a particular contract tx from being broadcast on mempool, but allowed in blocks,
50  //one should ensure that contractConsensus is false
51 
52  // Templates
53  static std::multimap<txnouttype, CScript> mTemplates;
54  if (mTemplates.empty())
55  {
56  // Standard tx, sender provides pubkey, receiver adds signature
57  mTemplates.insert(std::make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
58 
59  // Fabcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
60  mTemplates.insert(std::make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
61 
62  // Sender provides N pubkeys, receivers provides M signatures
63  mTemplates.insert(std::make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
64  // Contract creation tx
65  mTemplates.insert(std::make_pair(TX_CREATE, CScript() << OP_VERSION << OP_GAS_LIMIT << OP_GAS_PRICE << OP_DATA << OP_CREATE));
66 
67  // Call contract tx
68  mTemplates.insert(std::make_pair(TX_CALL, CScript() << OP_VERSION << OP_GAS_LIMIT << OP_GAS_PRICE << OP_DATA << OP_PUBKEYHASH << OP_CALL));
69  }
70 
71  vSolutionsRet.clear();
72 
73  // Shortcut for pay-to-script-hash, which are more constrained than the other types:
74  // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
75  if (scriptPubKey.IsPayToScriptHash())
76  {
77  typeRet = TX_SCRIPTHASH;
78  std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
79  vSolutionsRet.push_back(hashBytes);
80  return true;
81  }
82 
83  int witnessversion;
84  std::vector<unsigned char> witnessprogram;
85  if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
86  if (witnessversion == 0 && witnessprogram.size() == 20) {
87  typeRet = TX_WITNESS_V0_KEYHASH;
88  vSolutionsRet.push_back(witnessprogram);
89  return true;
90  }
91  if (witnessversion == 0 && witnessprogram.size() == 32) {
92  typeRet = TX_WITNESS_V0_SCRIPTHASH;
93  vSolutionsRet.push_back(witnessprogram);
94  return true;
95  }
96  return false;
97  }
98 
99  // Provably prunable, data-carrying output
100  //
101  // So long as script passes the IsUnspendable() test and all but the first
102  // byte passes the IsPushOnly() test we don't care what exactly is in the
103  // script.
104  if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
105  typeRet = TX_NULL_DATA;
106  return true;
107  }
108 
109  // Scan templates
110  const CScript& script1 = scriptPubKey;
111  for (const std::pair<txnouttype, CScript>& tplate : mTemplates)
112  {
113  const CScript& script2 = tplate.second;
114  vSolutionsRet.clear();
115 
116  opcodetype opcode1, opcode2;
117  std::vector<unsigned char> vch1, vch2;
119  version.rootVM=20; //set to some invalid value
120 
121  // Compare
122  CScript::const_iterator pc1 = script1.begin();
123  CScript::const_iterator pc2 = script2.begin();
124  while (true)
125  {
126  if (pc1 == script1.end() && pc2 == script2.end())
127  {
128  // Found a match
129  typeRet = tplate.first;
130  if (typeRet == TX_MULTISIG)
131  {
132  // Additional checks for TX_MULTISIG:
133  unsigned char m = vSolutionsRet.front()[0];
134  unsigned char n = vSolutionsRet.back()[0];
135  if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
136  return false;
137  }
138  return true;
139  }
140  if (!script1.GetOp(pc1, opcode1, vch1))
141  break;
142  if (!script2.GetOp(pc2, opcode2, vch2))
143  break;
144 
145  // Template matching opcodes:
146  if (opcode2 == OP_PUBKEYS)
147  {
148  while (vch1.size() >= 33 && vch1.size() <= 65)
149  {
150  vSolutionsRet.push_back(vch1);
151  if (!script1.GetOp(pc1, opcode1, vch1))
152  break;
153  }
154  if (!script2.GetOp(pc2, opcode2, vch2))
155  break;
156  // Normal situation is to fall through
157  // to other if/else statements
158  }
159 
160  if (opcode2 == OP_PUBKEY)
161  {
162  if (vch1.size() < 33 || vch1.size() > 65)
163  break;
164  vSolutionsRet.push_back(vch1);
165  }
166  else if (opcode2 == OP_PUBKEYHASH)
167  {
168  if (vch1.size() != sizeof(uint160))
169  break;
170  vSolutionsRet.push_back(vch1);
171  }
172  else if (opcode2 == OP_SMALLINTEGER)
173  { // Single-byte small integer pushed onto vSolutions
174  if (opcode1 == OP_0 ||
175  (opcode1 >= OP_1 && opcode1 <= OP_16))
176  {
177  char n = (char)CScript::DecodeOP_N(opcode1);
178  vSolutionsRet.push_back(valtype(1, n));
179  }
180  else
181  break;
182  }
184  else if (opcode2 == OP_VERSION)
185  {
186  if(0 <= opcode1 && opcode1 <= OP_PUSHDATA4)
187  {
188  if(vch1.empty() || vch1.size() > 4 || (vch1.back() & 0x80))
189  return false;
190 
192  if(!(version.toRaw() == VersionVM::GetEVMDefault().toRaw() || version.toRaw() == VersionVM::GetNoExec().toRaw())){
193  // only allow standard EVM and no-exec transactions to live in mempool
194  return false;
195  }
196  }
197  }
198  else if(opcode2 == OP_GAS_LIMIT) {
199  try {
200  uint64_t val = CScriptNum::vch_to_uint64(vch1);
201  if(contractConsensus) {
202  //consensus rules (this is checked more in depth later using DGP)
203  if (version.rootVM != 0 && val < 1) {
204  return false;
205  }
206  if (val > MAX_BLOCK_GAS_LIMIT_DGP) {
207  //do not allow transactions that could use more gas than is in a block
208  return false;
209  }
210  }else{
211  //standard mempool rules for contracts
212  //consensus rules for contracts
213  if (version.rootVM != 0 && val < STANDARD_MINIMUM_GAS_LIMIT) {
214  return false;
215  }
216  if (val > DEFAULT_BLOCK_GAS_LIMIT_DGP / 2) {
217  //don't allow transactions that use more than 1/2 block of gas to be broadcast on the mempool
218  return false;
219  }
220 
221  }
222  }
223  catch (const scriptnum_error &err) {
224  return false;
225  }
226  }
227  else if(opcode2 == OP_GAS_PRICE) {
228  try {
229  uint64_t val = CScriptNum::vch_to_uint64(vch1);
230  if(contractConsensus) {
231  //consensus rules (this is checked more in depth later using DGP)
232  if (version.rootVM != 0 && val < 1) {
233  return false;
234  }
235  }else{
236  //standard mempool rules
237  if (version.rootVM != 0 && val < STANDARD_MINIMUM_GAS_PRICE) {
238  return false;
239  }
240  }
241  }
242  catch (const scriptnum_error &err) {
243  return false;
244  }
245  }
246  else if(opcode2 == OP_DATA)
247  {
248  if(0 <= opcode1 && opcode1 <= OP_PUSHDATA4)
249  {
250  if(vch1.empty())
251  break;
252  }
253  }
255  else if (opcode1 != opcode2 || vch1 != vch2)
256  {
257  // Others must match exactly
258  break;
259  }
260  }
261  }
262 
263  vSolutionsRet.clear();
264  typeRet = TX_NONSTANDARD;
265  return false;
266 }
267 
268 bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, txnouttype *typeRet)
269 {
270  std::vector<valtype> vSolutions;
271  txnouttype whichType;
272  if (!Solver(scriptPubKey, whichType, vSolutions))
273  return false;
274 
275  if(typeRet){
276  *typeRet = whichType;
277  }
278 
279  if (whichType == TX_PUBKEY)
280  {
281  CPubKey pubKey(vSolutions[0]);
282  if (!pubKey.IsValid())
283  return false;
284 
285  addressRet = pubKey.GetID();
286  return true;
287  }
288  else if (whichType == TX_PUBKEYHASH)
289  {
290  addressRet = CKeyID(uint160(vSolutions[0]));
291  return true;
292  }
293  else if (whichType == TX_SCRIPTHASH)
294  {
295  addressRet = CScriptID(uint160(vSolutions[0]));
296  return true;
297  }
298  // Multisig txns have more than one address...
299  return false;
300 }
301 
302 bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
303 {
304  addressRet.clear();
305  typeRet = TX_NONSTANDARD;
306  std::vector<valtype> vSolutions;
307  if (!Solver(scriptPubKey, typeRet, vSolutions))
308  return false;
309  if (typeRet == TX_NULL_DATA){
310  // This is data, not addresses
311  return false;
312  }
313 
314  if (typeRet == TX_MULTISIG)
315  {
316  nRequiredRet = vSolutions.front()[0];
317  for (unsigned int i = 1; i < vSolutions.size()-1; i++)
318  {
319  CPubKey pubKey(vSolutions[i]);
320  if (!pubKey.IsValid())
321  continue;
322 
323  CTxDestination address = pubKey.GetID();
324  addressRet.push_back(address);
325  }
326 
327  if (addressRet.empty())
328  return false;
329  }
330  else
331  {
332  nRequiredRet = 1;
334  if (!ExtractDestination(scriptPubKey, address))
335  return false;
336  addressRet.push_back(address);
337  }
338 
339  return true;
340 }
341 
342 namespace
343 {
344 class CScriptVisitor : public boost::static_visitor<bool>
345 {
346 private:
347  CScript *script;
348 public:
349  CScriptVisitor(CScript *scriptin) { script = scriptin; }
350 
351  bool operator()(const CNoDestination &dest) const {
352  script->clear();
353  return false;
354  }
355 
356  bool operator()(const CKeyID &keyID) const {
357  script->clear();
358  *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
359  return true;
360  }
361 
362  bool operator()(const CScriptID &scriptID) const {
363  script->clear();
364  *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
365  return true;
366  }
367 };
368 } // namespace
369 
371 {
372  CScript script;
373 
374  boost::apply_visitor(CScriptVisitor(&script), dest);
375  return script;
376 }
377 
379 {
380  return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
381 }
382 
383 CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
384 {
385  CScript script;
386 
387  script << CScript::EncodeOP_N(nRequired);
388  for (const CPubKey& key : keys)
389  script << ToByteVector(key);
390  script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
391  return script;
392 }
393 
394 CScript GetScriptForWitness(const CScript& redeemscript)
395 {
396  CScript ret;
397 
398  txnouttype typ;
399  std::vector<std::vector<unsigned char> > vSolutions;
400  if (Solver(redeemscript, typ, vSolutions)) {
401  if (typ == TX_PUBKEY) {
402  unsigned char h160[20];
403  CHash160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160);
404  ret << OP_0 << std::vector<unsigned char>(&h160[0], &h160[20]);
405  return ret;
406  } else if (typ == TX_PUBKEYHASH) {
407  ret << OP_0 << vSolutions[0];
408  return ret;
409  }
410  }
411  uint256 hash;
412  CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin());
413  ret << OP_0 << ToByteVector(hash);
414  return ret;
415 }
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:201
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:79
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< std::vector< unsigned char > > &vSolutionsRet, bool contractConsensus)
Return public keys or hashes from scriptPubKey, for &#39;standard&#39; transaction types. ...
Definition: standard.cpp:46
static int DecodeOP_N(opcodetype opcode)
Encode/decode small integers:
Definition: script.h:603
static VersionVM GetNoExec()
bool IsPushOnly(const_iterator pc) const
Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
Definition: script.cpp:268
uint8_t rootVM
bool IsPayToScriptHash() const
Definition: script.cpp:207
static VersionVM GetEVMDefault()
bool fAcceptDatacarrier
Definition: standard.cpp:20
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Definition: standard.cpp:378
uint160 Hash160(const T1 pbegin, const T1 pend)
Compute the 160-bit hash an object.
Definition: hash.h:107
CScriptID()
Definition: standard.h:31
uint160()
Definition: uint256.h:122
unsigned char * begin()
Definition: uint256.h:65
void version()
Definition: main.cpp:53
Definition: script.h:74
bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< CTxDestination > &addressRet, int &nRequiredRet)
Definition: standard.cpp:302
size_type size() const
Definition: prevector.h:282
iterator end()
Definition: prevector.h:292
opcodetype
Script opcodes.
Definition: script.h:48
static uint64_t vch_to_uint64(const std::vector< unsigned char > &vch)
Definition: script.h:337
uint32_t toRaw()
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet, txnouttype *typeRet)
Definition: standard.cpp:268
An encapsulated public key.
Definition: pubkey.h:39
bool IsWitnessProgram(int &version, std::vector< unsigned char > &program) const
Definition: script.cpp:252
Definition: script.h:58
std::vector< unsigned char > valtype
Definition: standard.cpp:18
CHash160 & Write(const unsigned char *data, size_t len)
Definition: hash.h:57
const char * GetTxnOutputType(txnouttype t)
Definition: standard.cpp:25
static VersionVM fromRaw(uint32_t val)
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:370
const unsigned char * begin() const
Definition: pubkey.h:98
txnouttype
Definition: standard.h:51
256-bit opaque blob.
Definition: uint256.h:132
static opcodetype EncodeOP_N(int n)
Definition: script.h:610
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:417
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: hash.h:51
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
bool IsValid() const
Definition: pubkey.h:162
160-bit opaque blob.
Definition: uint256.h:120
iterator begin()
Definition: prevector.h:290
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:28
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Definition: standard.cpp:383
FixedHash< 20 > h160
Definition: FixedHash.h:341
bool GetOp(iterator &pc, opcodetype &opcodeRet, std::vector< unsigned char > &vchRet)
Definition: script.h:523
struct evm_uint160be address(struct evm_env *env)
Definition: capi.c:13
A hasher class for Fabcoin&#39;s 160-bit hash (SHA-256 + RIPEMD-160).
Definition: hash.h:45
A hasher class for SHA-256.
Definition: sha256.h:13
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:146
Definition: script.h:51
void clear()
Definition: script.h:712
CScript GetScriptForWitness(const CScript &redeemscript)
Definition: standard.cpp:394
unsigned nMaxDatacarrierBytes
Definition: standard.cpp:21
const unsigned char * end() const
Definition: pubkey.h:99
Definition: script.h:100
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:42
unsigned int size() const
Definition: uint256.h:85