Merge pull request #1379 from jl777/jl777

Jl777
This commit is contained in:
jl777
2019-04-06 00:40:53 -11:00
committed by GitHub
13 changed files with 965 additions and 650 deletions

View File

@@ -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<std::string> 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<CPubKey> 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

View File

@@ -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<uint256> 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<n-2; i++)
txidoprets.push_back(payments_juint256(jitem(params,2+i)));
for (i=0; i<txidoprets.size(); i++)
{
std::vector<uint8_t> 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<uint256> txidoprets; int64_t funds,fundsopret,totalallocations=0,allocation; char fundsaddr[64],fundsopretaddr[64],txidaddr[64],*outstr; uint256 createtxid,hashBlock;

View File

@@ -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::vector<CPubKey>pubkeys,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<CPubKey> pubkeys,uint256 bettoken)
CScript prices_betopret(CPubKey mypk,int32_t height,int64_t amount,int16_t leverage,int64_t firstprice,std::vector<uint16_t> 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<CPubKey> &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<uint16_t> &vec,uint256 &tokenid)
{
fprintf(stderr,"implement DecodePricesFundingOpRet\n");
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<std::pair<CAddressIndexKey, CAmount> > txids;
numvins = tx.vin.size();
numvouts = tx.vout.size();
preventCCvins = preventCCvouts = -1;
if ( numvouts < 1 )
return eval->Invalid("no vouts");
else
{
for (i=0; i<numvins; i++)
{
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
{
return eval->Invalid("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<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<uint16_t> &vec,std::vector<std::string> 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<synthetic.size(); i++)
{
need = 0;
opstr = synthetic[i];
if ( opstr == "*" )
opcode = PRICES_MULT, need = 2;
else if ( opstr == "/" )
opcode = PRICES_DIV, need = 2;
else if ( opstr == "!" )
opcode = PRICES_INV, need = 1;
else if ( opstr == "**/" )
opcode = PRICES_MMD, need = 3;
else if ( opstr == "*//" )
opcode = PRICES_MDD, need = 3;
else if ( opstr == "***" )
opcode = PRICES_MMM, need = 3;
else if ( opstr == "///" )
opcode = PRICES_DDD, need = 3;
else if ( (ind= komodo_priceind((char *)opstr.c_str())) >= 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<uint16_t> 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<vec.size(); i++)
{
opcode = vec[i];
ind = (opcode & (KOMODO_MAXPRICES-1));
switch ( opcode & KOMODO_PRICEMASK )
{
case 0:
pricestack[depth] = 0;
if ( prices_extract(pricedata,height,1,ind) == 0 )
{
if ( minmax == 0 )
pricestack[depth] = pricedata[2];
else
{
if ( leverage > 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<uint16_t> 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<std::string> 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<uint16_t> 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<uint16_t> 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<uint16_t> 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; i<PRICES_DAYWINDOW; i++)
{
if ( (profits= prices_syntheticprofits(costbasis,firstheight,firstheight+i,leverage,vec,positionsize,addedbets)) < 0 )
{
result.push_back(Pair("rekt",(int64_t)1));
result.push_back(Pair("rektheight",(int64_t)firstheight+i));
break;
}
}
if ( i == PRICES_DAYWINDOW )
result.push_back(Pair("rekt",0));
prices_betjson(result,profits,costbasis,positionsize,addedbets,leverage,firstheight,firstprice);
myfee = bettx.vout[1].nValue / 10;
result.push_back(Pair("myfee",myfee));
mtx.vout.push_back(CTxOut(myfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,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<uint16_t> 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<uint16_t> 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<uint16_t> 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<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint64_t mode; int32_t margin,maxleverage; std::vector<CPubKey>pubkeys; uint256 txid,hashBlock,oracletxid,longtoken,shorttoken,bettoken; CPubKey planpk,pricespk; char str[65]; CTransaction vintx;
UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > 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<uint16_t> 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<CPubKey> 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<N; i++)
{
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pubkeys[i])) << OP_CHECKSIG);
if ( CCaddress_balance(coinaddr) == 0 )
{
fprintf(stderr,"N.%d but pubkeys[%d] has no balance\n",N,i);
return("");
}
}
if ( GetCCaddress1of2(cp,houseaddr,pricespk,mypk) == 0 )
{
fprintf(stderr,"PricesCreateFunding cant create globaladdr\n");
return("");
}
if ( CCtoken_balance(houseaddr,longtoken) != CCfullsupply(longtoken) )
{
fprintf(stderr,"PricesCreateFunding (%s) globaladdr.%s token balance %.8f != %.8f\n",uint256_str(str,longtoken),houseaddr,(double)CCtoken_balance(houseaddr,longtoken)/COIN,(double)CCfullsupply(longtoken)/COIN);
return("");
}
if ( CCtoken_balance(houseaddr,shorttoken) != CCfullsupply(shorttoken) )
{
fprintf(stderr,"PricesCreateFunding (%s) globaladdr.%s token balance %.8f != %.8f\n",uint256_str(str,longtoken),houseaddr,(double)CCtoken_balance(houseaddr,longtoken)/COIN,(double)CCfullsupply(shorttoken)/COIN);
return("");
}
if ( GetTransaction(oracletxid,oracletx,hashBlock,false) == 0 || (numvouts= oracletx.vout.size()) <= 0 )
{
fprintf(stderr,"cant find oracletxid %s\n",uint256_str(str,oracletxid));
return("");
}
fprintf(stderr,"error check bettoken\n");
if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 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::vector<CPubKey>pubkeys; 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; i<pubkeys.size(); i++)
a.push_back(pubkey33_str(str,(uint8_t *)&pubkeys[i]));
result.push_back(Pair("pubkeys",a));
GetCCaddress1of2(cp,houseaddr,pricespk,planpk);
GetCCaddress1of2(cp,exposureaddr,pricespk,pricespk); // assets addr
result.push_back(Pair("houseaddr",houseaddr));
result.push_back(Pair("betaddr",exposureaddr));
result.push_back(Pair("longtoken",uint256_str(str,longtoken)));
supply = CCfullsupply(longtoken);
result.push_back(Pair("longsupply",supply));
balance = CCtoken_balance(houseaddr,longtoken);
result.push_back(Pair("longavail",balance));
exposure = CCtoken_balance(exposureaddr,longtoken);
result.push_back(Pair("longexposure",exposure));
result.push_back(Pair("shorttoken",uint256_str(str,shorttoken)));
supply = CCfullsupply(shorttoken);
result.push_back(Pair("shortsupply",supply));
balance = CCtoken_balance(houseaddr,shorttoken);
result.push_back(Pair("shortavail",balance));
exposure = CCtoken_balance(exposureaddr,shorttoken);
result.push_back(Pair("shortexposure",exposure));
sprintf(numstr,"%.8f",(double)CCtoken_balance(houseaddr,bettoken)/COIN);
result.push_back(Pair("funds",numstr));
}
return(result);
}
std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,CCchange = 0; uint64_t funding,mode; int32_t margin,maxleverage; char houseaddr[64],myaddr[64]; std::vector<CPubKey>pubkeys;
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<CPubKey> 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::vector<CPubKey>pubkeys;
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("");
}

View File

@@ -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<uint8_t> payload);
int32_t komodo_priceind(char *symbol);
#endif

View File

@@ -1552,27 +1552,25 @@ extern std::vector<uint8_t> 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<n; i++)
{
@@ -1673,7 +1671,7 @@ int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int6
// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight
CScript komodo_mineropret(int32_t nHeight)
{
CScript opret; char maxflags[2048]; uint32_t pricebits[2048],prevbits[2048]; int32_t maxflag,i,n,numzero=0;
CScript opret; char maxflags[KOMODO_MAXPRICES]; uint32_t pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES]; int32_t maxflag,i,n,numzero=0;
if ( Mineropret.size() >= 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<uint8_t> 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<uint8_t> 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<std::string> strvec)
{
int32_t i,errs=0; uint32_t price;
for (i=0; i<n; i++)
int32_t i,errs=0; uint32_t price; char *symbol;
for (i=0; i<n+strvec.size(); i++)
{
if ( (price= get_binanceprice(list[i])) == 0 )
if ( i < n )
symbol = (char *)list[i];
else symbol = (char *)strvec[i - n].c_str();
if ( (price= get_binanceprice(symbol)) == 0 )
errs++;
fprintf(stderr,"(%s %.8f) ",list[i],(double)price/SATOSHIDEN);
fprintf(stderr,"(%s %.8f) ",symbol,(double)price/SATOSHIDEN);
prices[i] = price;
}
fprintf(stderr," errs.%d\n",errs);
@@ -2109,15 +2108,14 @@ int32_t get_btcusd(uint32_t pricebits[4])
int32_t komodo_cbopretsize(uint64_t flags)
{
int32_t size = 0; uint32_t cryptoprices[sizeof(Cryptos)/sizeof(*Cryptos)],forexprices[sizeof(Forex)/sizeof(*Forex)];
int32_t size = 0;
if ( (ASSETCHAINS_CBOPRET & 1) != 0 )
{
size = PRICES_SIZEBIT0;
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
size += sizeof(forexprices);
size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t);
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
size += sizeof(cryptoprices);
size += (sizeof(Cryptos)/sizeof(*Cryptos) + ASSETCHAINS_PRICES.size())*sizeof(uint32_t);
}
return(size);
}
@@ -2125,7 +2123,7 @@ int32_t komodo_cbopretsize(uint64_t flags)
void komodo_cbopretupdate(int32_t forceflag)
{
static uint32_t lasttime,lastcrypto,lastbtc,pending;
static uint32_t pricebits[4],cryptoprices[sizeof(Cryptos)/sizeof(*Cryptos)],forexprices[sizeof(Forex)/sizeof(*Forex)];
static uint32_t pricebits[4],cryptoprices[KOMODO_MAXPRICES],forexprices[sizeof(Forex)/sizeof(*Forex)];
int32_t size; uint32_t flags=0,now;
if ( forceflag != 0 && pending != 0 )
{
@@ -2160,19 +2158,19 @@ if ( komodo_nextheight() > 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<Mineropret.size(); i++)
// fprintf(stderr,"%02x",Mineropret[i]);
//fprintf(stderr," <- set Mineropret[%d] size.%d %ld\n",(int32_t)Mineropret.size(),size,sizeof(PriceCache[0]));
@@ -2205,10 +2206,35 @@ if ( komodo_nextheight() > 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<sizeof(Forex)/sizeof(*Forex); j++)
PriceMult[i++] = 10000;
}
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
{
for (j=0; j<sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size(); j++)
PriceMult[i++] = 1;
}
}
return(PriceMult[ind]);
}
return(0);
}
char *komodo_pricename(char *name,int32_t ind)
{
strcpy(name,"error");
if ( (ASSETCHAINS_CBOPRET & 1) != 0 )
if ( (ASSETCHAINS_CBOPRET & 1) != 0 && ind < KOMODO_MAXPRICES )
{
if ( ind < 4 )
{
@@ -2240,32 +2266,49 @@ char *komodo_pricename(char *name,int32_t ind)
{
if ( ind < 0 )
return(0);
if ( ind < sizeof(Cryptos)/sizeof(*Cryptos) )
if ( ind < sizeof(Cryptos)/sizeof(*Cryptos) + ASSETCHAINS_PRICES.size() )
{
strcpy(name,Cryptos[ind]);
if ( ind < sizeof(Cryptos)/sizeof(*Cryptos) )
strcpy(name,Cryptos[ind]);
else
{
ind -= (sizeof(Cryptos)/sizeof(*Cryptos));
strcpy(name,ASSETCHAINS_PRICES[ind].c_str());
}
strcat(name,"BTC");
return(name);
} else ind -= sizeof(Cryptos)/sizeof(*Cryptos);
} else ind -= (sizeof(Cryptos)/sizeof(*Cryptos) + ASSETCHAINS_PRICES.size());
}
}
}
return(0);
}
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t daywindow,uint32_t *nonzprices,int32_t smoothwidth)
int32_t komodo_priceind(char *symbol)
{
char name[65]; int32_t i,n = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t));
for (i=1; i<n; i++)
{
komodo_pricename(name,i);
if ( strcmp(name,symbol) == 0 )
return(i);
}
return(-1);
}
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth)
{
int32_t i,j,k,n,iter,correlation,maxcorrelation=0; int64_t firstprice,price,sum,den,mult,refprice,lowprice,highprice;
if ( daywindow < 2 )
if ( PRICES_DAYWINDOW < 2 || ind >= KOMODO_MAXPRICES )
return(-1);
if ( ind < 36 )
mult = 10000;
else mult = 1;
memset(nonzprices,0,sizeof(*nonzprices)*daywindow);
for (iter=0; iter<daywindow; iter++)
mult = PriceMult[ind];
if ( nonzprices != 0 )
memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW);
for (iter=0; iter<PRICES_DAYWINDOW; iter++)
{
correlation = 0;
i = (iter + seed) % daywindow;
refprice = rawprices[i];
i = (iter + seed) % PRICES_DAYWINDOW;
refprice = rawprices[i*rawskip];
highprice = (refprice * (COIN + PRICES_MAXCHANGE*5)) / COIN;
lowprice = (refprice * (COIN - PRICES_MAXCHANGE*5)) / COIN;
if ( highprice == refprice )
@@ -2274,11 +2317,11 @@ int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int
lowprice--;
sum = 0;
//fprintf(stderr,"firsti.%d: ",i);
for (j=0; j<daywindow; j++,i++)
for (j=0; j<PRICES_DAYWINDOW; j++,i++)
{
if ( i >= 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; k++,i++)
i = (iter + seed) % PRICES_DAYWINDOW;
for (k=0; k<PRICES_DAYWINDOW; k++,i++)
{
if ( i >= 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<daywindow; i++)
for (i=0; i<PRICES_DAYWINDOW; i++)
if ( nonzprices[i] != 0 )
break;
firstprice = nonzprices[i];
//fprintf(stderr,"firsti.%d: ",i);
for (i=0; i<daywindow; i++)
for (i=0; i<PRICES_DAYWINDOW; i++)
{
if ( (price= nonzprices[i]) != 0 )
{
den += (daywindow - i);
sum += ((daywindow - i) * (price + firstprice*4)) / 5;
den += (PRICES_DAYWINDOW - i);
sum += ((PRICES_DAYWINDOW - i) * (price + firstprice*4)) / 5;
n++;
}
}
@@ -2420,62 +2464,29 @@ void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters)
} else memcpy(dest,src,width*sizeof(*dest));
}
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t daywindow,int64_t *nonzprices,int32_t smoothwidth)
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprices,int32_t numprices)
{
//const int64_t coeffs[7] = { -1, 9, -45, 1, 45, -9, 1 }; // / 60
const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 };
int32_t i,iter; int64_t smoothedden,smoothedsum,sum,den,smoothed[7],firstprice = correlated[0];
if ( daywindow < 2 )
//const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 };
int32_t i; int64_t sum=0,nonzprice,price;
if ( PRICES_DAYWINDOW < 2 )
return(0);
if ( smoothwidth != sizeof(smoothed)/sizeof(*smoothed) )
for (i=0; i<PRICES_DAYWINDOW; i++)
{
fprintf(stderr,"smoothwidth %d != %d\n",smoothwidth,(int32_t)(sizeof(smoothed)/sizeof(*smoothed)));
return(0);
}
memset(nonzprices,0,sizeof(*nonzprices)*daywindow);
for (i=1; i<daywindow; i++)
{
if ( correlated[i] == 0 )
correlated[i] = correlated[i-1];
if ( firstprice == 0 && correlated[i] != 0 )
{
firstprice = correlated[i];
if ( (nonzprice= correlated[i*cskip]) != 0 )
break;
}
}
if ( firstprice != 0 )
if ( nonzprice == 0 )
return(-1);
for (i=0; i<PRICES_DAYWINDOW; i++)
{
for (i=0; i<daywindow; i++)
{
if ( correlated[i] == 0 )
correlated[i] = firstprice;
else break;
}
//memcpy(orig,correlated,(daywindow+smoothwidth)*sizeof(*correlated));
for (iter=0; iter<smoothwidth; iter++)
{
sum = den = 0;
//smooth64(dest,correlated+iter,daywindow,1);
//smooth64(correlated+iter,dest,daywindow,1);
for (i=0; i<daywindow; i++)
{
sum += correlated[i+iter];//((daywindow - i) * (correlated[i+iter] + firstprice*4)) / 5;
den += 1;//(daywindow - i);
}
smoothed[iter] = (sum / den);
//memcpy(correlated,orig,(daywindow+smoothwidth)*sizeof(*correlated));
}
smoothedsum = 0;
smoothedden = 64;
for (i=0; i<7; i++)
{
//fprintf(stderr,"%.4f ",(double)smoothed[i]/10000);
smoothedsum += coeffs[i] * smoothed[i];
//smoothedden += (7-i);
}
//fprintf(stderr,"-> %.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);
}

