]> Git Repo - VerusCoin.git/blob - src/cc/eval.cpp
Merge pull request #128 from miketout/dev
[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_IMPORTPAYOUT:
77             //return ImportPayout(vparams, txTo, nIn);
78             break;
79             
80         case EVAL_IMPORTCOIN:
81             //return ImportCoin(vparams, txTo, nIn);
82             break;
83             
84         default:
85             // only support coinbase guard for now
86             if (ecode == EVAL_STAKEGUARD)
87                 return(ProcessCC(cp,this, vparams, txTo, nIn));
88             break;
89     }
90     return Invalid("invalid-code, dont forget to add EVAL_NEWCC to Eval::Dispatch");
91 }
92
93
94 bool Eval::GetSpendsConfirmed(uint256 hash, std::vector<CTransaction> &spends) const
95 {
96     // NOT IMPLEMENTED
97     return false;
98 }
99
100
101 bool Eval::GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const
102 {
103     // there is a LOCK(cs_main) in the normal GetTransaction(), which leads to deadlocks
104     //bool fAllowSlow = false; // Don't allow slow
105     //return GetTransaction(hash, txOut, hashBlock, fAllowSlow);
106     return myGetTransaction(hash, txOut,hashBlock);
107 }
108
109
110 bool Eval::GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex &block) const
111 {
112     uint256 hashBlock;
113     if (!GetTxUnconfirmed(hash, txOut, hashBlock))
114         return false;
115     if (hashBlock.IsNull() || !GetBlock(hashBlock, block))
116         return false;
117     return true;
118 }
119
120
121 unsigned int Eval::GetCurrentHeight() const
122 {
123     return chainActive.Height();
124 }
125
126 bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const
127 {
128     auto r = mapBlockIndex.find(hash);
129     if (r != mapBlockIndex.end()) {
130         blockIdx = *r->second;
131         return true;
132     }
133     fprintf(stderr, "CC Eval Error: Can't get block from index\n");
134     return false;
135 }
136
137 extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
138
139
140 int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const
141 {
142     return komodo_notaries(pubkeys, height, timestamp);
143 }
144
145
146 bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
147 {
148     if (tx.vin.size() < 11) return false;
149
150     uint8_t seenNotaries[64] = {0};
151     uint8_t notaries[64][33];
152     int nNotaries = GetNotaries(notaries, height, timestamp);
153
154     BOOST_FOREACH(const CTxIn &txIn, tx.vin)
155     {
156         // Get notary pubkey
157         CTransaction tx;
158         uint256 hashBlock;
159         if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
160         if (tx.vout.size() < txIn.prevout.n) return false;
161         CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
162         if (spk.size() != 35) return false;
163         std::vector<unsigned char> scriptVec = std::vector<unsigned char>(spk.begin(),spk.end());
164         const unsigned char *pk = scriptVec.data();
165         if (pk++[0] != 33) return false;
166         if (pk[33] != OP_CHECKSIG) return false;
167
168         // Check it's a notary
169         for (int i=0; i<nNotaries; i++) {
170             if (!seenNotaries[i]) {
171                 if (memcmp(pk, notaries[i], 33) == 0) {
172                     seenNotaries[i] = 1;
173                     goto found;
174                 }
175             }
176         }
177         return false;
178         found:;
179     }
180
181     return true;
182 }
183
184
185 /*
186  * Get MoM from a notarisation tx hash (on KMD)
187  */
188 bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const
189 {
190     CTransaction notarisationTx;
191     CBlockIndex block;
192     if (!GetTxConfirmed(notaryHash, notarisationTx, block)) return false;
193     if (!CheckNotaryInputs(notarisationTx, block.GetHeight(), block.nTime)) return false;
194     if (!ParseNotarisationOpReturn(notarisationTx, data)) return false;
195     return true;
196 }
197
198 /*
199  * Get MoMoM corresponding to a notarisation tx hash (on assetchain)
200  */
201 bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const
202 {
203     std::pair<uint256,NotarisationData> out;
204     if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false;
205     momom = out.second.MoMoM;
206     return true;
207 }
208
209
210 uint32_t Eval::GetAssetchainsCC() const
211 {
212     return ASSETCHAINS_CC;
213 }
214
215
216 std::string Eval::GetAssetchainsSymbol() const
217 {
218     return std::string(ASSETCHAINS_SYMBOL);
219 }
220
221
222 /*
223  * Notarisation data, ie, OP_RETURN payload in notarisation transactions
224  */
225 bool ParseNotarisationOpReturn(const CTransaction &tx, NotarisationData &data)
226 {
227     if (tx.vout.size() < 2) return false;
228     std::vector<unsigned char> vdata;
229     if (!GetOpReturnData(tx.vout[1].scriptPubKey, vdata)) return false;
230     bool out = E_UNMARSHAL(vdata, ss >> data);
231     return out;
232 }
233
234
235 /*
236  * Misc
237  */
238 std::string EvalToStr(EvalCode c)
239 {
240     FOREACH_EVAL(EVAL_GENERATE_STRING);
241     char s[10];
242     sprintf(s, "0x%x", c);
243     return std::string(s);
244
245 }
246
247
248 uint256 SafeCheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
249 {
250     if (nIndex == -1)
251         return uint256();
252     for (auto it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
253     {
254         if (nIndex & 1) {
255             if (*it == hash) {
256                 // non canonical. hash may be equal to node but never on the right.
257                 return uint256();
258             }
259             hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
260         }
261         else
262             hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
263         nIndex >>= 1;
264     }
265     return hash;
266 }
267
268
269 uint256 GetMerkleRoot(const std::vector<uint256>& vLeaves)
270 {
271     bool fMutated;
272     std::vector<uint256> vMerkleTree;
273     return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree);
274 }
This page took 0.062622 seconds and 4 git commands to generate.