diff --git a/src/cc/CCPrices.h b/src/cc/CCPrices.h index 1a68be7dd..1ecaebb2c 100644 --- a/src/cc/CCPrices.h +++ b/src/cc/CCPrices.h @@ -18,17 +18,33 @@ #define CC_PRICES_H #include "CCinclude.h" +int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind); + +#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) +#define PRICES_TXFEE 10000 +#define PRICES_MAXLEVERAGE 777 +#define PRICES_SMOOTHWIDTH 1 +#define KOMODO_MAXPRICES 2048 // must be power of 2 and less than 8192 +#define KOMODO_PRICEMASK (~(KOMODO_MAXPRICES - 1)) +#define PRICES_WEIGHT (KOMODO_MAXPRICES * 1) +#define PRICES_MULT (KOMODO_MAXPRICES * 2) +#define PRICES_DIV (KOMODO_MAXPRICES * 3) +#define PRICES_INV (KOMODO_MAXPRICES * 4) +#define PRICES_MDD (KOMODO_MAXPRICES * 5) +#define PRICES_MMD (KOMODO_MAXPRICES * 6) +#define PRICES_MMM (KOMODO_MAXPRICES * 7) +#define PRICES_DDD (KOMODO_MAXPRICES * 8) bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); // CCcustom +UniValue PricesBet(uint64_t txfee,int64_t amount,int16_t leverage,std::vector synthetic); +UniValue PricesAddFunding(uint64_t txfee,uint256 bettxid,int64_t amount); +UniValue PricesSetcostbasis(uint64_t txfee,uint256 bettxid); +UniValue PricesRekt(uint64_t txfee,uint256 bettxid,int32_t rektheight); +UniValue PricesCashout(uint64_t txfee,uint256 bettxid); +UniValue PricesInfo(uint256 bettxid,int32_t refheight); UniValue PricesList(); -UniValue PricesInfo(uint256 fundingtxid); -UniValue PricesStatus(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid); -std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletxid,uint64_t margin,uint64_t mode,uint256 longtoken,uint256 shorttoken,int32_t maxleverage,int64_t funding,std::vector pubkeys); -std::string PricesAddFunding(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,int64_t amount); -std::string PricesBet(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,int64_t amount,int32_t leverage); -std::string PricesFinish(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,uint256 bettxid); #endif diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index e0c4c8ada..ae83e2661 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -732,6 +732,78 @@ UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr) return(result); } +UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr) +{ + // need to code: exclude list of tokenid, dust threshold, maxpayees, excluded pubkeys[] + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ); CTransaction tx; CPubKey Paymentspk,mypk; char markeraddr[64]; std::vector txidoprets; uint256 hashBlock; int32_t i,n,numoprets=0,lockedblocks,minrelease; std::string rawtx; int64_t totalallocations = 0; + cJSON *params = payments_reparse(&n,jsonstr); + if ( params != 0 && n >= 4 ) + { + lockedblocks = juint(jitem(params,0),0); + minrelease = juint(jitem(params,1),0); + if ( lockedblocks < 0 || minrelease < 0 ) + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","negative parameter")); + if ( params != 0 ) + free_json(params); + return(result); + } + for (i=0; i scriptPubKey,opret; int64_t allocation; + if ( myGetTransaction(txidoprets[i],tx,hashBlock) != 0 && tx.vout.size() > 1 && DecodePaymentsTxidOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,allocation,scriptPubKey,opret) == 'T' ) + { + totalallocations += allocation; + if ( opret.size() > 0 ) + numoprets++; + } + else + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","invalid txidopret")); + result.push_back(Pair("txid",txidoprets[i].GetHex())); + result.push_back(Pair("txi",(int64_t)i)); + if ( params != 0 ) + free_json(params); + return(result); + } + } + if ( numoprets > 1 ) + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","too many opreturns")); + result.push_back(Pair("numoprets",(int64_t)numoprets)); + if ( params != 0 ) + free_json(params); + return(result); + } + mypk = pubkey2pk(Mypubkey()); + Paymentspk = GetUnspendable(cp,0); + if ( AddNormalinputs(mtx,mypk,2*PAYMENTS_TXFEE,60) > 0 ) + { + mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,PAYMENTS_TXFEE,Paymentspk,Paymentspk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,EncodePaymentsOpRet(lockedblocks,minrelease,totalallocations,txidoprets)); + if ( params != 0 ) + free_json(params); + return(payments_rawtxresult(result,rawtx,1)); + } + result.push_back(Pair("result","error")); + result.push_back(Pair("error","not enough normal funds")); + } + else + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","parameters error")); + } + if ( params != 0 ) + free_json(params); + return(result); +} + UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr) { UniValue result(UniValue::VOBJ),a(UniValue::VARR); CTransaction tx,txO; CPubKey Paymentspk,txidpk; int32_t i,j,n,flag=0,numoprets=0,lockedblocks,minrelease; std::vector txidoprets; int64_t funds,fundsopret,totalallocations=0,allocation; char fundsaddr[64],fundsopretaddr[64],txidaddr[64],*outstr; uint256 createtxid,hashBlock; diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 1ab5aa1cb..cedf05f2b 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -17,123 +17,115 @@ #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. +CBOPRET creates trustless oracles, which can be used for making a synthetic cash settlement system based on real world prices; - We need to assume there is an oracle for a specific price. In the event there are more than one provider, the majority need to be within correlation distance to update a pricepoint. - - int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format); - - Using the above function, a consensus price can be obtained for a datasource. + 0.5% fee based on betamount, NOT leveraged betamount!! + 0.1% collected by price basis determinant + 0.2% collected by rekt tx - given an oracletxid, the marketaddr and format can be extracted to be used for future calls to OraclePrice. This allows to set a starting price and that in turn allows cash settled leveraged trading! + PricesBet -> +/-leverage, amount, synthetic -> opreturn includes current price + funds are locked into 1of2 global CC address + for first day, long basis is MAX(correlated,smoothed), short is MIN() + reference price is the smoothed of the previous block + if synthetic value + amount goes negative, then anybody can rekt it to collect a rektfee, proof of rekt must be included to show cost basis, rekt price + original creator can liquidate at anytime and collect (synthetic value + amount) from globalfund + 0.5% of bet -> globalfund + + PricesStatus -> bettxid maxsamples returns initial params, cost basis, amount left, rekt:true/false, rektheight, initial synthetic price, current synthetic price, net gain - Funds work like with dice, ie. there is a Prices plan that traders bet against. + PricesRekt -> bettxid height -> 0.1% to miner, rest to global CC - PricesFunding oracletxid, margin, priceaveraging, maxleverage, funding, longtoken, shorttoken, N [pubkeys] + PricesClose -> bettxid returns (synthetic value + amount) - PricesBet -> oracletxid start with 'L', leverage, funding, direction - funds are locked into global CC address - it can be closed at anytime by the trader for cash settlement - the house account can close it if rekt + PricesList -> all bettxid -> list [bettxid, netgain] - Implementation Notes: - In order to eliminate the need for worrying about sybil attacks, each prices plan would be able to specific pubkey(s?) for whitelisted publishers. It would be possible to have a non-whitelisted plan that would use 50% correlation between publishers. - - delta neutral balancing of riskexposure: fabs(long exposure - short exposure) - bet +B at leverage L - absval(sum(+BLi) - sum(-Bli)) - - validate: update riskexposure and it needs to be <= funds - - PricesProfits: limit withdraw to funds in excess of riskexposure - PricesFinish: payout (if winning) and update riskexposure - need long/short exposure assets - - funding -> 1of2 CC global CC address and dealer address, exposure tokens to global 1of2 assets CC address - pricebet -> user funds and exposure token to 1of2 address. - pricewin -> winnings from dealer funds, exposure token back to global address - priceloss -> exposuretoken back to global address - - exposure address, funds address - - */ // start of consensus code -int64_t PricesOraclePrice(int64_t &rektprice,uint64_t mode,uint256 oracletxid,std::vectorpubkeys,int32_t dir,int64_t amount,int32_t leverage) -{ - int64_t price; - // howto ensure price when block it confirms it not known - // get price from oracle + current chaintip - // normalize leveraged amount - if ( dir > 0 ) - rektprice = price * leverage / (leverage-1); - else rektprice = price * (leverage-1) / leverage; - return(price); -} - -CScript EncodePricesFundingOpRet(uint8_t funcid,CPubKey planpk,uint256 oracletxid,uint256 longtoken,uint256 shorttoken,int32_t millimargin,uint64_t mode,int32_t maxleverage,std::vector pubkeys,uint256 bettoken) +CScript prices_betopret(CPubKey mypk,int32_t height,int64_t amount,int16_t leverage,int64_t firstprice,std::vector vec,uint256 tokenid) { CScript opret; - fprintf(stderr,"implement EncodePricesFundingOpRet\n"); + opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'B' << mypk << height << amount << leverage << firstprice << vec << tokenid); return(opret); } -uint8_t DecodePricesFundingOpRet(CScript scriptPubKey,CPubKey &planpk,uint256 &oracletxid,uint256 &longtoken,uint256 &shorttoken,int32_t &millimargin,uint64_t &mode,int32_t &maxleverage,std::vector &pubkeys,uint256 &bettoken) +uint8_t prices_betopretdecode(CScript scriptPubKey,CPubKey &pk,int32_t &height,int64_t &amount,int16_t &leverage,int64_t &firstprice,std::vector &vec,uint256 &tokenid) { - fprintf(stderr,"implement DecodePricesFundingOpRet\n"); + std::vector vopret; uint8_t e,f; + GetOpReturnData(scriptPubKey,vopret); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> height; ss >> amount; ss >> leverage; ss >> firstprice; ss >> vec; ss >> tokenid) != 0 && e == EVAL_PRICES && f == 'B' ) + { + return(f); + } + return(0); +} + +CScript prices_addopret(uint256 bettxid,CPubKey mypk,int64_t amount) +{ + CScript opret; + opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'A' << bettxid << mypk << amount); + return(opret); +} + +uint8_t prices_addopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int64_t &amount) +{ + std::vector vopret; uint8_t e,f; + GetOpReturnData(scriptPubKey,vopret); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> bettxid; ss >> pk; ss >> amount) != 0 && e == EVAL_PRICES && f == 'A' ) + { + return(f); + } + return(0); +} + +CScript prices_costbasisopret(uint256 bettxid,CPubKey mypk,int32_t height,int64_t costbasis) +{ + CScript opret; + opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'C' << bettxid << mypk << height << costbasis); + return(opret); +} + +uint8_t prices_costbasisopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int32_t &height,int64_t &costbasis) +{ + std::vector vopret; uint8_t e,f; + GetOpReturnData(scriptPubKey,vopret); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> bettxid; ss >> pk; ss >> height; ss >> costbasis) != 0 && e == EVAL_PRICES && f == 'C' ) + { + return(f); + } + return(0); +} + +CScript prices_finalopret(uint256 bettxid,int64_t profits,int32_t height,CPubKey mypk,int64_t firstprice,int64_t costbasis,int64_t addedbets,int64_t positionsize,int16_t leverage) +{ + CScript opret; + opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'F' << bettxid << profits << height << mypk << firstprice << costbasis << addedbets << positionsize << leverage); + return(opret); +} + +uint8_t prices_finalopretdecode(CScript scriptPubKey,uint256 &bettxid,int64_t &profits,int32_t &height,CPubKey &pk,int64_t &firstprice,int64_t &costbasis,int64_t &addedbets,int64_t &positionsize,int16_t &leverage) +{ + std::vector vopret; uint8_t e,f; + GetOpReturnData(scriptPubKey,vopret); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> bettxid; ss >> profits; ss >> height; ss >> pk; ss >> firstprice; ss >> costbasis; ss >> addedbets; ss >> positionsize; ss >> leverage) != 0 && e == EVAL_PRICES && f == 'F' ) + { + return(f); + } return(0); } bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - - return true; // TODO remove, for test dual-evals - - return eval->Invalid("no validation yet"); - std::vector > txids; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - preventCCvins = preventCCvouts = -1; - if ( numvouts < 1 ) - return eval->Invalid("no vouts"); - else - { - for (i=0; iInvalid("illegal normal vini"); - } - } - //fprintf(stderr,"check amounts\n"); - //if ( PricesExactAmounts(cp,eval,tx,1,10000) == false ) - { - fprintf(stderr,"Pricesget invalid amount\n"); - return false; - } - //else - { - txid = tx.GetHash(); - memcpy(hash,&txid,sizeof(hash)); - retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); - if ( retval != 0 ) - fprintf(stderr,"Pricesget validated\n"); - else fprintf(stderr,"Pricesget invalid\n"); - return(retval); - } - } + return true; } // end of consensus code // helper functions for rpc calls in rpcwallet.cpp -int64_t AddTokensInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char *destaddr,uint256 tolenid,int64_t total,int32_t maxinputs) +int64_t AddPricesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char *destaddr,int64_t total,int32_t maxinputs,uint256 vintxid,int32_t vinvout) { - // add threshold check int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; SetCCunspents(unspentOutputs,destaddr); @@ -141,11 +133,11 @@ int64_t AddTokensInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char { txid = it->first.txhash; vout = (int32_t)it->first.index; - // need to prevent dup + if ( vout == vinvout && txid == vintxid ) + continue; if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && vout < vintx.vout.size() ) { - // need to verify assetid - if ( (nValue= vintx.vout[vout].nValue) >= 10000 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) + if ( (nValue= vintx.vout[vout].nValue) >= total/maxinputs && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) { if ( total != 0 && maxinputs != 0 ) mtx.vin.push_back(CTxIn(txid,vout,CScript())); @@ -160,9 +152,461 @@ int64_t AddTokensInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char return(totalinputs); } +UniValue prices_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag) +{ + CTransaction tx; + if ( rawtx.size() > 0 ) + { + result.push_back(Pair("hex",rawtx)); + if ( DecodeHexTx(tx,rawtx) != 0 ) + { + if ( broadcastflag != 0 && myAddtomempool(tx) != 0 ) + RelayTransaction(tx); + result.push_back(Pair("txid",tx.GetHash().ToString())); + result.push_back(Pair("result","success")); + } else result.push_back(Pair("error","decode hex")); + } else result.push_back(Pair("error","couldnt finalize CCtx")); + return(result); +} + +int32_t prices_syntheticvec(std::vector &vec,std::vector synthetic) +{ + int32_t i,need,ind,depth = 0; std::string opstr; uint16_t opcode,weight; + if ( synthetic.size() == 0 ) + return(-1); + for (i=0; i= 0 ) + opcode = ind, need = 0; + else if ( (weight= atoi(opstr.c_str())) > 0 && weight < KOMODO_MAXPRICES ) + { + opcode = PRICES_WEIGHT | weight; + need = 1; + } else return(-2); + if ( depth < need ) + return(-3); + depth -= need; + if ( (opcode & KOMODO_PRICEMASK) != PRICES_WEIGHT ) // weight + depth++; + if ( depth > 3 ) + return(-4); + vec.push_back(opcode); + } + if ( depth != 0 ) + { + fprintf(stderr,"depth.%d not empty\n",depth); + return(-5); + } + return(0); +} + +int64_t prices_syntheticprice(std::vector vec,int32_t height,int32_t minmax,int16_t leverage) +{ + int32_t i,ind,errcode,depth,retval = -1; uint16_t opcode; int64_t *pricedata,pricestack[4],price,den,a,b,c; + pricedata = (int64_t *)calloc(sizeof(*pricedata)*3,1 + PRICES_DAYWINDOW*2 + PRICES_SMOOTHWIDTH); + price = den = depth = errcode = 0; + for (i=0; i 0 ) + pricestack[depth] = (pricedata[1] > pricedata[2]) ? pricedata[1] : pricedata[2]; // MAX + else pricestack[depth] = (pricedata[1] < pricedata[2]) ? pricedata[1] : pricedata[2]; // MIN + } + } + if ( pricestack[depth] == 0 ) + errcode = -1; + depth++; + break; + case PRICES_WEIGHT: // multiply by weight and consume top of stack by updating price + if ( depth == 1 ) + { + depth--; + price += pricestack[0] * ind; + den += ind; + } else errcode = -2; + break; + case PRICES_MULT: + if ( depth >= 2 ) + { + b = pricestack[--depth]; + a = pricestack[--depth]; + pricestack[depth++] = (a * b) / SATOSHIDEN; + } else errcode = -3; + break; + case PRICES_DIV: + if ( depth >= 2 ) + { + b = pricestack[--depth]; + a = pricestack[--depth]; + pricestack[depth++] = (a * SATOSHIDEN) / b; + } else errcode = -4; + break; + case PRICES_INV: + if ( depth >= 1 ) + { + a = pricestack[--depth]; + pricestack[depth++] = (SATOSHIDEN * SATOSHIDEN) / a; + } else errcode = -5; + break; + case PRICES_MDD: + if ( depth >= 3 ) + { + c = pricestack[--depth]; + b = pricestack[--depth]; + a = pricestack[--depth]; + pricestack[depth++] = (((a * SATOSHIDEN) / b) * SATOSHIDEN) / c; + } else errcode = -6; + break; + case PRICES_MMD: + if ( depth >= 3 ) + { + c = pricestack[--depth]; + b = pricestack[--depth]; + a = pricestack[--depth]; + pricestack[depth++] = (a * b) / c; + } else errcode = -7; + break; + case PRICES_MMM: + if ( depth >= 3 ) + { + c = pricestack[--depth]; + b = pricestack[--depth]; + a = pricestack[--depth]; + pricestack[depth++] = ((a * b) / SATOSHIDEN) * c; + } else errcode = -8; + break; + case PRICES_DDD: + if ( depth >= 3 ) + { + c = pricestack[--depth]; + b = pricestack[--depth]; + a = pricestack[--depth]; + pricestack[depth++] = (((((SATOSHIDEN * SATOSHIDEN) / a) * SATOSHIDEN) / b) * SATOSHIDEN) / c; + } else errcode = -9; + break; + default: + errcode = -10; + break; + } + if ( errcode != 0 ) + break; + } + free(pricedata); + if ( den == 0 ) + return(-11); + else if ( depth != 0 ) + return(-12); + else if ( errcode != 0 ) + return(errcode); + return(price / den); +} + +int64_t prices_syntheticprofits(int64_t &costbasis,int32_t firstheight,int32_t height,int16_t leverage,std::vector vec,int64_t positionsize,int64_t addedbets) +{ + int64_t price,profits = 0; int32_t minmax; + minmax = (height > firstheight+PRICES_DAYWINDOW); + if ( (price= prices_syntheticprice(vec,height,minmax,leverage)) < 0 ) + { + fprintf(stderr,"unexpected zero synthetic price at height.%d\n",height); + return(0); + } + if ( minmax != 0 ) + { + if ( leverage > 0 && price > costbasis ) + costbasis = price; + else if ( leverage < 0 && (costbasis == 0 || price < costbasis) ) + costbasis = price; + } + profits = ((price * SATOSHIDEN) / costbasis) - SATOSHIDEN; + profits *= leverage * positionsize; + return(positionsize + addedbets + profits); +} + +void prices_betjson(UniValue &result,int64_t profits,int64_t costbasis,int64_t positionsize,int64_t addedbets,int16_t leverage,int32_t firstheight,int64_t firstprice) +{ + result.push_back(Pair("profits",ValueFromAmount(profits))); + result.push_back(Pair("costbasis",ValueFromAmount(costbasis))); + result.push_back(Pair("positionsize",ValueFromAmount(positionsize))); + result.push_back(Pair("addedbets",ValueFromAmount(addedbets))); + result.push_back(Pair("leverage",(int64_t)leverage)); + result.push_back(Pair("firstheight",(int64_t)firstheight)); + result.push_back(Pair("firstprice",ValueFromAmount(firstprice))); +} + +int64_t prices_costbasis(CTransaction bettx) +{ + int64_t costbasis = 0; + // if vout1 is spent, follow and extract costbasis from opreturn + //uint8_t prices_costbasisopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int32_t &height,int64_t &costbasis) + + return(costbasis); +} + +int64_t prices_batontxid(uint256 &batontxid,CTransaction bettx,uint256 bettxid) +{ + int64_t addedbets = 0; + // iterate through batons, adding up vout1 -> addedbets + return(addedbets); +} + +UniValue PricesBet(uint64_t txfee,int64_t amount,int16_t leverage,std::vector synthetic) +{ + int32_t nextheight = komodo_nextheight(); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight); UniValue result(UniValue::VOBJ); + struct CCcontract_info *cp,C; CPubKey pricespk,mypk; int64_t betamount,firstprice; std::vector vec; char myaddr[64]; std::string rawtx; + if ( leverage > PRICES_MAXLEVERAGE || leverage < -PRICES_MAXLEVERAGE ) + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","leverage too big")); + return(result); + } + cp = CCinit(&C,EVAL_PRICES); + if ( txfee == 0 ) + txfee = PRICES_TXFEE; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + GetCCaddress(cp,myaddr,mypk); + if ( prices_syntheticvec(vec,synthetic) < 0 || (firstprice= prices_syntheticprice(vec,nextheight-1,1,leverage)) < 0 || vec.size() == 0 || vec.size() > 4096 ) + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","invalid synthetic")); + return(result); + } + if ( AddNormalinputs(mtx,mypk,amount+4*txfee,64) >= amount+4*txfee ) + { + betamount = (amount * 199) / 200; + mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk)); // baton for total funding + mtx.vout.push_back(MakeCC1vout(cp->evalcode,(amount-betamount)+2*txfee,pricespk)); + mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,betamount,pricespk,mypk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,prices_betopret(mypk,nextheight-1,amount,leverage,firstprice,vec,zeroid)); + return(prices_rawtxresult(result,rawtx,0)); + } + result.push_back(Pair("result","error")); + result.push_back(Pair("error","not enough funds")); + return(result); +} + +UniValue PricesAddFunding(uint64_t txfee,uint256 bettxid,int64_t amount) +{ + int32_t nextheight = komodo_nextheight(); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight); UniValue result(UniValue::VOBJ); + struct CCcontract_info *cp,C; CTransaction bettx; CPubKey pricespk,mypk; int64_t addedbets=0,betamount,firstprice; std::vector vec; uint256 batontxid; std::string rawtx; char myaddr[64]; + cp = CCinit(&C,EVAL_PRICES); + if ( txfee == 0 ) + txfee = PRICES_TXFEE; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + GetCCaddress(cp,myaddr,mypk); + if ( AddNormalinputs(mtx,mypk,amount+txfee,64) >= amount+txfee ) + { + if ( prices_batontxid(batontxid,bettx,bettxid) >= 0 ) + { + mtx.vin.push_back(CTxIn(batontxid,0,CScript())); + mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk)); // baton for total funding + mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,pricespk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,prices_addopret(bettxid,mypk,amount)); + return(prices_rawtxresult(result,rawtx,0)); + } + else + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","couldnt find batonttxid")); + return(result); + } + } + result.push_back(Pair("result","error")); + result.push_back(Pair("error","not enough funds")); + return(result); +} + +UniValue PricesSetcostbasis(uint64_t txfee,uint256 bettxid) +{ + int32_t nextheight = komodo_nextheight(); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight); UniValue result(UniValue::VOBJ); + struct CCcontract_info *cp,C; CTransaction bettx; uint256 hashBlock,batontxid,tokenid; int64_t myfee,positionsize=0,addedbets,firstprice=0,profits=0,costbasis=0; int32_t i,firstheight=0,height,numvouts; int16_t leverage=0; std::vector vec; CPubKey pk,mypk,pricespk; std::string rawtx; + cp = CCinit(&C,EVAL_PRICES); + if ( txfee == 0 ) + txfee = PRICES_TXFEE; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + if ( myGetTransaction(bettxid,bettx,hashBlock) != 0 && (numvouts= bettx.vout.size()) > 3 ) + { + if ( prices_betopretdecode(bettx.vout[numvouts-1].scriptPubKey,pk,firstheight,positionsize,leverage,firstprice,vec,tokenid) == 'B' ) + { + addedbets = prices_batontxid(batontxid,bettx,bettxid); + mtx.vin.push_back(CTxIn(bettxid,1,CScript())); + for (i=0; ievalcode,bettx.vout[1].nValue-myfee-txfee,pricespk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,prices_costbasisopret(bettxid,mypk,firstheight+PRICES_DAYWINDOW-1,costbasis)); + return(prices_rawtxresult(result,rawtx,0)); + } + } + result.push_back(Pair("result","error")); + result.push_back(Pair("error","cant find bettxid")); + return(result); +} + +UniValue PricesRekt(uint64_t txfee,uint256 bettxid,int32_t rektheight) +{ + int32_t nextheight = komodo_nextheight(); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight); UniValue result(UniValue::VOBJ); + struct CCcontract_info *cp,C; CTransaction bettx; uint256 hashBlock,tokenid,batontxid; int64_t myfee=0,positionsize,addedbets,firstprice,profits,ignore,costbasis=0; int32_t firstheight,numvouts; int16_t leverage; std::vector vec; CPubKey pk,mypk,pricespk; std::string rawtx; + cp = CCinit(&C,EVAL_PRICES); + if ( txfee == 0 ) + txfee = PRICES_TXFEE; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + if ( myGetTransaction(bettxid,bettx,hashBlock) != 0 && (numvouts= bettx.vout.size()) > 3 ) + { + if ( prices_betopretdecode(bettx.vout[numvouts-1].scriptPubKey,pk,firstheight,positionsize,leverage,firstprice,vec,tokenid) == 'B' ) + { + costbasis = prices_costbasis(bettx); + addedbets = prices_batontxid(batontxid,bettx,bettxid); + if ( (profits= prices_syntheticprofits(ignore,firstheight,rektheight,leverage,vec,positionsize,addedbets)) < 0 ) + { + myfee = (positionsize + addedbets) / 500; + } + prices_betjson(result,profits,costbasis,positionsize,addedbets,leverage,firstheight,firstprice); + if ( myfee != 0 ) + { + mtx.vin.push_back(CTxIn(bettxid,2,CScript())); + mtx.vout.push_back(CTxOut(myfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + mtx.vout.push_back(MakeCC1vout(cp->evalcode,bettx.vout[2].nValue-myfee-txfee,pricespk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,prices_finalopret(bettxid,profits,rektheight,mypk,firstprice,costbasis,addedbets,positionsize,leverage)); + return(prices_rawtxresult(result,rawtx,0)); + } + else + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","position not rekt")); + return(result); + } + } + else + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","cant decode opret")); + return(result); + } + } + result.push_back(Pair("result","error")); + result.push_back(Pair("error","cant find bettxid")); + return(result); +} + +UniValue PricesCashout(uint64_t txfee,uint256 bettxid) +{ + int32_t nextheight = komodo_nextheight(); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight); UniValue result(UniValue::VOBJ); + struct CCcontract_info *cp,C; char destaddr[64]; CTransaction bettx; uint256 hashBlock,batontxid,tokenid; int64_t CCchange=0,positionsize,inputsum,ignore,addedbets,firstprice,profits,costbasis=0; int32_t i,firstheight,height,numvouts; int16_t leverage; std::vector vec; CPubKey pk,mypk,pricespk; std::string rawtx; + cp = CCinit(&C,EVAL_PRICES); + if ( txfee == 0 ) + txfee = PRICES_TXFEE; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + GetCCaddress(cp,destaddr,pricespk); + if ( myGetTransaction(bettxid,bettx,hashBlock) != 0 && (numvouts= bettx.vout.size()) > 3 ) + { + if ( prices_betopretdecode(bettx.vout[numvouts-1].scriptPubKey,pk,firstheight,positionsize,leverage,firstprice,vec,tokenid) == 'B' ) + { + costbasis = prices_costbasis(bettx); + addedbets = prices_batontxid(batontxid,bettx,bettxid); + if ( (profits= prices_syntheticprofits(ignore,firstheight,nextheight-1,leverage,vec,positionsize,addedbets)) < 0 ) + { + prices_betjson(result,profits,costbasis,positionsize,addedbets,leverage,firstheight,firstprice); + result.push_back(Pair("result","error")); + result.push_back(Pair("error","position rekt")); + return(result); + } + prices_betjson(result,profits,costbasis,positionsize,addedbets,leverage,firstheight,firstprice); + mtx.vin.push_back(CTxIn(bettxid,2,CScript())); + if ( (inputsum= AddPricesInputs(cp,mtx,destaddr,profits+txfee,64,bettxid,2)) > profits+txfee ) + CCchange = (inputsum - profits); + mtx.vout.push_back(CTxOut(bettx.vout[2].nValue + profits,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + if ( CCchange >= txfee ) + mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,pricespk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,prices_finalopret(bettxid,profits,nextheight-1,mypk,firstprice,costbasis,addedbets,positionsize,leverage)); + return(prices_rawtxresult(result,rawtx,0)); + } + else + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","cant decode opret")); + return(result); + } + } + return(result); +} + +UniValue PricesInfo(uint256 bettxid,int32_t refheight) +{ + UniValue result(UniValue::VOBJ); CTransaction bettx; uint256 hashBlock,batontxid,tokenid; int64_t myfee,ignore,positionsize=0,addedbets=0,firstprice=0,profits=0,costbasis=0; int32_t i,firstheight=0,height,numvouts; int16_t leverage=0; std::vector vec; CPubKey pk,mypk,pricespk; std::string rawtx; + if ( myGetTransaction(bettxid,bettx,hashBlock) != 0 && (numvouts= bettx.vout.size()) > 3 ) + { + if ( prices_betopretdecode(bettx.vout[numvouts-1].scriptPubKey,pk,firstheight,positionsize,leverage,firstprice,vec,tokenid) == 'B' ) + { + costbasis = prices_costbasis(bettx); + addedbets = prices_batontxid(batontxid,bettx,bettxid); + if ( (profits= prices_syntheticprofits(ignore,firstheight,refheight,leverage,vec,positionsize,addedbets)) < 0 ) + { + result.push_back(Pair("rekt",1)); + result.push_back(Pair("rektfee",(positionsize + addedbets) / 500)); + } else result.push_back(Pair("rekt",0)); + result.push_back(Pair("batontxid",batontxid.GetHex())); + prices_betjson(result,profits,costbasis,positionsize,addedbets,leverage,firstheight,firstprice); + result.push_back(Pair("height",(int64_t)refheight)); + return(result); + } + } + result.push_back(Pair("result","error")); + result.push_back(Pair("error","cant find bettxid")); + return(result); +} + UniValue PricesList() { - UniValue result(UniValue::VARR); std::vector > addressIndex; struct CCcontract_info *cp,C; uint64_t mode; int32_t margin,maxleverage; std::vectorpubkeys; uint256 txid,hashBlock,oracletxid,longtoken,shorttoken,bettoken; CPubKey planpk,pricespk; char str[65]; CTransaction vintx; + UniValue result(UniValue::VARR); std::vector > addressIndex; struct CCcontract_info *cp,C; int64_t amount,firstprice; int32_t height; int16_t leverage; uint256 txid,hashBlock,tokenid; CPubKey pk,pricespk; std::vector vec; CTransaction vintx; char str[65]; cp = CCinit(&C,EVAL_PRICES); pricespk = GetUnspendable(cp,0); SetCCtxids(addressIndex,cp->normaladdr); @@ -171,7 +615,7 @@ UniValue PricesList() txid = it->first.txhash; if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { - if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' ) + if ( vintx.vout.size() > 0 && prices_betopretdecode(vintx.vout[vintx.vout.size()-1].scriptPubKey,pk,height,amount,leverage,firstprice,vec,tokenid) == 'B' ) { result.push_back(uint256_str(str,txid)); } @@ -180,274 +624,4 @@ UniValue PricesList() return(result); } -// longtoken satoshis limits long exposure -// shorttoken satoshis limits short exposure -// both must be in the 1of2 CC address with its total supply -// bettoken -std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletxid,uint64_t margin,uint64_t mode,uint256 longtoken,uint256 shorttoken,int32_t maxleverage,int64_t funding,std::vector pubkeys) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction oracletx; int64_t fullsupply,inputs,CCchange=0; uint256 hashBlock; char str[65],coinaddr[64],houseaddr[64]; CPubKey mypk,pricespk; int32_t i,N,numvouts; struct CCcontract_info *cp,C; - if ( funding < 100*COIN || maxleverage <= 0 || maxleverage > 10000 ) - { - CCerror = "invalid parameter error"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - return(""); - } - cp = CCinit(&C,EVAL_PRICES); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp,0); - if ( (N= (int32_t)pubkeys.size()) || N > 15 ) - { - fprintf(stderr,"too many pubkeys N.%d\n",N); - return(""); - } - for (i=0; i 0 ) - { - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(pricespk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesFundingOpRet('F',mypk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken))); - } - else - { - CCerror = "cant find enough inputs"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - } - return(""); -} - -UniValue PricesInfo(uint256 fundingtxid) -{ - UniValue result(UniValue::VOBJ),a(UniValue::VARR); CPubKey pricespk,planpk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction vintx; int64_t balance,supply,exposure; uint64_t funding,mode; int32_t i,margin,maxleverage; char numstr[65],houseaddr[64],exposureaddr[64],str[65]; std::vectorpubkeys; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_PRICES); - pricespk = GetUnspendable(cp,0); - if ( GetTransaction(fundingtxid,vintx,hashBlock,false) == 0 ) - { - fprintf(stderr,"cant find fundingtxid\n"); - ERR_RESULT("cant find fundingtxid"); - return(result); - } - if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' ) - { - result.push_back(Pair("result","success")); - result.push_back(Pair("fundingtxid",uint256_str(str,fundingtxid))); - result.push_back(Pair("bettoken",uint256_str(str,bettoken))); - result.push_back(Pair("oracletxid",uint256_str(str,oracletxid))); - sprintf(numstr,"%.3f",(double)margin/1000); - result.push_back(Pair("profitmargin",numstr)); - result.push_back(Pair("maxleverage",maxleverage)); - result.push_back(Pair("mode",(int64_t)mode)); - for (i=0; ipubkeys; - if ( amount < 10000 ) - { - CCerror = "amount must be positive"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - return(""); - } - cp = CCinit(&C,EVAL_PRICES); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp,0); - GetCCaddress(cp,myaddr,mypk); - if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 ) - { - fprintf(stderr,"cant find fundingtxid\n"); - return(""); - } - if ( tx.vout.size() > 0 && DecodePricesFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' && bettoken == refbettoken ) - { - GetCCaddress1of2(cp,houseaddr,pricespk,planpk); - if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) - { - if ( (inputs= AddTokensInputs(cp,mtx,myaddr,bettoken,amount,60)) >= amount ) - { - mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,amount,pricespk,planpk)); - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(planpk)) << OP_CHECKSIG)); - if ( inputs > amount+txfee ) - CCchange = (inputs - amount); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,mypk)); - // add addr2 - - std::vector voutTokenPubkeysEmpty; //TODO: add token vout pubkeys - return(FinalizeCCTx(0,cp,mtx,mypk,txfee, - EncodeTokenOpRet(bettoken, voutTokenPubkeysEmpty, - std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('t',/*bettoken,*/zeroid, 0, Mypubkey()))))); - } - else - { - CCerror = "cant find enough bet inputs"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - } - } - else - { - CCerror = "cant find enough inputs"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - } - } - return(""); -} - -std::string PricesBet(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount,int32_t leverage) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,tokenid,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,inputs2,longexposure,netexposure,shortexposure,CCchange = 0,CCchange2 = 0; uint64_t funding,mode; int32_t dir,margin,maxleverage; char houseaddr[64],myaddr[64],exposureaddr[64]; std::vectorpubkeys; - if ( amount < 0 ) - { - amount = -amount; - dir = -1; - } else dir = 1; - cp = CCinit(&C,EVAL_PRICES); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp,0); - GetCCaddress(cp,myaddr,mypk); - if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 ) - { - fprintf(stderr,"cant find fundingtxid\n"); - return(""); - } - if ( tx.vout.size() > 0 && DecodePricesFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' && bettoken == refbettoken ) - { - if ( leverage > maxleverage || leverage < 1 ) - { - fprintf(stderr,"illegal leverage\n"); - return(""); - } - GetCCaddress1of2(cp,houseaddr,pricespk,planpk); - GetCCaddress1of2(cp,exposureaddr,pricespk,pricespk); - if ( dir < 0 ) - tokenid = shorttoken; - else tokenid = longtoken; - exposure = leverage * amount; - longexposure = CCtoken_balance(exposureaddr,longtoken); - shortexposure = CCtoken_balance(exposureaddr,shorttoken); - netexposure = (longexposure - shortexposure + exposure*dir); - if ( netexposure < 0 ) - netexposure = -netexposure; - balance = CCtoken_balance(myaddr,bettoken) / COIN; - if ( balance < netexposure*9/10 ) // 10% extra room for dynamically closed bets in wrong direction - { - fprintf(stderr,"balance %lld < 90%% netexposure %lld, refuse bet\n",(long long)balance,(long long)netexposure); - return(""); - } - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) - { - if ( (inputs= AddTokensInputs(cp,mtx,houseaddr,tokenid,exposure,30)) >= exposure ) - { - if ( (inputs2= AddTokensInputs(cp,mtx,myaddr,bettoken,amount,30)) >= amount ) - { - mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,amount,pricespk,planpk)); - mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,exposure,pricespk,pricespk)); - if ( inputs > exposure+txfee ) - CCchange = (inputs - exposure); - if ( inputs2 > amount+txfee ) - CCchange2 = (inputs2 - amount); - mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,CCchange,pricespk,planpk)); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange2,mypk)); - // add addr2 and addr3 - //return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesExtra('T',tokenid,bettoken,zeroid,dir*leverage))); - CScript opret; - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); - } - else - { - fprintf(stderr,"cant find enough bettoken inputs\n"); - return(""); - } - } - else - { - fprintf(stderr,"cant find enough exposure inputs\n"); - return(""); - } - } - else - { - CCerror = "cant find enough inputsB"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - } - } - return(""); -} - -UniValue PricesStatus(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid) -{ - UniValue result(UniValue::VOBJ); - // get height of bettxid - // get price and rekt - // get current height and price - // what about if rekt in the past? - return(result); -} - -std::string PricesFinish(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid) -{ - return(""); -} - diff --git a/src/komodo_defs.h b/src/komodo_defs.h index c1eeb375b..49aa67081 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -37,6 +37,7 @@ #define KOMODO_MAXNVALUE (((uint64_t)1 << 63) - 1) #define KOMODO_BIT63SET(x) ((x) & ((uint64_t)1 << 63)) #define KOMODO_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN) +#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; int32_t MAX_BLOCK_SIZE(int32_t height); @@ -83,5 +84,6 @@ int tx_height( const uint256 &hash ); extern char NOTARYADDRS[64][36]; extern uint8_t NUM_NOTARIES; void komodo_netevent(std::vector payload); +int32_t komodo_priceind(char *symbol); #endif diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index e42b8aa4b..f7f7874ce 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1552,27 +1552,25 @@ extern std::vector Mineropret; // opreturn data set by the data gatheri #define PRICES_MAXCHANGE (COIN / 100) // maximum acceptable change, set at 1% #define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR #define KOMODO_LOCALPRICE_CACHESIZE 7 +#define KOMODO_MAXPRICES 2048 #define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) -const char *Cryptos[] = { "KMD", "ETH", "LTC", "BCHABC", "XMR", "IOTA", "DASH", "XEM", "ZEC", "WAVES", "RVN", "LSK", "DCR", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" }; // must be on binance (for now) - +const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) +// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" const char *Forex[] = { "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" }; // must be in ECB list -uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; +uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; +int64_t PriceMult[KOMODO_MAXPRICES]; int32_t komodo_cbopretsize(uint64_t flags); void komodo_PriceCache_shift() { int32_t i; for (i=KOMODO_LOCALPRICE_CACHESIZE-1; i>0; i--) - { memcpy(PriceCache[i],PriceCache[i-1],sizeof(PriceCache[i])); - //for (j=0; j<4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex); j++) - // PriceCache[i][j] = PriceCache[i-1][j]; - } memcpy(PriceCache[0],Mineropret.data(),Mineropret.size()); } @@ -1657,7 +1655,7 @@ int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *price // komodo_priceclamp() clamps any price that is beyond tolerance int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance) { - int32_t i; uint32_t newprice; char maxflags[2048]; + int32_t i; uint32_t newprice; char maxflags[KOMODO_MAXPRICES]; memset(maxflags,0,sizeof(maxflags)); for (i=1; i= PRICES_SIZEBIT0 ) { n = (int32_t)(Mineropret.size() / sizeof(uint32_t)); @@ -1727,13 +1725,11 @@ CScript komodo_mineropret(int32_t nHeight) // reconsiderblock 0034cf582018eacc0b4ae001491ce460113514cb1a3f217567ef4a2207de361a // reconsiderbloc 000abf51c023b64af327c50c1b060797b8cb281c696d30ab92fd002a8b8c9aea // are needed to sync past initial blocks with different data set -// pass in blockhash and nTime, latch if it is rejected due to local price, then if localprice changes in a way that would validate then issue reconsiderblock -// add rpc call for extracting rawprices int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey) { int32_t testchain_exemption = 350; - std::vector vopret; char maxflags[2048]; double btcusd,btcgbp,btceur; uint32_t localbits[2048],pricebits[2048],prevbits[2048],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now = (uint32_t)time(NULL); + std::vector vopret; char maxflags[KOMODO_MAXPRICES]; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now = (uint32_t)time(NULL); if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) { GetOpReturnData(scriptPubKey,vopret); @@ -1753,7 +1749,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i fprintf(stderr,"A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); return(-1); } - if ( lag2 < -testchain_exemption ) // must be close to last block timestamp + if ( lag2 < -60 ) //testchain_exemption ) // must be close to last block timestamp { fprintf(stderr,"B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3,ASSETCHAINS_BLOCKTIME,lag2<-ASSETCHAINS_BLOCKTIME); if ( nHeight > testchain_exemption ) @@ -2028,14 +2024,17 @@ uint32_t get_binanceprice(const char *symbol) return(price); } -int32_t get_cryptoprices(uint32_t *prices,const char *list[],int32_t n) +int32_t get_cryptoprices(uint32_t *prices,const char *list[],int32_t n,std::vector strvec) { - int32_t i,errs=0; uint32_t price; - for (i=0; i 333 ) // for debug only! flags |= 2; memcpy(&PriceCache[0][size/sizeof(uint32_t)],forexprices,sizeof(forexprices)); } - size += sizeof(forexprices); + size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t); } if ( (ASSETCHAINS_CBOPRET & 4) != 0 ) { if ( forceflag != 0 || flags != 0 ) { - get_cryptoprices(cryptoprices,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos))); + get_cryptoprices(cryptoprices,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)),ASSETCHAINS_PRICES); if ( flags == 0 ) komodo_PriceCache_shift(); - memcpy(&PriceCache[0][size/sizeof(uint32_t)],cryptoprices,sizeof(cryptoprices)); + memcpy(&PriceCache[0][size/sizeof(uint32_t)],cryptoprices,(sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t)); flags |= 4; // very rarely we can see flags == 6 case } - size += sizeof(cryptoprices); + size += (sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t); } if ( flags != 0 ) { @@ -2184,6 +2182,9 @@ if ( komodo_nextheight() > 333 ) // for debug only! if ( (flags & 4) != 0 ) lastcrypto = now; memcpy(Mineropret.data(),PriceCache[0],size); + // high volatility still strands nodes so we need to check new prices to approve a stuck block + // scan list of stuck blocks (one?) and auto reconsiderblock if it changed state + //int32_t i; for (i=0; i 333 ) // for debug only! pending = 0; } +int64_t komodo_pricemult(int32_t ind) +{ + int32_t i,j; + if ( (ASSETCHAINS_CBOPRET & 1) != 0 && ind < KOMODO_MAXPRICES ) + { + if ( PriceMult[0] == 0 ) + { + for (i=0; i<4; i++) + PriceMult[i] = 10000; + if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) + { + for (j=0; j= KOMODO_MAXPRICES ) return(-1); - if ( ind < 36 ) - mult = 10000; - else mult = 1; - memset(nonzprices,0,sizeof(*nonzprices)*daywindow); - for (iter=0; iter= daywindow ) + if ( i >= PRICES_DAYWINDOW ) i = 0; - if ( (price= rawprices[i]) == 0 ) + if ( (price= rawprices[i*rawskip]) == 0 ) { fprintf(stderr,"null rawprice.[%d]\n",i); return(-1); @@ -2288,28 +2331,29 @@ int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int //fprintf(stderr,"%.1f ",(double)price/10000); sum += price; correlation++; - if ( correlation > (daywindow>>1) ) + if ( correlation > (PRICES_DAYWINDOW>>1) ) { - return(refprice * mult); + if ( nonzprices == 0 ) + return(refprice * mult); //fprintf(stderr,"-> %.4f\n",(double)sum*mult/correlation); //return(sum*mult/correlation); n = 0; - i = (iter + seed) % daywindow; - for (k=0; k= daywindow ) + if ( i >= PRICES_DAYWINDOW ) i = 0; - if ( n > (daywindow>>1) ) + if ( n > (PRICES_DAYWINDOW>>1) ) nonzprices[i] = 0; else { - price = rawprices[i]; + price = rawprices[i*rawskip]; if ( price < lowprice || price > highprice ) nonzprices[i] = 0; else { nonzprices[i] = price; - //fprintf(stderr,"(%d %u) ",i,rawprices[i]); + //fprintf(stderr,"(%d %u) ",i,rawprices[i*rawskip]); n++; } } @@ -2318,17 +2362,17 @@ int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int if ( n != correlation ) return(-1); sum = den = n = 0; - for (i=0; i %.4f\n",(double)(smoothedsum/smoothedden)/10000); - return(smoothedsum/smoothedden); + if ( (price= correlated[i*cskip]) != 0 ) + nonzprice = price; + //correlated2[i] = nonzprice / PRICES_DAYWINDOW; // reduce precision + sum += nonzprice; } - return(0); + price = sum / PRICES_DAYWINDOW; + // improve smoothing with correlated2 processing + // price = smooth(correlated2,PRICES_DAYWINDOW,price/daywindow) * PRICES_DAYWINDOW; + return(price); } diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 0d8b2ed63..2d0fe4f4e 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1665,12 +1665,12 @@ uint64_t komodo_ac_block_subsidy(int nHeight) extern int64_t MAX_MONEY; void komodo_cbopretupdate(int32_t forceflag); -void SplitStr(const std::string& strVal, std::vector outVals); +void SplitStr(const std::string& strVal, std::vector &outVals); void komodo_args(char *argv0) { extern const char *Notaries_elected1[][2]; - std::string name,addn,hexstr; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256]; + std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256]; IS_KOMODO_NOTARY = GetBoolArg("-notary", false); IS_STAKED_NOTARY = GetArg("-stakednotary", -1); if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) { @@ -1735,7 +1735,7 @@ void komodo_args(char *argv0) { printf("KOMODO_REWIND %d\n",KOMODO_REWIND); } - if ( name.c_str()[0] != 0 ) + if ( name.c_str()[0] != 0 ) { std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0])); @@ -2075,6 +2075,15 @@ void komodo_args(char *argv0) if ( ASSETCHAINS_CBOPRET != 0 ) { extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_CBOPRET),(void *)&ASSETCHAINS_CBOPRET); + if ( ASSETCHAINS_PRICES.size() != 0 ) + { + for (i=0; i2*daywindow+2+smoothwidth; i++,ht--) + //prices2 = (uint32_t *)calloc(sizeof(*prices2),width); + i = 0; + for (ht=nextheight-1,i=0; i2; i++,ht--) { if ( ht < 0 || ht > chainActive.Height() ) throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); @@ -1224,13 +1265,14 @@ UniValue prices(const UniValue& params, bool fHelp) } else throw JSONRPCError(RPC_INVALID_PARAMETER, "no komodo_rawprices found"); } } + numsamples = i; ret.push_back(Pair("firstheight", (int64_t)nextheight-1-i)); UniValue timestamps(UniValue::VARR); for (i=0; i= width ) { - offset = j*width + i; - rngval = (rngval*11109 + 13849); - if ( (correlated[i]= komodo_pricecorrelated(rngval,j,&prices[offset],daywindow,prices2,smoothwidth)) < 0 ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "null correlated price"); + for (i=0; i ignoredMap = { \ + {"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1}, \ + {"RMUF3UDmzWFLSKV82iFbMaqzJpUnrWjcT4", 1}, \ + {"RA5imhVyJa7yHhggmBytWuDr923j2P1bxx", 1}, \ + {"RBM5LofZFodMeewUzoMWcxedm3L3hYRaWg", 1}, \ + {"RAdcko2d94TQUcJhtFHZZjMyWBKEVfgn4J", 1}, \ + {"RLzUaZ934k2EFCsAiVjrJqM8uU1vmMRFzk", 1}, \ + {"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1}, \ + {"RUDrX1v5toCsJMUgtvBmScKjwCB5NaR8py", 1}, \ + {"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1}, \ + {"RRvwmbkxR5YRzPGL5kMFHMe1AH33MeD8rN", 1}, \ + {"RQLQvSgpPAJNPgnpc8MrYsbBhep95nCS8L", 1}, \ + {"RK8JtBV78HdvEPvtV5ckeMPSTojZPzHUTe", 1}, \ + {"RHVs2KaCTGUMNv3cyWiG1jkEvZjigbCnD2", 1}, \ + {"RE3SVaDgdjkRPYA6TRobbthsfCmxQedVgF", 1}, \ + {"RW6S5Lw5ZCCvDyq4QV9vVy7jDHfnynr5mn", 1}, \ + {"RTkJwAYtdXXhVsS3JXBAJPnKaBfMDEswF8", 1}, \ + {"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} \ +}; + +int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold,int32_t top,std::vector > &vaddr) +{ + int64_t total = 0; int64_t totalAddresses = 0; std::string address; + int64_t utxos = 0; int64_t ignoredAddresses = 0; + DECLARE_IGNORELIST + boost::scoped_ptr iter(NewIterator()); + std::map addressAmounts; + for (iter->SeekToLast(); iter->Valid(); iter->Prev()) + { + boost::this_thread::interruption_point(); + try + { + std::vector slKey = std::vector(); + pair keyObj; + iter->GetKey(keyObj); + char chType = keyObj.first; + CAddressIndexIteratorKey indexKey = keyObj.second; + //fprintf(stderr, "chType=%d\n", chType); + if (chType == DB_ADDRESSUNSPENTINDEX) + { + try { + CAmount nValue; + iter->GetValue(nValue); + getAddressFromIndex(indexKey.type, indexKey.hashBytes, address); + if ( nValue > dustthreshold ) + { + std::map ::iterator ignored = ignoredMap.find(address); + if (ignored != ignoredMap.end()) + { + fprintf(stderr,"ignoring %s\n", address.c_str()); + ignoredAddresses++; + continue; + } + std::map ::iterator pos = addressAmounts.find(address); + if ( pos == addressAmounts.end() ) + { + // insert new address + utxo amount + //fprintf(stderr, "inserting new address %s with amount %li\n", address.c_str(), nValue); + addressAmounts[address] = nValue; + totalAddresses++; + } + else + { + // update unspent tally for this address + //fprintf(stderr, "updating address %s with new utxo amount %li\n", address.c_str(), nValue); + addressAmounts[address] += nValue; + } + //fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN); + // total += nValue; + utxos++; + } else fprintf(stderr,"ignoring amount=0 UTXO for %s\n", address.c_str()); + } + catch (const std::exception& e) + { + fprintf(stderr, "DONE %s: LevelDB addressindex exception! - %s\n", __func__, e.what()); + break; + } + } + } + catch (const std::exception& e) + { + fprintf(stderr, "DONE reading index entries\n"); + break; + } + } + fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses); + for (std::pair element : addressAmounts) + vaddr.push_back( make_pair(element.second, element.first) ); + std::sort(vaddr.rbegin(), vaddr.rend()); + int topN = 0; + for (std::vector>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) + { + //obj.push_back( make_pair("addr", it->second.c_str() ) ); + //char amount[32]; + //sprintf(amount, "%.8f", (double) it->first / COIN); + //obj.push_back( make_pair("amount", amount) ); + //obj.push_back( make_pair("segid",(int32_t)komodo_segid32((char *)it->second.c_str()) & 0x3f) ); + //addressesSorted.push_back(obj); + total += it->first; + topN++; + // If requested, only show top N addresses in output JSON + if ( top == topN ) + break; + } + return(topN); +} + UniValue CBlockTreeDB::Snapshot(int top) { int64_t total = 0; int64_t totalAddresses = 0; std::string address; int64_t utxos = 0; int64_t ignoredAddresses = 0; + DECLARE_IGNORELIST boost::scoped_ptr iter(NewIterator()); std::map addressAmounts; std::vector > vaddr; UniValue result(UniValue::VOBJ); result.push_back(Pair("start_time", (int) time(NULL))); - std::map ignoredMap = { + /* std::map ignoredMap = { {"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1}, {"RMUF3UDmzWFLSKV82iFbMaqzJpUnrWjcT4", 1}, {"RA5imhVyJa7yHhggmBytWuDr923j2P1bxx", 1}, @@ -466,7 +574,7 @@ UniValue CBlockTreeDB::Snapshot(int top) {"RW6S5Lw5ZCCvDyq4QV9vVy7jDHfnynr5mn", 1}, {"RTkJwAYtdXXhVsS3JXBAJPnKaBfMDEswF8", 1}, {"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} //Burnaddress for null privkey - }; + };*/ int64_t startingHeight = chainActive.Height(); //fprintf(stderr, "Starting snapshot at height %lli\n", startingHeight); diff --git a/src/txdb.h b/src/txdb.h index b9bae2fe4..9b80b922b 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -116,6 +116,7 @@ public: bool LoadBlockIndexGuts(); bool blockOnchainActive(const uint256 &hash); UniValue Snapshot(int top); + int32_t Snapshot2(int64_t dustthreshold,int32_t top,std::vector > &vaddr); }; #endif // BITCOIN_TXDB_H diff --git a/src/util.cpp b/src/util.cpp index 4265ff759..980d82ac9 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -394,7 +394,7 @@ void ParseParameters(int argc, const char* const argv[]) } } -void SplitStr(const std::string& strVal, std::vector outVals) +void SplitStr(const std::string& strVal, std::vector &outVals) { stringstream ss(strVal); std::string str; @@ -404,6 +404,10 @@ void SplitStr(const std::string& strVal, std::vector outVals) while ( ss >> str ) { + if ( str.size() == 0 ) + continue; + if ( str[str.size()-1] == ',' ) + str.resize(str.size()-1); outVals.push_back(str); while ( ss.peek() == ' ' ) ss.ignore(); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5456f3b9c..d720cf33f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6913,143 +6913,14 @@ UniValue priceslist(const UniValue& params, bool fHelp) UniValue pricesinfo(const UniValue& params, bool fHelp) { - uint256 fundingtxid; - if ( fHelp || params.size() != 1 ) + uint256 bettxid; int32_t height; + if ( fHelp || params.size() != 2 ) throw runtime_error("pricesinfo fundingtxid\n"); if ( ensure_CCrequirements(EVAL_PRICES) < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - return(PricesInfo(fundingtxid)); -} - -UniValue pricescreate(const UniValue& params, bool fHelp) -{ - UniValue result(UniValue::VOBJ); uint64_t mode; int64_t funding; int32_t i,n,margin,maxleverage; std::string hex; uint256 oracletxid,longtoken,shorttoken,bettoken; std::vector pubkeys; std::vectorpubkey; - if ( fHelp || params.size() < 8 ) - throw runtime_error("pricescreate bettoken oracletxid margin mode longtoken shorttoken maxleverage funding N [pubkeys]\n"); - if ( ensure_CCrequirements(EVAL_PRICES) < 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); - bettoken = Parseuint256((char *)params[0].get_str().c_str()); - oracletxid = Parseuint256((char *)params[1].get_str().c_str()); - margin = atof(params[2].get_str().c_str()) * 1000; - mode = atol(params[3].get_str().c_str()); - longtoken = Parseuint256((char *)params[4].get_str().c_str()); - shorttoken = Parseuint256((char *)params[5].get_str().c_str()); - maxleverage = atol(params[6].get_str().c_str()); - funding = atof(params[7].get_str().c_str()) * COIN + 0.00000000499999; - n = atoi(params[8].get_str().c_str()); - if ( n > 0 ) - { - for (i=0; i 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } - else - { - ERR_RESULT("couldnt create prices funding transaction"); - } - return(result); -} - -UniValue pricesaddfunding(const UniValue& params, bool fHelp) -{ - UniValue result(UniValue::VOBJ); std::string hex; uint256 fundingtxid,bettoken; int64_t amount; - if ( fHelp || params.size() != 3 ) - throw runtime_error("pricesaddfunding fundingtxid bettoken amount\n"); - if ( ensure_CCrequirements(EVAL_PRICES) < 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); - fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - bettoken = Parseuint256((char *)params[1].get_str().c_str()); - amount = atof(params[2].get_str().c_str()) * COIN + 0.00000000499999; - hex = PricesAddFunding(0,bettoken,fundingtxid,amount); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } - else - { - ERR_RESULT("couldnt create pricesaddfunding transaction"); - } - return(result); -} - -UniValue pricesbet(const UniValue& params, bool fHelp) -{ - UniValue result(UniValue::VOBJ); std::string hex; uint256 fundingtxid,bettoken; int64_t amount; int32_t leverage; - if ( fHelp || params.size() != 4 ) - throw runtime_error("pricesbet fundingtxid bettoken amount leverage\n"); - if ( ensure_CCrequirements(EVAL_PRICES) < 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); - fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - bettoken = Parseuint256((char *)params[1].get_str().c_str()); - amount = atof(params[2].get_str().c_str()) * COIN + 0.00000000499999; - leverage = atoi(params[3].get_str().c_str()); - hex = PricesBet(0,bettoken,fundingtxid,amount,leverage); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } - else - { - ERR_RESULT("couldnt create pricesbet transaction"); - } - return(result); -} - -UniValue pricesstatus(const UniValue& params, bool fHelp) -{ - uint256 fundingtxid,bettxid,bettoken; - if ( fHelp || params.size() != 3 ) - throw runtime_error("pricesstatus fundingtxid bettoken bettxid\n"); - if ( ensure_CCrequirements(EVAL_PRICES) < 0 ) - throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - bettoken = Parseuint256((char *)params[1].get_str().c_str()); - bettxid = Parseuint256((char *)params[2].get_str().c_str()); - return(PricesStatus(0,bettoken,fundingtxid,bettxid)); -} - -UniValue pricesfinish(const UniValue& params, bool fHelp) -{ - UniValue result(UniValue::VOBJ); uint256 fundingtxid,bettxid,bettoken; std::string hex; - if ( fHelp || params.size() != 3 ) - throw runtime_error("pricesfinish fundingtxid bettoken bettxid\n"); - if ( ensure_CCrequirements(EVAL_PRICES) < 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); - fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - bettoken = Parseuint256((char *)params[1].get_str().c_str()); - bettxid = Parseuint256((char *)params[2].get_str().c_str()); - hex = PricesFinish(0,bettoken,fundingtxid,bettxid); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } - else - { - ERR_RESULT("couldnt create pricesfinish transaction"); - } - return(result); + bettxid = Parseuint256((char *)params[0].get_str().c_str()); + height = atoi(params[1].get_str().c_str()); + return(PricesInfo(bettxid,height)); } UniValue dicefund(const UniValue& params, bool fHelp)