]>
Commit | Line | Data |
---|---|---|
f345b953 | 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 | ||
561f3e18 SS |
16 | #include <assert.h> |
17 | #include <cryptoconditions.h> | |
18 | ||
20c3ac51 | 19 | #include "primitives/block.h" |
2c8d8268 | 20 | #include "primitives/transaction.h" |
8a8e10f0 | 21 | #include "script/cc.h" |
2c8d8268 | 22 | #include "cc/eval.h" |
20c3ac51 | 23 | #include "cc/utils.h" |
6d450023 | 24 | #include "cc/CCinclude.h" |
561f3e18 SS |
25 | #include "main.h" |
26 | #include "chain.h" | |
aa9eec45 | 27 | #include "core_io.h" |
0ffacf04 | 28 | #include "crosschain.h" |
561f3e18 SS |
29 | |
30 | ||
31 | Eval* EVAL_TEST = 0; | |
287efad4 | 32 | struct CCcontract_info CCinfos[0x100]; |
63600b1d | 33 | extern pthread_mutex_t KOMODO_CC_mutex; |
561f3e18 SS |
34 | |
35 | bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn) | |
36 | { | |
20c3ac51 | 37 | EvalRef eval; |
63600b1d | 38 | pthread_mutex_lock(&KOMODO_CC_mutex); |
561f3e18 | 39 | bool out = eval->Dispatch(cond, tx, nIn); |
63600b1d | 40 | pthread_mutex_unlock(&KOMODO_CC_mutex); |
1f5f9d29 | 41 | //fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid()); |
561f3e18 SS |
42 | assert(eval->state.IsValid() == out); |
43 | ||
44 | if (eval->state.IsValid()) return true; | |
45 | ||
46 | std::string lvl = eval->state.IsInvalid() ? "Invalid" : "Error!"; | |
39c9911e SS |
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()); | |
aa9eec45 | 52 | if (eval->state.IsError()) fprintf(stderr, "Culprit: %s\n", EncodeHexTx(tx).data()); |
561f3e18 SS |
53 | return false; |
54 | } | |
2c8d8268 SS |
55 | |
56 | ||
57 | /* | |
58 | * Test the validity of an Eval node | |
59 | */ | |
561f3e18 | 60 | bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn) |
2c8d8268 | 61 | { |
287efad4 | 62 | struct CCcontract_info *cp; |
39c9911e SS |
63 | if (cond->codeLength == 0) |
64 | return Invalid("empty-eval"); | |
2c8d8268 | 65 | |
39c9911e | 66 | uint8_t ecode = cond->code[0]; |
287efad4 | 67 | cp = &CCinfos[(int32_t)ecode]; |
68 | if ( cp->didinit == 0 ) | |
69 | { | |
70 | CCinit(cp,ecode); | |
71 | cp->didinit = 1; | |
72 | } | |
39c9911e | 73 | std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength); |
44a9fd7c | 74 | switch ( ecode ) |
75 | { | |
ef32da96 MT |
76 | case EVAL_PBAASDEFINITION: |
77 | case EVAL_SERVICEREWARD: | |
78 | case EVAL_EARNEDNOTARIZATION: | |
79 | case EVAL_ACCEPTEDNOTARIZATION: | |
80 | case EVAL_FINALIZENOTARIZATION: | |
a6e612cc | 81 | case EVAL_RESERVE_OUTPUT: |
e87527cf MT |
82 | case EVAL_CROSSCHAIN_EXPORT: |
83 | case EVAL_CROSSCHAIN_IMPORT: | |
84 | case EVAL_INSTANTSPEND: | |
a6e612cc | 85 | case EVAL_RESERVE_INPUT: |
e87527cf MT |
86 | if (!chainActive.LastTip() || CConstVerusSolutionVector::activationHeight.ActiveVersion(chainActive.LastTip()->GetHeight()) < CActivationHeight::SOLUTION_VERUSV3) |
87 | { | |
88 | // if chain is not able to process this yet, don't drop through to do so | |
89 | break; | |
90 | } | |
91 | ||
92 | case EVAL_STAKEGUARD: | |
b2a98c42 MT |
93 | return(ProcessCC(cp,this, vparams, txTo, nIn)); |
94 | break; | |
95 | ||
44a9fd7c | 96 | case EVAL_IMPORTPAYOUT: |
8a727a26 | 97 | //return ImportPayout(vparams, txTo, nIn); |
44a9fd7c | 98 | break; |
99 | ||
100 | case EVAL_IMPORTCOIN: | |
8a727a26 | 101 | //return ImportCoin(vparams, txTo, nIn); |
44a9fd7c | 102 | break; |
0cb91a8d | 103 | } |
216f23be | 104 | return Invalid("invalid-code, dont forget to add EVAL_NEWCC to Eval::Dispatch"); |
2c8d8268 | 105 | } |
9ef101bc SS |
106 | |
107 | ||
47296322 | 108 | bool Eval::GetSpendsConfirmed(uint256 hash, std::vector<CTransaction> &spends) const |
9ef101bc | 109 | { |
561f3e18 | 110 | // NOT IMPLEMENTED |
9ef101bc SS |
111 | return false; |
112 | } | |
113 | ||
114 | ||
47296322 | 115 | bool Eval::GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const |
561f3e18 | 116 | { |
02c68a7b | 117 | // there is a LOCK(cs_main) in the normal GetTransaction(), which leads to deadlocks |
fc40b06c | 118 | //bool fAllowSlow = false; // Don't allow slow |
119 | //return GetTransaction(hash, txOut, hashBlock, fAllowSlow); | |
21f17b88 | 120 | return myGetTransaction(hash, txOut,hashBlock); |
561f3e18 SS |
121 | } |
122 | ||
123 | ||
47296322 SS |
124 | bool Eval::GetTxConfirmed(const uint256 &hash, CTransaction &txOut, CBlockIndex &block) const |
125 | { | |
126 | uint256 hashBlock; | |
127 | if (!GetTxUnconfirmed(hash, txOut, hashBlock)) | |
128 | return false; | |
129 | if (hashBlock.IsNull() || !GetBlock(hashBlock, block)) | |
130 | return false; | |
131 | return true; | |
132 | } | |
133 | ||
134 | ||
561f3e18 SS |
135 | unsigned int Eval::GetCurrentHeight() const |
136 | { | |
137 | return chainActive.Height(); | |
138 | } | |
139 | ||
561f3e18 | 140 | bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const |
9ef101bc | 141 | { |
561f3e18 SS |
142 | auto r = mapBlockIndex.find(hash); |
143 | if (r != mapBlockIndex.end()) { | |
144 | blockIdx = *r->second; | |
145 | return true; | |
146 | } | |
47296322 | 147 | fprintf(stderr, "CC Eval Error: Can't get block from index\n"); |
9ef101bc SS |
148 | return false; |
149 | } | |
150 | ||
561f3e18 SS |
151 | extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); |
152 | ||
153 | ||
9bf132a5 SS |
154 | int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const |
155 | { | |
156 | return komodo_notaries(pubkeys, height, timestamp); | |
157 | } | |
158 | ||
159 | ||
561f3e18 SS |
160 | bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const |
161 | { | |
162 | if (tx.vin.size() < 11) return false; | |
163 | ||
9bf132a5 | 164 | uint8_t seenNotaries[64] = {0}; |
561f3e18 | 165 | uint8_t notaries[64][33]; |
9bf132a5 | 166 | int nNotaries = GetNotaries(notaries, height, timestamp); |
561f3e18 SS |
167 | |
168 | BOOST_FOREACH(const CTxIn &txIn, tx.vin) | |
169 | { | |
170 | // Get notary pubkey | |
171 | CTransaction tx; | |
172 | uint256 hashBlock; | |
47296322 | 173 | if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false; |
561f3e18 | 174 | if (tx.vout.size() < txIn.prevout.n) return false; |
9bf132a5 SS |
175 | CScript spk = tx.vout[txIn.prevout.n].scriptPubKey; |
176 | if (spk.size() != 35) return false; | |
9feb4b9e | 177 | std::vector<unsigned char> scriptVec = std::vector<unsigned char>(spk.begin(),spk.end()); |
178 | const unsigned char *pk = scriptVec.data(); | |
9bf132a5 SS |
179 | if (pk++[0] != 33) return false; |
180 | if (pk[33] != OP_CHECKSIG) return false; | |
561f3e18 SS |
181 | |
182 | // Check it's a notary | |
183 | for (int i=0; i<nNotaries; i++) { | |
184 | if (!seenNotaries[i]) { | |
185 | if (memcmp(pk, notaries[i], 33) == 0) { | |
186 | seenNotaries[i] = 1; | |
187 | goto found; | |
188 | } | |
189 | } | |
190 | } | |
191 | return false; | |
192 | found:; | |
193 | } | |
9bf132a5 SS |
194 | |
195 | return true; | |
196 | } | |
197 | ||
198 | ||
39c9911e | 199 | /* |
e4f943d8 | 200 | * Get MoM from a notarisation tx hash (on KMD) |
39c9911e SS |
201 | */ |
202 | bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const | |
203 | { | |
204 | CTransaction notarisationTx; | |
205 | CBlockIndex block; | |
206 | if (!GetTxConfirmed(notaryHash, notarisationTx, block)) return false; | |
4b729ec5 | 207 | if (!CheckNotaryInputs(notarisationTx, block.GetHeight(), block.nTime)) return false; |
20c3ac51 | 208 | if (!ParseNotarisationOpReturn(notarisationTx, data)) return false; |
39c9911e SS |
209 | return true; |
210 | } | |
211 | ||
e4f943d8 SS |
212 | /* |
213 | * Get MoMoM corresponding to a notarisation tx hash (on assetchain) | |
214 | */ | |
215 | bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const | |
0cb91a8d | 216 | { |
0ffacf04 SS |
217 | std::pair<uint256,NotarisationData> out; |
218 | if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false; | |
219 | momom = out.second.MoMoM; | |
220 | return true; | |
0df96a2f SS |
221 | } |
222 | ||
223 | ||
224 | uint32_t Eval::GetAssetchainsCC() const | |
225 | { | |
226 | return ASSETCHAINS_CC; | |
227 | } | |
228 | ||
229 | ||
230 | std::string Eval::GetAssetchainsSymbol() const | |
231 | { | |
232 | return std::string(ASSETCHAINS_SYMBOL); | |
0cb91a8d SS |
233 | } |
234 | ||
56cf273f | 235 | |
39c9911e SS |
236 | /* |
237 | * Notarisation data, ie, OP_RETURN payload in notarisation transactions | |
238 | */ | |
20c3ac51 | 239 | bool ParseNotarisationOpReturn(const CTransaction &tx, NotarisationData &data) |
9bf132a5 | 240 | { |
20c3ac51 | 241 | if (tx.vout.size() < 2) return false; |
9bf132a5 | 242 | std::vector<unsigned char> vdata; |
20c3ac51 SS |
243 | if (!GetOpReturnData(tx.vout[1].scriptPubKey, vdata)) return false; |
244 | bool out = E_UNMARSHAL(vdata, ss >> data); | |
245 | return out; | |
561f3e18 SS |
246 | } |
247 | ||
248 | ||
249 | /* | |
39c9911e | 250 | * Misc |
561f3e18 | 251 | */ |
39c9911e | 252 | std::string EvalToStr(EvalCode c) |
561f3e18 | 253 | { |
39c9911e SS |
254 | FOREACH_EVAL(EVAL_GENERATE_STRING); |
255 | char s[10]; | |
256 | sprintf(s, "0x%x", c); | |
257 | return std::string(s); | |
0cb91a8d SS |
258 | |
259 | } | |
260 | ||
261 | ||
262 | uint256 SafeCheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex) | |
263 | { | |
264 | if (nIndex == -1) | |
265 | return uint256(); | |
266 | for (auto it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it) | |
267 | { | |
268 | if (nIndex & 1) { | |
269 | if (*it == hash) { | |
270 | // non canonical. hash may be equal to node but never on the right. | |
271 | return uint256(); | |
272 | } | |
273 | hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); | |
274 | } | |
275 | else | |
276 | hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); | |
277 | nIndex >>= 1; | |
278 | } | |
279 | return hash; | |
561f3e18 | 280 | } |
20c3ac51 SS |
281 | |
282 | ||
283 | uint256 GetMerkleRoot(const std::vector<uint256>& vLeaves) | |
284 | { | |
285 | bool fMutated; | |
286 | std::vector<uint256> vMerkleTree; | |
287 | return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree); | |
288 | } |