]> Git Repo - VerusCoin.git/blame - src/script/script.cpp
Fixes for staking from smart transactions
[VerusCoin.git] / src / script / script.cpp
CommitLineData
cbd22a50 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
2d79bba3 3// Distributed under the MIT software license, see the accompanying
bc909a7a 4// file COPYING or https://www.opensource.org/licenses/mit-license.php .
cbd22a50 5
6#include "script.h"
7
85c579e3
CF
8#include "tinyformat.h"
9#include "utilstrencodings.h"
8a8e10f0 10#include "script/cc.h"
0cb91a8d 11#include "cc/eval.h"
2c8d8268 12#include "cryptoconditions/include/cryptoconditions.h"
68b309c0 13#include "standard.h"
989b1de1 14#include "pbaas/reserves.h"
7a912018 15#include "key_io.h"
b826c625 16#include "univalue.h"
757e67a5 17#include "pbaas/identity.h"
cbd22a50 18
19using namespace std;
0cb91a8d 20
db8eb54b 21namespace {
9feb4b9e 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 }
db8eb54b
CF
29} // anon namespace
30
cbd22a50 31const 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";
07f83521
SS
149 case OP_CHECKCRYPTOCONDITION : return "OP_CHECKCRYPTOCONDITION";
150 case OP_CHECKCRYPTOCONDITIONVERIFY
151 : return "OP_CHECKCRYPTOCONDITIONVERIFY";
cbd22a50 152
c938fb1f 153 // expansion
cbd22a50 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
ef54c6e1 177uint160 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
56fe75cb 186CTxDestination 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
222CTransferDestination 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
2f416b17 238CTransferDestination IdentityToTransferDestination(const CIdentity &identity)
239{
240 return CTransferDestination(CTransferDestination::DEST_FULLID, ::AsVector(identity));
241}
242
243CIdentity 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
56fe75cb 257std::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
267std::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
277CStakeInfo::CStakeInfo(std::vector<unsigned char> vch)
278{
279 ::FromVector(vch, *this);
280}
281
282std::vector<unsigned char> CStakeInfo::AsVector() const
283{
284 return ::AsVector(*this);
285}
286
a4f9bc97 287unsigned int CScript::MAX_SCRIPT_ELEMENT_SIZE = MAX_SCRIPT_ELEMENT_SIZE_V2;
288
cbd22a50 289unsigned 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
313unsigned 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
8b78a819
T
337bool 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
fa7bf712 348bool 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
cbd22a50 356bool CScript::IsPayToScriptHash() const
357{
358 // Extra-fast test for pay-to-script-hash CScripts:
359 return (this->size() == 23 &&
29a8ade7
PW
360 (*this)[0] == OP_HASH160 &&
361 (*this)[1] == 0x14 &&
362 (*this)[22] == OP_EQUAL);
cbd22a50 363}
364
8a727a26 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
368bool CScript::GetBalancedData(const_iterator& pc, std::vector<std::vector<unsigned char>>& vSolutions) const
a99ca25a 369{
8a727a26 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;
3bfa5e22 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;
8a727a26 407 }
8a727a26 408 }
409 else
410 return false;
411 }
412 return netPushes == 0;
413}
414
3bfa5e22 415// this returns true if either there is nothing left and pc points at the end
8a727a26 416// if there is data, it also returns all the values as byte vectors in a list of vectors
60b798c4 417bool CScript::GetPushedData(CScript::const_iterator pc, std::vector<std::vector<unsigned char>>& vData) const
8a727a26 418{
419 vector<unsigned char> data;
420 opcodetype opcode;
3bfa5e22 421 std::vector<unsigned char> vch1 = std::vector<unsigned char>(1);
8a727a26 422
423 vData.clear();
424
60b798c4 425 while (pc < end())
8a727a26 426 {
60b798c4 427 if (GetOp(pc, opcode, data))
8a727a26 428 {
60b798c4 429 if (opcode == OP_0)
8a727a26 430 {
60b798c4
MT
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);
8a727a26 438 }
60b798c4
MT
439 else if (opcode > 0 && opcode <= OP_PUSHDATA4 && data.size() > 0)
440 {
441 vData.push_back(data);
442 }
443 else
444 return false;
8a727a26 445 }
8a727a26 446 }
60b798c4
MT
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
452bool 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;
8a727a26 463}
464
06f41160 465bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript, std::vector<std::vector<unsigned char>>& vParams) const
8a727a26 466{
467 const_iterator pc = begin();
2f537fa1 468 vector<unsigned char> firstParam;
a99ca25a 469 vector<unsigned char> data;
28b94612 470 opcodetype opcode;
2f537fa1 471 if (this->GetOp(pc, opcode, firstParam))
28b94612
SS
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)
8a727a26 476 {
477 const_iterator pcCCEnd = pc;
06f41160 478 if (GetBalancedData(pc, vParams))
8a727a26 479 {
480 if (pCCSubScript)
b7c685b8 481 *pCCSubScript = CScript(begin(), pcCCEnd);
2f537fa1 482 vParams.push_back(firstParam);
3bfa5e22 483 return true;
8a727a26 484 }
485 }
486 return false;
487}
488
489bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript) const
490{
06f41160 491 std::vector<std::vector<unsigned char>> vParams;
492 return IsPayToCryptoCondition(pCCSubScript, vParams);
8a727a26 493}
494
495bool CScript::IsPayToCryptoCondition() const
496{
b2a98c42
MT
497 return IsPayToCryptoCondition((CScript *)NULL);
498}
499
715182a4 500extern uint160 ASSETCHAINS_CHAINID, VERUS_CHAINID;
7a912018 501
b2a98c42
MT
502bool CScript::IsInstantSpend() const
503{
7a912018 504 COptCCParams p;
505 bool isInstantSpend = false;
8496077f 506 if (!_IsVerusActive() && IsPayToCryptoCondition(p) && p.IsValid())
b2a98c42 507 {
7a912018 508 // instant spends must be to expected instant spend crypto conditions and to the right address as well
715182a4 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)))
7a912018 513 {
514 isInstantSpend = true;
515 }
b2a98c42 516 }
7a912018 517 return isInstantSpend;
b2a98c42
MT
518}
519
e7c700b5
MT
520bool 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]);
2f537fa1 530 for (int i = 1; i < vParams.size(); i++)
531 {
532 ccParams.vData.push_back(vParams[i]);
533 }
e7c700b5 534 }
a73ab4b4 535 else
536 {
537 // make sure that we return it in a consistent and known state
538 ccParams = COptCCParams();
539 }
e7c700b5
MT
540 return true;
541 }
a73ab4b4 542 ccParams = COptCCParams();
e7c700b5
MT
543 return false;
544}
545
68b309c0 546bool CScript::IsPayToCryptoCondition(CScript *ccSubScript, std::vector<std::vector<unsigned char>> &vParams, COptCCParams &optParams) const
b2a98c42 547{
68b309c0
MT
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}
b2a98c42 558
68b309c0
MT
559bool 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))
b2a98c42 565 {
68b309c0 566 *ecode = p.evalCode;
b2a98c42
MT
567 return true;
568 }
569 return false;
a99ca25a
SS
570}
571
19f01561 572CScript &CScript::ReplaceCCParams(const COptCCParams &params)
989b1de1
MT
573{
574 CScript subScript;
575 std::vector<std::vector<unsigned char>> vParams;
576 COptCCParams p;
19f01561 577 if (this->IsPayToCryptoCondition(&subScript, vParams, p) || p.evalCode != params.evalCode)
989b1de1 578 {
19f01561 579 // add the object to the end of the script
580 *this = subScript;
581 *this << params.AsVector() << OP_DROP;
989b1de1 582 }
19f01561 583 return *this;
989b1de1
MT
584}
585
15197dca 586bool 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:
adb5cebb 599 case EVAL_IDENTITY_COMMITMENT:
600 case EVAL_IDENTITY_PRIMARY:
601 case EVAL_IDENTITY_REVOKE:
602 case EVAL_IDENTITY_RECOVER:
603 case EVAL_IDENTITY_RESERVATION:
15197dca 604 {
605 isSpendable = false;
606 break;
607 }
608 }
609 return isSpendable;
610}
611
612bool CScript::IsSpendableOutputType() const
613{
614 COptCCParams p;
615 if (IsPayToCryptoCondition(p))
616 {
617 return IsSpendableOutputType(p);
618 }
619 // default for non-CC outputs is true, this is to protect from accidentally spending specific CC output types,
620 // even though they could be spent
621 return true;
622}
623
624CCurrencyValueMap CScript::ReserveOutValue(COptCCParams &p, bool spendableOnly) const
989b1de1 625{
56fe75cb 626 CCurrencyValueMap retVal;
4b7d1485 627
989b1de1 628 // already validated above
15197dca 629 if (IsPayToCryptoCondition(p) && p.IsValid() && (!spendableOnly || IsSpendableOutputType(p)))
989b1de1
MT
630 {
631 switch (p.evalCode)
632 {
633 case EVAL_RESERVE_OUTPUT:
634 {
56fe75cb 635 CTokenOutput ro(p.vData[0]);
0ab273d2 636 if (ro.nValue)
637 {
638 retVal.valueMap[ro.currencyID] = ro.nValue;
639 }
989b1de1
MT
640 break;
641 }
15197dca 642
643 case EVAL_RESERVE_DEPOSIT:
644 {
645 CTokenOutput ro(p.vData[0]);
646 if (ro.nValue)
647 {
648 retVal.valueMap[ro.currencyID] = ro.nValue;
649 }
650 break;
651 }
652
34d1aa13
MT
653 case EVAL_CURRENCYSTATE:
654 {
655 CCoinbaseCurrencyState cbcs(p.vData[0]);
56fe75cb 656 for (int i = 0; i < cbcs.currencies.size(); i++)
657 {
658 if (cbcs.reserveOut[i])
659 {
660 retVal.valueMap[cbcs.currencies[i]] = cbcs.reserveOut[i];
661 }
662 }
34d1aa13
MT
663 break;
664 }
15197dca 665
989b1de1
MT
666 case EVAL_RESERVE_TRANSFER:
667 {
668 CReserveTransfer rt(p.vData[0]);
815a42a6 669 // this currency can only be present as native
f023c2d4 670 if (!(rt.flags & (rt.MINT_CURRENCY | rt.PREALLOCATE)) && rt.currencyID != ASSETCHAINS_CHAINID)
815a42a6 671 {
672 retVal.valueMap[rt.currencyID] = rt.nValue + rt.nFees;
673 }
989b1de1
MT
674 break;
675 }
15197dca 676
989b1de1
MT
677 case EVAL_RESERVE_EXCHANGE:
678 {
679 CReserveExchange re(p.vData[0]);
e7e14f44
MT
680 // reserve out amount when converting to reserve is 0, since the amount cannot be calculated in isolation as an input
681 // if reserve in, we can consider the output the same reserve value as the input
56fe75cb 682 if (!(re.flags & re.TO_RESERVE))
683 {
684 retVal.valueMap[re.currencyID] = re.nValue;
685 }
e7e14f44
MT
686 break;
687 }
0ab273d2 688 case EVAL_CROSSCHAIN_IMPORT:
689 {
690 CCrossChainImport cci(p.vData[0]);
691 // reserve out amount when converting to reserve is 0, since the amount cannot be calculated in isolation as an input
692 // if reserve in, we can consider the output the same reserve value as the input
693 retVal = cci.totalReserveOutMap;
694 break;
695 }
e7e14f44
MT
696 }
697 }
56fe75cb 698 return retVal;
e7e14f44
MT
699}
700
56fe75cb 701CCurrencyValueMap CScript::ReserveOutValue() const
e7e14f44
MT
702{
703 COptCCParams p;
cdbadc7f 704 return ReserveOutValue(p);
989b1de1
MT
705}
706
56fe75cb 707bool CScript::SetReserveOutValue(const CCurrencyValueMap &newValues)
989b1de1
MT
708{
709 COptCCParams p;
710 CAmount newVal = 0;
711
712 // already validated above
713 if (::IsPayToCryptoCondition(*this, p) && p.IsValid())
714 {
715 switch (p.evalCode)
716 {
717 case EVAL_RESERVE_OUTPUT:
718 {
56fe75cb 719 if (newValues.valueMap.size() != 1)
720 {
721 return false;
722 }
723 CTokenOutput ro(p.vData[0]);
724 ro.currencyID = newValues.valueMap.begin()->first;
725 ro.nValue = newValues.valueMap.begin()->second;
989b1de1
MT
726 p.vData[0] = ro.AsVector();
727 break;
728 }
729 case EVAL_RESERVE_TRANSFER:
730 {
56fe75cb 731 if (newValues.valueMap.size() != 1)
732 {
733 return false;
734 }
989b1de1 735 CReserveTransfer rt(p.vData[0]);
56fe75cb 736 rt.currencyID = newValues.valueMap.begin()->first;
737 rt.nValue = newValues.valueMap.begin()->second;
989b1de1
MT
738 p.vData[0] = rt.AsVector();
739 break;
740 }
741 case EVAL_RESERVE_EXCHANGE:
742 {
56fe75cb 743 if (newValues.valueMap.size() != 1)
744 {
745 return false;
746 }
989b1de1 747 CReserveExchange re(p.vData[0]);
56fe75cb 748 re.currencyID = newValues.valueMap.begin()->first;
749 re.nValue = newValues.valueMap.begin()->second;
989b1de1
MT
750 p.vData[0] = re.AsVector();
751 break;
752 }
cdbadc7f 753 case EVAL_CROSSCHAIN_IMPORT:
754 {
755 CCrossChainImport cci(p.vData[0]);
56fe75cb 756 cci.importValue = newValues;
cdbadc7f 757 p.vData[0] = cci.AsVector();
758 break;
759 }
760 // cross chain import thread holds the original conversion amounts
761 case EVAL_CURRENCYSTATE:
762 {
763 CCoinbaseCurrencyState cbcs(p.vData[0]);
56fe75cb 764 for (int i = 0; i < cbcs.currencies.size(); i++)
765 {
766 auto it = newValues.valueMap.find(cbcs.currencies[i]);
767 if (it != newValues.valueMap.end())
768 {
769 cbcs.reserveOut[i] = it->second;
770 }
771 }
cdbadc7f 772 p.vData[0] = cbcs.AsVector();
773 break;
774 }
775
989b1de1
MT
776 default:
777 return false;
778 }
779 *this = ReplaceCCParams(p);
780 return true;
781 }
782 return false;
783}
784
2c8d8268
SS
785bool CScript::MayAcceptCryptoCondition() const
786{
787 // Get the type mask of the condition
788 const_iterator pc = this->begin();
789 vector<unsigned char> data;
790 opcodetype opcode;
791 if (!this->GetOp(pc, opcode, data)) return false;
792 if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false;
793 CC *cond = cc_readConditionBinary(data.data(), data.size());
794 if (!cond) return false;
b2a98c42 795
0574c740 796 uint32_t eCode;
797 if (!IsPayToCryptoCondition(&eCode))
798 {
799 return false;
800 }
801
802 bool out = IsSupportedCryptoCondition(cond, eCode);
b2a98c42 803
563581af
SS
804 cc_free(cond);
805 return out;
2c8d8268
SS
806}
807
6da11b8b 808// also checks if the eval code is consistent
809bool CScript::MayAcceptCryptoCondition(int evalCode) const
810{
811 // Get the type mask of the condition
812 const_iterator pc = this->begin();
813 vector<unsigned char> data;
814 opcodetype opcode;
815 if (!this->GetOp(pc, opcode, data)) return false;
816 if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false;
817 CC *cond = cc_readConditionBinary(data.data(), data.size());
818 if (!cond) return false;
819
0574c740 820 bool out = IsSupportedCryptoCondition(cond, evalCode);
6da11b8b 821
822 cc_free(cond);
823 return out;
824}
825
0cb91a8d
SS
826bool CScript::IsCoinImport() const
827{
828 const_iterator pc = this->begin();
829 vector<unsigned char> data;
830 opcodetype opcode;
831 if (this->GetOp(pc, opcode, data))
832 if (opcode > OP_0 && opcode <= OP_PUSHDATA4)
833 return data.begin()[0] == EVAL_IMPORTCOIN;
834 return false;
835}
836
cbd22a50 837bool CScript::IsPushOnly() const
838{
839 const_iterator pc = begin();
840 while (pc < end())
841 {
842 opcodetype opcode;
843 if (!GetOp(pc, opcode))
844 return false;
845 // Note that IsPushOnly() *does* consider OP_RESERVED to be a
846 // push-type opcode, however execution of OP_RESERVED fails, so
d752ba86 847 // it's not relevant to P2SH/BIP62 as the scriptSig would fail prior to
cbd22a50 848 // the P2SH special validation code being executed.
849 if (opcode > OP_16)
850 return false;
851 }
852 return true;
853}
854
e980a26d 855// if the front of the script has check lock time verify. this is a fairly simple check.
856// accepts NULL as parameter if unlockTime is not needed.
857bool CScript::IsCheckLockTimeVerify(int64_t *unlockTime) const
858{
859 opcodetype op;
860 std::vector<unsigned char> unlockTimeParam = std::vector<unsigned char>();
861 CScript::const_iterator it = this->begin();
862
863 if (this->GetOp2(it, op, &unlockTimeParam))
864 {
865 if (unlockTimeParam.size() >= 0 && unlockTimeParam.size() < 6 &&
9feb4b9e 866 (*this)[unlockTimeParam.size() + 1] == OP_CHECKLOCKTIMEVERIFY)
e980a26d 867 {
868 int i = unlockTimeParam.size() - 1;
869 for (*unlockTime = 0; i >= 0; i--)
870 {
871 *unlockTime <<= 8;
872 *unlockTime |= *((unsigned char *)unlockTimeParam.data() + i);
873 }
874 return true;
875 }
876 }
877 return false;
878}
879
880bool CScript::IsCheckLockTimeVerify() const
881{
882 int64_t ult;
883 return this->IsCheckLockTimeVerify(&ult);
884}
885
db8eb54b
CF
886std::string CScript::ToString() const
887{
888 std::string str;
889 opcodetype opcode;
890 std::vector<unsigned char> vch;
891 const_iterator pc = begin();
892 while (pc < end())
893 {
894 if (!str.empty())
895 str += " ";
896 if (!GetOp(pc, opcode, vch))
897 {
898 str += "[error]";
899 return str;
900 }
901 if (0 <= opcode && opcode <= OP_PUSHDATA4)
902 str += ValueString(vch);
903 else
904 str += GetOpName(opcode);
905 }
906 return str;
907}
88d014d0 908
f381d4e0 909CScript::ScriptType CScript::GetType() const
6cf0e50b
LR
910{
911 if (this->IsPayToPublicKeyHash())
88d014d0 912 {
f381d4e0 913 return CScript::P2PKH;
88d014d0 914 }
915 else if (this->IsPayToScriptHash())
916 {
f381d4e0 917 return CScript::P2SH;
88d014d0 918 }
919 else if (this->IsPayToPublicKey())
920 {
921 return CScript::P2PK;
922 }
923 else if (this->IsPayToCryptoCondition())
924 {
925 return CScript::P2CC;
926 }
927
68e174e2 928 // We don't know this script type
f381d4e0 929 return CScript::UNKNOWN;
6cf0e50b
LR
930}
931
6cf0e50b
LR
932uint160 CScript::AddressHash() const
933{
88d014d0 934 uint160 addressHash;
935 COptCCParams p;
936 if (this->IsPayToScriptHash()) {
937 addressHash = uint160(std::vector<unsigned char>(this->begin()+2, this->begin()+22));
6cf0e50b 938 }
88d014d0 939 else if (this->IsPayToPublicKeyHash())
940 {
941 addressHash = uint160(std::vector<unsigned char>(this->begin()+3, this->begin()+23));
942 }
943 else if (this->IsPayToPublicKey())
944 {
945 std::vector<unsigned char> hashBytes(this->begin()+1, this->begin()+34);
946 addressHash = Hash160(hashBytes);
947 }
948 else if (this->IsPayToCryptoCondition(p)) {
949 if (p.IsValid() && (p.vKeys.size()))
950 {
2f537fa1 951 COptCCParams master;
952 if (p.version >= p.VERSION_V3 && p.vData.size() > 1 && (master = COptCCParams(p.vData.back())).IsValid() && master.vKeys.size())
953 {
954 addressHash = GetDestinationID(master.vKeys[0]);
955 }
956 else
957 {
958 addressHash = GetDestinationID(p.vKeys[0]);
959 }
88d014d0 960 }
961 else
962 {
963 vector<unsigned char> hashBytes(this->begin(), this->end());
964 addressHash = Hash160(hashBytes);
965 }
966 }
967 return addressHash;
6cf0e50b 968}
88d014d0 969
3d682fc8 970std::vector<CTxDestination> CScript::GetDestinations() const
2f537fa1 971{
3d682fc8 972 std::vector<CTxDestination> destinations;
2f537fa1 973 COptCCParams p;
05cef42a 974 if (this->IsPayToCryptoCondition(p))
975 {
976 if (p.IsValid() && (p.vKeys.size()))
977 {
978 destinations = p.GetDestinations();
979 }
980 else
981 {
982 vector<unsigned char> hashBytes(this->begin(), this->end());
983 destinations.push_back(CKeyID(Hash160(hashBytes)));
984 }
985 }
986 else if (this->IsPayToScriptHash()) {
3d682fc8 987 destinations.push_back(CScriptID(uint160(std::vector<unsigned char>(this->begin()+2, this->begin()+22))));
2f537fa1 988 }
989 else if (this->IsPayToPublicKeyHash())
990 {
3d682fc8 991 destinations.push_back(CKeyID(uint160(std::vector<unsigned char>(this->begin()+3, this->begin()+23))));
2f537fa1 992 }
993 else if (this->IsPayToPublicKey())
994 {
995 std::vector<unsigned char> hashBytes(this->begin()+1, this->begin()+34);
3d682fc8 996 destinations.push_back(CPubKey(hashBytes));
2f537fa1 997 }
3d682fc8 998 return destinations;
2f537fa1 999}
1000
757e67a5 1001uint160 GetNameID(const std::string &Name, const uint160 &parent)
1002{
1003 uint160 writeable = parent;
1004 return CIdentity::GetID(Name, writeable);
1005}
1006
b826c625 1007CAmount AmountFromValueNoErr(const UniValue& value)
1008{
1009 try
1010 {
1011 CAmount amount;
1012 if (!value.isNum() && !value.isStr())
1013 {
1014 amount = 0;
1015 }
1016 else if (!ParseFixedPoint(value.getValStr(), 8, &amount))
1017 {
1018 amount = 0;
1019 }
1020 else if (!MoneyRange(amount))
1021 {
1022 amount = 0;
1023 }
1024 return amount;
1025 }
1026 catch(const std::exception& e)
1027 {
1028 return 0;
1029 }
1030}
1031
b826c625 1032CCurrencyValueMap::CCurrencyValueMap(const std::vector<uint160> &currencyIDs, const std::vector<CAmount> &amounts)
1033{
1034 int commonNum = currencyIDs.size() >= amounts.size() ? amounts.size() : currencyIDs.size();
1035 for (int i = 0; i < commonNum; i++)
1036 {
1037 valueMap[currencyIDs[i]] = amounts[i];
1038 }
1039}
1040
1041bool operator<(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1042{
1043 // to be less than means, in this order:
1044 // 1. To have fewer non-zero currencies.
1045 // 2. If not fewer currencies, to be unable to be subtracted from the one being checked
1046 // without creating negative values
1047 if (!a.valueMap.size() && !b.valueMap.size())
1048 {
1049 return false;
1050 }
1051 bool isaltb = false;
1052
1053 for (auto &oneVal : b.valueMap)
1054 {
1055 if (oneVal.second)
1056 {
1057 auto it = a.valueMap.find(oneVal.first);
1058 if (it == a.valueMap.end() || it->second < oneVal.second)
1059 {
1060 isaltb = true;
1061 }
1062 }
1063 }
1064 return isaltb;
1065}
1066
1067bool operator>(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1068{
1069 return b < a;
1070}
1071
1072bool operator==(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1073{
1074 if (a.valueMap.size() != b.valueMap.size())
1075 {
1076 return false;
1077 }
1078
1079 bool isaeqb = true;
1080 for (auto &oneVal : a.valueMap)
1081 {
1082 auto it = b.valueMap.find(oneVal.first);
1083 if (it == b.valueMap.end() || it->second != oneVal.second)
1084 {
1085 isaeqb = false;
1086 break;
1087 }
1088 }
1089 return isaeqb;
1090}
1091
1092bool operator!=(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1093{
1094 return !(a == b);
1095}
1096
1097bool operator<=(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1098{
1099 return (a < b) || (a == b);
1100}
1101
1102bool operator>=(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1103{
1104 return b <= a;
1105}
1106
1107CCurrencyValueMap operator+(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1108{
1109 CCurrencyValueMap retVal = a;
1110 if (a.valueMap.size() || b.valueMap.size())
1111 {
1112 for (auto &oneVal : b.valueMap)
1113 {
1114 auto it = retVal.valueMap.find(oneVal.first);
1115 if (it == retVal.valueMap.end())
1116 {
1117 retVal.valueMap[oneVal.first] = oneVal.second;
1118 }
1119 else
1120 {
1121 it->second += oneVal.second;
1122 }
1123 }
1124 }
1125 return retVal;
1126}
1127
1128CCurrencyValueMap operator-(const CCurrencyValueMap& a, const CCurrencyValueMap& b)
1129{
1130 CCurrencyValueMap retVal = a;
1131 if (a.valueMap.size() || b.valueMap.size())
1132 {
1133 for (auto &oneVal : b.valueMap)
1134 {
1135 auto it = retVal.valueMap.find(oneVal.first);
1136 if (it == retVal.valueMap.end())
1137 {
1138 retVal.valueMap[oneVal.first] = -oneVal.second;
1139 }
1140 else
1141 {
1142 it->second -= oneVal.second;
1143 }
1144 }
1145 }
1146 return retVal;
1147}
1148
1149CCurrencyValueMap operator+(const CCurrencyValueMap& a, int b)
1150{
1151 CCurrencyValueMap retVal = a;
1152 for (auto &oneVal : retVal.valueMap)
1153 {
1154 oneVal.second += b;
1155 }
1156 return retVal;
1157}
1158
1159CCurrencyValueMap operator-(const CCurrencyValueMap& a, int b)
1160{
1161 CCurrencyValueMap retVal = a;
1162 for (auto &oneVal : retVal.valueMap)
1163 {
1164 oneVal.second -= b;
1165 }
1166 return retVal;
1167}
1168
1169CCurrencyValueMap operator*(const CCurrencyValueMap& a, int b)
1170{
1171 CCurrencyValueMap retVal = a;
1172 for (auto &oneVal : retVal.valueMap)
1173 {
1174 oneVal.second *= b;
1175 }
1176 return retVal;
1177}
1178
1179const CCurrencyValueMap &CCurrencyValueMap::operator-=(const CCurrencyValueMap& operand)
1180{
1181 return *this = *this - operand;
1182}
1183
1184const CCurrencyValueMap &CCurrencyValueMap::operator+=(const CCurrencyValueMap& operand)
1185{
1186 return *this = *this + operand;
1187}
1188
1189// determine if the operand intersects this map
1190bool CCurrencyValueMap::Intersects(const CCurrencyValueMap& operand) const
1191{
1192 bool retVal = false;
1193
1194 if (valueMap.size() && operand.valueMap.size())
1195 {
1196 for (auto &oneVal : valueMap)
1197 {
1198 auto it = operand.valueMap.find(oneVal.first);
1199 if (it != operand.valueMap.end())
1200 {
1201 if (it->second > 0 && oneVal.second > 0)
1202 {
1203 retVal = true;
1204 break;
1205 }
1206 }
1207 }
1208 }
1209 return retVal;
1210}
1211
1212CCurrencyValueMap CCurrencyValueMap::IntersectingValues(const CCurrencyValueMap& operand) const
1213{
1214 CCurrencyValueMap retVal;
1215
1216 if (valueMap.size() && operand.valueMap.size())
1217 {
1218 for (auto &oneVal : valueMap)
1219 {
1220 auto it = operand.valueMap.find(oneVal.first);
1221 if (it != operand.valueMap.end() &&
1222 it->second != 0 &&
1223 oneVal.second != 0)
1224 {
1225 retVal.valueMap[oneVal.first] = oneVal.second;
1226 }
1227 }
1228 }
1229 return retVal;
1230}
1231
1232CCurrencyValueMap CCurrencyValueMap::CanonicalMap() const
1233{
1234 CCurrencyValueMap retVal;
1235 for (auto valPair : valueMap)
1236 {
1237 if (valPair.second != 0)
1238 {
1239 retVal.valueMap.insert(valPair);
1240 }
1241 }
1242 return retVal;
1243}
1244
1245CCurrencyValueMap CCurrencyValueMap::NonIntersectingValues(const CCurrencyValueMap& operand) const
1246{
1247 CCurrencyValueMap retVal = operand;
1248
1249 if (valueMap.size() && operand.valueMap.size())
1250 {
1251 for (auto &oneVal : valueMap)
1252 {
1253 auto it = operand.valueMap.find(oneVal.first);
1254 if (it != operand.valueMap.end())
1255 {
1256 if (it->second > 0 && oneVal.second > 0)
1257 {
1258 retVal.valueMap.erase(it);
1259 }
1260 }
1261 }
1262 }
1263 return retVal;
1264}
1265
1266bool CCurrencyValueMap::IsValid() const
1267{
1268 for (auto &oneVal : valueMap)
1269 {
1270 if (oneVal.first.IsNull())
1271 {
1272 return false;
1273 }
1274 }
1275 return true;
1276}
1277
1278bool CCurrencyValueMap::HasNegative() const
1279{
1280 for (auto &oneVal : valueMap)
1281 {
1282 if (oneVal.second < 0)
1283 {
1284 return true;
1285 }
1286 }
1287 return false;
1288}
1289
1290// subtract, but do not subtract to negative values
1291CCurrencyValueMap CCurrencyValueMap::SubtractToZero(const CCurrencyValueMap& operand) const
1292{
1293 CCurrencyValueMap retVal = *this;
1294 std::vector<uint160> toRemove;
1295 if (valueMap.size() && operand.valueMap.size())
1296 {
1297 for (auto &oneVal : retVal.valueMap)
1298 {
1299 auto it = operand.valueMap.find(oneVal.first);
1300 if (it != operand.valueMap.end())
1301 {
1302 oneVal.second = oneVal.second - it->second;
1303 if (oneVal.second <= 0)
1304 {
1305 toRemove.push_back(oneVal.first);
1306 }
1307 }
1308 }
1309 }
1310 for (auto &toErase : toRemove)
1311 {
1312 retVal.valueMap.erase(toErase);
1313 }
1314 return retVal;
1315}
1316
1317std::vector<CAmount> CCurrencyValueMap::AsCurrencyVector(const std::vector<uint160> &currencies) const
1318{
1319 std::vector<CAmount> retVal(currencies.size());
1320 for (int i = 0; i < currencies.size(); i++)
1321 {
1322 auto it = valueMap.find(currencies[i]);
1323 retVal[i] = it != valueMap.end() ? it->second : 0;
1324 }
1325 return retVal;
1326}
This page took 0.437681 seconds and 4 git commands to generate.