diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index 82623d4b9..cbf40d603 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -17,10 +17,11 @@ int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs) { - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t j,vout,n = 0; + char coinaddr[64],destaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t j,vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; @@ -32,6 +33,10 @@ int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK continue; if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { + Getscriptaddress(destaddr,vintx.vout[vout].scriptPubKey); + if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 ) + continue; + fprintf(stderr,"check %s %.8f\n",destaddr,(double)vintx.vout[vout].nValue/COIN); if ( (nValue= IsAssetvout(price,origpubkey,vintx,vout,assetid)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) { if ( total != 0 && maxinputs != 0 ) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index afc113083..4beb722a1 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -67,12 +67,12 @@ struct CC_utxo struct CCcontract_info { uint256 prevtxid; - char unspendableCCaddr[64],CChexstr[72],normaladdr[64],unspendableaddr2[64]; - uint8_t CCpriv[32],unspendablepriv2[32]; - CPubKey unspendablepk2; + char unspendableCCaddr[64],CChexstr[72],normaladdr[64],unspendableaddr2[64],unspendableaddr3[64]; + uint8_t CCpriv[32],unspendablepriv2[32],unspendablepriv3[32]; + CPubKey unspendablepk2,unspendablepk3; bool (*validate)(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); bool (*ismyvin)(CScript const& scriptSig); - uint8_t evalcode,evalcode2,didinit; + uint8_t evalcode,evalcode2,evalcode3,didinit; }; struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode); @@ -126,6 +126,8 @@ CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk); CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2); CC *MakeCCcond1(uint8_t evalcode,CPubKey pk); CC* GetCryptoCondition(CScript const& scriptSig); +void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr); +void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr); bool IsCCInput(CScript const& scriptSig); int32_t unstringbits(char *buf,uint64_t bits); uint64_t stringbits(char *str); diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index c9196e951..b92879359 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -41,7 +41,7 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScrip std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret) { auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; int64_t utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*othercond2=0,*cond; CPubKey unspendablepk; + CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; int64_t utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*othercond2=0,*othercond3=0,*cond; CPubKey unspendablepk; n = mtx.vout.size(); for (i=0; ievalcode2,cp->unspendablepk2); cond = othercond2; } + else if ( strcmp(destaddr,cp->unspendableaddr3) == 0 ) + { + //fprintf(stderr,"matched %s unspendable3!\n",cp->unspendableaddr3); + privkey = cp->unspendablepriv3; + if ( othercond3 == 0 ) + othercond3 = MakeCCcond1(cp->evalcode3,cp->unspendablepk3); + cond = othercond3; + } else { fprintf(stderr,"vini.%d has unknown CC address.(%s)\n",i,destaddr); @@ -155,6 +163,10 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran cc_free(mycond); if ( othercond != 0 ) cc_free(othercond); + if ( othercond2 != 0 ) + cc_free(othercond2); + if ( othercond3 != 0 ) + cc_free(othercond3); std::string strHex = EncodeHexTx(mtx); if ( strHex.size() > 0 ) return(strHex); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 3a448a92c..a91d6ffdd 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -169,6 +169,22 @@ CPubKey pubkey2pk(std::vector pubkey) return(pk); } +void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr) +{ + cp->evalcode2 = evalcode; + cp->unspendablepk2 = pk; + memcpy(cp->unspendablepriv2,priv,32); + strcpy(cp->unspendableaddr2,coinaddr); +} + +void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr) +{ + cp->evalcode3 = evalcode; + cp->unspendablepk3 = pk; + memcpy(cp->unspendablepriv3,priv,32); + strcpy(cp->unspendableaddr3,coinaddr); +} + bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) { CTxDestination address; txnouttype whichType; @@ -339,6 +355,8 @@ bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector param //if ( txid == cp->prevtxid ) // return(true); //fprintf(stderr,"process CC %02x\n",cp->evalcode); + cp->evalcode2 = cp->evalcode3 = 0; + cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0; if ( paramsNull.size() != 0 ) // Don't expect params return eval->Invalid("Cannot have params"); else if ( ctx.vout.size() == 0 ) diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index da8b9c4f2..46c2a305b 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -19,7 +19,6 @@ #include #include "cJSON.c" - char hexbyte(int32_t c) { c &= 0xf; @@ -312,22 +311,25 @@ uint64_t get_btcusd() cJSON *get_komodocli(char **retstrp,char *acname,char *method,char *arg0,char *arg1,char *arg2) { long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,*fname = "/tmp/komodocli"; - sprintf(cmdstr,"./komodo-cli -ac_name=%s %s %s %s %s > %s\n",acname,method,arg0,arg1,arg2,fname); + if ( acname[0] != 0 ) + sprintf(cmdstr,"./komodo-cli -ac_name=%s %s %s %s %s > %s\n",acname,method,arg0,arg1,arg2,fname); + else sprintf(cmdstr,"./komodo-cli %s %s %s %s > %s\n",method,arg0,arg1,arg2,fname); system(cmdstr); *retstrp = 0; if ( (jsonstr= filestr(&fsize,fname)) != 0 ) { //fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr); - if ( (retjson= cJSON_Parse(jsonstr)) == 0 ) + if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 ) *retstrp = jsonstr; else free(jsonstr); } return(retjson); } -void komodobroadcast(char *acname,cJSON *hexjson) +bits256 komodobroadcast(char *acname,cJSON *hexjson) { - char *hexstr,*retstr; cJSON *retjson; + char *hexstr,*retstr,str[65]; cJSON *retjson; bits256 txid; + memset(txid.bytes,0,sizeof(txid)); if ( (hexstr= jstr(hexjson,"hex")) != 0 ) { if ( (retjson= get_komodocli(&retstr,acname,"sendrawtransaction",hexstr,"","")) != 0 ) @@ -337,10 +339,126 @@ void komodobroadcast(char *acname,cJSON *hexjson) } else if ( retstr != 0 ) { - fprintf(stderr,"txid.(%s)\n",retstr); + if ( strlen(retstr) >= 64 ) + { + retstr[64] = 0; + decode_hex(txid.bytes,32,retstr); + } + fprintf(stderr,"txid.(%s)\n",bits256_str(str,txid)); free(retstr); } } + return(txid); +} + +int32_t get_KMDheight(char *acname) +{ + cJSON *retjson; char *retstr; int32_t height=0; + if ( (retjson= get_komodocli(&retstr,acname,"getinfo","","","")) != 0 ) + { + height = jint(retjson,"blocks"); + //fprintf(stderr,"%s height.%d\n",acname[0]!=0?acname:"KMD",height); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_KMDheight.(%s) error.(%s)\n",acname,retstr); + free(retstr); + } + return(height); +} + +bits256 get_KMDblockhash(int32_t height) +{ + cJSON *retjson; char *retstr,heightstr[32]; bits256 hash; + memset(hash.bytes,0,sizeof(hash)); + sprintf(heightstr,"%d",height); + if ( (retjson= get_komodocli(&retstr,"","getblockhash",heightstr,"","")) != 0 ) + { + fprintf(stderr,"unexpected blockhash json.(%s)\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + //fprintf(stderr,"get_KMDblockhash.(%s) %d\n",retstr,(int32_t)strlen(retstr)); + if ( strlen(retstr) >= 64 ) + { + retstr[64] = 0; + decode_hex(hash.bytes,32,retstr); + } + free(retstr); + } + return(hash); +} + +bits256 get_KMDmerkleroot(bits256 blockhash) +{ + cJSON *retjson; char *retstr,str[65]; bits256 merkleroot; + memset(merkleroot.bytes,0,sizeof(merkleroot)); + if ( (retjson= get_komodocli(&retstr,"","getblockheader",bits256_str(str,blockhash),"","")) != 0 ) + { + merkleroot = jbits256(retjson,"merkleroot"); + //fprintf(stderr,"got merkleroot.(%s)\n",bits256_str(str,merkleroot)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_KMDmerkleroot error.(%s)\n",retstr); + free(retstr); + } + return(merkleroot); +} + +int32_t get_KMDheader(bits256 *blockhashp,bits256 *merklerootp,int32_t prevheight) +{ + int32_t height = 0; char str[65]; + if ( prevheight == 0 ) + height = get_KMDheight("") - 20; + else height = prevheight + 1; + if ( height > 0 ) + { + *blockhashp = get_KMDblockhash(height); + if ( bits256_nonz(*blockhashp) != 0 ) + { + *merklerootp = get_KMDmerkleroot(*blockhashp); + if ( bits256_nonz(*merklerootp) != 0 ) + return(height); + } + } + memset(blockhashp,0,sizeof(*blockhashp)); + memset(merklerootp,0,sizeof(*merklerootp)); + return(0); +} + +int32_t get_oracledata(int32_t prevheight,char *hexstr,int32_t maxsize,char *format) +{ + uint32_t i,height; uint64_t price; bits256 blockhash,merkleroot; + hexstr[0] = 0; + if ( format[0] == 'L' || format[0] == 'l' ) + { + if ( (price= get_btcusd()) != 0 ) + { + for (i=0; i<8; i++) + sprintf(&hexstr[i*2],"%02x",(uint8_t)((price >> (i*8)) & 0xff)); + hexstr[16] = 0; + return(16); + } + } + else if ( strcmp(format,"Ihh") == 0 ) + { + if ( (height= get_KMDheader(&blockhash,&merkleroot,prevheight)) > prevheight ) + { + for (i=0; i<4; i++) + sprintf(&hexstr[i*2],"%02x",(uint8_t)((height >> (i*8)) & 0xff)); + for (i=0; i<32; i++) + sprintf(&hexstr[8 + (31-i)*2],"%02x",blockhash.bytes[i]); + for (i=0; i<32; i++) + sprintf(&hexstr[8 + 64 + (31-i)*2],"%02x",merkleroot.bytes[i]); + hexstr[8 + 64*2] = 0; + return(height); + } + } + return(0); } /* @@ -365,39 +483,60 @@ oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 034 */ -#define ORACLETXID "4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3" -#define MYPUBKEY "02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92" -#define ACNAME "ORCL" +//#define ORACLETXID "4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3" +//#define MYPUBKEY "02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92" +//#define ACNAME "ORCL" int32_t main(int32_t argc,char **argv) { - cJSON *clijson,*clijson2,*regjson,*item; int32_t i,j,n; char *retstr,*retstr2,*pkstr,hexstr[64]; uint64_t price; - printf("Powered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd())); + cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,n,height,prevheight = 0; char *format,*acname,*oraclestr,*pkstr,*pubstr,*retstr,*retstr2,hexstr[4096]; uint64_t price; bits256 txid; + if ( argc != 5 ) + { + printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT\nPowered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd())); + return(-1); + } + acname = argv[1]; + oraclestr = argv[2]; + pkstr = argv[3]; + format = argv[4]; + if ( strncmp(format,"Ihh",3) != 0 && format[0] != 'L' ) + { + printf("only formats of L and Ihh are supported now\n"); + return(-1); + } + acheight = 0; while ( 1 ) { retstr = 0; - if ( (price= get_btcusd()) != 0 && (clijson= get_komodocli(&retstr,ACNAME,"oraclesinfo",ORACLETXID,"","")) != 0 ) + if ( acheight != (height= get_KMDheight(acname)) && (clijson= get_komodocli(&retstr,acname,"oraclesinfo",oraclestr,"","")) != 0 ) { + acheight = height; if ( (regjson= jarray(&n,clijson,"registered")) != 0 ) { for (i=0; i> (j*8)) & 0xff)); - hexstr[16] = 0; - if ( (clijson2= get_komodocli(&retstr2,ACNAME,"oraclesdata",ORACLETXID,hexstr,"")) != 0 ) + if ( (height= get_oracledata(prevheight,hexstr,sizeof(hexstr),"Ihh")) != 0 ) { - //printf("data.(%s)\n",jprint(clijson2,0)); - komodobroadcast(ACNAME,clijson2); - free_json(clijson2); - } - else if ( retstr2 != 0 ) - { - printf("error parsing oraclesdata.(%s)\n",retstr2); - free(retstr2); + if ( (clijson2= get_komodocli(&retstr2,acname,"oraclesdata",oraclestr,hexstr,"")) != 0 ) + { + //printf("data.(%s)\n",jprint(clijson2,0)); + txid = komodobroadcast(acname,clijson2); + if ( bits256_nonz(txid) != 0 ) + { + prevheight = height; + acheight = get_KMDheight(acname); + printf("ht.%d <- %s\n",height,hexstr); + } + free_json(clijson2); + } + else if ( retstr2 != 0 ) + { + printf("error parsing oraclesdata.(%s)\n",retstr2); + free(retstr2); + } } break; } @@ -410,7 +549,8 @@ int32_t main(int32_t argc,char **argv) printf("got json parse error.(%s)\n",retstr); free(retstr); } - sleep(60); + sleep(10); + // best check is for txid to not be in mempool, ie confirmed } return(0); } diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index b98b95111..cabb2e2c0 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -17,10 +17,8 @@ /* prevent duplicate bindtxid and cointxid via mempool scan + baton from mempool for oracle -assets vin selector needs to filter by signable vins - -loop on merkle oracle string oracles */ @@ -464,8 +462,10 @@ uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,u { CTransaction tx; uint256 hash,mhash,hashBlock,oracletxid; int64_t val; int32_t numvouts; int64_t merkleht; CPubKey pk; std::vectordata; txid = zeroid; + char str[65]; fprintf(stderr,"reverse scan %s\n",uint256_str(str,batontxid)); while ( GetTransaction(batontxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { + fprintf(stderr,"reverse scan %s\n",uint256_str(str,batontxid)); if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,hash,pk,data) == 'D' && oracletxid == reforacletxid ) { if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height ) @@ -558,7 +558,7 @@ int64_t GatewaysDepositval(CTransaction tx) std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vectorproof,CPubKey destpub,int64_t amount) { - CMutableTransaction mtx; CTransaction bindtx; CPubKey mypk,gatewayspk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid; int64_t totalsupply; int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2; std::string coin; struct CCcontract_info *cp,C; std::vector pubkeys,publishers; std::vectortxids; char str[65],depositaddr[64],txidaddr[64]; + CMutableTransaction mtx; CTransaction bindtx; CPubKey mypk,gatewayspk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid; int64_t totalsupply; int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2; std::string coin; struct CCcontract_info *cp,C; std::vector pubkeys,publishers; std::vectortxids; char str[67],depositaddr[64],txidaddr[64]; cp = CCinit(&C,EVAL_GATEWAYS); if ( txfee == 0 ) txfee = 10000; @@ -575,15 +575,11 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std:: fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); return(""); } - if ( GatewaysCointxidExists(cp,cointxid) != 0 ) - { - fprintf(stderr,"cointxid.%s already exists\n",uint256_str(str,cointxid)); - return(""); - } n = (int32_t)pubkeys.size(); merkleroot = zeroid; for (i=m=0; i msigpubkeys; int64_t totalsupply,depositamount,inputs,CCchange=0; int32_t numvouts; uint256 hashBlock,assetid,oracletxid; char str[65],depositaddr[64]; + CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint8_t M,N,taddr,prefix,prefix2,mypriv[32]; std::string coin; std::vector msigpubkeys; int64_t totalsupply,depositamount,inputs,CCchange=0; int32_t numvouts; uint256 hashBlock,assetid,oracletxid; char str[65],depositaddr[64],coinaddr[64]; cp = CCinit(&C,EVAL_GATEWAYS); assetscp = CCinit(&C2,EVAL_ASSETS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); gatewayspk = GetUnspendable(cp,0); - _GetCCaddress(cp->unspendableaddr2,EVAL_ASSETS,gatewayspk); - memcpy(cp->unspendablepriv2,cp->CCpriv,32); - assetscp->evalcode2 = cp->evalcode2 = EVAL_ASSETS; - assetscp->unspendablepk2 = gatewayspk; - cp->unspendablepk2 = gatewayspk; - memcpy(assetscp->unspendablepriv2,cp->CCpriv,32); - strcpy(assetscp->unspendableaddr2,cp->unspendableaddr2); + _GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk); + CCaddr2set(assetscp,EVAL_ASSETS,gatewayspk,cp->CCpriv,coinaddr); + Myprivkey(mypriv); + _GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk); + CCaddr3set(assetscp,EVAL_GATEWAYS,mypk,mypriv,coinaddr); if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) { fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 82e1d4ab0..506605248 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -276,6 +276,33 @@ uint256 OracleBatonUtxo(uint64_t txfee,struct CCcontract_info *cp,uint256 refora return(batontxid); } +uint256 OraclesBatontxid(uint256 reforacletxid,CPubKey refpk) +{ + std::vector > unspentOutputs; + CTransaction regtx; uint256 hash,txid,batontxid,oracletxid; CPubKey pk; int32_t numvouts,height,maxheight=0; int64_t datafee; char markeraddr[64],batonaddr[64]; std::vector data; struct CCcontract_info *cp,C; + batontxid = zeroid; + cp = CCinit(&C,EVAL_ORACLES); + CCtxidaddr(markeraddr,reforacletxid); + SetCCunspents(unspentOutputs,markeraddr); + char str[67]; fprintf(stderr,"markeraddr.(%s) %s\n",markeraddr,pubkey33_str(str,(uint8_t *)&refpk)); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + fprintf(stderr,"check %s\n",uint256_str(str,txid)); + height = (int32_t)it->second.blockHeight; + if ( myGetTransaction(txid,regtx,hash) != 0 ) + { + if ( regtx.vout.size() > 0 && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == reforacletxid && pk == refpk ) + { + Getscriptaddress(batonaddr,regtx.vout[1].scriptPubKey); + batontxid = OracleBatonUtxo(10000,cp,oracletxid,batonaddr,pk,data); + break; + } + } + } + return(batontxid); +} + int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen) { char _str[65]; int32_t sflag = 0,i,val32,len = 0,slen = 0,dlen = 0; uint32_t uval32; uint16_t uval16; int16_t val16; int64_t val = 0; uint64_t uval = 0; @@ -477,33 +504,6 @@ int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char * return(0); } -uint256 OraclesBatontxid(uint256 reforacletxid,CPubKey refpk) -{ - std::vector > unspentOutputs; - CTransaction tx; uint256 hash,txid,rettxid,oracletxid; CPubKey pk; int32_t numvouts,maxheight=0; int64_t datafee,ht; char markeraddr[64]; std::vector data; struct CCcontract_info *cp,C; - rettxid = zeroid; - cp = CCinit(&C,EVAL_ORACLES); - CCtxidaddr(markeraddr,reforacletxid); - SetCCunspents(unspentOutputs,markeraddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - //ht = (int32_t)it->second.blockHeight; - if ( myGetTransaction(txid,tx,hash) != 0 && (numvouts= tx.vout.size()) > 0 ) - { - if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,hash,pk,data) == 'D' && oracletxid == reforacletxid && pk == refpk ) - { - if ( oracle_format(&hash,&ht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && ht > maxheight ) - { - maxheight = ht; - rettxid = txid; - } - } - } - } - return(rettxid); -} - int64_t IsOraclesvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) { char destaddr[64]; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index aac0c0f21..a799a5efc 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -107,6 +107,11 @@ static UniValue ValuePoolDesc( UniValue blockheaderToJSON(const CBlockIndex* blockindex) { UniValue result(UniValue::VOBJ); + if ( blockindex == 0 ) + { + result.push_back(Pair("error", "null blockhash")); + return(result); + } result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); int confirmations = -1; // Only report confirmations if the block is on the main chain