View File

@@ -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<std::string> outVals);
void SplitStr(const std::string& strVal, std::vector<std::string> &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; i<ASSETCHAINS_PRICES.size(); i++)
{
symbol = ASSETCHAINS_PRICES[i];
memcpy(&extraptr[extralen],(char *)symbol.c_str(),symbol.size());
extralen += symbol.size();
}
}
komodo_cbopretupdate(1); // will set Mineropret
fprintf(stderr,"This blockchain uses data produced from CoinDesk Bitcoin Price Index\n");
}

View File

@@ -1176,18 +1176,58 @@ UniValue paxprice(const UniValue& params, bool fHelp)
int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight);
char *komodo_pricename(char *name,int32_t ind);
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t numprices,int64_t *correlated2,int32_t smoothwidth);
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t numprices,uint32_t *rawprices2,int32_t smoothwidth);
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *correlated2,int32_t numprices);
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth);
int32_t komodo_nextheight();
uint32_t komodo_heightstamp(int32_t height);
int64_t komodo_pricemult(int32_t ind);
#define PRICES_SMOOTHWIDTH 1
int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind)
{
int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; int64_t *correlated2; uint32_t rawprices[1440*6],*ptr;
//daywindow = (3600*24/ASSETCHAINS_BLOCKTIME) + 1;
//pricedata = (uint32_t *)calloc(sizeof(*prices)*3,numblocks + daywindow*2 + PRICES_SMOOTHWIDTH);
width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH;
komodo_heightpricebits(&seed,rawprices,firstheight + numblocks - 1);
if ( firstheight < width )
return(-1);
for (i=0; i<width; i++)
{
if ( (n= komodo_heightpricebits(&ignore,rawprices,firstheight + numblocks - 1 - i)) < 0 )
return(-1);
if ( numpricefeeds < 0 )
numpricefeeds = n;
if ( n != numpricefeeds )
return(-2);
ptr = (uint32_t *)&pricedata[i*3];
ptr[0] = rawprices[ind];
ptr[1] = rawprices[0]; // timestamp
}
rngval = seed;
correlated2 = (int64_t *)calloc(sizeof(*correlated2),width);
for (i=0; i<numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH; i++)
{
rngval = (rngval*11109 + 13849);
ptr = (uint32_t *)&pricedata[i*3];
correlated2[i] = ptr[0];
if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 )
{
free(correlated2);
return(-3);
}
}
for (i=0; i<numblocks; i++)
pricedata[i*3+2] = komodo_pricesmoothed(&pricedata[i*3+1],3,correlated2,numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH);
return(0);
}
UniValue prices(const UniValue& params, bool fHelp)
{
int32_t smoothwidth = 7;
if ( fHelp || params.size() != 1 )
throw runtime_error("prices maxsamples\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ); uint64_t seed,rngval; int64_t smoothed,*correlated,*correlated2; char name[64],*str; uint32_t rawprices[2048],*prices,*prices2; uint32_t i,width,j,numpricefeeds=-1,n,nextheight,offset,ht,num=0,daywindow = (3600*24/ASSETCHAINS_BLOCKTIME) + 1;
UniValue ret(UniValue::VOBJ); uint64_t seed,rngval; int64_t smoothed,*correlated,*correlated2; char name[64],*str; uint32_t rawprices[1440*6],*prices; uint32_t i,width,j,numpricefeeds=-1,n,numsamples,nextheight,offset,ht;
if ( ASSETCHAINS_CBOPRET == 0 )
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
@@ -1196,17 +1236,18 @@ UniValue prices(const UniValue& params, bool fHelp)
maxsamples = 1;
nextheight = komodo_nextheight();
UniValue a(UniValue::VARR);
if ( daywindow < 7 )
daywindow = 7;
width = maxsamples+2*daywindow+smoothwidth;
if ( PRICES_DAYWINDOW < 7 )
throw JSONRPCError(RPC_INVALID_PARAMETER, "daywindow is too small");
width = maxsamples+2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH;
numpricefeeds = komodo_heightpricebits(&seed,rawprices,nextheight-1);
if ( numpricefeeds <= 0 )
throw JSONRPCError(RPC_INVALID_PARAMETER, "illegal numpricefeeds");
prices = (uint32_t *)calloc(sizeof(*prices),width*numpricefeeds);
correlated = (int64_t *)calloc(sizeof(*correlated),width);
correlated2 = (int64_t *)calloc(sizeof(*correlated2),width);
prices2 = (uint32_t *)calloc(sizeof(*prices2),width);
for (ht=nextheight-1,i=0; i<width&&ht>2*daywindow+2+smoothwidth; i++,ht--)
//prices2 = (uint32_t *)calloc(sizeof(*prices2),width);
i = 0;
for (ht=nextheight-1,i=0; i<width&&ht>2; 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<maxsamples; i++)
timestamps.push_back((int64_t)prices[i]);
ret.push_back(Pair("timestamps",timestamps));
rngval = seed;
//for (i=0; i<daywindow; i++)
//for (i=0; i<PRICES_DAYWINDOW; i++)
// fprintf(stderr,"%.4f ",(double)prices[width+i]/10000);
//fprintf(stderr," maxsamples.%d\n",maxsamples);
for (j=1; j<numpricefeeds; j++)
@@ -1239,22 +1281,37 @@ UniValue prices(const UniValue& params, bool fHelp)
if ( (str= komodo_pricename(name,j)) != 0 )
{
item.push_back(Pair("name",str));
for (i=0; i<maxsamples+daywindow+smoothwidth; i++)
if ( numsamples >= 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<maxsamples+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH&&i<numsamples; i++)
{
offset = j*width + i;
rngval = (rngval*11109 + 13849);
correlated2[i] = prices[offset];
if ( (correlated[i]= komodo_pricecorrelated(rngval,j,&prices[offset],1,0,PRICES_SMOOTHWIDTH)) < 0 )
throw JSONRPCError(RPC_INVALID_PARAMETER, "null correlated price");
}
for (i=0; i<maxsamples&&i<numsamples; i++)
{
offset = j*width + i;
smoothed = komodo_pricesmoothed(&correlated[i],1,correlated2,maxsamples+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH);
UniValue parr(UniValue::VARR);
parr.push_back(ValueFromAmount((int64_t)prices[offset] * komodo_pricemult(j)));
parr.push_back(ValueFromAmount(correlated[i]));
parr.push_back(ValueFromAmount(smoothed));
// compare to alternate method
p.push_back(parr);
}
}
for (i=0; i<maxsamples; i++)
else
{
offset = j*width + i;
smoothed = komodo_pricesmoothed(&correlated[i],daywindow,correlated2,smoothwidth);
UniValue parr(UniValue::VARR);
parr.push_back(ValueFromAmount((int64_t)prices[offset] * (j<36?10000:1)));
parr.push_back(ValueFromAmount(correlated[i]));
parr.push_back(ValueFromAmount(smoothed));
p.push_back(parr);
for (i=0; i<maxsamples&&i<numsamples; i++)
{
offset = j*width + i;
UniValue parr(UniValue::VARR);
parr.push_back(ValueFromAmount((int64_t)prices[offset] * komodo_pricemult(j)));
p.push_back(parr);
}
}
item.push_back(Pair("prices",p));
} else item.push_back(Pair("name","error"));
@@ -1266,10 +1323,10 @@ UniValue prices(const UniValue& params, bool fHelp)
ret.push_back(Pair("height",(int64_t)nextheight-1));
ret.push_back(Pair("maxsamples",(int64_t)maxsamples));
ret.push_back(Pair("width",(int64_t)width));
ret.push_back(Pair("daywindow",(int64_t)daywindow));
ret.push_back(Pair("daywindow",(int64_t)PRICES_DAYWINDOW));
ret.push_back(Pair("numpricefeeds",(int64_t)numpricefeeds));
free(prices);
free(prices2);
//free(prices2);
free(correlated);
free(correlated2);
return ret;

View File

@@ -445,11 +445,6 @@ static const CRPCCommand vRPCCommands[] =
{ "prices", "pricesaddress", &pricesaddress, true },
{ "prices", "priceslist", &priceslist, true },
{ "prices", "pricesinfo", &pricesinfo, true },
{ "prices", "pricescreate", &pricescreate, true },
{ "prices", "pricesaddfunding", &pricesaddfunding, true },
{ "prices", "pricesbet", &pricesbet, true },
{ "prices", "pricesstatus", &pricesstatus, true },
{ "prices", "pricesfinish", &pricesfinish, true },
// Pegs
{ "pegs", "pegsaddress", &pegsaddress, true },

View File

@@ -272,11 +272,6 @@ extern UniValue oraclessamples(const UniValue& params, bool fHelp);
extern UniValue pricesaddress(const UniValue& params, bool fHelp);
extern UniValue priceslist(const UniValue& params, bool fHelp);
extern UniValue pricesinfo(const UniValue& params, bool fHelp);
extern UniValue pricescreate(const UniValue& params, bool fHelp);
extern UniValue pricesaddfunding(const UniValue& params, bool fHelp);
extern UniValue pricesbet(const UniValue& params, bool fHelp);
extern UniValue pricesstatus(const UniValue& params, bool fHelp);
extern UniValue pricesfinish(const UniValue& params, bool fHelp);
extern UniValue pegsaddress(const UniValue& params, bool fHelp);
extern UniValue marmaraaddress(const UniValue& params, bool fHelp);
extern UniValue marmara_poolpayout(const UniValue& params, bool fHelp);

View File

@@ -438,17 +438,125 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type,
bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address);
uint32_t komodo_segid32(char *coinaddr);
#define DECLARE_IGNORELIST std::map <std::string,int> 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 <std::pair<CAmount, std::string>> &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<CDBIterator> iter(NewIterator());
std::map <std::string, CAmount> addressAmounts;
for (iter->SeekToLast(); iter->Valid(); iter->Prev())
{
boost::this_thread::interruption_point();
try
{
std::vector<unsigned char> slKey = std::vector<unsigned char>();
pair<char, CAddressIndexIteratorKey> 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 <std::string, int>::iterator ignored = ignoredMap.find(address);
if (ignored != ignoredMap.end())
{
fprintf(stderr,"ignoring %s\n", address.c_str());
ignoredAddresses++;
continue;
}
std::map <std::string, CAmount>::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<std::string, CAmount> element : addressAmounts)
vaddr.push_back( make_pair(element.second, element.first) );
std::sort(vaddr.rbegin(), vaddr.rend());
int topN = 0;
for (std::vector<std::pair<CAmount, std::string>>::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<CDBIterator> iter(NewIterator());
std::map <std::string, CAmount> addressAmounts;
std::vector <std::pair<CAmount, std::string>> vaddr;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("start_time", (int) time(NULL)));
std::map <std::string,int> ignoredMap = {
/* std::map <std::string,int> 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);

View File

@@ -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 <std::pair<CAmount, std::string>> &vaddr);
};
#endif // BITCOIN_TXDB_H

View File

@@ -394,7 +394,7 @@ void ParseParameters(int argc, const char* const argv[])
}
}
void SplitStr(const std::string& strVal, std::vector<std::string> outVals)
void SplitStr(const std::string& strVal, std::vector<std::string> &outVals)
{
stringstream ss(strVal);
std::string str;
@@ -404,6 +404,10 @@ void SplitStr(const std::string& strVal, std::vector<std::string> 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();

View File

@@ -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<CPubKey> pubkeys; std::vector<uint8_t>pubkey;
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<n; i++)
{
if ( params.size() < 9+i+1 )
throw runtime_error("not enough parameters for N pubkeys\n");
pubkey = ParseHex(params[9+i].get_str().c_str());
pubkeys.push_back(pubkey2pk(pubkey));
}
}
hex = PricesCreateFunding(0,bettoken,oracletxid,margin,mode,longtoken,shorttoken,maxleverage,funding,pubkeys);
if ( hex.size() > 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)