From 366625ca2308ec6584cbfe0ba9e35520465c2550 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sun, 2 Sep 2018 03:40:52 -1100 Subject: [PATCH] Initial oracles CC without validation --- src/cc/CCOracles.h | 7 +- src/cc/CCinclude.h | 1 + src/cc/CCutils.cpp | 9 ++ src/cc/MofN.cpp | 10 ++ src/cc/fsm.cpp | 2 + src/cc/gateways.cpp | 5 + src/cc/oracles.cpp | 243 ++++++++++++++++++++++++++++++++------- src/cc/payments.cpp | 3 + src/cc/pegs.cpp | 5 + src/cc/prices.cpp | 4 + src/cc/triggers.cpp | 2 + src/rpcserver.cpp | 8 +- src/rpcserver.h | 6 + src/wallet/rpcwallet.cpp | 112 +++++++++++++++++- 14 files changed, 370 insertions(+), 47 deletions(-) diff --git a/src/cc/CCOracles.h b/src/cc/CCOracles.h index 7080edc9d..2f279b1c1 100644 --- a/src/cc/CCOracles.h +++ b/src/cc/CCOracles.h @@ -20,8 +20,13 @@ #include "CCinclude.h" bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); +std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format); +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 OraclesInfo(); +UniValue OracleInfo(uint256 origtxid); +UniValue OraclesList(); #endif diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index bdb95ed82..fd54f924c 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -93,6 +93,7 @@ int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv); // CCutils +CPubKey buf2pk(uint8_t *buf33); void endiancpy(uint8_t *dest,uint8_t *src,int32_t len); uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv); CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 059d70910..90d9c3e26 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -149,6 +149,15 @@ uint256 Parseuint256(char *hexstr) return(txid); } +CPubKey buf2pk(uint8_t *buf33) +{ + CPubKey pk; int32_t i; uint8_t *dest; + dest = (uint8_t *)pk.begin(); + for (i=0; i<33; i++) + dest[i] = buf33[i]; + return(pk); +} + CPubKey pubkey2pk(std::vector pubkey) { CPubKey pk; int32_t i,n; uint8_t *dest,*pubkey33; diff --git a/src/cc/MofN.cpp b/src/cc/MofN.cpp index 40c48f65d..84952176f 100644 --- a/src/cc/MofN.cpp +++ b/src/cc/MofN.cpp @@ -22,6 +22,16 @@ ability to post partial signatures and construct a full transaction from M such partial signatures a new transaction would refer to the initialtx and other partial would refer to both + There is no need for a CC contract to use it for normal multisig as normal multisig transactions are already supported. + + In order to take advantage of CC powers, we can create a more powerful multisig using shamir's secret MofN (up to 255) algo to allow spends. Using the same non-interactive partial signing is possible. also, in addition to spending, data payload can have additional data that is also revealed when the funds are spent. + + rpc calls needed: + 1) create msig address (normal or shamir) + 2) post payment with partial sig + 3) add partial sig to 2) + 4) combine and submit M partial sigs + */ // start of consensus code diff --git a/src/cc/fsm.cpp b/src/cc/fsm.cpp index 04c620e99..41601b437 100644 --- a/src/cc/fsm.cpp +++ b/src/cc/fsm.cpp @@ -17,6 +17,8 @@ #include "../txmempool.h" /* + FSM CC is a highlevel CC contract that mostly uses other CC contracts. A finite state machine is defined, which combines triggers, payments and whatever other events/actions into a state machine + */ // start of consensus code diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 295e2fa4b..8f5d00f26 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -16,6 +16,11 @@ #include "CCGateways.h" /* + Uses MofN CC's normal msig handling to create automated deposits -> token issuing. And partial signing by the selected pubkeys for releasing the funds. A user would be able to select which pubkeys to use to construct the automated deposit/redeem multisigs. + + the potential pubkeys to be used would be based on active oracle data providers with recent activity. + + */ // start of consensus code diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 33888d483..9bbb425a3 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -16,6 +16,46 @@ #include "CCOracles.h" /* + An oracles CC has the purpose of converting offchain data into onchain data + simplest would just be to have a pubkey(s) that are trusted to provide such data, but this wont need to have a CC involved at all and can just be done by convention + + That begs the question, "what would an oracles CC do?" + A couple of things come to mind, ie. payments to oracles for future offchain data and maybe some sort of dispute/censoring ability + + first step is to define the data that the oracle is providing. A simple name:description tx can be created to define the name and description of the oracle data. + linked to this txid would be two types of transactions: + a) oracle providers + b) oracle data users + + In order to be resistant to sybil attacks, the feedback mechanism needs to have a cost. combining with the idea of payments for data, the oracle providers will be ranked by actual payments made to each oracle for each data type. + + Required transactions: + 0) create oracle description -> just needs to create txid for oracle data + 1) register as oracle data provider with price -> become a registered oracle data provider + 2) pay provider for N oracle data points -> lock funds for oracle provider + 3) publish oracle data point -> publish data and collect payment + + create: + vins.*: normal inputs + vout.0: txfee tag to oracle normal address + vout.1: opreturn with name and description and format for data + + register: + vins.*: normal inputs + vout.0: txfee tag to normal marker address + vout.1: opreturn with createtxid, pubkey and price per data point + + subscribe: + vins.*: normal inputs + vout.0: subscription fee to publishers CC address + vout.1: opreturn with createtxid, registered provider's pubkey, amount + + data: + vin.0: normal input + vin.1+: subscription vout.0 + vout.0: change to publishers CC address + vout.1: payment for dataprovider + vout.2: opreturn with data in proper format */ @@ -139,73 +179,188 @@ int64_t AddOraclesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPu return(totalinputs); } -std::string OraclesGet(uint64_t txfee,int64_t nValue) +int64_t LifetimeOraclesFunds(struct CCcontract_info *cp,uint256 oracletxid,CPubKey regpk) { - CMutableTransaction mtx,tmpmtx; CPubKey mypk,Oraclespk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; + char coinaddr[64]; CPubKey pk; int64_t total=0,num; uint256 txid,hashBlock; CTransaction subtx; + std::vector > addressIndex; + GetCCaddress(cp,coinaddr,regpk); + SetCCtxids(addressIndex,coinaddr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) + { + txid = it->first.txhash; + if ( GetTransaction(txid,subtx,hashBlock,false) != 0 ) + { + if ( subtx.vout.size() > 0 && DecodeOraclesOpRet(subtx.vout[subtx.vout.size()-1].scriptPubKey,subtxid,pk,num) == 'S' && subtxid == oracletxid && regpk == pk ) + { + total += subtx.vout[0].nValue; + } + } + } + return(total); +} + +std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format) +{ + CMutableTransaction mtx; CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_ORACLES); + if ( name.size() > 32 || description.size() > 4096 || format.size() > 4096 ) + { + fprintf(stderr,"name.%d or description.%d is too big\n",(int32_t)name.size(),(int32_t)description.size()); + return(""); + } if ( txfee == 0 ) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); Oraclespk = GetUnspendable(cp,0); + if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + { + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(Oraclespk)) << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesCreateOpRet('C',name,description,format))); + } + return(""); +} + +std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee) +{ + CMutableTransaction mtx; CPubKey mypk,markerpubkey; struct CCcontract_info *cp,C; uint8_t buf33[33]; char markeraddr[64]; + cp = CCinit(&C,EVAL_ORACLES); + if ( name.size() > 32 || description.size() > 4096 || format.size() > 4096 ) + { + fprintf(stderr,"name.%d or description.%d is too big\n",(int32_t)name.size(),(int32_t)description.size()); + return(""); + } + if ( txfee == 0 ) + txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( (inputs= AddOraclesInputs(cp,mtx,Oraclespk,nValue+txfee,60)) > 0 ) - { - if ( inputs > nValue ) - CCchange = (inputs - nValue - txfee); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_ORACLES,CCchange,Oraclespk)); - mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - fprintf(stderr,"start at %u\n",(uint32_t)time(NULL)); - j = rand() & 0xfffffff; - for (i=0; i<1000000; i++,j++) - { - tmpmtx = mtx; - rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_ORACLES << (uint8_t)'G' << j)); - if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) - { - len >>= 1; - decode_hex(buf,len,(char *)rawhex.c_str()); - hash = bits256_doublesha256(0,buf,len); - if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) - { - fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL)); - return(rawhex); - } - //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); - } - } - fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL)); + buf33[0] = 0x02; + endiancpy(&buf[1],(uint8_t *)&oracletxid,32); + markerpubkey = buf2pk(buf33); + Getscriptaddress(markeraddr,CScript() << markerpubkey << OP_CHECKSIG); + if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + { + mtx.vout.push_back(CTxOut(txfee,CScript() << markerpubkey << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,datafee))); + } + return(""); +} + +std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount) +{ + CMutableTransaction mtx; CPubKey mypk,markerpubkey; struct CCcontract_info *cp,C; uint8_t buf33[33]; char markeraddr[64]; + cp = CCinit(&C,EVAL_ORACLES); + if ( name.size() > 32 || description.size() > 4096 || format.size() > 4096 ) + { + fprintf(stderr,"name.%d or description.%d is too big\n",(int32_t)name.size(),(int32_t)description.size()); return(""); - } else fprintf(stderr,"cant find Oracles inputs\n"); + } + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + buf33[0] = 0x02; + endiancpy(&buf[1],(uint8_t *)&oracletxid,32); + markerpubkey = buf2pk(buf33); + Getscriptaddress(markeraddr,CScript() << markerpubkey << OP_CHECKSIG); + if ( AddNormalinputs(mtx,mypk,amount + 2*txfee,1) > 0 ) + { + mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,publisher)); + mtx.vout.push_back(CTxOut(txfee,CScript() << markerpubkey << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,amount))); + } return(""); } -std::string OraclesFund(uint64_t txfee,int64_t funds) +std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector data) { - CMutableTransaction mtx; CPubKey mypk,Oraclespk; CScript opret; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk; int64_t datafee,inputs,CCchange = 0; struct CCcontract_info *cp,C; char coinaddr[64]; cp = CCinit(&C,EVAL_ORACLES); + if ( data.size() > 8192 ) + { + fprintf(stderr,"datasize %d is too big\n",(int32_t)data.size()); + return(""); + } + if ( (datafee= OracleDatafee(oracletxid)) <= 0 ) + { + fprintf(stderr,"datafee %.8f is illegal\n",(double)datafee/COIN); + return(""); + } if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - Oraclespk = GetUnspendable(cp,0); - if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) + GetCCaddress(cp,coinaddr,mypk); + if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) { - mtx.vout.push_back(MakeCC1vout(EVAL_ORACLES,funds,Oraclespk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); + if ( (inputs= AddOracleInputs(cp,mtx,mypk,oracletxid,datafee,60)) > 0 ) + { + if ( inputs > datafee ) + CCchange = (inputs - datafee); + mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,mypk)); + mtx.vout.push_back(CTxOut(txfee,CScript() << mypk << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesData('D',oracletxid,mypk,data))); + } } return(""); } -UniValue OraclesInfo() +UniValue OracleInfo(uint256 origtxid) { - UniValue result(UniValue::VOBJ); char numstr[64]; - CMutableTransaction mtx; CPubKey Oraclespk; struct CCcontract_info *cp,C; int64_t funding; - result.push_back(Pair("result","success")); - result.push_back(Pair("name","Oracles")); + UniValue result(UniValue::VOBJ),a(UniValue::VARR),obj(UniValue::VOBJ); std::vector > addressIndex; CTransaction regtx; std::string name,description,format; uint256 hashBlock,txid,oracletxid; CMutableTransaction mtx; CPubKey Oraclespk,markerpubkey; struct CCcontract_info *cp,C; uint8_t buf33[33]; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64]; cp = CCinit(&C,EVAL_ORACLES); Oraclespk = GetUnspendable(cp,0); - funding = AddOraclesInputs(cp,mtx,Oraclespk,0,0); - sprintf(numstr,"%.8f",(double)funding/COIN); - result.push_back(Pair("funding",numstr)); + buf33[0] = 0x02; + endiancpy(&buf[1],(uint8_t *)&origtxid,32); + markerpubkey = buf2pk(buf33); + Getscriptaddress(markeraddr,CScript() << markerpubkey << OP_CHECKSIG); + if ( GetTransaction(origtxid,vintx,hashBlock,false) != 0 ) + { + if ( vintx.vout.size() > 0 && DecodeOraclesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,name,description,format) == 'C' ) + { + result.push_back(Pair("txid",uint256_str(str,origtxid))); + result.push_back(Pair("name",name)); + result.push_back(Pair("description",description)); + result.push_back(Pair("marker",markeraddr)); + SetCCtxids(addressIndex,markeraddr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) + { + txid = it->first.txhash; + if ( GetTransaction(txid,regtx,hashBlock,false) != 0 ) + { + if ( vintx.vout.size() > 0 && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid ) + { + result.push_back(Pair("provider",pubkey33_str(str,(uint8_t *)pk.begin()))); + funding = LifetimeOraclesFunds(cp,oracletxid,pk); + sprintf(numstr,"%.8f",(double)funding/COIN); + obj.push_back(Pair("lifetime",numstr)); + funding = AddOraclesInputs(cp,mtx,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)); + } + } + return(result); +} + +UniValue OraclesList() +{ + UniValue result(UniValue::VARR); std::vector > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction createtx; std::string name,description,format; char str[65]; + cp = CCinit(&C,EVAL_ORACLES); + SetCCtxids(addressIndex,cp->normaladdr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) + { + txid = it->first.txhash; + if ( GetTransaction(txid,createtx,hashBlock,false) != 0 ) + { + if ( createtx.vout.size() > 0 && DecodeOraclesFundingOpRet(createtx.vout[createtx.vout.size()-1].scriptPubKey,name,description,format) == 'C' ) + { + result.push_back(uint256_str(str,txid)); + } + } + } return(result); } diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index d340c1938..6cd751b8d 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -16,6 +16,9 @@ #include "CCPayments.h" /* + Payments CC is a catchall CC, supported invoices, zpayments, automated funds allocation, including token based revshare + + */ // start of consensus code diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 7f5ca4f14..959d2fcd2 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -16,6 +16,11 @@ #include "CCPegs.h" /* + Pegs CC builds on top of Prices CC and would bind a pricefeed to a token bid/ask automated marketmaking. + + Funds deposited into CC address for a specific peg would then be used to fund the bid/ask as the pricefeed changes the price. Profits/losses would accumulate in the associated address. + + In the event funds exceed a specified level, it can be spent into a collection address. The idea is that the collection address can further be used for revshares. */ // start of consensus code diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 4c7ee5183..f865e45b1 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -16,6 +16,10 @@ #include "CCPrices.h" /* + Prices CC would best build on top of the oracles CC, ie. to combine payments for multiple oracles and to calculate a 51% protected price feed. + + CC locked funds can be used for automated trading + */ // start of consensus code diff --git a/src/cc/triggers.cpp b/src/cc/triggers.cpp index 08226bbff..93107f4a9 100644 --- a/src/cc/triggers.cpp +++ b/src/cc/triggers.cpp @@ -16,6 +16,8 @@ #include "CCTriggers.h" /* + Triggers CC is a building block CC that allows creation of event -> action processing, where events are defined during trigger creation and actions to be mostly done via payments, but by making payments to other CC contracts, it can be used to invoke other CC contracts + */ // start of consensus code diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2545ca883..9e2c1ded2 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -386,7 +386,13 @@ static const CRPCCommand vRPCCommands[] = { "channels", "channelsrefund", &channelsrefund, true }, /* Oracles */ - { "oracles", "oraclesaddress", &oraclesaddress, true }, + { "oracles", "oraclesaddress", &oraclesaddress, true }, + { "oracles", "oracleslist", &oracleslist, true }, + { "oracles", "oraclesinfo", &oraclesinfo, true }, + { "oracles", "oraclescreate", &oraclescreate, true }, + { "oracles", "oraclesregister", &oraclesregister, true }, + { "oracles", "oraclessubscribe", &oraclessubscribe, true }, + { "oracles", "oraclesdata", &oraclesdata, true }, /* Prices */ { "prices", "pricesaddress", &pricesaddress, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index e15951dbd..354ecabea 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -224,6 +224,12 @@ extern UniValue tokenfillask(const UniValue& params, bool fHelp); extern UniValue mofnaddress(const UniValue& params, bool fHelp); extern UniValue channelsaddress(const UniValue& params, bool fHelp); 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 oraclesregister(const UniValue& params, bool fHelp); +extern UniValue oraclessubscribe(const UniValue& params, bool fHelp); +extern UniValue oraclesdata(const UniValue& params, bool fHelp); extern UniValue pricesaddress(const UniValue& params, bool fHelp); extern UniValue pegsaddress(const UniValue& params, bool fHelp); extern UniValue triggersaddress(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 70a0630ff..cdc0d5489 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5347,7 +5347,6 @@ UniValue rewardsunlock(const UniValue& params, bool fHelp) UniValue rewardslist(const UniValue& params, bool fHelp) { - uint256 tokenid; if ( fHelp || params.size() > 0 ) throw runtime_error("rewardslist\n"); if ( ensure_CCrequirements() < 0 ) @@ -5366,6 +5365,117 @@ UniValue rewardsinfo(const UniValue& params, bool fHelp) return(RewardsInfo(fundingtxid)); } +UniValue oracleslist(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() > 0 ) + throw runtime_error("oracleslist\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + return(OraclesList()); +} + +UniValue oraclesinfo(const UniValue& params, bool fHelp) +{ + uint256 txid; + if ( fHelp || params.size() != 1 ) + throw runtime_error("oraclesinfo oracletxid\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + txid = Parseuint256((char *)params[0].get_str().c_str()); + return(OracleInfo(txid)); +} + +UniValue oraclesregister(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 txid; int64_t datafee; + if ( fHelp || params.size() != 2 ) + throw runtime_error("oraclesregister oracletxid datafee\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + txid = Parseuint256((char *)params[0].get_str().c_str()); + datafee = atol((char *)params[1].get_str().c_str()); + hex = OracleRegister(0,txid,datafee); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt register with oracle txid"); + return(result); +} + +UniValue oraclessubscribe(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 txid; int64_t amount; std::vector pubkey; + if ( fHelp || params.size() != 3 ) + throw runtime_error("oraclessubscribe oracletxid publisher datafee\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + txid = Parseuint256((char *)params[0].get_str().c_str()); + pubkey = ParseHex(params[1].get_str().c_str()); + amount = atol((char *)params[2].get_str().c_str()); + hex = OracleSubscribe(0,txid,pubkey2pk(pubkey),amount); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt register with oracle txid"); + return(result); +} + +UniValue oraclesdata(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 txid; std::vector data; + if ( fHelp || params.size() != 2 ) + throw runtime_error("oraclesdata oracletxid hexstr\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + txid = Parseuint256((char *)params[0].get_str().c_str()); + data = ParseHex(params[1].get_str().c_str()); + hex = OracleData(0,txid,data); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt publish data with oracle txid"); + return(result); +} + +UniValue oraclescreate(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); std::string name,description,format,hex; + if ( fHelp || params.size() != 3 ) + throw runtime_error("oraclescreate name description format\n"); + if ( ensure_CCrequirements() < 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); + name = params[0].get_str(); + if ( name.size() == 0 || name.size() > 32) + { + ERR_RESULT("oracles name must not be empty and up to 32 characters"); + return(result); + } + description = params[1].get_str(); + if ( description.size() > 4096 ) + { + ERR_RESULT("oracles description must be <= 4096 characters"); + return(result); + } + format = params[2].get_str(); + if ( format.size() > 4096 ) + { + ERR_RESULT("oracles format must be <= 4096 characters"); + return(result); + } + hex = OracleCreate(0,name,description,format); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt create oracle"); + return(result); +} + UniValue FSMcreate(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); std::string name,states,hex;