Commit | Line | Data |
---|---|---|
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 | ||
15 | Eval* EVAL_TEST = 0; | |
16 | ||
17 | ||
18 | bool 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 | 41 | bool 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 | 61 | bool Eval::GetSpendsConfirmed(uint256 hash, std::vector<CTransaction> &spends) const |
9ef101bc | 62 | { |
561f3e18 | 63 | // NOT IMPLEMENTED |
9ef101bc SS |
64 | return false; |
65 | } | |
66 | ||
67 | ||
47296322 | 68 | bool 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 |
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 | ||
561f3e18 SS |
86 | unsigned int Eval::GetCurrentHeight() const |
87 | { | |
88 | return chainActive.Height(); | |
89 | } | |
90 | ||
91 | ||
92 | bool 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 | |
104 | extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); | |
105 | ||
106 | ||
9bf132a5 SS |
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 | ||
561f3e18 SS |
113 | bool 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 | */ |
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; | |
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 | */ | |
167 | bool 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 | ||
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); | |
0cb91a8d SS |
185 | } |
186 | ||
56cf273f | 187 | |
39c9911e SS |
188 | /* |
189 | * Notarisation data, ie, OP_RETURN payload in notarisation transactions | |
190 | */ | |
20c3ac51 | 191 | bool 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 | 204 | std::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 | ||
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; | |
561f3e18 | 232 | } |
20c3ac51 SS |
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 | } |