]> Git Repo - VerusCoin.git/blob - src/cc/eval.cpp
Initial reserves implementation core
[VerusCoin.git] / src / cc / eval.cpp
1 /******************************************************************************
2  * Copyright © 2014-2018 The SuperNET Developers.                             *
3  *                                                                            *
4  * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at                  *
5  * the top-level directory of this distribution for the individual copyright  *
6  * holder information and the developer policies on copyright and licensing.  *
7  *                                                                            *
8  * Unless otherwise agreed in a custom licensing agreement, no part of the    *
9  * SuperNET software, including this file may be copied, modified, propagated *
10  * or distributed except according to the terms contained in the LICENSE file *
11  *                                                                            *
12  * Removal or modification of this copyright notice is prohibited.            *
13  *                                                                            *
14  ******************************************************************************/
15
16 #include <assert.h>
17 #include <cryptoconditions.h>
18
19 #include "primitives/block.h"
20 #include "primitives/transaction.h"
21 #include "script/cc.h"
22 #include "cc/eval.h"
23 #include "cc/utils.h"
24 #include "cc/CCinclude.h"
25 #include "main.h"
26 #include "chain.h"
27 #include "core_io.h"
28 #include "crosschain.h"
29
30
31 Eval* EVAL_TEST = 0;
32 struct CCcontract_info CCinfos[0x100];
33 extern pthread_mutex_t KOMODO_CC_mutex;
34
35 bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn)
36 {
37     EvalRef eval;
38     pthread_mutex_lock(&KOMODO_CC_mutex);
39     bool out = eval->Dispatch(cond, tx, nIn);
40     pthread_mutex_unlock(&KOMODO_CC_mutex);
41     //fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid());
42     assert(eval->state.IsValid() == out);
43
44     if (eval->state.IsValid()) return true;
45
46     std::string lvl = eval->state.IsInvalid() ? "Invalid" : "Error!";
47     fprintf(stderr, "CC Eval %s %s: %s spending tx %s\n",
48             EvalToStr(cond->code[0]).data(),
49             lvl.data(),
50             eval->state.GetRejectReason().data(),
51             tx.vin[nIn].prevout.hash.GetHex().data());
52     if (eval->state.IsError()) fprintf(stderr, "Culprit: %s\n", EncodeHexTx(tx).data());
53     return false;
54 }
55
56
57 /*
58  * Test the validity of an Eval node
59  */
60 bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
61 {
62     struct CCcontract_info *cp;
63     if (cond->codeLength == 0)
64         return Invalid("empty-eval");
65
66     uint8_t ecode = cond->code[0];
67     cp = &CCinfos[(int32_t)ecode];
68     if ( cp->didinit == 0 )
69     {
70         CCinit(cp,ecode);
71         cp->didinit = 1;
72     }
73     std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
74     switch ( ecode )
75     {
76         case EVAL_PBAASDEFINITION:
77         case EVAL_SERVICEREWARD:
78         case EVAL_EARNEDNOTARIZATION:
79         case EVAL_ACCEPTEDNOTARIZATION:
80         case EVAL_FINALIZENOTARIZATION:
81         case EVAL_RESERVE_OUTPUT:
82         case EVAL_CROSSCHAIN_EXPORT:
83         case EVAL_CROSSCHAIN_IMPORT:
84         case EVAL_COINBASECONVERSIONOUT:
85         case EVAL_RESERVE_TRANSFER:
86             if (!chainActive.LastTip() || CConstVerusSolutionVector::activationHeight.ActiveVersion(chainActive.LastTip()->GetHeight()) < CActivationHeight::SOLUTION_VERUSV3)
87             {
88                 // if chain is not able to process this yet, don't drop through to do so
89                 break;
90             }
91
92         case EVAL_STAKEGUARD:
93             return(ProcessCC(cp,this, vparams, txTo, nIn));
94             break;
95
96         case EVAL_IMPORTPAYOUT:
97             //return ImportPayout(vparams, txTo, nIn);
98             break;
99             
100         case EVAL_IMPORTCOIN:
101             //return ImportCoin(vparams, txTo, nIn);
102             break;
103     }
104     return Invalid("invalid-code, dont forget to add EVAL_NEWCC to Eval::Dispatch");
105 }
106
107
108 bool Eval::GetSpendsConfirmed(uint256 hash, std::vector<CTransaction> &spends) const
109 {
110     // NOT IMPLEMENTED
111     return false;
112 }
113
114
115 bool Eval::GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const
116 {
117     // there is a LOCK(cs_main) in the normal GetTransaction(), which leads to deadlocks
118     //bool fAllowSlow = false; // Don't allow slow
119     //return GetTransaction(hash, txOut, hashBlock, fAllowSlow);
120     return myGetTransaction(hash, txOut,hashBlock);
121 }
122
123
124 bool Eval::GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex &block) const
125 {
126     uint256 hashBlock;
127     if (!GetTxUnconfirmed(hash, txOut, hashBlock))
128         return false;
129     if (hashBlock.IsNull() || !GetBlock(hashBlock, block))
130         return false;
131     return true;
132 }
133
134
135 unsigned int Eval::GetCurrentHeight() const
136 {
137     return chainActive.Height();
138 }
139
140 bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const
141 {
142     auto r = mapBlockIndex.find(hash);
143     if (r != mapBlockIndex.end()) {
144         blockIdx = *r->second;
145         return true;
146     }
147     fprintf(stderr, "CC Eval Error: Can't get block from index\n");
148     return false;
149 }
150
151 extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
152
153
154 int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const
155 {
156     return komodo_notaries(pubkeys, height, timestamp);
157 }
158
159
160 bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
161 {
162     if (tx.vin.size() < 11) return false;
163
164     uint8_t seenNotaries[64] = {0};
165     uint8_t notaries[64][33];
166     int nNotaries = GetNotaries(notaries, height, timestamp);
167
168     BOOST_FOREACH(const CTxIn &txIn, tx.vin)
169     {
170         // Get notary pubkey
171         CTransaction tx;
172         uint256 hashBlock;
173         if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
174         if (tx.vout.size() < txIn.prevout.n) return false;
175         CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
176         if (spk.size() != 35) return false;
177         std::vector<unsigned char> scriptVec = std::vector<unsigned char>(spk.begin(),spk.end());
178         const unsigned char *pk = scriptVec.data();
179         if (pk++[0] != 33) return false;
180         if (pk[33] != OP_CHECKSIG) return false;
181
182         // Check it's a notary
183         for (int i=0; i<nNotaries; i++) {
184             if (!seenNotaries[i]) {
185                 if (memcmp(pk, notaries[i], 33) == 0) {
186                     seenNotaries[i] = 1;
187                     goto found;
188                 }
189             }
190         }
191         return false;
192         found:;
193     }
194
195     return true;
196 }
197
198
199 /*
200  * Get MoM from a notarisation tx hash (on KMD)
201  */
202 bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const
203 {
204     CTransaction notarisationTx;
205     CBlockIndex block;
206     if (!GetTxConfirmed(notaryHash, notarisationTx, block)) return false;
207     if (!CheckNotaryInputs(notarisationTx, block.GetHeight(), block.nTime)) return false;
208     if (!ParseNotarisationOpReturn(notarisationTx, data)) return false;
209     return true;
210 }
211
212 /*
213  * Get MoMoM corresponding to a notarisation tx hash (on assetchain)
214  */
215 bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const
216 {
217     std::pair<uint256,NotarisationData> out;
218     if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false;
219     momom = out.second.MoMoM;
220     return true;
221 }
222
223
224 uint32_t Eval::GetAssetchainsCC() const
225 {
226     return ASSETCHAINS_CC;
227 }
228
229
230 std::string Eval::GetAssetchainsSymbol() const
231 {
232     return std::string(ASSETCHAINS_SYMBOL);
233 }
234
235
236 /*
237  * Notarisation data, ie, OP_RETURN payload in notarisation transactions
238  */
239 bool ParseNotarisationOpReturn(const CTransaction &tx, NotarisationData &data)
240 {
241     if (tx.vout.size() < 2) return false;
242     std::vector<unsigned char> vdata;
243     if (!GetOpReturnData(tx.vout[1].scriptPubKey, vdata)) return false;
244     bool out = E_UNMARSHAL(vdata, ss >> data);
245     return out;
246 }
247
248
249 /*
250  * Misc
251  */
252 std::string EvalToStr(EvalCode c)
253 {
254     FOREACH_EVAL(EVAL_GENERATE_STRING);
255     char s[10];
256     sprintf(s, "0x%x", c);
257     return std::string(s);
258
259 }
260
261
262 uint256 SafeCheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
263 {
264     if (nIndex == -1)
265         return uint256();
266     for (auto it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
267     {
268         if (nIndex & 1) {
269             if (*it == hash) {
270                 // non canonical. hash may be equal to node but never on the right.
271                 return uint256();
272             }
273             hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
274         }
275         else
276             hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
277         nIndex >>= 1;
278     }
279     return hash;
280 }
281
282
283 uint256 GetMerkleRoot(const std::vector<uint256>& vLeaves)
284 {
285     bool fMutated;
286     std::vector<uint256> vMerkleTree;
287     return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree);
288 }
This page took 0.039398 seconds and 4 git commands to generate.