]> Git Repo - VerusCoin.git/blob - src/cc/eval.cpp
Merge remote-tracking branch 'jl/jl777' into momo
[VerusCoin.git] / src / cc / eval.cpp
1 #include <assert.h>
2 #include <cryptoconditions.h>
3
4 #include "primitives/block.h"
5 #include "primitives/transaction.h"
6 #include "script/cc.h"
7 #include "cc/eval.h"
8 #include "cc/utils.h"
9 #include "main.h"
10 #include "chain.h"
11 #include "core_io.h"
12 #include "crosschain.h"
13
14
15 Eval* EVAL_TEST = 0;
16
17
18 bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn)
19 {
20     EvalRef eval;
21
22     bool out = eval->Dispatch(cond, tx, nIn);
23     assert(eval->state.IsValid() == out);
24
25     if (eval->state.IsValid()) return true;
26
27     std::string lvl = eval->state.IsInvalid() ? "Invalid" : "Error!";
28     fprintf(stderr, "CC Eval %s %s: %s spending tx %s\n",
29             EvalToStr(cond->code[0]).data(),
30             lvl.data(),
31             eval->state.GetRejectReason().data(),
32             tx.vin[nIn].prevout.hash.GetHex().data());
33     if (eval->state.IsError()) fprintf(stderr, "Culprit: %s\n", EncodeHexTx(tx).data());
34     return false;
35 }
36
37
38 /*
39  * Test the validity of an Eval node
40  */
41 bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
42 {
43     if (cond->codeLength == 0)
44         return Invalid("empty-eval");
45
46     uint8_t ecode = cond->code[0];
47     std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
48
49     if (ecode == EVAL_IMPORTPAYOUT) {
50         return ImportPayout(vparams, txTo, nIn);
51     }
52
53     if (ecode == EVAL_IMPORTCOIN) {
54         return ImportCoin(vparams, txTo, nIn);
55     }
56
57     return Invalid("invalid-code");
58 }
59
60
61 bool Eval::GetSpendsConfirmed(uint256 hash, std::vector<CTransaction> &spends) const
62 {
63     // NOT IMPLEMENTED
64     return false;
65 }
66
67
68 bool Eval::GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const
69 {
70     bool fAllowSlow = false; // Don't allow slow
71     return GetTransaction(hash, txOut, hashBlock, fAllowSlow);
72 }
73
74
75 bool Eval::GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex &block) const
76 {
77     uint256 hashBlock;
78     if (!GetTxUnconfirmed(hash, txOut, hashBlock))
79         return false;
80     if (hashBlock.IsNull() || !GetBlock(hashBlock, block))
81         return false;
82     return true;
83 }
84
85
86 unsigned int Eval::GetCurrentHeight() const
87 {
88     return chainActive.Height();
89 }
90
91
92 bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const
93 {
94     auto r = mapBlockIndex.find(hash);
95     if (r != mapBlockIndex.end()) {
96         blockIdx = *r->second;
97         return true;
98     }
99     fprintf(stderr, "CC Eval Error: Can't get block from index\n");
100     return false;
101 }
102
103
104 extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
105
106
107 int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const
108 {
109     return komodo_notaries(pubkeys, height, timestamp);
110 }
111
112
113 bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
114 {
115     if (tx.vin.size() < 11) return false;
116
117     uint8_t seenNotaries[64] = {0};
118     uint8_t notaries[64][33];
119     int nNotaries = GetNotaries(notaries, height, timestamp);
120
121     BOOST_FOREACH(const CTxIn &txIn, tx.vin)
122     {
123         // Get notary pubkey
124         CTransaction tx;
125         uint256 hashBlock;
126         if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
127         if (tx.vout.size() < txIn.prevout.n) return false;
128         CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
129         if (spk.size() != 35) return false;
130         const unsigned char *pk = spk.data();
131         if (pk++[0] != 33) return false;
132         if (pk[33] != OP_CHECKSIG) return false;
133
134         // Check it's a notary
135         for (int i=0; i<nNotaries; i++) {
136             if (!seenNotaries[i]) {
137                 if (memcmp(pk, notaries[i], 33) == 0) {
138                     seenNotaries[i] = 1;
139                     goto found;
140                 }
141             }
142         }
143         return false;
144         found:;
145     }
146
147     return true;
148 }
149
150
151 /*
152  * Get MoM from a notarisation tx hash (on KMD)
153  */
154 bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const
155 {
156     CTransaction notarisationTx;
157     CBlockIndex block;
158     if (!GetTxConfirmed(notaryHash, notarisationTx, block)) return false;
159     if (!CheckNotaryInputs(notarisationTx, block.nHeight, block.nTime)) return false;
160     if (!ParseNotarisationOpReturn(notarisationTx, data)) return false;
161     return true;
162 }
163
164 /*
165  * Get MoMoM corresponding to a notarisation tx hash (on assetchain)
166  */
167 bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const
168 {
169     std::pair<uint256,NotarisationData> out;
170     if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false;
171     momom = out.second.MoMoM;
172     return true;
173 }
174
175
176 uint32_t Eval::GetAssetchainsCC() const
177 {
178     return ASSETCHAINS_CC;
179 }
180
181
182 std::string Eval::GetAssetchainsSymbol() const
183 {
184     return std::string(ASSETCHAINS_SYMBOL);
185 }
186
187
188 /*
189  * Notarisation data, ie, OP_RETURN payload in notarisation transactions
190  */
191 bool ParseNotarisationOpReturn(const CTransaction &tx, NotarisationData &data)
192 {
193     if (tx.vout.size() < 2) return false;
194     std::vector<unsigned char> vdata;
195     if (!GetOpReturnData(tx.vout[1].scriptPubKey, vdata)) return false;
196     bool out = E_UNMARSHAL(vdata, ss >> data);
197     return out;
198 }
199
200
201 /*
202  * Misc
203  */
204 std::string EvalToStr(EvalCode c)
205 {
206     FOREACH_EVAL(EVAL_GENERATE_STRING);
207     char s[10];
208     sprintf(s, "0x%x", c);
209     return std::string(s);
210
211 }
212
213
214 uint256 SafeCheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
215 {
216     if (nIndex == -1)
217         return uint256();
218     for (auto it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
219     {
220         if (nIndex & 1) {
221             if (*it == hash) {
222                 // non canonical. hash may be equal to node but never on the right.
223                 return uint256();
224             }
225             hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
226         }
227         else
228             hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
229         nIndex >>= 1;
230     }
231     return hash;
232 }
233
234
235 uint256 GetMerkleRoot(const std::vector<uint256>& vLeaves)
236 {
237     bool fMutated;
238     std::vector<uint256> vMerkleTree;
239     return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree);
240 }
This page took 0.037845 seconds and 4 git commands to generate.