hdac SDK
SDK for hdac blockchain development
script.h
1 #ifndef SCRIPT_H
2 #define SCRIPT_H
3 
4 #include <cassert>
5 #include <vector>
6 #include <limits>
7 #include <cstring>
8 #include <string>
9 #include <stdexcept>
10 #include "hdacscript.h"
11 
12 template <typename T>
13 std::vector<unsigned char> ToByteVector(const T& in)
14 {
15  return std::vector<unsigned char>(in.begin(), in.end());
16 }
17 
19 enum opcodetype
20 {
21  // push value
22  OP_0 = 0x00,
23  OP_FALSE = OP_0,
24  OP_PUSHDATA1 = 0x4c,
25  OP_PUSHDATA2 = 0x4d,
26  OP_PUSHDATA4 = 0x4e,
27  OP_1NEGATE = 0x4f,
28  OP_RESERVED = 0x50,
29  OP_1 = 0x51,
30  OP_TRUE=OP_1,
31  OP_2 = 0x52,
32  OP_3 = 0x53,
33  OP_4 = 0x54,
34  OP_5 = 0x55,
35  OP_6 = 0x56,
36  OP_7 = 0x57,
37  OP_8 = 0x58,
38  OP_9 = 0x59,
39  OP_10 = 0x5a,
40  OP_11 = 0x5b,
41  OP_12 = 0x5c,
42  OP_13 = 0x5d,
43  OP_14 = 0x5e,
44  OP_15 = 0x5f,
45  OP_16 = 0x60,
46 
47  // control
48  OP_NOP = 0x61,
49  OP_VER = 0x62,
50  OP_IF = 0x63,
51  OP_NOTIF = 0x64,
52  OP_VERIF = 0x65,
53  OP_VERNOTIF = 0x66,
54  OP_ELSE = 0x67,
55  OP_ENDIF = 0x68,
56  OP_VERIFY = 0x69,
57  OP_RETURN = 0x6a,
58 
59  // stack ops
60  OP_TOALTSTACK = 0x6b,
61  OP_FROMALTSTACK = 0x6c,
62  OP_2DROP = 0x6d,
63  OP_2DUP = 0x6e,
64  OP_3DUP = 0x6f,
65  OP_2OVER = 0x70,
66  OP_2ROT = 0x71,
67  OP_2SWAP = 0x72,
68  OP_IFDUP = 0x73,
69  OP_DEPTH = 0x74,
70  OP_DROP = 0x75,
71  OP_DUP = 0x76,
72  OP_NIP = 0x77,
73  OP_OVER = 0x78,
74  OP_PICK = 0x79,
75  OP_ROLL = 0x7a,
76  OP_ROT = 0x7b,
77  OP_SWAP = 0x7c,
78  OP_TUCK = 0x7d,
79 
80  // splice ops
81  OP_CAT = 0x7e,
82  OP_SUBSTR = 0x7f,
83  OP_LEFT = 0x80,
84  OP_RIGHT = 0x81,
85  OP_SIZE = 0x82,
86 
87  // bit logic
88  OP_INVERT = 0x83,
89  OP_AND = 0x84,
90  OP_OR = 0x85,
91  OP_XOR = 0x86,
92  OP_EQUAL = 0x87,
93  OP_EQUALVERIFY = 0x88,
94  OP_RESERVED1 = 0x89,
95  OP_RESERVED2 = 0x8a,
96 
97  // numeric
98  OP_1ADD = 0x8b,
99  OP_1SUB = 0x8c,
100  OP_2MUL = 0x8d,
101  OP_2DIV = 0x8e,
102  OP_NEGATE = 0x8f,
103  OP_ABS = 0x90,
104  OP_NOT = 0x91,
105  OP_0NOTEQUAL = 0x92,
106 
107  OP_ADD = 0x93,
108  OP_SUB = 0x94,
109  OP_MUL = 0x95,
110  OP_DIV = 0x96,
111  OP_MOD = 0x97,
112  OP_LSHIFT = 0x98,
113  OP_RSHIFT = 0x99,
114 
115  OP_BOOLAND = 0x9a,
116  OP_BOOLOR = 0x9b,
117  OP_NUMEQUAL = 0x9c,
118  OP_NUMEQUALVERIFY = 0x9d,
119  OP_NUMNOTEQUAL = 0x9e,
120  OP_LESSTHAN = 0x9f,
121  OP_GREATERTHAN = 0xa0,
122  OP_LESSTHANOREQUAL = 0xa1,
123  OP_GREATERTHANOREQUAL = 0xa2,
124  OP_MIN = 0xa3,
125  OP_MAX = 0xa4,
126 
127  OP_WITHIN = 0xa5,
128 
129  // crypto
130  OP_RIPEMD160 = 0xa6,
131  OP_SHA1 = 0xa7,
132  OP_SHA256 = 0xa8,
133  OP_HASH160 = 0xa9,
134  OP_HASH256 = 0xaa,
135  OP_CODESEPARATOR = 0xab,
136  OP_CHECKSIG = 0xac,
137  OP_CHECKSIGVERIFY = 0xad,
138  OP_CHECKMULTISIG = 0xae,
139  OP_CHECKMULTISIGVERIFY = 0xaf,
140 
141  // expansion
142  OP_NOP1 = 0xb0,
143  OP_NOP2 = 0xb1,
144  OP_NOP3 = 0xb2,
145  OP_NOP4 = 0xb3,
146  OP_NOP5 = 0xb4,
147  OP_NOP6 = 0xb5,
148  OP_NOP7 = 0xb6,
149  OP_NOP8 = 0xb7,
150  OP_NOP9 = 0xb8,
151  OP_NOP10 = 0xb9,
152 
153 
154  // template matching params
155  OP_DROPDATA = 0xf8,
156 
157  OP_SMALLDATA = 0xf9,
158  OP_SMALLINTEGER = 0xfa,
159  OP_PUBKEYS = 0xfb,
160  OP_PUBKEYHASH = 0xfd,
161  OP_PUBKEY = 0xfe,
162 
163  OP_INVALIDOPCODE = 0xff,
164 };
165 
166 class scriptnum_error : public std::runtime_error
167 {
168 public:
169  explicit scriptnum_error(const std::string& str) : std::runtime_error(str) {}
170 };
171 
173 {
182 public:
183 
184  explicit CScriptNum(const int64_t& n)
185  {
186  m_value = n;
187  }
188 
189  explicit CScriptNum(const std::vector<unsigned char>& vch, bool fRequireMinimal)
190  {
191  if (vch.size() > nMaxNumSize) {
192  throw scriptnum_error("script number overflow");
193  }
194  if (fRequireMinimal && vch.size() > 0) {
195  // Check that the number is encoded with the minimum possible
196  // number of bytes.
197  //
198  // If the most-significant-byte - excluding the sign bit - is zero
199  // then we're not minimal. Note how this test also rejects the
200  // negative-zero encoding, 0x80.
201  if ((vch.back() & 0x7f) == 0) {
202  // One exception: if there's more than one byte and the most
203  // significant bit of the second-most-significant-byte is set
204  // it would conflict with the sign bit. An example of this case
205  // is +-255, which encode to 0xff00 and 0xff80 respectively.
206  // (big-endian).
207  if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) {
208  throw scriptnum_error("non-minimally encoded script number");
209  }
210  }
211  }
212  m_value = set_vch(vch);
213  }
214 
215  inline bool operator==(const int64_t& rhs) const { return m_value == rhs; }
216  inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; }
217  inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; }
218  inline bool operator< (const int64_t& rhs) const { return m_value < rhs; }
219  inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; }
220  inline bool operator> (const int64_t& rhs) const { return m_value > rhs; }
221 
222  inline bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); }
223  inline bool operator!=(const CScriptNum& rhs) const { return operator!=(rhs.m_value); }
224  inline bool operator<=(const CScriptNum& rhs) const { return operator<=(rhs.m_value); }
225  inline bool operator< (const CScriptNum& rhs) const { return operator< (rhs.m_value); }
226  inline bool operator>=(const CScriptNum& rhs) const { return operator>=(rhs.m_value); }
227  inline bool operator> (const CScriptNum& rhs) const { return operator> (rhs.m_value); }
228 
229  inline CScriptNum operator+( const int64_t& rhs) const { return CScriptNum(m_value + rhs);}
230  inline CScriptNum operator-( const int64_t& rhs) const { return CScriptNum(m_value - rhs);}
231  inline CScriptNum operator+( const CScriptNum& rhs) const { return operator+(rhs.m_value); }
232  inline CScriptNum operator-( const CScriptNum& rhs) const { return operator-(rhs.m_value); }
233 
234  inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); }
235  inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); }
236 
237  inline CScriptNum operator-() const
238  {
239  assert(m_value != std::numeric_limits<int64_t>::min());
240  return CScriptNum(-m_value);
241  }
242 
243  inline CScriptNum& operator=( const int64_t& rhs)
244  {
245  m_value = rhs;
246  return *this;
247  }
248 
249  inline CScriptNum& operator+=( const int64_t& rhs)
250  {
251  assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
252  (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
253  m_value += rhs;
254  return *this;
255  }
256 
257  inline CScriptNum& operator-=( const int64_t& rhs)
258  {
259  assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
260  (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
261  m_value -= rhs;
262  return *this;
263  }
264 
265  int getint() const
266  {
267  if (m_value > std::numeric_limits<int>::max())
268  return std::numeric_limits<int>::max();
269  else if (m_value < std::numeric_limits<int>::min())
270  return std::numeric_limits<int>::min();
271  return (int)m_value;
272  }
273 
274  std::vector<unsigned char> getvch() const
275  {
276  return serialize(m_value);
277  }
278 
279  static std::vector<unsigned char> serialize(const int64_t& value)
280  {
281  if(value == 0)
282  return std::vector<unsigned char>();
283 
284  std::vector<unsigned char> result;
285  const bool neg = value < 0;
286  uint64_t absvalue = neg ? -value : value;
287 
288  while(absvalue)
289  {
290  result.push_back(absvalue & 0xff);
291  absvalue >>= 8;
292  }
293 
294 // - If the most significant byte is >= 0x80 and the value is positive, push a
295 // new zero-byte to make the significant byte < 0x80 again.
296 
297 // - If the most significant byte is >= 0x80 and the value is negative, push a
298 // new 0x80 byte that will be popped off when converting to an integral.
299 
300 // - If the most significant byte is < 0x80 and the value is negative, add
301 // 0x80 to it, since it will be subtracted and interpreted as a negative when
302 // converting to an integral.
303 
304  if (result.back() & 0x80)
305  result.push_back(neg ? 0x80 : 0);
306  else if (neg)
307  result.back() |= 0x80;
308 
309  return result;
310  }
311 
312  static const size_t nMaxNumSize = 4;
313 
314 private:
315  static int64_t set_vch(const std::vector<unsigned char>& vch)
316  {
317  if (vch.empty())
318  return 0;
319 
320  int64_t result = 0;
321  for (size_t i = 0; i != vch.size(); ++i)
322  result |= static_cast<int64_t>(vch[i]) << 8*i;
323 
324  // If the input vector's most significant byte is 0x80, remove it from
325  // the result's msb and return a negative.
326  if (vch.back() & 0x80)
327  return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));
328 
329  return result;
330  }
331 
332  int64_t m_value;
333 };
334 
336 class CScript : public std::vector<unsigned char>
337 {
338 protected:
339  CScript& push_int64(int64_t n)
340  {
341  if (n == -1 || (n >= 1 && n <= 16))
342  {
343  push_back((unsigned char)(n + (OP_1 - 1)));
344  }
345  else if (n == 0)
346  {
347  push_back(OP_0);
348  }
349  else
350  {
351  *this << CScriptNum::serialize(n);
352  }
353  return *this;
354  }
355 public:
356  CScript() { }
357  CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { }
358  CScript(const_iterator pbegin, const_iterator pend) : std::vector<unsigned char>(pbegin, pend) { }
359  CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { }
360 
361  CScript& operator+=(const CScript& b)
362  {
363  insert(end(), b.begin(), b.end());
364  return *this;
365  }
366 
367  friend CScript operator+(const CScript& a, const CScript& b)
368  {
369  CScript ret = a;
370  ret += b;
371  return ret;
372  }
373 
374  CScript(int64_t b) { operator<<(b); }
375 
376  explicit CScript(opcodetype b) { operator<<(b); }
377  explicit CScript(const CScriptNum& b) { operator<<(b); }
378  explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); }
379 
380 
381  CScript& operator<<(int64_t b) { return push_int64(b); }
382 
383  CScript& operator<<(opcodetype opcode)
384  {
385  if (opcode < 0 || opcode > 0xff)
386  throw std::runtime_error("CScript::operator<<() : invalid opcode");
387  insert(end(), (unsigned char)opcode);
388  return *this;
389  }
390 
391  CScript& operator<<(const CScriptNum& b)
392  {
393  *this << b.getvch();
394  return *this;
395  }
396 
397  CScript& operator<<(const std::vector<unsigned char>& b)
398  {
399  if (b.size() < OP_PUSHDATA1)
400  {
401  insert(end(), (unsigned char)b.size());
402  }
403  else if (b.size() <= 0xff)
404  {
405  insert(end(), OP_PUSHDATA1);
406  insert(end(), (unsigned char)b.size());
407  }
408  else if (b.size() <= 0xffff)
409  {
410  insert(end(), OP_PUSHDATA2);
411  unsigned short nSize = (unsigned short)b.size();
412  insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize));
413  }
414  else
415  {
416  insert(end(), OP_PUSHDATA4);
417  unsigned int nSize = b.size();
418  insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize));
419  }
420  insert(end(), b.begin(), b.end());
421  return *this;
422  }
423 
424  CScript& operator<<(const CScript& b)
425  {
426  // I'm not sure if this should push the script or concatenate scripts.
427  // If there's ever a use for pushing a script onto a script, delete this member fn
428  assert(!"Warning: Pushing a CScript onto a CScript with << is probably not intended, use + to concatenate!");
429  return *this;
430  }
431 
432 
433  bool GetOp(iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet)
434  {
435  // Wrapper so it can be called with either iterator or const_iterator
436  const_iterator pc2 = pc;
437  bool fRet = GetOp2(pc2, opcodeRet, &vchRet);
438  pc = begin() + (pc2 - begin());
439  return fRet;
440  }
441 
442  bool GetOp(iterator& pc, opcodetype& opcodeRet)
443  {
444  const_iterator pc2 = pc;
445  bool fRet = GetOp2(pc2, opcodeRet, NULL);
446  pc = begin() + (pc2 - begin());
447  return fRet;
448  }
449 
450  bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
451  {
452  return GetOp2(pc, opcodeRet, &vchRet);
453  }
454 
455  bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const
456  {
457  return GetOp2(pc, opcodeRet, NULL);
458  }
459 
460  bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) const
461  {
462  opcodeRet = OP_INVALIDOPCODE;
463  if (pvchRet)
464  pvchRet->clear();
465  if (pc >= end())
466  return false;
467 
468  // Read instruction
469  if (end() - pc < 1)
470  return false;
471  unsigned int opcode = *pc++;
472 
473  // Immediate operand
474  if (opcode <= OP_PUSHDATA4)
475  {
476  unsigned int nSize = 0;
477  if (opcode < OP_PUSHDATA1)
478  {
479  nSize = opcode;
480  }
481  else if (opcode == OP_PUSHDATA1)
482  {
483  if (end() - pc < 1)
484  return false;
485  nSize = *pc++;
486  }
487  else if (opcode == OP_PUSHDATA2)
488  {
489  if (end() - pc < 2)
490  return false;
491  nSize = 0;
492  memcpy(&nSize, &pc[0], 2);
493  pc += 2;
494  }
495  else if (opcode == OP_PUSHDATA4)
496  {
497  if (end() - pc < 4)
498  return false;
499  memcpy(&nSize, &pc[0], 4);
500  pc += 4;
501  }
502  if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize)
503  return false;
504  if (pvchRet)
505  pvchRet->assign(pc, pc + nSize);
506  pc += nSize;
507  }
508 
509  opcodeRet = (opcodetype)opcode;
510  return true;
511  }
512 
514  static int DecodeOP_N(opcodetype opcode)
515  {
516  if (opcode == OP_0)
517  return 0;
518  assert(opcode >= OP_1 && opcode <= OP_16);
519  return (int)opcode - (int)(OP_1 - 1);
520  }
521  static opcodetype EncodeOP_N(int n)
522  {
523  assert(n >= 0 && n <= 16);
524  if (n == 0)
525  return OP_0;
526  return (opcodetype)(OP_1+n-1);
527  }
528 
529  int FindAndDelete(const CScript& b)
530  {
531  int nFound = 0;
532  if (b.empty())
533  return nFound;
534  iterator pc = begin();
535  opcodetype opcode;
536  do
537  {
538  while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0)
539  {
540  pc = erase(pc, pc + b.size());
541  ++nFound;
542  }
543  }
544  while (GetOp(pc, opcode));
545  return nFound;
546  }
547  int Find(opcodetype op) const
548  {
549  int nFound = 0;
550  opcodetype opcode;
551  for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);)
552  if (opcode == op)
553  ++nFound;
554  return nFound;
555  }
556 
564  unsigned int GetSigOpCount(bool fAccurate) const;
565 
570  unsigned int GetSigOpCount(const CScript& scriptSig) const;
571 
572  bool IsPayToScriptHash() const;
573 
575  bool IsPushOnly() const;
576 
577  bool HasSmallIntegerInTheBeginning() const;
578 
584  bool IsUnspendable() const
585  {
586  int op_drop_offset[2];
587  int op_drop_size[2];
588  int op_return_offset,op_return_size;
589  return (mc_ParseOpDropOpReturnScript((unsigned char*)&begin()[0],(int)size(),op_drop_offset,op_drop_size,2,&op_return_offset,&op_return_size)) != NULL;
590  }
591 
592  std::string ToString() const;
593 
594  CScript RemoveOpDrops() const;
595 
596  void clear()
597  {
598  // The default std::vector::clear() does not release memory.
599  std::vector<unsigned char>().swap(*this);
600  }
601 };
602 
603 const char* GetOpName(opcodetype opcode);
604 
605 #endif // SCRIPT_H
static int DecodeOP_N(opcodetype opcode)
Definition: script.h:514
CScriptNum(const int64_t &n)
Definition: script.h:184
Definition: script.h:166
Definition: script.h:172
bool IsUnspendable() const
Definition: script.h:584
Definition: script.h:336