]> Git Repo - VerusCoin.git/blob - src/script/script.cpp
Merge branch 'dev' of github.com:miketout/VerusCoin into dev
[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 https://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 #include "key_io.h"
16 #include "univalue.h"
17 #include "pbaas/identity.h"
18
19 using namespace std;
20
21 namespace {
22     inline std::string ValueString(const std::vector<unsigned char>& vch)
23     {
24         if (vch.size() <= 4)
25             return strprintf("%d", CScriptNum(vch, false).getint());
26         else
27             return HexStr(vch);
28     }
29 } // anon namespace
30
31 const char* GetOpName(opcodetype opcode)
32 {
33     switch (opcode)
34     {
35     // push value
36     case OP_0                      : return "0";
37     case OP_PUSHDATA1              : return "OP_PUSHDATA1";
38     case OP_PUSHDATA2              : return "OP_PUSHDATA2";
39     case OP_PUSHDATA4              : return "OP_PUSHDATA4";
40     case OP_1NEGATE                : return "-1";
41     case OP_RESERVED               : return "OP_RESERVED";
42     case OP_1                      : return "1";
43     case OP_2                      : return "2";
44     case OP_3                      : return "3";
45     case OP_4                      : return "4";
46     case OP_5                      : return "5";
47     case OP_6                      : return "6";
48     case OP_7                      : return "7";
49     case OP_8                      : return "8";
50     case OP_9                      : return "9";
51     case OP_10                     : return "10";
52     case OP_11                     : return "11";
53     case OP_12                     : return "12";
54     case OP_13                     : return "13";
55     case OP_14                     : return "14";
56     case OP_15                     : return "15";
57     case OP_16                     : return "16";
58
59     // control
60     case OP_NOP                    : return "OP_NOP";
61     case OP_VER                    : return "OP_VER";
62     case OP_IF                     : return "OP_IF";
63     case OP_NOTIF                  : return "OP_NOTIF";
64     case OP_VERIF                  : return "OP_VERIF";
65     case OP_VERNOTIF               : return "OP_VERNOTIF";
66     case OP_ELSE                   : return "OP_ELSE";
67     case OP_ENDIF                  : return "OP_ENDIF";
68     case OP_VERIFY                 : return "OP_VERIFY";
69     case OP_RETURN                 : return "OP_RETURN";
70
71     // stack ops
72     case OP_TOALTSTACK             : return "OP_TOALTSTACK";
73     case OP_FROMALTSTACK           : return "OP_FROMALTSTACK";
74     case OP_2DROP                  : return "OP_2DROP";
75     case OP_2DUP                   : return "OP_2DUP";
76     case OP_3DUP                   : return "OP_3DUP";
77     case OP_2OVER                  : return "OP_2OVER";
78     case OP_2ROT                   : return "OP_2ROT";
79     case OP_2SWAP                  : return "OP_2SWAP";
80     case OP_IFDUP                  : return "OP_IFDUP";
81     case OP_DEPTH                  : return "OP_DEPTH";
82     case OP_DROP                   : return "OP_DROP";
83     case OP_DUP                    : return "OP_DUP";
84     case OP_NIP                    : return "OP_NIP";
85     case OP_OVER                   : return "OP_OVER";
86     case OP_PICK                   : return "OP_PICK";
87     case OP_ROLL                   : return "OP_ROLL";
88     case OP_ROT                    : return "OP_ROT";
89     case OP_SWAP                   : return "OP_SWAP";
90     case OP_TUCK                   : return "OP_TUCK";
91
92     // splice ops
93     case OP_CAT                    : return "OP_CAT";
94     case OP_SUBSTR                 : return "OP_SUBSTR";
95     case OP_LEFT                   : return "OP_LEFT";
96     case OP_RIGHT                  : return "OP_RIGHT";
97     case OP_SIZE                   : return "OP_SIZE";
98
99     // bit logic
100     case OP_INVERT                 : return "OP_INVERT";
101     case OP_AND                    : return "OP_AND";
102     case OP_OR                     : return "OP_OR";
103     case OP_XOR                    : return "OP_XOR";
104     case OP_EQUAL                  : return "OP_EQUAL";
105     case OP_EQUALVERIFY            : return "OP_EQUALVERIFY";
106     case OP_RESERVED1              : return "OP_RESERVED1";
107     case OP_RESERVED2              : return "OP_RESERVED2";
108
109     // numeric
110     case OP_1ADD                   : return "OP_1ADD";
111     case OP_1SUB                   : return "OP_1SUB";
112     case OP_2MUL                   : return "OP_2MUL";
113     case OP_2DIV                   : return "OP_2DIV";
114     case OP_NEGATE                 : return "OP_NEGATE";
115     case OP_ABS                    : return "OP_ABS";
116     case OP_NOT                    : return "OP_NOT";
117     case OP_0NOTEQUAL              : return "OP_0NOTEQUAL";
118     case OP_ADD                    : return "OP_ADD";
119     case OP_SUB                    : return "OP_SUB";
120     case OP_MUL                    : return "OP_MUL";
121     case OP_DIV                    : return "OP_DIV";
122     case OP_MOD                    : return "OP_MOD";
123     case OP_LSHIFT                 : return "OP_LSHIFT";
124     case OP_RSHIFT                 : return "OP_RSHIFT";
125     case OP_BOOLAND                : return "OP_BOOLAND";
126     case OP_BOOLOR                 : return "OP_BOOLOR";
127     case OP_NUMEQUAL               : return "OP_NUMEQUAL";
128     case OP_NUMEQUALVERIFY         : return "OP_NUMEQUALVERIFY";
129     case OP_NUMNOTEQUAL            : return "OP_NUMNOTEQUAL";
130     case OP_LESSTHAN               : return "OP_LESSTHAN";
131     case OP_GREATERTHAN            : return "OP_GREATERTHAN";
132     case OP_LESSTHANOREQUAL        : return "OP_LESSTHANOREQUAL";
133     case OP_GREATERTHANOREQUAL     : return "OP_GREATERTHANOREQUAL";
134     case OP_MIN                    : return "OP_MIN";
135     case OP_MAX                    : return "OP_MAX";
136     case OP_WITHIN                 : return "OP_WITHIN";
137
138     // crypto
139     case OP_RIPEMD160              : return "OP_RIPEMD160";
140     case OP_SHA1                   : return "OP_SHA1";
141     case OP_SHA256                 : return "OP_SHA256";
142     case OP_HASH160                : return "OP_HASH160";
143     case OP_HASH256                : return "OP_HASH256";
144     case OP_CODESEPARATOR          : return "OP_CODESEPARATOR";
145     case OP_CHECKSIG               : return "OP_CHECKSIG";
146     case OP_CHECKSIGVERIFY         : return "OP_CHECKSIGVERIFY";
147     case OP_CHECKMULTISIG          : return "OP_CHECKMULTISIG";
148     case OP_CHECKMULTISIGVERIFY    : return "OP_CHECKMULTISIGVERIFY";
149     case OP_CHECKCRYPTOCONDITION   : return "OP_CHECKCRYPTOCONDITION";
150     case OP_CHECKCRYPTOCONDITIONVERIFY
151                                    : return "OP_CHECKCRYPTOCONDITIONVERIFY";
152
153     // expansion
154     case OP_NOP1                   : return "OP_NOP1";
155     case OP_NOP2                   : return "OP_NOP2";
156     case OP_NOP3                   : return "OP_NOP3";
157     case OP_NOP4                   : return "OP_NOP4";
158     case OP_NOP5                   : return "OP_NOP5";
159     case OP_NOP6                   : return "OP_NOP6";
160     case OP_NOP7                   : return "OP_NOP7";
161     case OP_NOP8                   : return "OP_NOP8";
162     case OP_NOP9                   : return "OP_NOP9";
163     case OP_NOP10                  : return "OP_NOP10";
164
165     case OP_INVALIDOPCODE          : return "OP_INVALIDOPCODE";
166
167     // Note:
168     //  The template matching params OP_SMALLDATA/etc are defined in opcodetype enum
169     //  as kind of implementation hack, they are *NOT* real opcodes.  If found in real
170     //  Script, just let the default: case deal with them.
171
172     default:
173         return "OP_UNKNOWN";
174     }
175 }
176
177 uint160 GetConditionID(uint160 cid, int32_t condition)
178 {
179     CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
180     hw << condition;
181     hw << cid;
182     uint256 chainHash = hw.GetHash();
183     return Hash160(chainHash.begin(), chainHash.end());
184 }
185
186 CTxDestination TransferDestinationToDestination(const CTransferDestination &transferDest)
187 {
188     CTxDestination retDest;
189     switch (transferDest.type)
190     {
191     case CTransferDestination::DEST_PKH:
192         retDest = CKeyID(uint160(transferDest.destination));
193         break;
194
195     case CTransferDestination::DEST_PK:
196         {
197             CPubKey pk;
198             pk.Set(transferDest.destination.begin(), transferDest.destination.end());
199             retDest = pk;
200             break;
201         }
202
203     case CTransferDestination::DEST_SH:
204         retDest = CScriptID(uint160(transferDest.destination));
205         break;
206
207     case CTransferDestination::DEST_ID:
208         retDest = CIdentityID(uint160(transferDest.destination));
209         break;
210
211     case CTransferDestination::DEST_FULLID:
212         retDest = CIdentityID(CIdentity(transferDest.destination).GetID());
213         break;
214
215     case CTransferDestination::DEST_QUANTUM:
216         retDest = CQuantumID(uint160(transferDest.destination));
217         break;
218     }
219     return retDest;
220 }
221
222 CTransferDestination DestinationToTransferDestination(const CTxDestination &dest)
223 {
224     CTransferDestination retDest;
225     switch (dest.which())
226     {
227     case CTransferDestination::DEST_PKH:
228     case CTransferDestination::DEST_PK:
229     case CTransferDestination::DEST_SH:
230     case CTransferDestination::DEST_ID:
231     case CTransferDestination::DEST_QUANTUM:
232         retDest = CTransferDestination(dest.which(), GetDestinationBytes(dest));
233         break;
234     }
235     return retDest;
236 }
237
238 CTransferDestination IdentityToTransferDestination(const CIdentity &identity)
239 {
240     return CTransferDestination(CTransferDestination::DEST_FULLID, ::AsVector(identity));
241 }
242
243 CIdentity TransferDestinationToIdentity(const CTransferDestination &dest)
244 {
245     CIdentity retIdentity;
246     switch (dest.type)
247     {
248         case CTransferDestination::DEST_FULLID:
249         {
250             ::FromVector(dest.destination, retIdentity);
251             break;
252         }        
253     }
254     return retIdentity;
255 }
256
257 std::vector<CTxDestination> TransferDestinationsToDestinations(const std::vector<CTransferDestination> &transferDests)
258 {
259     std::vector<CTxDestination> retDests;
260     for (auto &dest : transferDests)
261     {
262         retDests.push_back(TransferDestinationToDestination(dest));
263     }
264     return retDests;
265 }
266
267 std::vector<CTransferDestination> DestinationsToTransferDestinations(const std::vector<CTxDestination> &dests)
268 {
269     std::vector<CTransferDestination> retDests;
270     for (auto &dest : dests)
271     {
272         retDests.push_back(DestinationToTransferDestination(dest));
273     }
274     return retDests;
275 }
276
277 CStakeInfo::CStakeInfo(std::vector<unsigned char> vch)
278 {
279     ::FromVector(vch, *this);
280 }
281
282 std::vector<unsigned char> CStakeInfo::AsVector() const
283 {
284     return ::AsVector(*this);
285 }
286
287 unsigned int CScript::MAX_SCRIPT_ELEMENT_SIZE = MAX_SCRIPT_ELEMENT_SIZE_V2;
288
289 unsigned int CScript::GetSigOpCount(bool fAccurate) const
290 {
291     unsigned int n = 0;
292     const_iterator pc = begin();
293     opcodetype lastOpcode = OP_INVALIDOPCODE;
294     while (pc < end())
295     {
296         opcodetype opcode;
297         if (!GetOp(pc, opcode))
298             break;
299         if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY)
300             n++;
301         else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY)
302         {
303             if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
304                 n += DecodeOP_N(lastOpcode);
305             else
306                 n += 20;
307         }
308         lastOpcode = opcode;
309     }
310     return n;
311 }
312
313 unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
314 {
315     if (!IsPayToScriptHash())
316         return GetSigOpCount(true);
317
318     // This is a pay-to-script-hash scriptPubKey;
319     // get the last item that the scriptSig
320     // pushes onto the stack:
321     const_iterator pc = scriptSig.begin();
322     vector<unsigned char> data;
323     while (pc < scriptSig.end())
324     {
325         opcodetype opcode;
326         if (!scriptSig.GetOp(pc, opcode, data))
327             return 0;
328         if (opcode > OP_16)
329             return 0;
330     }
331
332     /// ... and return its opcount:
333     CScript subscript(data.begin(), data.end());
334     return subscript.GetSigOpCount(true);
335 }
336
337 bool CScript::IsPayToPublicKeyHash() const
338 {
339     // Extra-fast test for pay-to-pubkey-hash CScripts:
340     return (this->size() == 25 &&
341             (*this)[0] == OP_DUP &&
342             (*this)[1] == OP_HASH160 &&
343             (*this)[2] == 0x14 &&
344             (*this)[23] == OP_EQUALVERIFY &&
345             (*this)[24] == OP_CHECKSIG);
346 }
347
348 bool CScript::IsPayToPublicKey() const
349 {
350     // Extra-fast test for pay-to-pubkey CScripts:
351     return (this->size() == 35 &&
352             (*this)[0] == 33 &&
353             (*this)[34] == OP_CHECKSIG);
354 }
355
356 bool CScript::IsPayToScriptHash() const
357 {
358     // Extra-fast test for pay-to-script-hash CScripts:
359     return (this->size() == 23 &&
360             (*this)[0] == OP_HASH160 &&
361             (*this)[1] == 0x14 &&
362             (*this)[22] == OP_EQUAL);
363 }
364
365 // this returns true if either there is nothing left and pc points at the end, or 
366 // all instructions from the pc to the end of the script are balanced pushes and pops
367 // if there is data, it also returns all the values as byte vectors in a list of vectors
368 bool CScript::GetBalancedData(const_iterator& pc, std::vector<std::vector<unsigned char>>& vSolutions) const
369 {
370     int netPushes = 0;
371     vSolutions.clear();
372
373     while (pc < end())
374     {
375         vector<unsigned char> data;
376         opcodetype opcode;
377         if (this->GetOp(pc, opcode, data))
378         {
379             if (opcode == OP_DROP)
380             {
381                 // this should never pop what it hasn't pushed (like a success code)
382                 if (--netPushes < 0)
383                     return false;
384             } 
385             else 
386             {
387                 // push or fail
388                 netPushes++;
389                 if (opcode == OP_0)
390                 {
391                     data.resize(1);
392                     data[0] = 0;
393                     vSolutions.push_back(data);
394                 }
395                 else if (opcode >= OP_1 && opcode <= OP_16)
396                 {
397                     data.resize(1);
398                     data[0] = (opcode - OP_1) + 1;
399                     vSolutions.push_back(data);
400                 }
401                 else if (opcode > 0 && opcode <= OP_PUSHDATA4 && data.size() > 0)
402                 {
403                     vSolutions.push_back(data);
404                 }
405                 else
406                     return false;
407             }
408         }
409         else
410             return false;
411     }
412     return netPushes == 0;
413 }
414
415 // this returns true if either there is nothing left and pc points at the end
416 // if there is data, it also returns all the values as byte vectors in a list of vectors
417 bool CScript::GetPushedData(CScript::const_iterator pc, std::vector<std::vector<unsigned char>>& vData) const
418 {
419     vector<unsigned char> data;
420     opcodetype opcode;
421     std::vector<unsigned char> vch1 = std::vector<unsigned char>(1);
422
423     vData.clear();
424
425     while (pc < end())
426     {
427         if (GetOp(pc, opcode, data))
428         {
429             if (opcode == OP_0)
430             {
431                 vch1[0] = 0;
432                 vData.push_back(vch1);
433             }
434             else if (opcode >= OP_1 && opcode <= OP_16)
435             {
436                 vch1[0] = (opcode - OP_1) + 1;
437                 vData.push_back(vch1);
438             }
439             else if (opcode > 0 && opcode <= OP_PUSHDATA4 && data.size() > 0)
440             {
441                 vData.push_back(data);
442             }
443             else
444                 return false;
445         }
446     }
447     return vData.size() != 0;
448 }
449
450 // this returns true if either there is nothing left and pc points at the end
451 // if there is data, it also returns all the values as byte vectors in a list of vectors
452 bool CScript::GetOpretData(std::vector<std::vector<unsigned char>>& vData) const
453 {
454     vector<unsigned char> data;
455     opcodetype opcode;
456     CScript::const_iterator pc = this->begin();
457
458     if (GetOp(pc, opcode, data) && opcode == OP_RETURN)
459     {
460         return GetPushedData(pc, vData);
461     }
462     else return false;
463 }
464
465 bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript, std::vector<std::vector<unsigned char>>& vParams) const
466 {
467     const_iterator pc = begin();
468     vector<unsigned char> firstParam;
469     vector<unsigned char> data;
470     opcodetype opcode;
471     if (this->GetOp(pc, opcode, firstParam))
472         // Sha256 conditions are <76 bytes
473         if (opcode > OP_0 && opcode < OP_PUSHDATA1)
474             if (this->GetOp(pc, opcode, data))
475                 if (opcode == OP_CHECKCRYPTOCONDITION)
476                 {
477                     const_iterator pcCCEnd = pc;
478                     if (GetBalancedData(pc, vParams))
479                     {
480                         if (pCCSubScript)
481                             *pCCSubScript = CScript(begin(), pcCCEnd);
482                         vParams.push_back(firstParam);
483                         return true;
484                     }
485                 }
486     return false;
487 }
488
489 bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript) const
490 {
491     std::vector<std::vector<unsigned char>> vParams;
492     return IsPayToCryptoCondition(pCCSubScript, vParams);
493 }
494
495 bool CScript::IsPayToCryptoCondition() const
496 {
497     return IsPayToCryptoCondition((CScript *)NULL);
498 }
499
500 extern uint160 ASSETCHAINS_CHAINID, VERUS_CHAINID;
501
502 bool CScript::IsInstantSpend() const
503 {
504     COptCCParams p;
505     bool isInstantSpend = false;
506     if (!_IsVerusActive() && IsPayToCryptoCondition(p) && p.IsValid())
507     {
508         // instant spends must be to expected instant spend crypto conditions and to the right address as well
509         if ((p.evalCode == EVAL_EARNEDNOTARIZATION && GetDestinationID(p.vKeys[0]) == GetConditionID(VERUS_CHAINID, p.evalCode)) || 
510             (p.evalCode == EVAL_CURRENCYSTATE && GetDestinationID(p.vKeys[0]) == GetConditionID(ASSETCHAINS_CHAINID, p.evalCode)) || 
511             (p.evalCode == EVAL_CROSSCHAIN_IMPORT && GetDestinationID(p.vKeys[0]) == GetConditionID(VERUS_CHAINID, p.evalCode)) ||
512             (p.evalCode == EVAL_CROSSCHAIN_EXPORT && GetDestinationID(p.vKeys[0]) == GetConditionID(VERUS_CHAINID, p.evalCode)))
513         {
514             isInstantSpend = true;
515         }
516     }
517     return isInstantSpend;
518 }
519
520 bool CScript::IsPayToCryptoCondition(COptCCParams &ccParams) const
521 {
522     CScript subScript;
523     std::vector<std::vector<unsigned char>> vParams;
524
525     if (IsPayToCryptoCondition(&subScript, vParams))
526     {
527         if (!vParams.empty())
528         {
529             ccParams = COptCCParams(vParams[0]);
530             for (int i = 1; i < vParams.size(); i++)
531             {
532                 ccParams.vData.push_back(vParams[i]);
533             }
534         }
535         else
536         {
537             // make sure that we return it in a consistent and known state
538             ccParams = COptCCParams();
539         }
540         return true;
541     }
542     ccParams = COptCCParams();
543     return false;
544 }
545
546 bool CScript::IsPayToCryptoCondition(CScript *ccSubScript, std::vector<std::vector<unsigned char>> &vParams, COptCCParams &optParams) const
547 {
548     if (IsPayToCryptoCondition(ccSubScript, vParams))
549     {
550         if (vParams.size() > 0)
551         {
552             optParams = COptCCParams(vParams[0]);
553             return optParams.IsValid();
554         }
555     }
556     return false;
557 }
558
559 bool CScript::IsPayToCryptoCondition(uint32_t *ecode) const
560 {
561     CScript sub;
562     std::vector<std::vector<unsigned char>> vParams;
563     COptCCParams p;
564     if (IsPayToCryptoCondition(&sub, vParams, p))
565     {
566         *ecode = p.evalCode;
567         return true;
568     }
569     return false;
570 }
571
572 CScript &CScript::ReplaceCCParams(const COptCCParams &params)
573 {
574     CScript subScript;
575     std::vector<std::vector<unsigned char>> vParams;
576     COptCCParams p;
577     if (this->IsPayToCryptoCondition(&subScript, vParams, p) || p.evalCode != params.evalCode)
578     {
579         // add the object to the end of the script
580         *this = subScript;
581         *this << params.AsVector() << OP_DROP;
582     }
583     return *this;
584 }
585
586 bool CScript::IsSpendableOutputType(const COptCCParams &p) const
587 {
588     bool isSpendable = true;
589     if (!p.IsValid())
590     {
591         return isSpendable;
592     }
593     switch (p.evalCode)
594     {
595         case EVAL_CURRENCYSTATE:
596         case EVAL_RESERVE_TRANSFER:
597         case EVAL_RESERVE_EXCHANGE:
598         case EVAL_CROSSCHAIN_IMPORT:
599         {
600             isSpendable = false;
601             break;
602         }
603     }
604     return isSpendable;
605 }
606
607 bool CScript::IsSpendableOutputType() const
608 {
609     COptCCParams p;
610     if (IsPayToCryptoCondition(p))
611     {
612         return IsSpendableOutputType(p);
613     }
614     // default for non-CC outputs is true, this is to protect from accidentally spending specific CC output types, 
615     // even though they could be spent
616     return true;
617 }
618
619 CCurrencyValueMap CScript::ReserveOutValue(COptCCParams &p, bool spendableOnly) const
620 {
621     CCurrencyValueMap retVal;
622
623     // already validated above
624     if (IsPayToCryptoCondition(p) && p.IsValid() && (!spendableOnly || IsSpendableOutputType(p)))
625     {
626         switch (p.evalCode)
627         {
628             case EVAL_RESERVE_OUTPUT:
629             {
630                 CTokenOutput ro(p.vData[0]);
631                 if (ro.nValue)
632                 {
633                     retVal.valueMap[ro.currencyID] = ro.nValue;
634                 }
635                 break;
636             }
637
638             case EVAL_RESERVE_DEPOSIT:
639             {
640                 CTokenOutput ro(p.vData[0]);
641                 if (ro.nValue)
642                 {
643                     retVal.valueMap[ro.currencyID] = ro.nValue;
644                 }
645                 break;
646             }
647
648             case EVAL_CURRENCYSTATE:
649             {
650                 CCoinbaseCurrencyState cbcs(p.vData[0]);
651                 for (int i = 0; i < cbcs.currencies.size(); i++)
652                 {
653                     if (cbcs.reserveOut[i])
654                     {
655                         retVal.valueMap[cbcs.currencies[i]] = cbcs.reserveOut[i];
656                     }
657                 }
658                 break;
659             }
660
661             case EVAL_RESERVE_TRANSFER:
662             {
663                 CReserveTransfer rt(p.vData[0]);
664                 // this currency can only be present as native
665                 if (!(rt.flags & (rt.MINT_CURRENCY | rt.PREALLOCATE)) && rt.currencyID != ASSETCHAINS_CHAINID)
666                 {
667                     retVal.valueMap[rt.currencyID] = rt.nValue + rt.nFees;
668                 }
669                 break;
670             }
671
672             case EVAL_RESERVE_EXCHANGE:
673             {
674                 CReserveExchange re(p.vData[0]);
675                 // reserve out amount when converting to reserve is 0, since the amount cannot be calculated in isolation as an input
676                 // if reserve in, we can consider the output the same reserve value as the input
677                 if (!(re.flags & re.TO_RESERVE))
678                 {
679                     retVal.valueMap[re.currencyID] = re.nValue;
680                 }
681                 break;
682             }
683             case EVAL_CROSSCHAIN_IMPORT:
684             {
685                 CCrossChainImport cci(p.vData[0]);
686                 // reserve out amount when converting to reserve is 0, since the amount cannot be calculated in isolation as an input
687                 // if reserve in, we can consider the output the same reserve value as the input
688                 retVal = cci.totalReserveOutMap;
689                 break;
690             }
691         }
692     }
693     return retVal;
694 }
695
696 CCurrencyValueMap CScript::ReserveOutValue() const
697 {
698     COptCCParams p;
699     return ReserveOutValue(p);
700 }
701
702 bool CScript::SetReserveOutValue(const CCurrencyValueMap &newValues)
703 {
704     COptCCParams p;
705     CAmount newVal = 0;
706
707     // already validated above
708     if (::IsPayToCryptoCondition(*this, p) && p.IsValid())
709     {
710         switch (p.evalCode)
711         {
712             case EVAL_RESERVE_OUTPUT:
713             {
714                 if (newValues.valueMap.size() != 1)
715                 {
716                     return false;
717                 }
718                 CTokenOutput ro(p.vData[0]);
719                 ro.currencyID = newValues.valueMap.begin()->first;
720                 ro.nValue = newValues.valueMap.begin()->second;
721                 p.vData[0] = ro.AsVector();
722                 break;
723             }
724             case EVAL_RESERVE_TRANSFER:
725             {
726                 if (newValues.valueMap.size() != 1)
727                 {
728                     return false;
729                 }
730                 CReserveTransfer rt(p.vData[0]);
731                 rt.currencyID = newValues.valueMap.begin()->first;
732                 rt.nValue = newValues.valueMap.begin()->second;
733                 p.vData[0] = rt.AsVector();
734                 break;
735             }
736             case EVAL_RESERVE_EXCHANGE:
737             {
738                 if (newValues.valueMap.size() != 1)
739                 {
740                     return false;
741                 }
742                 CReserveExchange re(p.vData[0]);
743                 re.currencyID = newValues.valueMap.begin()->first;
744                 re.nValue = newValues.valueMap.begin()->second;
745                 p.vData[0] = re.AsVector();
746                 break;
747             }
748             case EVAL_CROSSCHAIN_IMPORT:
749             {
750                 CCrossChainImport cci(p.vData[0]);
751                 cci.importValue = newValues;
752                 p.vData[0] = cci.AsVector();
753                 break;
754             }
755             // cross chain import thread holds the original conversion amounts
756             case EVAL_CURRENCYSTATE:
757             {
758                 CCoinbaseCurrencyState cbcs(p.vData[0]);
759                 for (int i = 0; i < cbcs.currencies.size(); i++)
760                 {
761                     auto it = newValues.valueMap.find(cbcs.currencies[i]);
762                     if (it != newValues.valueMap.end())
763                     {
764                         cbcs.reserveOut[i] = it->second;
765                     }
766                 }
767                 p.vData[0] = cbcs.AsVector();
768                 break;
769             }
770
771             default:
772                 return false;
773         }
774         *this = ReplaceCCParams(p);
775         return true;
776     }
777     return false;
778 }
779
780 bool CScript::MayAcceptCryptoCondition() const
781 {
782     // Get the type mask of the condition
783     const_iterator pc = this->begin();
784     vector<unsigned char> data;
785     opcodetype opcode;
786     if (!this->GetOp(pc, opcode, data)) return false;
787     if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false;
788     CC *cond = cc_readConditionBinary(data.data(), data.size());
789     if (!cond) return false;
790
791     uint32_t eCode;
792     if (!IsPayToCryptoCondition(&eCode))
793     {
794         return false;
795     }
796
797     bool out = IsSupportedCryptoCondition(cond, eCode);
798
799     cc_free(cond);
800     return out;
801 }
802
803 // also checks if the eval code is consistent
804 bool CScript::MayAcceptCryptoCondition(int evalCode) const
805 {
806     // Get the type mask of the condition
807     const_iterator pc = this->begin();
808     vector<unsigned char> data;
809     opcodetype opcode;
810     if (!this->GetOp(pc, opcode, data)) return false;
811     if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false;
812     CC *cond = cc_readConditionBinary(data.data(), data.size());
813     if (!cond) return false;
814
815     bool out = IsSupportedCryptoCondition(cond, evalCode);
816
817     cc_free(cond);
818     return out;
819 }
820
821 bool CScript::IsCoinImport() const
822 {
823     const_iterator pc = this->begin();
824     vector<unsigned char> data;
825     opcodetype opcode;
826     if (this->GetOp(pc, opcode, data))
827         if (opcode > OP_0 && opcode <= OP_PUSHDATA4)
828             return data.begin()[0] == EVAL_IMPORTCOIN;
829     return false;
830 }
831
832 bool CScript::IsPushOnly() const
833 {
834     const_iterator pc = begin();
835     while (pc < end())
836     {
837         opcodetype opcode;
838         if (!GetOp(pc, opcode))
839             return false;
840         // Note that IsPushOnly() *does* consider OP_RESERVED to be a
841         // push-type opcode, however execution of OP_RESERVED fails, so
842         // it's not relevant to P2SH/BIP62 as the scriptSig would fail prior to
843         // the P2SH special validation code being executed.
844         if (opcode > OP_16)
845             return false;
846     }
847     return true;
848 }
849
850 // if the front of the script has check lock time verify. this is a fairly simple check.
851 // accepts NULL as parameter if unlockTime is not needed.
852 bool CScript::IsCheckLockTimeVerify(int64_t *unlockTime) const
853 {
854     opcodetype op;
855     std::vector<unsigned char> unlockTimeParam = std::vector<unsigned char>();
856     CScript::const_iterator it = this->begin();
857
858     if (this->GetOp2(it, op, &unlockTimeParam))
859     {
860         if (unlockTimeParam.size() >= 0 && unlockTimeParam.size() < 6 &&
861             (*this)[unlockTimeParam.size() + 1] == OP_CHECKLOCKTIMEVERIFY)
862         {
863             int i = unlockTimeParam.size() - 1;
864             for (*unlockTime = 0; i >= 0; i--)
865             {
866                 *unlockTime <<= 8;
867                 *unlockTime |= *((unsigned char *)unlockTimeParam.data() + i);
868             }
869             return true;
870         }
871     }
872     return false;
873 }
874
875 bool CScript::IsCheckLockTimeVerify() const
876 {
877     int64_t ult;
878     return this->IsCheckLockTimeVerify(&ult);
879 }
880
881 std::string CScript::ToString() const
882 {
883     std::string str;
884     opcodetype opcode;
885     std::vector<unsigned char> vch;
886     const_iterator pc = begin();
887     while (pc < end())
888     {
889         if (!str.empty())
890             str += " ";
891         if (!GetOp(pc, opcode, vch))
892         {
893             str += "[error]";
894             return str;
895         }
896         if (0 <= opcode && opcode <= OP_PUSHDATA4)
897             str += ValueString(vch);
898         else
899             str += GetOpName(opcode);
900     }
901     return str;
902 }
903
904 CScript::ScriptType CScript::GetType() const
905 {
906     if (this->IsPayToPublicKeyHash())
907     {
908         return CScript::P2PKH;
909     }
910     else if (this->IsPayToScriptHash())
911     {
912         return CScript::P2SH;
913     }
914     else if (this->IsPayToPublicKey())
915     {
916         return CScript::P2PK;
917     }
918     else if (this->IsPayToCryptoCondition())
919     {
920         return CScript::P2CC;
921     }
922
923     // We don't know this script type
924     return CScript::UNKNOWN;
925 }
926
927 uint160 CScript::AddressHash() const
928 {
929     uint160 addressHash;
930     COptCCParams p;
931     if (this->IsPayToScriptHash()) {
932         addressHash = uint160(std::vector<unsigned char>(this->begin()+2, this->begin()+22));
933     }
934     else if (this->IsPayToPublicKeyHash())
935     {
936         addressHash = uint160(std::vector<unsigned char>(this->begin()+3, this->begin()+23));
937     }
938     else if (this->IsPayToPublicKey())
939     {
940         std::vector<unsigned char> hashBytes(this->begin()+1, this->begin()+34);
941         addressHash = Hash160(hashBytes);
942     }
943     else if (this->IsPayToCryptoCondition(p)) {
944         if (p.IsValid() && (p.vKeys.size()))
945         {
946             COptCCParams master;
947             if (p.version >= p.VERSION_V3 && p.vData.size() > 1 && (master = COptCCParams(p.vData.back())).IsValid() && master.vKeys.size())
948             {
949                 addressHash = GetDestinationID(master.vKeys[0]);
950             }
951             else
952             {
953                 addressHash = GetDestinationID(p.vKeys[0]);
954             }
955         }
956         else
957         {
958             vector<unsigned char> hashBytes(this->begin(), this->end());
959             addressHash = Hash160(hashBytes);
960         }
961     }
962     return addressHash;
963 }
964
965 std::vector<CTxDestination> CScript::GetDestinations() const
966 {
967     std::vector<CTxDestination> destinations;
968     COptCCParams p;
969     if (this->IsPayToCryptoCondition(p))
970     {
971         if (p.IsValid() && (p.vKeys.size()))
972         {
973             destinations = p.GetDestinations();
974         }
975         else
976         {
977             vector<unsigned char> hashBytes(this->begin(), this->end());
978             destinations.push_back(CKeyID(Hash160(hashBytes)));
979         }
980     }
981     else if (this->IsPayToScriptHash()) {
982         destinations.push_back(CScriptID(uint160(std::vector<unsigned char>(this->begin()+2, this->begin()+22))));
983     }
984     else if (this->IsPayToPublicKeyHash())
985     {
986         destinations.push_back(CKeyID(uint160(std::vector<unsigned char>(this->begin()+3, this->begin()+23))));
987     }
988     else if (this->IsPayToPublicKey())
989     {
990         std::vector<unsigned char> hashBytes(this->begin()+1, this->begin()+34);
991         destinations.push_back(CPubKey(hashBytes));
992     }
993     return destinations;
994 }
995
996 uint160 GetNameID(const std::string &Name, const uint160 &parent)
997 {
998     uint160 writeable = parent;
999     return CIdentity::GetID(Name, writeable);
1000 }
1001
1002 CAmount AmountFromValueNoErr(const UniValue& value)
1003 {
1004     try
1005     {
1006         CAmount amount;
1007         if (!value.isNum() && !value.isStr())
1008         {
1009             amount = 0;
1010         }
1011         else if (!ParseFixedPoint(value.getValStr(), 8, &amount))
1012         {
1013             amount = 0;
1014         }
1015         else if (!MoneyRange(amount))
1016         {
1017             amount = 0;
1018         }
1019         return amount;
1020     }
1021     catch(const std::exception& e)
1022     {
1023         return 0;
1024     }
1025 }
1026
1027 CCurrencyValueMap::CCurrencyValueMap(const std::vector<uint160> &currencyIDs, const std::vector<CAmount> &amounts)
1028 {
1029     int commonNum = currencyIDs.size() >= amounts.size() ? amounts.size() : currencyIDs.size();
1030     for (int i = 0; i < commonNum; i++)
1031     {
1032         valueMap[currencyIDs[i]] = amounts[i];
1033     }
1034 }
1035
1036 bool operator<(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1037 {
1038     // to be less than means, in this order:
1039     // 1. To have fewer non-zero currencies.
1040     // 2. If not fewer currencies, to be unable to be subtracted from the one being checked
1041     //    without creating negative values
1042     if (!a.valueMap.size() && !b.valueMap.size())
1043     {
1044         return false;
1045     }
1046     bool isaltb = false;
1047
1048     for (auto &oneVal : b.valueMap)
1049     {
1050         if (oneVal.second)
1051         {
1052             auto it = a.valueMap.find(oneVal.first);
1053             if (it == a.valueMap.end() || it->second < oneVal.second)
1054             {
1055                 isaltb = true;
1056             }
1057         }
1058     }
1059     return isaltb;
1060 }
1061
1062 bool operator>(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1063 {
1064     return b < a;
1065 }
1066
1067 bool operator==(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1068 {
1069     if (a.valueMap.size() != b.valueMap.size())
1070     {
1071         return false;
1072     }
1073
1074     bool isaeqb = true;
1075     for (auto &oneVal : a.valueMap)
1076     {
1077         auto it = b.valueMap.find(oneVal.first);
1078         if (it == b.valueMap.end() || it->second != oneVal.second)
1079         {
1080             isaeqb = false;
1081             break;
1082         }
1083     }
1084     return isaeqb;
1085 }
1086
1087 bool operator!=(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1088 {
1089     return !(a == b);
1090 }
1091
1092 bool operator<=(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1093 {
1094     return (a < b) || (a == b);
1095 }
1096
1097 bool operator>=(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1098 {
1099     return b <= a;
1100 }
1101
1102 CCurrencyValueMap operator+(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1103 {
1104     CCurrencyValueMap retVal = a;
1105     if (a.valueMap.size() || b.valueMap.size())
1106     {
1107         for (auto &oneVal : b.valueMap)
1108         {
1109             auto it = retVal.valueMap.find(oneVal.first);
1110             if (it == retVal.valueMap.end())
1111             {
1112                 retVal.valueMap[oneVal.first] = oneVal.second;
1113             }
1114             else
1115             {
1116                 it->second += oneVal.second;
1117             }
1118         }
1119     }
1120     return retVal;
1121 }
1122
1123 CCurrencyValueMap operator-(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1124 {
1125     CCurrencyValueMap retVal = a;
1126     if (a.valueMap.size() || b.valueMap.size())
1127     {
1128         for (auto &oneVal : b.valueMap)
1129         {
1130             auto it = retVal.valueMap.find(oneVal.first);
1131             if (it == retVal.valueMap.end())
1132             {
1133                 retVal.valueMap[oneVal.first] = -oneVal.second;
1134             }
1135             else
1136             {
1137                 it->second -= oneVal.second;
1138             }
1139         }
1140     }
1141     return retVal;
1142 }
1143
1144 CCurrencyValueMap operator+(const CCurrencyValueMap& a, int b)
1145 {
1146     CCurrencyValueMap retVal = a;
1147     for (auto &oneVal : retVal.valueMap)
1148     {
1149         oneVal.second += b;
1150     }
1151     return retVal;
1152 }
1153
1154 CCurrencyValueMap operator-(const CCurrencyValueMap& a, int b)
1155 {
1156     CCurrencyValueMap retVal = a;
1157     for (auto &oneVal : retVal.valueMap)
1158     {
1159         oneVal.second -= b;
1160     }
1161     return retVal;
1162 }
1163
1164 CCurrencyValueMap operator*(const CCurrencyValueMap& a, int b)
1165 {
1166     CCurrencyValueMap retVal = a;
1167     for (auto &oneVal : retVal.valueMap)
1168     {
1169         oneVal.second *= b;
1170     }
1171     return retVal;
1172 }
1173
1174 const CCurrencyValueMap &CCurrencyValueMap::operator-=(const CCurrencyValueMap& operand)
1175 {
1176     return *this = *this - operand;
1177 }
1178
1179 const CCurrencyValueMap &CCurrencyValueMap::operator+=(const CCurrencyValueMap& operand)
1180 {
1181     return *this = *this + operand;
1182 }
1183
1184 // determine if the operand intersects this map
1185 bool CCurrencyValueMap::Intersects(const CCurrencyValueMap& operand) const
1186 {
1187     bool retVal = false;
1188
1189     if (valueMap.size() && operand.valueMap.size())
1190     {
1191         for (auto &oneVal : valueMap)
1192         {
1193             auto it = operand.valueMap.find(oneVal.first);
1194             if (it != operand.valueMap.end())
1195             {
1196                 if (it->second > 0 && oneVal.second > 0)
1197                 {
1198                     retVal = true;
1199                     break;
1200                 }
1201             }
1202         }
1203     }
1204     return retVal;
1205 }
1206
1207 CCurrencyValueMap CCurrencyValueMap::IntersectingValues(const CCurrencyValueMap& operand) const
1208 {
1209     CCurrencyValueMap retVal;
1210
1211     if (valueMap.size() && operand.valueMap.size())
1212     {
1213         for (auto &oneVal : valueMap)
1214         {
1215             auto it = operand.valueMap.find(oneVal.first);
1216             if (it != operand.valueMap.end() &&
1217                 it->second != 0 && 
1218                 oneVal.second != 0)
1219             {
1220                 retVal.valueMap[oneVal.first] = oneVal.second;
1221             }
1222         }
1223     }
1224     return retVal;
1225 }
1226
1227 CCurrencyValueMap CCurrencyValueMap::CanonicalMap() const
1228 {
1229     CCurrencyValueMap retVal;
1230     for (auto valPair : valueMap)
1231     {
1232         if (valPair.second != 0)
1233         {
1234             retVal.valueMap.insert(valPair);
1235         }
1236     }
1237     return retVal;
1238 }
1239
1240 CCurrencyValueMap CCurrencyValueMap::NonIntersectingValues(const CCurrencyValueMap& operand) const
1241 {
1242     CCurrencyValueMap retVal = operand;
1243
1244     if (valueMap.size() && operand.valueMap.size())
1245     {
1246         for (auto &oneVal : valueMap)
1247         {
1248             auto it = operand.valueMap.find(oneVal.first);
1249             if (it != operand.valueMap.end())
1250             {
1251                 if (it->second > 0 && oneVal.second > 0)
1252                 {
1253                     retVal.valueMap.erase(it);
1254                 }
1255             }
1256         }
1257     }
1258     return retVal;
1259 }
1260
1261 bool CCurrencyValueMap::IsValid() const
1262 {
1263     for (auto &oneVal : valueMap)
1264     {
1265         if (oneVal.first.IsNull())
1266         {
1267             return false;
1268         }
1269     }
1270     return true;
1271 }
1272
1273 bool CCurrencyValueMap::HasNegative() const
1274 {
1275     for (auto &oneVal : valueMap)
1276     {
1277         if (oneVal.second < 0)
1278         {
1279             return true;
1280         }
1281     }
1282     return false;
1283 }
1284
1285 // subtract, but do not subtract to negative values
1286 CCurrencyValueMap CCurrencyValueMap::SubtractToZero(const CCurrencyValueMap& operand) const
1287 {
1288     CCurrencyValueMap retVal = *this;
1289     std::vector<uint160> toRemove;
1290     if (valueMap.size() && operand.valueMap.size())
1291     {
1292         for (auto &oneVal : retVal.valueMap)
1293         {
1294             auto it = operand.valueMap.find(oneVal.first);
1295             if (it != operand.valueMap.end())
1296             {
1297                 oneVal.second = oneVal.second - it->second;
1298                 if (oneVal.second <= 0)
1299                 {
1300                     toRemove.push_back(oneVal.first);
1301                 }
1302             }
1303         }
1304     }
1305     for (auto &toErase : toRemove)
1306     {
1307         retVal.valueMap.erase(toErase);
1308     }
1309     return retVal;
1310 }
1311
1312 std::vector<CAmount> CCurrencyValueMap::AsCurrencyVector(const std::vector<uint160> &currencies) const
1313 {
1314     std::vector<CAmount> retVal(currencies.size());
1315     for (int i = 0; i < currencies.size(); i++)
1316     {
1317         auto it = valueMap.find(currencies[i]);
1318         retVal[i] = it != valueMap.end() ? it->second : 0;
1319     }
1320     return retVal;
1321 }
This page took 0.101375 seconds and 4 git commands to generate.