From 0f24aec58740a6afeedd186705e9dc8e1c39e880 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Mon, 27 May 2019 21:31:15 -0700 Subject: [PATCH 1/2] Give correct CLI asset name and RPC ports in rpc examples --- src/rpc/server.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 500d175e0..e36e8b4c9 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -45,6 +46,7 @@ using namespace RPCServer; using namespace std; +extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; static bool fRPCRunning = false; static bool fRPCInWarmup = true; @@ -853,21 +855,30 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms std::string HelpExampleCli(const std::string& methodname, const std::string& args) { - return "> komodo-cli " + methodname + " " + args + "\n"; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + return "> komodo-cli " + methodname + " " + args + "\n"; + } else if ((strncmp(ASSETCHAINS_SYMBOL, "HUSH3", 5) == 0) ) { + return "> hush-cli " + methodname + " " + args + "\n"; + } else { + return "> komodo-cli -ac_name=" + strprintf("%s", ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; + } } std::string HelpExampleRpc(const std::string& methodname, const std::string& args) { - return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", " - "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:7771/\n"; + return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", " + "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:" + to_string(ASSETCHAINS_RPCPORT) + "/\n"; } string experimentalDisabledHelpMsg(const string& rpc, const string& enableArg) { + string daemon = ASSETCHAINS_SYMBOL[0] == 0 ? "komodod" : "hushd"; + string ticker = ASSETCHAINS_SYMBOL[0] == 0 ? "komodo" : ASSETCHAINS_SYMBOL; + return "\nWARNING: " + rpc + " is disabled.\n" - "To enable it, restart zcashd with the -experimentalfeatures and\n" + "To enable it, restart " + daemon + " with the -experimentalfeatures and\n" "-" + enableArg + " commandline options, or add these two lines\n" - "to the zcash.conf file:\n\n" + "to the " + ticker + ".conf file:\n\n" "experimentalfeatures=1\n" + enableArg + "=1\n"; } From 01f597a2c83264fc7dddf9496bec972d9ba8ed68 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Tue, 28 May 2019 15:40:43 +0200 Subject: [PATCH 2/2] Oracles pubkey spoofing in register tx fix - Fix activation on July 15th 2019 00:00 - Added oraclesfund tx to fund Oracles CC address of pubkey that will register, and spend it in register tx - oraclessamples gets baton address as input instead of txid to show all data from publisher --- src/cc/CCOracles.h | 4 +- src/cc/oracles.cpp | 246 ++++++++++++++++++++++++++++++++------- src/rpc/server.cpp | 1 + src/rpc/server.h | 1 + src/wallet/rpcwallet.cpp | 28 ++++- 5 files changed, 233 insertions(+), 47 deletions(-) diff --git a/src/cc/CCOracles.h b/src/cc/CCOracles.h index 7f952e5f5..9f6a35966 100644 --- a/src/cc/CCOracles.h +++ b/src/cc/CCOracles.h @@ -21,12 +21,12 @@ bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format); +std::string OracleFund(int64_t txfee,uint256 oracletxid); std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee); std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount); std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector data); - // CCcustom -UniValue OracleDataSamples(uint256 reforacletxid,uint256 batontxid,int32_t num); +UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num); UniValue OracleInfo(uint256 origtxid); UniValue OraclesList(); diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 7cd429182..f019ae271 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -92,10 +92,11 @@ vout.n-1: opreturn with oracletxid, prevbatontxid and data in proper format */ +extern int32_t komodo_currentheight(); +#define PUBKEY_SPOOFING_FIX_ACTIVATION 1563148800 +#define CC_MARKER_VALUE 10000 // start of consensus code - - CScript EncodeOraclesCreateOpRet(uint8_t funcid,std::string name,std::string description,std::string format) { CScript opret; uint8_t evalcode = EVAL_ORACLES; @@ -124,6 +125,7 @@ uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,s CScript EncodeOraclesOpRet(uint8_t funcid,uint256 oracletxid,CPubKey pk,int64_t num) { CScript opret; uint8_t evalcode = EVAL_ORACLES; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << oracletxid << pk << num); return(opret); } @@ -131,11 +133,12 @@ CScript EncodeOraclesOpRet(uint8_t funcid,uint256 oracletxid,CPubKey pk,int64_t uint8_t DecodeOraclesOpRet(const CScript &scriptPubKey,uint256 &oracletxid,CPubKey &pk,int64_t &num) { std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey,vopret); script = (uint8_t *)vopret.data(); if ( vopret.size() > 2 && script[0] == EVAL_ORACLES ) { - if (script[0] == EVAL_ORACLES && (script[1]== 'R' || script[1] == 'S') && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num)!=0) + if (script[0] == EVAL_ORACLES && (script[1]== 'R' || script[1] == 'S' || script[1] == 'F') && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num)!=0) return(f); else return(script[1]); } @@ -633,9 +636,25 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio else return(true); } +int32_t GetLatestTimestamp(int32_t height) +{ + uint256 blockHash; CBlock block; CBlockIndex* pindex; + + blockHash = chainActive[height]->GetBlockHash(); + pindex = mapBlockIndex[blockHash]; + if ( komodo_blockload(block,pindex) == 0 ) + { + return(block.nTime); + } + return(0); +} + bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { - uint256 txid,oracletxid,batontxid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; uint8_t *script; std::vector vopret,data; CScript scriptPubKey; CPubKey publisher; + uint256 oracletxid,batontxid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; int64_t amount; uint256 hashblock; + uint8_t *script; std::vector vopret,data; CPubKey publisher,tmppk,oraclespk; char tmpaddress[64],vinaddress[64],oraclesaddr[64]; + CTransaction tmptx; std::string name,desc,format; + numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; @@ -643,10 +662,11 @@ bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t return eval->Invalid("no vouts"); else { - txid = tx.GetHash(); GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); if ( vopret.size() > 2 ) - { + { + oraclespk=GetUnspendable(cp,0); + Getscriptaddress(oraclesaddr,CScript() << ParseHex(HexStr(oraclespk)) << OP_CHECKSIG); script = (uint8_t *)vopret.data(); switch ( script[1] ) { @@ -657,13 +677,45 @@ bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t // vout.n-1: opreturn with name and description and format for data return eval->Invalid("unexpected OraclesValidate for create"); break; - case 'R': // register + case 'F': // fund (activation on Jul 15th 2019 00:00) // vins.*: normal inputs + // vout.0: txfee to oracle CC address of users pubkey + // vout.1: change, if any + // vout.n-1: opreturn with createtxid, pubkey and amount + return eval->Invalid("unexpected OraclesValidate for create"); + break; + case 'R': // register + // vin.0: normal inputs + // vin.n-1: CC input from pubkeys oracle CC addres - to prove that register came from pubkey that is registred (activation on Jul 15th 2019 00:00) // vout.0: txfee tag to normal marker address // vout.1: baton CC utxo - // vout.2: change, if any + // vout.2: marker from oraclesfund tx to normal pubkey address (activation on Jul 15th 2019 00:00) + // vout.n-2: change, if any // vout.n-1: opreturn with createtxid, pubkey and price per data point - return eval->Invalid("unexpected OraclesValidate for register"); + if (GetLatestTimestamp(eval->GetCurrentHeight())>PUBKEY_SPOOFING_FIX_ACTIVATION) + { + if ((numvouts=tx.vout.size()) < 1 || DecodeOraclesOpRet(tx.vout[numvouts-1].scriptPubKey,oracletxid,tmppk,amount)!='R') + return eval->Invalid("invalid oraclesregister OP_RETURN data!"); + else if (myGetTransaction(oracletxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid oraclescreate txid!"); + else if ((numvouts=tmptx.vout.size()) < 1 || DecodeOraclesCreateOpRet(tmptx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C') + return eval->Invalid("invalid oraclescreate OP_RETURN data!"); + else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for oraclescreate!"); + else if (ConstrainVout(tmptx.vout[0],0,oraclesaddr,txfee)==0) + return eval->Invalid("invalid marker for oraclescreate!"); + else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for oraclesregister!"); + else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 + || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE || !Getscriptaddress(vinaddress,tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].scriptPubKey) + || !GetCCaddress(cp,tmpaddress,tmppk) || strcmp(tmpaddress,vinaddress)!=0) + return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC for oraclesregister or pubkey not same as vin pubkey, register must be done from owner of pubkey that registers to oracle!!"); + else if (CCtxidaddr(tmpaddress,oracletxid).IsValid() && ConstrainVout(tx.vout[0],0,tmpaddress,txfee)==0) + return eval->Invalid("invalid marker for oraclesregister!"); + else if (!Getscriptaddress(tmpaddress,CScript() << ParseHex(HexStr(tmppk)) << OP_CHECKSIG) || ConstrainVout(tx.vout[2],0,tmpaddress,CC_MARKER_VALUE)==0) + return eval->Invalid("pubkey in OP_RETURN and in vout.2 not matching, register must be done from owner of pubkey that registers to oracle!"); + } + else return eval->Invalid("unexpected OraclesValidate for register"); break; case 'S': // subscribe // vins.*: normal inputs @@ -762,6 +814,45 @@ int64_t LifetimeOraclesFunds(struct CCcontract_info *cp,uint256 oracletxid,CPubK return(total); } +int64_t AddMyOraclesFunds(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 oracletxid) +{ + char coinaddr[64],funcid; int64_t nValue,tmpamount; uint256 tmporacletxid,txid,hashBlock,ignoretxid; int32_t numvouts,vout,ignorevin; + std::vector > unspentOutputs; CTransaction vintx; CPubKey tmppk; + + GetCCaddress(cp,coinaddr,pk); + SetCCunspents(unspentOutputs,coinaddr,true); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = it->second.satoshis; + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && (numvouts=vintx.vout.size())>0) + { + if ((funcid=DecodeOraclesOpRet(vintx.vout[numvouts-1].scriptPubKey,tmporacletxid,tmppk,tmpamount))!=0 && funcid=='F' && tmppk==pk + && tmporacletxid==oracletxid && tmpamount==nValue && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout)==0) + { + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + return (nValue); + } + } else fprintf(stderr,"couldnt find transaction\n"); + } + + BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) + { + const CTransaction &txmempool = e.GetTx(); + const uint256 &hash = txmempool.GetHash(); + nValue=txmempool.vout[0].nValue; + + if ((funcid=DecodeOraclesOpRet(txmempool.vout[txmempool.vout.size()-1].scriptPubKey,tmporacletxid,tmppk,tmpamount))!=0 && funcid=='F' + && tmppk==pk && tmporacletxid==oracletxid && tmpamount==nValue && myIsutxo_spentinmempool(ignoretxid,ignorevin,hash,0)==0) + { + mtx.vin.push_back(CTxIn(hash,0,CScript())); + return (nValue); + } + } + return (0); +} + std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -802,10 +893,36 @@ std::string OracleCreate(int64_t txfee,std::string name,std::string description, return(""); } +std::string OracleFund(int64_t txfee,uint256 oracletxid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk,oraclespk; struct CCcontract_info *cp,C; + + if (GetLatestTimestamp(komodo_currentheight())evalcode,CC_MARKER_VALUE,mypk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('F',oracletxid,mypk,CC_MARKER_VALUE))); + } + CCerror = strprintf("error adding normal inputs"); + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); +} + std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,markerpubkey,batonpk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64]; + CPubKey mypk,markerpubkey,batonpk,oraclespk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64]; + cp = CCinit(&C,EVAL_ORACLES); if ( txfee == 0 ) txfee = 10000; @@ -816,12 +933,20 @@ std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee) return(""); } mypk = pubkey2pk(Mypubkey()); + oraclespk = GetUnspendable(cp,0); batonpk = OracleBatonPk(batonaddr,cp); markerpubkey = CCtxidaddr(markeraddr,oracletxid); - if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 ) + if (AddNormalinputs(mtx,mypk,3*txfee,4)) { + if (GetLatestTimestamp(komodo_currentheight())>PUBKEY_SPOOFING_FIX_ACTIVATION && AddMyOraclesFunds(cp,mtx,mypk,oracletxid)!=CC_MARKER_VALUE) + { + CCerror = strprintf("error adding inputs from your Oracles CC address, please fund it first with oraclesfund rpc!"); + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + } mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,batonpk)); + if (GetLatestTimestamp(komodo_currentheight())>PUBKEY_SPOOFING_FIX_ACTIVATION) mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,datafee))); } CCerror = strprintf("error adding normal inputs"); @@ -924,43 +1049,70 @@ std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector da UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatlen) { - uint256 hash; int32_t i,j=0; int64_t val; char str[IGUANA_MAXSCRIPTSIZE*2+1]; + UniValue obj(UniValue::VARR); uint256 hash; int32_t i,j=0; int64_t val; char str[IGUANA_MAXSCRIPTSIZE*2+1]; for (i=0; i= datalen ) break; } - return(str); + return(obj); } -UniValue OracleDataSamples(uint256 reforacletxid,uint256 batontxid,int32_t num) +UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num) { - UniValue result(UniValue::VOBJ),b(UniValue::VARR); CTransaction tx,oracletx; uint256 hashBlock,btxid,oracletxid; - CPubKey pk; std::string name,description,format; int32_t numvouts,n=0; std::vector data; char str[67], *formatstr = 0; + UniValue result(UniValue::VOBJ),b(UniValue::VARR); CTransaction tx,oracletx; uint256 txid,hashBlock,btxid,oracletxid; + CPubKey pk; std::string name,description,format; int32_t numvouts,n=0,vout; std::vector data; char *formatstr = 0; + std::vector > addressIndex; int64_t nValue; result.push_back(Pair("result","success")); if ( GetTransaction(reforacletxid,oracletx,hashBlock,false) != 0 && (numvouts=oracletx.vout.size()) > 0 ) { if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' ) { - while ( GetTransaction(batontxid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0 ) + BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) { - if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid ) + const CTransaction &txmempool = e.GetTx(); + const uint256 &hash = txmempool.GetHash(); + if ((numvouts=txmempool.vout.size())>0 && DecodeOraclesData(txmempool.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid ) { if ( (formatstr= (char *)format.c_str()) == 0 ) formatstr = (char *)""; UniValue a(UniValue::VOBJ); - a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()))); - a.push_back(Pair("txid",uint256_str(str,batontxid))); + a.push_back(Pair("txid",hash.GetHex())); + a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()))); b.push_back(a); - batontxid = btxid; if ( ++n >= num && num != 0) break; - } else break; + } + } + SetCCtxids(addressIndex,batonaddr,true); + if (addressIndex.size()>0) + { + for (std::vector >::const_iterator it=addressIndex.end()-1; it!=addressIndex.begin(); it--) + { + txid=it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second; + if (vout==1 && nValue==10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0 ) + { + if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid ) + { + if ( (formatstr= (char *)format.c_str()) == 0 ) + formatstr = (char *)""; + UniValue a(UniValue::VOBJ); + a.push_back(Pair("txid",txid.GetHex())); + a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size()))); + b.push_back(a); + if ( ++n >= num && num != 0) + break; + } + } + } } } } @@ -971,10 +1123,12 @@ UniValue OracleDataSamples(uint256 reforacletxid,uint256 batontxid,int32_t num) UniValue OracleInfo(uint256 origtxid) { UniValue result(UniValue::VOBJ),a(UniValue::VARR); - std::vector > unspentOutputs; + std::vector > unspentOutputs; int32_t height; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction regtx,tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk; + CTransaction tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk; struct CCcontract_info *cp,C; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector data; + std::map> publishers; + cp = CCinit(&C,EVAL_ORACLES); CCtxidaddr(markeraddr,origtxid); if ( GetTransaction(origtxid,tx,hashBlock,false) == 0 ) @@ -998,28 +1152,38 @@ UniValue OracleInfo(uint256 origtxid) for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; - if ( GetTransaction(txid,regtx,hashBlock,false) != 0 ) + height = (int32_t)it->second.blockHeight; + if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && + DecodeOraclesOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid ) { - if ( regtx.vout.size() > 0 && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid ) + if (publishers.find(pk)==publishers.end() || height>publishers[pk].second) { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("publisher",pubkey33_str(str,(uint8_t *)pk.begin()))); - Getscriptaddress(batonaddr,regtx.vout[1].scriptPubKey); - batontxid = OracleBatonUtxo(10000,cp,oracletxid,batonaddr,pk,data); - obj.push_back(Pair("baton",batonaddr)); - obj.push_back(Pair("batontxid",uint256_str(str,batontxid))); - funding = LifetimeOraclesFunds(cp,oracletxid,pk); - sprintf(numstr,"%.8f",(double)funding/COIN); - obj.push_back(Pair("lifetime",numstr)); - funding = AddOracleInputs(cp,mtx,oracletxid,pk,0,0); - sprintf(numstr,"%.8f",(double)funding/COIN); - obj.push_back(Pair("funds",numstr)); - sprintf(numstr,"%.8f",(double)datafee/COIN); - obj.push_back(Pair("datafee",numstr)); - a.push_back(obj); + publishers[pk].first=txid; + publishers[pk].second=height; } } } + for (std::map>::iterator it = publishers.begin(); it != publishers.end(); ++it) + { + if ( GetTransaction(it->second.first,tx,hashBlock,false) != 0 && DecodeOraclesOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R') + { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("publisher",pubkey33_str(str,(uint8_t *)pk.begin()))); + Getscriptaddress(batonaddr,tx.vout[1].scriptPubKey); + batontxid = OracleBatonUtxo(10000,cp,oracletxid,batonaddr,pk,data); + obj.push_back(Pair("baton",batonaddr)); + obj.push_back(Pair("batontxid",uint256_str(str,batontxid))); + funding = LifetimeOraclesFunds(cp,oracletxid,pk); + sprintf(numstr,"%.8f",(double)funding/COIN); + obj.push_back(Pair("lifetime",numstr)); + funding = AddOracleInputs(cp,mtx,oracletxid,pk,0,0); + sprintf(numstr,"%.8f",(double)funding/COIN); + obj.push_back(Pair("funds",numstr)); + sprintf(numstr,"%.8f",(double)datafee/COIN); + obj.push_back(Pair("datafee",numstr)); + a.push_back(obj); + } + } result.push_back(Pair("registered",a)); } } diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index e36e8b4c9..5d7fd6d74 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -456,6 +456,7 @@ static const CRPCCommand vRPCCommands[] = { "oracles", "oracleslist", &oracleslist, true }, { "oracles", "oraclesinfo", &oraclesinfo, true }, { "oracles", "oraclescreate", &oraclescreate, true }, + { "oracles", "oraclesfund", &oraclesfund, true }, { "oracles", "oraclesregister", &oraclesregister, true }, { "oracles", "oraclessubscribe", &oraclessubscribe, true }, { "oracles", "oraclesdata", &oraclesdata, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index b9fb33198..27e7288cd 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -267,6 +267,7 @@ extern UniValue oraclesaddress(const UniValue& params, bool fHelp); extern UniValue oracleslist(const UniValue& params, bool fHelp); extern UniValue oraclesinfo(const UniValue& params, bool fHelp); extern UniValue oraclescreate(const UniValue& params, bool fHelp); +extern UniValue oraclesfund(const UniValue& params, bool fHelp); extern UniValue oraclesregister(const UniValue& params, bool fHelp); extern UniValue oraclessubscribe(const UniValue& params, bool fHelp); extern UniValue oraclesdata(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e9a9e38c6..e6e66caf7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6760,6 +6760,26 @@ UniValue oraclesinfo(const UniValue& params, bool fHelp) return(OracleInfo(txid)); } +UniValue oraclesfund(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 txid; std::string hex; + if ( fHelp || params.size() != 1 ) + throw runtime_error("oraclesfund oracletxid\n"); + if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + txid = Parseuint256((char *)params[0].get_str().c_str()); + hex = OracleFund(0,txid); + RETURN_IF_ERROR(CCerror); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt fund with oracle txid"); + return(result); +} + UniValue oraclesregister(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); uint256 txid; int64_t datafee; std::string hex; @@ -6806,17 +6826,17 @@ UniValue oraclessubscribe(const UniValue& params, bool fHelp) UniValue oraclessamples(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); uint256 txid,batontxid; int32_t num; + UniValue result(UniValue::VOBJ); uint256 txid; int32_t num; char *batonaddr; if ( fHelp || params.size() != 3 ) - throw runtime_error("oraclessamples oracletxid batonutxo num\n"); + throw runtime_error("oraclessamples oracletxid batonaddress num\n"); if ( ensure_CCrequirements(EVAL_ORACLES) < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); txid = Parseuint256((char *)params[0].get_str().c_str()); - batontxid = Parseuint256((char *)params[1].get_str().c_str()); + batonaddr = (char *)params[1].get_str().c_str(); num = atoi((char *)params[2].get_str().c_str()); - return(OracleDataSamples(txid,batontxid,num)); + return(OracleDataSamples(txid,batonaddr,num)); } UniValue oraclesdata(const UniValue& params, bool fHelp)