merge dev; tests broken, need to use wallet for block rewards
[VerusCoin.git] / src / cc / eval.cpp
CommitLineData
561f3e18
SS
1#include <assert.h>
2#include <cryptoconditions.h>
3
20c3ac51 4#include "primitives/block.h"
2c8d8268 5#include "primitives/transaction.h"
8a8e10f0 6#include "script/cc.h"
2c8d8268 7#include "cc/eval.h"
20c3ac51 8#include "cc/utils.h"
561f3e18
SS
9#include "main.h"
10#include "chain.h"
aa9eec45 11#include "core_io.h"
0ffacf04 12#include "crosschain.h"
561f3e18
SS
13
14
15Eval* EVAL_TEST = 0;
16
17
18bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn)
19{
20c3ac51 20 EvalRef eval;
561f3e18
SS
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!";
39c9911e
SS
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());
aa9eec45 33 if (eval->state.IsError()) fprintf(stderr, "Culprit: %s\n", EncodeHexTx(tx).data());
561f3e18
SS
34 return false;
35}
2c8d8268
SS
36
37
38/*
39 * Test the validity of an Eval node
40 */
561f3e18 41bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
2c8d8268 42{
39c9911e
SS
43 if (cond->codeLength == 0)
44 return Invalid("empty-eval");
2c8d8268 45
39c9911e
SS
46 uint8_t ecode = cond->code[0];
47 std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
2c8d8268 48
39c9911e
SS
49 if (ecode == EVAL_IMPORTPAYOUT) {
50 return ImportPayout(vparams, txTo, nIn);
9ef101bc 51 }
9ef101bc 52
0cb91a8d
SS
53 if (ecode == EVAL_IMPORTCOIN) {
54 return ImportCoin(vparams, txTo, nIn);
55 }
56
39c9911e 57 return Invalid("invalid-code");
2c8d8268 58}
9ef101bc
SS
59
60
47296322 61bool Eval::GetSpendsConfirmed(uint256 hash, std::vector<CTransaction> &spends) const
9ef101bc 62{
561f3e18 63 // NOT IMPLEMENTED
9ef101bc
SS
64 return false;
65}
66
67
47296322 68bool Eval::GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const
561f3e18 69{
47296322 70 bool fAllowSlow = false; // Don't allow slow
561f3e18
SS
71 return GetTransaction(hash, txOut, hashBlock, fAllowSlow);
72}
73
74
47296322
SS
75bool 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
561f3e18
SS
86unsigned int Eval::GetCurrentHeight() const
87{
88 return chainActive.Height();
89}
90
91
92bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const
9ef101bc 93{
561f3e18
SS
94 auto r = mapBlockIndex.find(hash);
95 if (r != mapBlockIndex.end()) {
96 blockIdx = *r->second;
97 return true;
98 }
47296322 99 fprintf(stderr, "CC Eval Error: Can't get block from index\n");
9ef101bc
SS
100 return false;
101}
102
561f3e18
SS
103
104extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
105
106
9bf132a5
SS
107int32_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
561f3e18
SS
113bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
114{
115 if (tx.vin.size() < 11) return false;
116
9bf132a5 117 uint8_t seenNotaries[64] = {0};
561f3e18 118 uint8_t notaries[64][33];
9bf132a5 119 int nNotaries = GetNotaries(notaries, height, timestamp);
561f3e18
SS
120
121 BOOST_FOREACH(const CTxIn &txIn, tx.vin)
122 {
123 // Get notary pubkey
124 CTransaction tx;
125 uint256 hashBlock;
47296322 126 if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
561f3e18 127 if (tx.vout.size() < txIn.prevout.n) return false;
9bf132a5
SS
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;
561f3e18
SS
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 }
9bf132a5
SS
146
147 return true;
148}
149
150
39c9911e 151/*
e4f943d8 152 * Get MoM from a notarisation tx hash (on KMD)
39c9911e
SS
153 */
154bool 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;
20c3ac51 160 if (!ParseNotarisationOpReturn(notarisationTx, data)) return false;
39c9911e
SS
161 return true;
162}
163
e4f943d8
SS
164/*
165 * Get MoMoM corresponding to a notarisation tx hash (on assetchain)
166 */
167bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const
0cb91a8d 168{
0ffacf04
SS
169 std::pair<uint256,NotarisationData> out;
170 if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false;
171 momom = out.second.MoMoM;
172 return true;
0df96a2f
SS
173}
174
175
176uint32_t Eval::GetAssetchainsCC() const
177{
178 return ASSETCHAINS_CC;
179}
180
181
182std::string Eval::GetAssetchainsSymbol() const
183{
184 return std::string(ASSETCHAINS_SYMBOL);
0cb91a8d
SS
185}
186
56cf273f 187
39c9911e
SS
188/*
189 * Notarisation data, ie, OP_RETURN payload in notarisation transactions
190 */
20c3ac51 191bool ParseNotarisationOpReturn(const CTransaction &tx, NotarisationData &data)
9bf132a5 192{
20c3ac51 193 if (tx.vout.size() < 2) return false;
9bf132a5 194 std::vector<unsigned char> vdata;
20c3ac51
SS
195 if (!GetOpReturnData(tx.vout[1].scriptPubKey, vdata)) return false;
196 bool out = E_UNMARSHAL(vdata, ss >> data);
197 return out;
561f3e18
SS
198}
199
200
201/*
39c9911e 202 * Misc
561f3e18 203 */
39c9911e 204std::string EvalToStr(EvalCode c)
561f3e18 205{
39c9911e
SS
206 FOREACH_EVAL(EVAL_GENERATE_STRING);
207 char s[10];
208 sprintf(s, "0x%x", c);
209 return std::string(s);
0cb91a8d
SS
210
211}
212
213
214uint256 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;
561f3e18 232}
20c3ac51
SS
233
234
235uint256 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.071708 seconds and 4 git commands to generate.