]> Git Repo - VerusCoin.git/blob - src/script/script.cpp
Reserve import transactions and APIs
[VerusCoin.git] / src / script / script.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 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.h"
7
8 #include "tinyformat.h"
9 #include "utilstrencodings.h"
10 #include "script/cc.h"
11 #include "cc/eval.h"
12 #include "cryptoconditions/include/cryptoconditions.h"
13 #include "standard.h"
14 #include "pbaas/reserves.h"
15
16 using namespace std;
17
18 namespace {
19     inline std::string ValueString(const std::vector<unsigned char>& vch)
20     {
21         if (vch.size() <= 4)
22             return strprintf("%d", CScriptNum(vch, false).getint());
23         else
24             return HexStr(vch);
25     }
26 } // anon namespace
27
28 const char* GetOpName(opcodetype opcode)
29 {
30     switch (opcode)
31     {
32     // push value
33     case OP_0                      : return "0";
34     case OP_PUSHDATA1              : return "OP_PUSHDATA1";
35     case OP_PUSHDATA2              : return "OP_PUSHDATA2";
36     case OP_PUSHDATA4              : return "OP_PUSHDATA4";
37     case OP_1NEGATE                : return "-1";
38     case OP_RESERVED               : return "OP_RESERVED";
39     case OP_1                      : return "1";
40     case OP_2                      : return "2";
41     case OP_3                      : return "3";
42     case OP_4                      : return "4";
43     case OP_5                      : return "5";
44     case OP_6                      : return "6";
45     case OP_7                      : return "7";
46     case OP_8                      : return "8";
47     case OP_9                      : return "9";
48     case OP_10                     : return "10";
49     case OP_11                     : return "11";
50     case OP_12                     : return "12";
51     case OP_13                     : return "13";
52     case OP_14                     : return "14";
53     case OP_15                     : return "15";
54     case OP_16                     : return "16";
55
56     // control
57     case OP_NOP                    : return "OP_NOP";
58     case OP_VER                    : return "OP_VER";
59     case OP_IF                     : return "OP_IF";
60     case OP_NOTIF                  : return "OP_NOTIF";
61     case OP_VERIF                  : return "OP_VERIF";
62     case OP_VERNOTIF               : return "OP_VERNOTIF";
63     case OP_ELSE                   : return "OP_ELSE";
64     case OP_ENDIF                  : return "OP_ENDIF";
65     case OP_VERIFY                 : return "OP_VERIFY";
66     case OP_RETURN                 : return "OP_RETURN";
67
68     // stack ops
69     case OP_TOALTSTACK             : return "OP_TOALTSTACK";
70     case OP_FROMALTSTACK           : return "OP_FROMALTSTACK";
71     case OP_2DROP                  : return "OP_2DROP";
72     case OP_2DUP                   : return "OP_2DUP";
73     case OP_3DUP                   : return "OP_3DUP";
74     case OP_2OVER                  : return "OP_2OVER";
75     case OP_2ROT                   : return "OP_2ROT";
76     case OP_2SWAP                  : return "OP_2SWAP";
77     case OP_IFDUP                  : return "OP_IFDUP";
78     case OP_DEPTH                  : return "OP_DEPTH";
79     case OP_DROP                   : return "OP_DROP";
80     case OP_DUP                    : return "OP_DUP";
81     case OP_NIP                    : return "OP_NIP";
82     case OP_OVER                   : return "OP_OVER";
83     case OP_PICK                   : return "OP_PICK";
84     case OP_ROLL                   : return "OP_ROLL";
85     case OP_ROT                    : return "OP_ROT";
86     case OP_SWAP                   : return "OP_SWAP";
87     case OP_TUCK                   : return "OP_TUCK";
88
89     // splice ops
90     case OP_CAT                    : return "OP_CAT";
91     case OP_SUBSTR                 : return "OP_SUBSTR";
92     case OP_LEFT                   : return "OP_LEFT";
93     case OP_RIGHT                  : return "OP_RIGHT";
94     case OP_SIZE                   : return "OP_SIZE";
95
96     // bit logic
97     case OP_INVERT                 : return "OP_INVERT";
98     case OP_AND                    : return "OP_AND";
99     case OP_OR                     : return "OP_OR";
100     case OP_XOR                    : return "OP_XOR";
101     case OP_EQUAL                  : return "OP_EQUAL";
102     case OP_EQUALVERIFY            : return "OP_EQUALVERIFY";
103     case OP_RESERVED1              : return "OP_RESERVED1";
104     case OP_RESERVED2              : return "OP_RESERVED2";
105
106     // numeric
107     case OP_1ADD                   : return "OP_1ADD";
108     case OP_1SUB                   : return "OP_1SUB";
109     case OP_2MUL                   : return "OP_2MUL";
110     case OP_2DIV                   : return "OP_2DIV";
111     case OP_NEGATE                 : return "OP_NEGATE";
112     case OP_ABS                    : return "OP_ABS";
113     case OP_NOT                    : return "OP_NOT";
114     case OP_0NOTEQUAL              : return "OP_0NOTEQUAL";
115     case OP_ADD                    : return "OP_ADD";
116     case OP_SUB                    : return "OP_SUB";
117     case OP_MUL                    : return "OP_MUL";
118     case OP_DIV                    : return "OP_DIV";
119     case OP_MOD                    : return "OP_MOD";
120     case OP_LSHIFT                 : return "OP_LSHIFT";
121     case OP_RSHIFT                 : return "OP_RSHIFT";
122     case OP_BOOLAND                : return "OP_BOOLAND";
123     case OP_BOOLOR                 : return "OP_BOOLOR";
124     case OP_NUMEQUAL               : return "OP_NUMEQUAL";
125     case OP_NUMEQUALVERIFY         : return "OP_NUMEQUALVERIFY";
126     case OP_NUMNOTEQUAL            : return "OP_NUMNOTEQUAL";
127     case OP_LESSTHAN               : return "OP_LESSTHAN";
128     case OP_GREATERTHAN            : return "OP_GREATERTHAN";
129     case OP_LESSTHANOREQUAL        : return "OP_LESSTHANOREQUAL";
130     case OP_GREATERTHANOREQUAL     : return "OP_GREATERTHANOREQUAL";
131     case OP_MIN                    : return "OP_MIN";
132     case OP_MAX                    : return "OP_MAX";
133     case OP_WITHIN                 : return "OP_WITHIN";
134
135     // crypto
136     case OP_RIPEMD160              : return "OP_RIPEMD160";
137     case OP_SHA1                   : return "OP_SHA1";
138     case OP_SHA256                 : return "OP_SHA256";
139     case OP_HASH160                : return "OP_HASH160";
140     case OP_HASH256                : return "OP_HASH256";
141     case OP_CODESEPARATOR          : return "OP_CODESEPARATOR";
142     case OP_CHECKSIG               : return "OP_CHECKSIG";
143     case OP_CHECKSIGVERIFY         : return "OP_CHECKSIGVERIFY";
144     case OP_CHECKMULTISIG          : return "OP_CHECKMULTISIG";
145     case OP_CHECKMULTISIGVERIFY    : return "OP_CHECKMULTISIGVERIFY";
146     case OP_CHECKCRYPTOCONDITION   : return "OP_CHECKCRYPTOCONDITION";
147     case OP_CHECKCRYPTOCONDITIONVERIFY
148                                    : return "OP_CHECKCRYPTOCONDITIONVERIFY";
149
150     // expansion
151     case OP_NOP1                   : return "OP_NOP1";
152     case OP_NOP2                   : return "OP_NOP2";
153     case OP_NOP3                   : return "OP_NOP3";
154     case OP_NOP4                   : return "OP_NOP4";
155     case OP_NOP5                   : return "OP_NOP5";
156     case OP_NOP6                   : return "OP_NOP6";
157     case OP_NOP7                   : return "OP_NOP7";
158     case OP_NOP8                   : return "OP_NOP8";
159     case OP_NOP9                   : return "OP_NOP9";
160     case OP_NOP10                  : return "OP_NOP10";
161
162     case OP_INVALIDOPCODE          : return "OP_INVALIDOPCODE";
163
164     // Note:
165     //  The template matching params OP_SMALLDATA/etc are defined in opcodetype enum
166     //  as kind of implementation hack, they are *NOT* real opcodes.  If found in real
167     //  Script, just let the default: case deal with them.
168
169     default:
170         return "OP_UNKNOWN";
171     }
172 }
173
174 unsigned int CScript::GetSigOpCount(bool fAccurate) const
175 {
176     unsigned int n = 0;
177     const_iterator pc = begin();
178     opcodetype lastOpcode = OP_INVALIDOPCODE;
179     while (pc < end())
180     {
181         opcodetype opcode;
182         if (!GetOp(pc, opcode))
183             break;
184         if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY)
185             n++;
186         else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY)
187         {
188             if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
189                 n += DecodeOP_N(lastOpcode);
190             else
191                 n += 20;
192         }
193         lastOpcode = opcode;
194     }
195     return n;
196 }
197
198 unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
199 {
200     if (!IsPayToScriptHash())
201         return GetSigOpCount(true);
202
203     // This is a pay-to-script-hash scriptPubKey;
204     // get the last item that the scriptSig
205     // pushes onto the stack:
206     const_iterator pc = scriptSig.begin();
207     vector<unsigned char> data;
208     while (pc < scriptSig.end())
209     {
210         opcodetype opcode;
211         if (!scriptSig.GetOp(pc, opcode, data))
212             return 0;
213         if (opcode > OP_16)
214             return 0;
215     }
216
217     /// ... and return its opcount:
218     CScript subscript(data.begin(), data.end());
219     return subscript.GetSigOpCount(true);
220 }
221
222 bool CScript::IsPayToPublicKeyHash() const
223 {
224     // Extra-fast test for pay-to-pubkey-hash CScripts:
225     return (this->size() == 25 &&
226             (*this)[0] == OP_DUP &&
227             (*this)[1] == OP_HASH160 &&
228             (*this)[2] == 0x14 &&
229             (*this)[23] == OP_EQUALVERIFY &&
230             (*this)[24] == OP_CHECKSIG);
231 }
232
233 bool CScript::IsPayToPublicKey() const
234 {
235     // Extra-fast test for pay-to-pubkey CScripts:
236     return (this->size() == 35 &&
237             (*this)[0] == 33 &&
238             (*this)[34] == OP_CHECKSIG);
239 }
240
241 bool CScript::IsPayToScriptHash() const
242 {
243     // Extra-fast test for pay-to-script-hash CScripts:
244     return (this->size() == 23 &&
245             (*this)[0] == OP_HASH160 &&
246             (*this)[1] == 0x14 &&
247             (*this)[22] == OP_EQUAL);
248 }
249
250 // this returns true if either there is nothing left and pc points at the end, or 
251 // all instructions from the pc to the end of the script are balanced pushes and pops
252 // if there is data, it also returns all the values as byte vectors in a list of vectors
253 bool CScript::GetBalancedData(const_iterator& pc, std::vector<std::vector<unsigned char>>& vSolutions) const
254 {
255     int netPushes = 0;
256     vSolutions.clear();
257
258     while (pc < end())
259     {
260         vector<unsigned char> data;
261         opcodetype opcode;
262         if (this->GetOp(pc, opcode, data))
263         {
264             if (opcode == OP_DROP)
265             {
266                 // this should never pop what it hasn't pushed (like a success code)
267                 if (--netPushes < 0)
268                     return false;
269             } 
270             else 
271             {
272                 // push or fail
273                 netPushes++;
274                 if (opcode == OP_0)
275                 {
276                     data.resize(1);
277                     data[0] = 0;
278                     vSolutions.push_back(data);
279                 }
280                 else if (opcode >= OP_1 && opcode <= OP_16)
281                 {
282                     data.resize(1);
283                     data[0] = (opcode - OP_1) + 1;
284                     vSolutions.push_back(data);
285                 }
286                 else if (opcode > 0 && opcode <= OP_PUSHDATA4 && data.size() > 0)
287                 {
288                     vSolutions.push_back(data);
289                 }
290                 else
291                     return false;
292             }
293         }
294         else
295             return false;
296     }
297     return netPushes == 0;
298 }
299
300 // this returns true if either there is nothing left and pc points at the end
301 // if there is data, it also returns all the values as byte vectors in a list of vectors
302 bool CScript::GetPushedData(CScript::const_iterator pc, std::vector<std::vector<unsigned char>>& vData) const
303 {
304     vector<unsigned char> data;
305     opcodetype opcode;
306     std::vector<unsigned char> vch1 = std::vector<unsigned char>(1);
307
308     vData.clear();
309
310     while (pc < end())
311     {
312         if (GetOp(pc, opcode, data))
313         {
314             if (opcode == OP_0)
315             {
316                 vch1[0] = 0;
317                 vData.push_back(vch1);
318             }
319             else if (opcode >= OP_1 && opcode <= OP_16)
320             {
321                 vch1[0] = (opcode - OP_1) + 1;
322                 vData.push_back(vch1);
323             }
324             else if (opcode > 0 && opcode <= OP_PUSHDATA4 && data.size() > 0)
325             {
326                 vData.push_back(data);
327             }
328             else
329                 return false;
330         }
331     }
332     return vData.size() != 0;
333 }
334
335 // this returns true if either there is nothing left and pc points at the end
336 // if there is data, it also returns all the values as byte vectors in a list of vectors
337 bool CScript::GetOpretData(std::vector<std::vector<unsigned char>>& vData) const
338 {
339     vector<unsigned char> data;
340     opcodetype opcode;
341     CScript::const_iterator pc = this->begin();
342
343     if (GetOp(pc, opcode, data) && opcode == OP_RETURN)
344     {
345         return GetPushedData(pc, vData);
346     }
347     else return false;
348 }
349
350 bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript, std::vector<std::vector<unsigned char>>& vParams) const
351 {
352     const_iterator pc = begin();
353     vector<unsigned char> data;
354     opcodetype opcode;
355     if (this->GetOp(pc, opcode, data))
356         // Sha256 conditions are <76 bytes
357         if (opcode > OP_0 && opcode < OP_PUSHDATA1)
358             if (this->GetOp(pc, opcode, data))
359                 if (opcode == OP_CHECKCRYPTOCONDITION)
360                 {
361                     const_iterator pcCCEnd = pc;
362                     if (GetBalancedData(pc, vParams))
363                     {
364                         if (pCCSubScript)
365                             *pCCSubScript = CScript(begin(),pcCCEnd);
366                         return true;
367                     }
368                 }
369     return false;
370 }
371
372 bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript) const
373 {
374     std::vector<std::vector<unsigned char>> vParams;
375     return IsPayToCryptoCondition(pCCSubScript, vParams);
376 }
377
378 bool CScript::IsPayToCryptoCondition() const
379 {
380     return IsPayToCryptoCondition((CScript *)NULL);
381 }
382
383 bool CScript::IsInstantSpend() const
384 {
385     uint32_t ecode;
386     if (!IsPayToCryptoCondition(&ecode))
387     {
388         ecode = 0;
389     }
390     // only instant spend for now
391     return ecode == EVAL_EARNEDNOTARIZATION;
392 }
393
394 bool CScript::IsPayToCryptoCondition(COptCCParams &ccParams) const
395 {
396     CScript subScript;
397     std::vector<std::vector<unsigned char>> vParams;
398
399     if (IsPayToCryptoCondition(&subScript, vParams))
400     {
401         if (!vParams.empty())
402         {
403             ccParams = COptCCParams(vParams[0]);
404         }
405         return true;
406     }
407     return false;
408 }
409
410 bool CScript::IsPayToCryptoCondition(CScript *ccSubScript, std::vector<std::vector<unsigned char>> &vParams, COptCCParams &optParams) const
411 {
412     if (IsPayToCryptoCondition(ccSubScript, vParams))
413     {
414         if (vParams.size() > 0)
415         {
416             optParams = COptCCParams(vParams[0]);
417             return optParams.IsValid();
418         }
419     }
420     return false;
421 }
422
423 bool CScript::IsPayToCryptoCondition(uint32_t *ecode) const
424 {
425     CScript sub;
426     std::vector<std::vector<unsigned char>> vParams;
427     COptCCParams p;
428     if (IsPayToCryptoCondition(&sub, vParams, p))
429     {
430         *ecode = p.evalCode;
431         return true;
432     }
433     return false;
434 }
435
436 CScript CScript::ReplaceCCParams(const COptCCParams &params)
437 {
438     CScript subScript;
439     std::vector<std::vector<unsigned char>> vParams;
440     COptCCParams p;
441     if (!this->IsPayToCryptoCondition(&subScript, vParams, p) || p.evalCode != params.evalCode)
442     {
443         return CScript();
444     }
445
446     // add the object to the end of the script
447     subScript << params.AsVector() << OP_DROP;
448
449     return subScript;
450 }
451
452 int64_t CScript::ReserveOutValue() const
453 {
454     COptCCParams p;
455     CAmount newVal = 0;
456
457     // already validated above
458     if (::IsPayToCryptoCondition(*this, p) && p.IsValid())
459     {
460         switch (p.evalCode)
461         {
462             case EVAL_RESERVE_OUTPUT:
463             {
464                 CReserveOutput ro(p.vData[0]);
465                 return ro.nValue;
466                 break;
467             }
468             case EVAL_CURRENCYSTATE:
469             {
470                 CCoinbaseCurrencyState cbcs(p.vData[0]);
471                 return cbcs.ReserveOut.nValue;
472                 break;
473             }
474             case EVAL_RESERVE_TRANSFER:
475             {
476                 CReserveTransfer rt(p.vData[0]);
477                 return rt.nValue;
478                 break;
479             }
480             case EVAL_RESERVE_EXCHANGE:
481             {
482                 CReserveExchange re(p.vData[0]);
483                 // reserve out amount when converting to reserve is 0, since the amount cannot be calculated in isolation as an input
484                 // if reserve in, we can consider the output the same reserve value as the input
485                 return (re.flags & re.TO_RESERVE) ? 0 : re.nValue;
486                 break;
487             }
488         }
489     }
490     return 0;
491 }
492
493 int64_t CScript::ReserveOutValue(const CCurrencyState &currencyState) const
494 {
495     COptCCParams p;
496     CAmount newVal = 0;
497
498     // already validated above
499     if (::IsPayToCryptoCondition(*this, p) && p.IsValid())
500     {
501         switch (p.evalCode)
502         {
503             case EVAL_RESERVE_OUTPUT:
504             {
505                 CReserveOutput ro(p.vData[0]);
506                 return ro.nValue;
507                 break;
508             }
509             case EVAL_RESERVE_TRANSFER:
510             {
511                 CReserveTransfer rt(p.vData[0]);
512                 return rt.nValue;
513                 break;
514             }
515             case EVAL_RESERVE_EXCHANGE:
516             {
517                 CReserveExchange re(p.vData[0]);
518                 // reserve out amount when converting to reserve is 0, since the amount cannot be calculated in isolation as an input
519                 // if reserve in, we can consider the output the same reserve value as the input
520                 return (re.flags & re.TO_RESERVE) ? currencyState.NativeToReserve(re.nValue) : re.nValue;
521                 break;
522             }
523         }
524     }
525     return 0;
526 }
527
528 bool CScript::SetReserveOutValue(int64_t newValue)
529 {
530     COptCCParams p;
531     CAmount newVal = 0;
532
533     // already validated above
534     if (::IsPayToCryptoCondition(*this, p) && p.IsValid())
535     {
536         switch (p.evalCode)
537         {
538             case EVAL_RESERVE_OUTPUT:
539             {
540                 CReserveOutput ro(p.vData[0]);
541                 p.vData[0] = ro.AsVector();
542                 break;
543             }
544             case EVAL_RESERVE_TRANSFER:
545             {
546                 CReserveTransfer rt(p.vData[0]);
547                 rt.nValue = newValue;
548                 p.vData[0] = rt.AsVector();
549                 break;
550             }
551             case EVAL_RESERVE_EXCHANGE:
552             {
553                 CReserveExchange re(p.vData[0]);
554                 re.nValue = newValue;
555                 p.vData[0] = re.AsVector();
556                 break;
557             }
558             default:
559                 return false;
560         }
561         *this = ReplaceCCParams(p);
562         return true;
563     }
564     return false;
565 }
566
567 bool CScript::MayAcceptCryptoCondition() const
568 {
569     // Get the type mask of the condition
570     const_iterator pc = this->begin();
571     vector<unsigned char> data;
572     opcodetype opcode;
573     if (!this->GetOp(pc, opcode, data)) return false;
574     if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false;
575     CC *cond = cc_readConditionBinary(data.data(), data.size());
576     if (!cond) return false;
577
578     bool out = IsSupportedCryptoCondition(cond);
579
580     cc_free(cond);
581     return out;
582 }
583
584 bool CScript::IsCoinImport() const
585 {
586     const_iterator pc = this->begin();
587     vector<unsigned char> data;
588     opcodetype opcode;
589     if (this->GetOp(pc, opcode, data))
590         if (opcode > OP_0 && opcode <= OP_PUSHDATA4)
591             return data.begin()[0] == EVAL_IMPORTCOIN;
592     return false;
593 }
594
595 bool CScript::IsPushOnly() const
596 {
597     const_iterator pc = begin();
598     while (pc < end())
599     {
600         opcodetype opcode;
601         if (!GetOp(pc, opcode))
602             return false;
603         // Note that IsPushOnly() *does* consider OP_RESERVED to be a
604         // push-type opcode, however execution of OP_RESERVED fails, so
605         // it's not relevant to P2SH/BIP62 as the scriptSig would fail prior to
606         // the P2SH special validation code being executed.
607         if (opcode > OP_16)
608             return false;
609     }
610     return true;
611 }
612
613 // if the front of the script has check lock time verify. this is a fairly simple check.
614 // accepts NULL as parameter if unlockTime is not needed.
615 bool CScript::IsCheckLockTimeVerify(int64_t *unlockTime) const
616 {
617     opcodetype op;
618     std::vector<unsigned char> unlockTimeParam = std::vector<unsigned char>();
619     CScript::const_iterator it = this->begin();
620
621     if (this->GetOp2(it, op, &unlockTimeParam))
622     {
623         if (unlockTimeParam.size() >= 0 && unlockTimeParam.size() < 6 &&
624             (*this)[unlockTimeParam.size() + 1] == OP_CHECKLOCKTIMEVERIFY)
625         {
626             int i = unlockTimeParam.size() - 1;
627             for (*unlockTime = 0; i >= 0; i--)
628             {
629                 *unlockTime <<= 8;
630                 *unlockTime |= *((unsigned char *)unlockTimeParam.data() + i);
631             }
632             return true;
633         }
634     }
635     return false;
636 }
637
638 bool CScript::IsCheckLockTimeVerify() const
639 {
640     int64_t ult;
641     return this->IsCheckLockTimeVerify(&ult);
642 }
643
644 std::string CScript::ToString() const
645 {
646     std::string str;
647     opcodetype opcode;
648     std::vector<unsigned char> vch;
649     const_iterator pc = begin();
650     while (pc < end())
651     {
652         if (!str.empty())
653             str += " ";
654         if (!GetOp(pc, opcode, vch))
655         {
656             str += "[error]";
657             return str;
658         }
659         if (0 <= opcode && opcode <= OP_PUSHDATA4)
660             str += ValueString(vch);
661         else
662             str += GetOpName(opcode);
663     }
664     return str;
665 }
This page took 0.062864 seconds and 4 git commands to generate.