]> Git Repo - VerusCoin.git/blob - src/cc/eval.cpp
Merge branch 'dev' of https://github.com/jl777/komodo into trunk-merge
[VerusCoin.git] / src / cc / eval.cpp
1 #include <assert.h>
2 #include <cryptoconditions.h>
3
4 #include "primitives/transaction.h"
5 #include "script/cc.h"
6 #include "cc/eval.h"
7 #include "main.h"
8 #include "chain.h"
9 #include "core_io.h"
10
11
12 Eval* EVAL_TEST = 0;
13
14
15 bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn)
16 {
17     Eval eval_;
18     Eval *eval = EVAL_TEST;
19     if (!eval) eval = &eval_;
20
21     bool out = eval->Dispatch(cond, tx, nIn);
22     assert(eval->state.IsValid() == out);
23
24     if (eval->state.IsValid()) return true;
25
26     std::string lvl = eval->state.IsInvalid() ? "Invalid" : "Error!";
27     fprintf(stderr, "CC Eval %s %s: %s spending tx %s\n",
28             EvalToStr(cond->code[0]).data(),
29             lvl.data(),
30             eval->state.GetRejectReason().data(),
31             tx.vin[nIn].prevout.hash.GetHex().data());
32     if (eval->state.IsError()) fprintf(stderr, "Culprit: %s\n", EncodeHexTx(tx).data());
33     return false;
34 }
35
36
37 /*
38  * Test the validity of an Eval node
39  */
40 bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
41 {
42     if (cond->codeLength == 0)
43         return Invalid("empty-eval");
44
45     uint8_t ecode = cond->code[0];
46     std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
47
48     if (ecode == EVAL_IMPORTPAYOUT) {
49         return ImportPayout(vparams, txTo, nIn);
50     }
51
52     return Invalid("invalid-code");
53 }
54
55
56 bool Eval::GetSpendsConfirmed(uint256 hash, std::vector<CTransaction> &spends) const
57 {
58     // NOT IMPLEMENTED
59     return false;
60 }
61
62
63 bool Eval::GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const
64 {
65     bool fAllowSlow = false; // Don't allow slow
66     return GetTransaction(hash, txOut, hashBlock, fAllowSlow);
67 }
68
69
70 bool Eval::GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex &block) const
71 {
72     uint256 hashBlock;
73     if (!GetTxUnconfirmed(hash, txOut, hashBlock))
74         return false;
75     if (hashBlock.IsNull() || !GetBlock(hashBlock, block))
76         return false;
77     return true;
78 }
79
80
81 unsigned int Eval::GetCurrentHeight() const
82 {
83     return chainActive.Height();
84 }
85
86
87 bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const
88 {
89     auto r = mapBlockIndex.find(hash);
90     if (r != mapBlockIndex.end()) {
91         blockIdx = *r->second;
92         return true;
93     }
94     fprintf(stderr, "CC Eval Error: Can't get block from index\n");
95     return false;
96 }
97
98
99 extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
100
101
102 int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const
103 {
104     return komodo_notaries(pubkeys, height, timestamp);
105 }
106
107
108 bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
109 {
110     if (tx.vin.size() < 11) return false;
111
112     uint8_t seenNotaries[64] = {0};
113     uint8_t notaries[64][33];
114     int nNotaries = GetNotaries(notaries, height, timestamp);
115
116     BOOST_FOREACH(const CTxIn &txIn, tx.vin)
117     {
118         // Get notary pubkey
119         CTransaction tx;
120         uint256 hashBlock;
121         if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
122         if (tx.vout.size() < txIn.prevout.n) return false;
123         CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
124         if (spk.size() != 35) return false;
125         const unsigned char *pk = spk.data();
126         if (pk++[0] != 33) return false;
127         if (pk[33] != OP_CHECKSIG) return false;
128
129         // Check it's a notary
130         for (int i=0; i<nNotaries; i++) {
131             if (!seenNotaries[i]) {
132                 if (memcmp(pk, notaries[i], 33) == 0) {
133                     seenNotaries[i] = 1;
134                     goto found;
135                 }
136             }
137         }
138         return false;
139         found:;
140     }
141
142     return true;
143 }
144
145
146 /*
147  * Get MoM from a notarisation tx hash
148  */
149 bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const
150 {
151     CTransaction notarisationTx;
152     CBlockIndex block;
153     if (!GetTxConfirmed(notaryHash, notarisationTx, block)) return false;
154     if (!CheckNotaryInputs(notarisationTx, block.nHeight, block.nTime)) return false;
155     if (notarisationTx.vout.size() < 2) return false;
156     if (!data.Parse(notarisationTx.vout[1].scriptPubKey)) return false;
157     return true;
158 }
159
160
161 /*
162  * Notarisation data, ie, OP_RETURN payload in notarisation transactions
163  */
164 extern char ASSETCHAINS_SYMBOL[16];
165
166 bool NotarisationData::Parse(const CScript scriptPK)
167 {
168     *this = NotarisationData();
169
170     std::vector<unsigned char> vdata;
171     if (!GetOpReturnData(scriptPK, vdata)) return false;
172
173     CDataStream ss(vdata, SER_NETWORK, PROTOCOL_VERSION);
174
175     try {
176         ss >> blockHash;
177         ss >> height;
178         if (ASSETCHAINS_SYMBOL[0])
179             ss >> txHash;
180
181         char *nullPos = (char*) memchr(&ss[0], 0, ss.size());
182         if (!nullPos) return false;
183         ss.read(symbol, nullPos-&ss[0]+1);
184
185         if (ss.size() < 36) return false;
186         ss >> MoM;
187         ss >> MoMDepth;
188     } catch (...) {
189         return false;
190     }
191     return true;
192 }
193
194
195 /*
196  * Misc
197  */
198
199 std::string EvalToStr(EvalCode c)
200 {
201     FOREACH_EVAL(EVAL_GENERATE_STRING);
202     char s[10];
203     sprintf(s, "0x%x", c);
204     return std::string(s);
205 }
This page took 0.060943 seconds and 4 git commands to generate.