]>
Commit | Line | Data |
---|---|---|
44a9fd7c | 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 | ||
16 | #include "CCinclude.h" | |
17 | ||
18 | /* | |
19 | CCutils has low level functions that are universally useful for all contracts. | |
20 | */ | |
21 | ||
810f6366 | 22 | void endiancpy(uint8_t *dest,uint8_t *src,int32_t len) |
23 | { | |
24 | int32_t i,j=0; | |
25 | #if defined(WORDS_BIGENDIAN) | |
26 | for (i=31; i>=0; i--) | |
27 | dest[j++] = src[i]; | |
28 | #else | |
29 | memcpy(dest,src,len); | |
30 | #endif | |
31 | } | |
db3b8abe | 32 | |
d7a84c74 | 33 | CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2) |
34 | { | |
35 | std::vector<CC*> pks; | |
36 | pks.push_back(CCNewSecp256k1(pk1)); | |
d5d98d1f | 37 | pks.push_back(CCNewSecp256k1(pk2)); |
d7a84c74 | 38 | CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode)); |
39 | CC *Sig = CCNewThreshold(1, pks); | |
40 | return CCNewThreshold(2, {condCC, Sig}); | |
41 | } | |
42 | ||
3a27113e | 43 | CC *MakeCCcond1(uint8_t evalcode, CPubKey pk) |
26e796c0 | 44 | { |
45 | std::vector<CC*> pks; | |
46 | pks.push_back(CCNewSecp256k1(pk)); | |
47 | CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode)); | |
48 | CC *Sig = CCNewThreshold(1, pks); | |
49 | return CCNewThreshold(2, {condCC, Sig}); | |
50 | } | |
51 | ||
770924f5 | 52 | CC *MakeCCcond1(uint8_t evalcode, CTxDestination dest) |
41f170fd | 53 | { |
770924f5 | 54 | CPubKey pk = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest); |
41f170fd | 55 | std::vector<CC*> pks; |
770924f5 | 56 | if (pk.IsValid()) |
57 | { | |
58 | pks.push_back(CCNewSecp256k1(pk)); | |
59 | } | |
60 | else | |
61 | { | |
62 | pks.push_back(CCNewHashedSecp256k1(CKeyID(GetDestinationID(dest)))); | |
63 | } | |
41f170fd | 64 | CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode)); |
3a27113e | 65 | CC *Sig = CCNewThreshold(1, pks); |
353949fe | 66 | return CCNewThreshold(2, {condCC, Sig}); |
41f170fd MT |
67 | } |
68 | ||
b35cb19a | 69 | CC *MakeCCcondAny(uint8_t evalcode, std::vector<CTxDestination> dests) |
70 | { | |
71 | std::vector<CC*> pks; | |
72 | for (auto dest : dests) | |
73 | { | |
74 | CPubKey pk = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest); | |
75 | if (pk.IsValid()) | |
76 | { | |
77 | pks.push_back(CCNewSecp256k1(pk)); | |
78 | } | |
79 | else | |
80 | { | |
81 | pks.push_back(CCNewHashedSecp256k1(CKeyID(GetDestinationID(dest)))); | |
82 | } | |
83 | } | |
84 | ||
85 | CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode)); | |
86 | CC *Sig = CCNewThreshold(1, pks); | |
87 | return CCNewThreshold(2, {condCC, Sig}); | |
88 | } | |
89 | ||
b7c685b8 | 90 | CTxOut MakeCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk) |
2492726d | 91 | { |
92 | CTxOut vout; | |
93 | CC *payoutCond = MakeCCcond1(evalcode,pk); | |
94 | vout = CTxOut(nValue,CCPubKey(payoutCond)); | |
95 | cc_free(payoutCond); | |
96 | return(vout); | |
97 | } | |
98 | ||
7fe1ffc7 | 99 | CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2) |
810f6366 | 100 | { |
101 | CTxOut vout; | |
7fe1ffc7 | 102 | CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2); |
810f6366 | 103 | vout = CTxOut(nValue,CCPubKey(payoutCond)); |
104 | cc_free(payoutCond); | |
105 | return(vout); | |
106 | } | |
107 | ||
44a9fd7c | 108 | CC* GetCryptoCondition(CScript const& scriptSig) |
109 | { | |
110 | auto pc = scriptSig.begin(); | |
111 | opcodetype opcode; | |
112 | std::vector<unsigned char> ffbin; | |
113 | if (scriptSig.GetOp(pc, opcode, ffbin)) | |
114 | return cc_readFulfillmentBinary((uint8_t*)ffbin.data(), ffbin.size()-1); | |
115 | } | |
116 | ||
117 | bool IsCCInput(CScript const& scriptSig) | |
118 | { | |
119 | CC *cond; | |
120 | if ( (cond= GetCryptoCondition(scriptSig)) == 0 ) | |
121 | return false; | |
122 | cc_free(cond); | |
123 | return true; | |
124 | } | |
125 | ||
cfea7a46 | 126 | int32_t unstringbits(char *buf,uint64_t bits) |
127 | { | |
128 | int32_t i; | |
129 | for (i=0; i<8; i++,bits>>=8) | |
130 | if ( (buf[i]= (char)(bits & 0xff)) == 0 ) | |
131 | break; | |
132 | buf[i] = 0; | |
133 | return(i); | |
134 | } | |
135 | ||
136 | uint64_t stringbits(char *str) | |
137 | { | |
138 | uint64_t bits = 0; | |
139 | if ( str == 0 ) | |
140 | return(0); | |
141 | int32_t i,n = (int32_t)strlen(str); | |
142 | if ( n > 8 ) | |
143 | n = 8; | |
144 | for (i=n-1; i>=0; i--) | |
145 | bits = (bits << 8) | (str[i] & 0xff); | |
146 | //printf("(%s) -> %llx %llu\n",str,(long long)bits,(long long)bits); | |
147 | return(bits); | |
148 | } | |
149 | ||
44a9fd7c | 150 | uint256 revuint256(uint256 txid) |
151 | { | |
152 | uint256 revtxid; int32_t i; | |
153 | for (i=31; i>=0; i--) | |
154 | ((uint8_t *)&revtxid)[31-i] = ((uint8_t *)&txid)[i]; | |
155 | return(revtxid); | |
156 | } | |
157 | ||
158 | char *uint256_str(char *dest,uint256 txid) | |
159 | { | |
160 | int32_t i,j=0; | |
161 | for (i=31; i>=0; i--) | |
162 | sprintf(&dest[j++ * 2],"%02x",((uint8_t *)&txid)[i]); | |
1cdfa0b5 | 163 | dest[64] = 0; |
164 | return(dest); | |
165 | } | |
166 | ||
167 | char *pubkey33_str(char *dest,uint8_t *pubkey33) | |
168 | { | |
169 | int32_t i; | |
170 | if ( pubkey33 != 0 ) | |
171 | { | |
172 | for (i=0; i<33; i++) | |
173 | sprintf(&dest[i * 2],"%02x",pubkey33[i]); | |
174 | } else dest[0] = 0; | |
175 | return(dest); | |
44a9fd7c | 176 | } |
177 | ||
178 | uint256 Parseuint256(char *hexstr) | |
179 | { | |
180 | uint256 txid; int32_t i; std::vector<unsigned char> txidbytes(ParseHex(hexstr)); | |
02c68a7b | 181 | memset(&txid,0,sizeof(txid)); |
182 | if ( strlen(hexstr) == 64 ) | |
183 | { | |
184 | for (i=31; i>=0; i--) | |
185 | ((uint8_t *)&txid)[31-i] = ((uint8_t *)txidbytes.data())[i]; | |
186 | } | |
44a9fd7c | 187 | return(txid); |
188 | } | |
189 | ||
366625ca | 190 | CPubKey buf2pk(uint8_t *buf33) |
191 | { | |
192 | CPubKey pk; int32_t i; uint8_t *dest; | |
193 | dest = (uint8_t *)pk.begin(); | |
194 | for (i=0; i<33; i++) | |
195 | dest[i] = buf33[i]; | |
196 | return(pk); | |
197 | } | |
198 | ||
5cf0c1db | 199 | CPubKey pubkey2pk(std::vector<uint8_t> pubkey) |
200 | { | |
201 | CPubKey pk; int32_t i,n; uint8_t *dest,*pubkey33; | |
202 | n = pubkey.size(); | |
203 | dest = (uint8_t *)pk.begin(); | |
204 | pubkey33 = (uint8_t *)pubkey.data(); | |
205 | for (i=0; i<n; i++) | |
206 | dest[i] = pubkey33[i]; | |
207 | return(pk); | |
208 | } | |
209 | ||
23e0b80b | 210 | void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr) |
211 | { | |
212 | cp->evalcode2 = evalcode; | |
213 | cp->unspendablepk2 = pk; | |
214 | memcpy(cp->unspendablepriv2,priv,32); | |
215 | strcpy(cp->unspendableaddr2,coinaddr); | |
216 | } | |
217 | ||
218 | void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr) | |
219 | { | |
220 | cp->evalcode3 = evalcode; | |
221 | cp->unspendablepk3 = pk; | |
222 | memcpy(cp->unspendablepriv3,priv,32); | |
223 | strcpy(cp->unspendableaddr3,coinaddr); | |
224 | } | |
225 | ||
44a9fd7c | 226 | bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) |
227 | { | |
68b9a352 | 228 | CTxDestination address; |
229 | txnouttype whichType; | |
230 | std::vector<std::vector<unsigned char>> vvch = std::vector<std::vector<unsigned char>>(); | |
231 | if (Solver(scriptPubKey, whichType, vvch) && vvch[0].size() == 20) | |
44a9fd7c | 232 | { |
68b9a352 | 233 | address = CKeyID(uint160(vvch[0])); |
44a9fd7c | 234 | strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str()); |
235 | return(true); | |
236 | } | |
191f3bbd | 237 | fprintf(stderr,"Solver for scriptPubKey failed\n%s\n", scriptPubKey.ToString().c_str()); |
44a9fd7c | 238 | return(false); |
239 | } | |
240 | ||
905fe35e | 241 | bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn, |
242 | CTransaction &txOut, std::vector<std::vector<unsigned char>> &preConditions, std::vector<std::vector<unsigned char>> ¶ms) | |
8a727a26 | 243 | { |
8a727a26 | 244 | uint256 blockHash; |
8a727a26 | 245 | |
281a5e2e | 246 | if (myGetTransaction(tx.vin[nIn].prevout.hash, txOut, blockHash) && txOut.vout.size() > tx.vin[nIn].prevout.n) |
8a727a26 | 247 | { |
248 | CBlockIndex index; | |
249 | if (eval->GetBlock(blockHash, index)) | |
250 | { | |
251 | // read preconditions | |
252 | CScript subScript = CScript(); | |
253 | preConditions.clear(); | |
254 | if (txOut.vout[tx.vin[nIn].prevout.n].scriptPubKey.IsPayToCryptoCondition(&subScript, preConditions)) | |
255 | { | |
256 | // read any available parameters in the output transaction | |
257 | params.clear(); | |
191f3bbd | 258 | if (tx.vout.size() > 0 && tx.vout[tx.vout.size() - 1].scriptPubKey.IsOpReturn()) |
259 | { | |
60b798c4 | 260 | if (tx.vout[tx.vout.size() - 1].scriptPubKey.GetOpretData(params) && params.size() == 1) |
281a5e2e | 261 | { |
26bf01e9 | 262 | CScript scr = CScript(params[0].begin(), params[0].end()); |
263 | ||
51848bbc | 264 | // printf("Script decoding inner:\n%s\nouter:\n%s\n", scr.ToString().c_str(), tx.vout[tx.vout.size() - 1].scriptPubKey.ToString().c_str()); |
26bf01e9 | 265 | |
60b798c4 | 266 | if (!scr.GetPushedData(scr.begin(), params)) |
281a5e2e | 267 | { |
60b798c4 | 268 | return false; |
281a5e2e | 269 | } |
60b798c4 | 270 | else return true; |
281a5e2e | 271 | } |
60b798c4 | 272 | else return false; |
191f3bbd | 273 | } |
60b798c4 | 274 | else return true; |
8a727a26 | 275 | } |
276 | } | |
277 | } | |
60b798c4 | 278 | return false; |
8a727a26 | 279 | } |
280 | ||
612f676a | 281 | CPubKey CCtxidaddr(char *txidaddr,uint256 txid) |
282 | { | |
283 | uint8_t buf33[33]; CPubKey pk; | |
284 | buf33[0] = 0x02; | |
285 | endiancpy(&buf33[1],(uint8_t *)&txid,32); | |
286 | pk = buf2pk(buf33); | |
384c05de | 287 | Getscriptaddress(txidaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); |
612f676a | 288 | return(pk); |
289 | } | |
290 | ||
3515c101 | 291 | bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk) |
ec6fec40 | 292 | { |
293 | CC *payoutCond; | |
294 | destaddr[0] = 0; | |
3515c101 | 295 | if ( (payoutCond= MakeCCcond1(evalcode,pk)) != 0 ) |
ec6fec40 | 296 | { |
297 | Getscriptaddress(destaddr,CCPubKey(payoutCond)); | |
298 | cc_free(payoutCond); | |
810f6366 | 299 | } |
300 | return(destaddr[0] != 0); | |
301 | } | |
302 | ||
3515c101 | 303 | bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk) |
304 | { | |
305 | destaddr[0] = 0; | |
306 | if ( pk.size() == 0 ) | |
307 | pk = GetUnspendable(cp,0); | |
308 | return(_GetCCaddress(destaddr,cp->evalcode,pk)); | |
309 | } | |
310 | ||
810f6366 | 311 | bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2) |
312 | { | |
313 | CC *payoutCond; | |
314 | destaddr[0] = 0; | |
315 | if ( (payoutCond= MakeCCcond1of2(cp->evalcode,pk,pk2)) != 0 ) | |
316 | { | |
317 | Getscriptaddress(destaddr,CCPubKey(payoutCond)); | |
318 | cc_free(payoutCond); | |
ec6fec40 | 319 | } |
320 | return(destaddr[0] != 0); | |
321 | } | |
322 | ||
59da6d30 | 323 | bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,int64_t nValue) |
d082e563 | 324 | { |
325 | char destaddr[64]; | |
326 | if ( vout.scriptPubKey.IsPayToCryptoCondition() != CCflag ) | |
36e071fc | 327 | { |
328 | fprintf(stderr,"constrain vout error isCC %d vs %d CCflag\n",vout.scriptPubKey.IsPayToCryptoCondition(),CCflag); | |
d082e563 | 329 | return(false); |
36e071fc | 330 | } |
d082e563 | 331 | else if ( cmpaddr != 0 && (Getscriptaddress(destaddr,vout.scriptPubKey) == 0 || strcmp(destaddr,cmpaddr) != 0) ) |
37e67a2a | 332 | { |
20eb6d30 | 333 | fprintf(stderr,"constrain vout error addr %s vs %s\n",cmpaddr!=0?cmpaddr:"",destaddr!=0?destaddr:""); |
d082e563 | 334 | return(false); |
37e67a2a | 335 | } |
698d25f7 | 336 | else if ( nValue != 0 && nValue != vout.nValue ) //(nValue == 0 && vout.nValue < 10000) || ( |
37e67a2a | 337 | { |
338 | fprintf(stderr,"constrain vout error nValue %.8f vs %.8f\n",(double)nValue/COIN,(double)vout.nValue/COIN); | |
d082e563 | 339 | return(false); |
37e67a2a | 340 | } |
d082e563 | 341 | else return(true); |
342 | } | |
343 | ||
e49eb6ed | 344 | bool PreventCC(Eval* eval,const CTransaction &tx,int32_t preventCCvins,int32_t numvins,int32_t preventCCvouts,int32_t numvouts) |
02c68a7b | 345 | { |
346 | int32_t i; | |
347 | if ( preventCCvins >= 0 ) | |
348 | { | |
349 | for (i=preventCCvins; i<numvins; i++) | |
350 | { | |
351 | if ( IsCCInput(tx.vin[i].scriptSig) != 0 ) | |
352 | return eval->Invalid("invalid CC vin"); | |
353 | } | |
354 | } | |
355 | if ( preventCCvouts >= 0 ) | |
356 | { | |
357 | for (i=preventCCvouts; i<numvouts; i++) | |
358 | { | |
359 | if ( tx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 ) | |
ee360983 | 360 | { |
361 | fprintf(stderr,"vout.%d is CC\n",i); | |
02c68a7b | 362 | return eval->Invalid("invalid CC vout"); |
ee360983 | 363 | } |
02c68a7b | 364 | } |
365 | } | |
366 | return(true); | |
367 | } | |
368 | ||
44a9fd7c | 369 | std::vector<uint8_t> Mypubkey() |
370 | { | |
371 | extern uint8_t NOTARY_PUBKEY33[33]; | |
372 | std::vector<uint8_t> pubkey; int32_t i; uint8_t *dest,*pubkey33; | |
373 | pubkey33 = NOTARY_PUBKEY33; | |
374 | pubkey.resize(33); | |
375 | dest = pubkey.data(); | |
376 | for (i=0; i<33; i++) | |
377 | dest[i] = pubkey33[i]; | |
378 | return(pubkey); | |
379 | } | |
380 | ||
381 | bool Myprivkey(uint8_t myprivkey[]) | |
382 | { | |
383 | char coinaddr[64]; std::string strAddress; char *dest; int32_t i,n; CBitcoinAddress address; CKeyID keyID; CKey vchSecret; | |
384 | if ( Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG) != 0 ) | |
385 | { | |
386 | n = (int32_t)strlen(coinaddr); | |
387 | strAddress.resize(n+1); | |
388 | dest = (char *)strAddress.data(); | |
389 | for (i=0; i<n; i++) | |
390 | dest[i] = coinaddr[i]; | |
391 | dest[i] = 0; | |
392 | if ( address.SetString(strAddress) != 0 && address.GetKeyID(keyID) != 0 ) | |
393 | { | |
394 | #ifdef ENABLE_WALLET | |
395 | if ( pwalletMain->GetKey(keyID,vchSecret) != 0 ) | |
396 | { | |
397 | memcpy(myprivkey,vchSecret.begin(),32); | |
558b29ac | 398 | if ( 0 ) |
ff780022 | 399 | { |
400 | for (i=0; i<32; i++) | |
401 | fprintf(stderr,"0x%02x, ",myprivkey[i]); | |
aed3f987 | 402 | fprintf(stderr," found privkey for %s!\n",dest); |
ff780022 | 403 | } |
44a9fd7c | 404 | return(true); |
405 | } | |
406 | #endif | |
407 | } | |
408 | } | |
409 | fprintf(stderr,"privkey for the -pubkey= address is not in the wallet, importprivkey!\n"); | |
410 | return(false); | |
411 | } | |
412 | ||
287efad4 | 413 | CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv) |
414 | { | |
415 | if ( unspendablepriv != 0 ) | |
416 | memcpy(unspendablepriv,cp->CCpriv,32); | |
417 | return(pubkey2pk(ParseHex(cp->CChexstr))); | |
418 | } | |
419 | ||
4ecaf167 | 420 | bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector<uint8_t> paramsNull,const CTransaction &ctx, unsigned int nIn, bool fulfilled) |
287efad4 | 421 | { |
e4e12ec0 | 422 | CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> origpubkey; |
90c81155 | 423 | height = KOMODO_CONNECTING; |
ad274d5b | 424 | if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation |
425 | return(true); | |
57c2bccd | 426 | if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE ) |
90c81155 | 427 | return eval->Invalid("CC are disabled or not active yet"); |
e4e12ec0 | 428 | if ( (KOMODO_CONNECTING & (1<<30)) != 0 ) |
429 | { | |
430 | from_mempool = 1; | |
431 | height &= ((1<<30) - 1); | |
432 | } | |
756e9cf7 | 433 | //fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE); |
4d2b7323 | 434 | // there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example |
7347a801 | 435 | //txid = ctx.GetHash(); |
436 | //if ( txid == cp->prevtxid ) | |
437 | // return(true); | |
b4795ed6 | 438 | //fprintf(stderr,"process CC %02x\n",cp->evalcode); |
23e0b80b | 439 | cp->evalcode2 = cp->evalcode3 = 0; |
440 | cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0; | |
287efad4 | 441 | if ( paramsNull.size() != 0 ) // Don't expect params |
442 | return eval->Invalid("Cannot have params"); | |
191f3bbd | 443 | //else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses |
444 | // return eval->Invalid("no-vouts"); | |
4ecaf167 | 445 | else if ( (*cp->validate)(cp, eval, ctx, nIn, fulfilled) != 0 ) |
287efad4 | 446 | { |
7adbb3e3 | 447 | //fprintf(stderr,"done CC %02x\n",cp->evalcode); |
7347a801 | 448 | //cp->prevtxid = txid; |
287efad4 | 449 | return(true); |
450 | } | |
7adbb3e3 | 451 | //fprintf(stderr,"invalid CC %02x\n",cp->evalcode); |
287efad4 | 452 | return(false); |
453 | } | |
454 | ||
da07d84b | 455 | int64_t CCduration(int32_t &numblocks,uint256 txid) |
2b011ff7 | 456 | { |
da07d84b | 457 | CTransaction tx; uint256 hashBlock; uint32_t txheight,txtime=0; char str[65]; CBlockIndex *pindex; int64_t duration = 0; |
458 | numblocks = 0; | |
fb89b441 | 459 | if ( myGetTransaction(txid,tx,hashBlock) == 0 ) |
2b011ff7 | 460 | { |
f1c75a66 | 461 | fprintf(stderr,"CCduration cant find duration txid %s\n",uint256_str(str,txid)); |
2b011ff7 | 462 | return(0); |
463 | } | |
f1c75a66 | 464 | else if ( hashBlock == zeroid ) |
465 | { | |
466 | fprintf(stderr,"CCduration no hashBlock for txid %s\n",uint256_str(str,txid)); | |
467 | return(0); | |
468 | } | |
4b729ec5 | 469 | else if ( (pindex= mapBlockIndex[hashBlock]) == 0 || (txtime= pindex->nTime) == 0 || (txheight= pindex->GetHeight()) <= 0 ) |
f1c75a66 | 470 | { |
da07d84b | 471 | fprintf(stderr,"CCduration no txtime %u or txheight.%d %p for txid %s\n",txtime,txheight,pindex,uint256_str(str,txid)); |
f1c75a66 | 472 | return(0); |
473 | } | |
4b729ec5 | 474 | else if ( (pindex= chainActive.LastTip()) == 0 || pindex->nTime < txtime || pindex->GetHeight() <= txheight ) |
f1c75a66 | 475 | { |
4b729ec5 | 476 | fprintf(stderr,"CCduration backwards timestamps %u %u for txid %s hts.(%d %d)\n",(uint32_t)pindex->nTime,txtime,uint256_str(str,txid),txheight,(int32_t)pindex->GetHeight()); |
f1c75a66 | 477 | return(0); |
478 | } | |
4b729ec5 | 479 | numblocks = (pindex->GetHeight() - txheight); |
f1c75a66 | 480 | duration = (pindex->nTime - txtime); |
4b729ec5 | 481 | fprintf(stderr,"duration %d (%u - %u) numblocks %d (%d - %d)\n",(int32_t)duration,(uint32_t)pindex->nTime,txtime,numblocks,pindex->GetHeight(),txheight); |
2b011ff7 | 482 | return(duration); |
483 | } | |
484 |