Browse Source

change to prices_getbetinfo()

z_createrawtransaction
dimxy 5 years ago
parent
commit
bac6d503af
  1. 1
      src/cc/CCPrices.h
  2. 615
      src/cc/prices.cpp
  3. 13
      src/rpc/blockchain.cpp
  4. 2
      src/rpc/server.cpp
  5. 2
      src/rpc/server.h

1
src/cc/CCPrices.h

@ -49,6 +49,7 @@ UniValue PricesRekt(int64_t txfee,uint256 bettxid,int32_t rektheight);
UniValue PricesCashout(int64_t txfee,uint256 bettxid);
UniValue PricesInfo(uint256 bettxid,int32_t refheight);
UniValue PricesList(uint32_t filter, CPubKey mypk);
UniValue PricesGetOrderbook();
#endif

615
src/cc/prices.cpp

@ -20,16 +20,38 @@
#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos)
#define N_CCMARKER 1
#define NVOUT_CCMARKER 1
#define NVOUT_NORMALMARKER 3
typedef struct BetInfo {
int64_t amount;
typedef struct OneBetData {
int64_t positionsize;
int32_t firstheight;
int64_t costbasis;
int64_t profits;
BetInfo() { amount = 0; firstheight = 0; costbasis = 0; profits = 0; } // it is important to clear costbasis as it will be calculated as minmax from inital value 0
} betinfo;
OneBetData() { positionsize = 0; firstheight = 0; costbasis = 0; profits = 0; } // it is important to clear costbasis as it will be calculated as minmax from inital value 0
} onebetdata;
typedef struct BetInfo {
int64_t averageCostbasis, firstprice, lastprice, liquidationprice, equity;
int64_t rektfee;
int32_t lastheight;
int16_t leverage;
bool isOpen, isRekt;
uint256 tokenid;
std::vector<uint16_t> parsed;
std::vector<onebetdata> bets;
CPubKey pk;
BetInfo() {
averageCostbasis = firstprice = lastprice = liquidationprice = equity = 0;
lastheight = 0;
leverage = 0;
rektfee = 0;
isOpen = isRekt = false;
}
} BetInfo;
/*
CBOPRET creates trustless oracles, which can be used for making a synthetic cash settlement system based on real world prices;
@ -145,7 +167,7 @@ uint8_t prices_finalopretdecode(CScript scriptPubKey,uint256 &bettxid,int64_t &p
}
// price opret basic validation and retrieval
static uint8_t CheckPricesOpret(const CTransaction & tx, vscript_t &opret)
static uint8_t PricesCheckOpret(const CTransaction & tx, vscript_t &opret)
{
if (tx.vout.size() > 0 && GetOpReturnData(tx.vout.back().scriptPubKey, opret) && opret.size() > 2 && opret.begin()[0] == EVAL_PRICES && IS_CHARINSTR(opret.begin()[1], "BACF"))
return opret.begin()[1];
@ -217,7 +239,7 @@ static bool ValidateAddFundingTx(struct CCcontract_info *cp, Eval *eval, const C
return eval->Invalid("cannot decode opreturn for add funding tx");
pricespk = GetUnspendable(cp, 0);
uint8_t vintxFuncId = CheckPricesOpret(vintx, vintxOpret);
uint8_t vintxFuncId = PricesCheckOpret(vintx, vintxOpret);
if (vintxFuncId != 'A' && vintxFuncId != 'B') { // if vintx is bettx
return eval->Invalid("incorrect vintx funcid");
}
@ -352,7 +374,7 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
if (strcmp(ASSETCHAINS_SYMBOL, "REKT0") == 0 && chainActive.Height() < 2965)
return true;
// check basic opret rules:
if (CheckPricesOpret(tx, vopret) == 0)
if (PricesCheckOpret(tx, vopret) == 0)
return eval->Invalid("tx has no prices opreturn");
uint8_t funcId = vopret.begin()[1];
@ -375,7 +397,7 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
if (!myGetTransaction(vin.prevout.hash, vintx, hashBlock))
return eval->Invalid("cannot load vintx");
if (CheckPricesOpret(vintx, vintxOpret) == 0) {
if (PricesCheckOpret(vintx, vintxOpret) == 0) {
//return eval->Invalid("cannot find prices opret in vintx");
std::cerr << "PricesValidate() " << "cannot find prices opret in vintx" << std::endl;
}
@ -486,7 +508,7 @@ int64_t AddPricesInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, ch
if (GetTransaction(txid, vintx, hashBlock, false) != 0 && vout < vintx.vout.size())
{
vscript_t vopret;
uint8_t funcId = CheckPricesOpret(vintx, vopret);
uint8_t funcId = PricesCheckOpret(vintx, vopret);
if (funcId == 'B' && vout == 1) // skip cc marker
continue;
@ -1215,7 +1237,7 @@ int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t
}
// makes result json object
void prices_betjson(UniValue &result, std::vector<BetInfo> bets, int16_t leverage, int32_t endheight, int64_t lastprice)
void prices_betjson(UniValue &result, std::vector<OneBetData> bets, int16_t leverage, int32_t endheight, int64_t lastprice)
{
UniValue resultbets(UniValue::VARR);
@ -1224,12 +1246,12 @@ void prices_betjson(UniValue &result, std::vector<BetInfo> bets, int16_t leverag
for (auto b : bets) {
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("positionsize", ValueFromAmount(b.amount)));
entry.push_back(Pair("positionsize", ValueFromAmount(b.positionsize)));
entry.push_back(Pair("profits", ValueFromAmount(b.profits)));
entry.push_back(Pair("costbasis", ValueFromAmount(b.costbasis)));
entry.push_back(Pair("firstheight", b.firstheight));
resultbets.push_back(entry);
totalbets += b.amount;
totalbets += b.positionsize;
totalprofits += b.profits;
}
int64_t equity = totalbets + totalprofits;
@ -1277,7 +1299,7 @@ int64_t prices_costbasis(CTransaction bettx, uint256 &txidCostbasis)
}
// enumerates and retrieves added bets, returns the last baton txid
int64_t prices_enumaddedbets(uint256 &batontxid, std::vector<BetInfo> &bets, uint256 bettxid)
int64_t prices_enumaddedbets(uint256 &batontxid, std::vector<OneBetData> &bets, uint256 bettxid)
{
int64_t addedBetsTotal = 0;
int32_t vini;
@ -1304,10 +1326,10 @@ int64_t prices_enumaddedbets(uint256 &batontxid, std::vector<BetInfo> &bets, uin
txBaton.vout.size() > 0 &&
(funcId = prices_addopretdecode(txBaton.vout.back().scriptPubKey, bettxidInOpret, pk, amount)) != 0)
{
BetInfo added;
OneBetData added;
addedBetsTotal += amount;
added.amount = amount;
added.positionsize = amount;
added.firstheight = blockIdx.GetHeight();
bets.push_back(added);
std::cerr << "prices_batontxid() added amount=" << amount << std::endl;
@ -1357,9 +1379,9 @@ UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector<
betamount = (amount * 199) / 200;
mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, mypk)); // vout0 baton for total funding
// mtx.vout.push_back(MakeCC1vout(cp->evalcode, (amount - betamount) + 2 * txfee, pricespk)); // vout1, when spent, costbasis is set
mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, pricespk)); // vout1 cc marker (N_CCMARKER)
mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, pricespk)); // vout1 cc marker (NVOUT_CCMARKER)
mtx.vout.push_back(MakeCC1vout(cp->evalcode, betamount, pricespk)); // vout2 betamount
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(pricespk)) << OP_CHECKSIG)); // vout3 normal marker - TODO: remove it as we have cc marker now, when move to the new chain
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(pricespk)) << OP_CHECKSIG)); // vout3 normal marker NVOUT_NORMALMARKER - TODO: remove it as we have cc marker now, when move to the new chain
rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_betopret(mypk, nextheight - 1, amount, leverage, firstprice, vec, zeroid));
return(prices_rawtxresult(result, rawtx, 0));
}
@ -1389,7 +1411,7 @@ UniValue PricesAddFunding(int64_t txfee, uint256 bettxid, int64_t amount)
//GetCCaddress(cp, myaddr, mypk);
if (AddNormalinputs(mtx, mypk, amount + 2*txfee, 64) >= amount + 2*txfee)
{
std::vector<BetInfo> bets;
std::vector<OneBetData> bets;
if (prices_enumaddedbets(batontxid, bets, bettxid) >= 0)
{
mtx.vin.push_back(CTxIn(batontxid, 0, CScript()));
@ -1411,7 +1433,7 @@ UniValue PricesAddFunding(int64_t txfee, uint256 bettxid, int64_t amount)
}
// scan chain from the initial bet's first position upto the chain tip and calculate bet's costbasises and profits, breaks if rekt detected
int32_t prices_scanchain(std::vector<BetInfo> &bets, int16_t leverage, std::vector<uint16_t> vec, int64_t &lastprice, int32_t &endheight) {
int32_t prices_scanchain(std::vector<OneBetData> &bets, int16_t leverage, std::vector<uint16_t> vec, int64_t &lastprice, int32_t &endheight) {
if (bets.size() == 0)
return -1;
@ -1427,13 +1449,13 @@ int32_t prices_scanchain(std::vector<BetInfo> &bets, int16_t leverage, std::vect
if (height > bets[i].firstheight) {
int32_t retcode = prices_syntheticprofits(bets[i].costbasis, bets[i].firstheight, height, leverage, vec, bets[i].amount, bets[i].profits, lastprice);
int32_t retcode = prices_syntheticprofits(bets[i].costbasis, bets[i].firstheight, height, leverage, vec, bets[i].positionsize, bets[i].profits, lastprice);
if (retcode < 0) {
std::cerr << "prices_scanchain() prices_syntheticprofits returned -1, breaking" << std::endl;
stop = true;
break;
}
totalbets += bets[i].amount;
totalbets += bets[i].positionsize;
totalprofits += bets[i].profits;
}
}
@ -1523,117 +1545,222 @@ UniValue PricesSetcostbasis(int64_t txfee, uint256 bettxid)
return(result);
}
// pricesrekt rpc: anyone can rekt a bet at some block where losses reached limit, collecting fee
UniValue PricesRekt(int64_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, firstprice, lastprice = 0, positionsize;
int32_t firstheight;
int16_t leverage;
std::vector<uint16_t> vec;
CPubKey pk, mypk, pricespk;
std::string rawtx;
char destaddr[64];
cp = CCinit(&C, EVAL_PRICES);
if (txfee == 0)
txfee = PRICES_TXFEE;
mypk = pubkey2pk(Mypubkey());
pricespk = GetUnspendable(cp, 0);
GetCCaddress(cp, destaddr, pricespk);
int32_t prices_getbetinfo(uint256 bettxid, BetInfo &betinfo)
{
CTransaction bettx;
uint256 hashBlock, batontxid, tokenid;
if (myGetTransaction(bettxid, bettx, hashBlock) != 0 && bettx.vout.size() > 3)
if (myGetTransaction(bettxid, bettx, hashBlock) && bettx.vout.size() > 3)
{
if (prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vec, tokenid) == 'B')
if (hashBlock.IsNull())
return -2;
OneBetData bet1;
if (prices_betopretdecode(bettx.vout.back().scriptPubKey, betinfo.pk, bet1.firstheight, bet1.positionsize, betinfo.leverage, betinfo.firstprice, betinfo.parsed, betinfo.tokenid) == 'B')
{
uint256 finaltxid;
int32_t vini;
int32_t finalheight, endheight;
std::vector<BetInfo> bets;
BetInfo bet1;
int32_t finaltxheight; //, endheight;
//std::vector<OneBetData> bets;
if (CCgetspenttxid(finaltxid, vini, finalheight, bettxid, N_CCMARKER) == 0) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position closed"));
return result;
}
bet1.amount = positionsize;
bet1.firstheight = firstheight;
bets.push_back(bet1);
if (CCgetspenttxid(finaltxid, vini, finaltxheight, bettxid, NVOUT_CCMARKER) == 0)
betinfo.isOpen = false;
else
betinfo.isOpen = true;
prices_enumaddedbets(batontxid, bets, bettxid);
//bet1.amount = betinfo.positionsize;
//bet1.firstheight = firstheight;
betinfo.bets.push_back(bet1);
if (prices_scanchain(bets, leverage, vec, lastprice, endheight) < 0) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "error scanning chain"));
return(result);
prices_enumaddedbets(batontxid, betinfo.bets, bettxid);
if (prices_scanchain(betinfo.bets, betinfo.leverage, betinfo.parsed, betinfo.lastprice, betinfo.lastheight) < 0) {
return -4;
}
mpz_t mpzTotalbets;
mpz_t mpzTotalprofits;
mpz_t mpzTotalcostbasis;
mpz_init(mpzTotalbets);
mpz_init(mpzTotalprofits);
mpz_init(mpzTotalcostbasis);
int64_t totalbets = 0;
int64_t totalprofits = 0;
for (auto b : bets) {
totalbets += b.amount;
for (auto b : betinfo.bets) {
mpz_t mpzProduct;
mpz_t mpzProfits;
mpz_init(mpzProduct);
mpz_init(mpzProfits);
//totalprofits += b.profits;
//dcostbasis += b.amount * (double)b.costbasis;
// costbasis += b.amount * (b.costbasis / PRICES_POINTFACTOR); // prevent int64 overflow (but we have underflow for 1/BTC)
// std::cerr << "PricesInfo() acc dcostbasis=" << dcostbasis << " b.amount=" << b.amount << " b.costbasis/PRICES_POINTFACTOR=" << (b.costbasis / PRICES_POINTFACTOR) << std::endl;
//std::cerr << "PricesInfo() acc dcostbasis=" << dcostbasis << " b.amount=" << b.amount << " b.costbasis/PRICES_POINTFACTOR=" << (b.costbasis / PRICES_POINTFACTOR) << std::endl;
mpz_set_ui(mpzProduct, b.costbasis);
mpz_mul_ui(mpzProduct, mpzProduct, (uint64_t)b.positionsize); // b.costbasis * b.amount
mpz_add(mpzTotalcostbasis, mpzTotalcostbasis, mpzProduct); //averageCostbasis += b.costbasis * b.amount;
mpz_add_ui(mpzTotalbets, mpzTotalbets, (uint64_t)b.positionsize); //totalbets += b.amount;
mpz_add(mpzTotalprofits, mpzTotalprofits, mpzProfits); //totalprofits += b.profits;
totalbets += b.positionsize;
totalprofits += b.profits;
mpz_clear(mpzProduct);
mpz_clear(mpzProfits);
}
prices_betjson(result, bets, leverage, endheight, lastprice); // fill output json
betinfo.equity = totalbets + totalprofits;
//int64_t averageCostbasis = 0;
int64_t equity = totalbets + totalprofits;
if (equity < 0)
{
myfee = totalbets / 500; // consolation fee for loss
}
if (myfee != 0)
{
int64_t CCchange = 0, inputsum;
if (mpz_get_ui(mpzTotalbets) != 0) { //prevent zero div
mpz_t mpzAverageCostbasis;
mpz_init(mpzAverageCostbasis);
mtx.vin.push_back(CTxIn(bettxid, N_CCMARKER, CScript())); // spend cc marker
if ((inputsum = AddPricesInputs(cp, mtx, destaddr, myfee + txfee, 64)) > myfee + txfee) // TODO: why do we take txfee from global addr and not from user's addr?
CCchange = (inputsum - myfee);
mtx.vout.push_back(CTxOut(myfee, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
if (CCchange >= txfee)
mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, pricespk));
//averageCostbasis = totalcostbasis / totalbets;
mpz_mul_ui(mpzTotalcostbasis, mpzTotalcostbasis, SATOSHIDEN); // profits *= SATOSHIDEN normalization to prevent loss of significance while division
mpz_tdiv_q(mpzAverageCostbasis, mpzTotalcostbasis, mpzTotalbets);
/// mtx.vout.push_back(MakeCC1vout(cp->evalcode, bettx.vout[2].nValue - myfee - txfee, pricespk)); // change
rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_finalopret(bettxid, totalprofits, rektheight, mypk, firstprice, 0, totalbets - positionsize, positionsize, leverage));
return(prices_rawtxresult(result, rawtx, 0));
mpz_tdiv_q_ui(mpzAverageCostbasis, mpzAverageCostbasis, SATOSHIDEN); // profits /= SATOSHIDEN de-normalization
betinfo.averageCostbasis = mpz_get_ui(mpzAverageCostbasis);
mpz_clear(mpzAverageCostbasis);
}
betinfo.liquidationprice = 0;
if (betinfo.leverage != 0) {// prevent zero div
betinfo.liquidationprice = betinfo.averageCostbasis - betinfo.averageCostbasis / betinfo.leverage;
}
if (betinfo.equity >= 0)
betinfo.isRekt = true;
else
{
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position not rekt"));
return(result);
betinfo.isRekt = false;
betinfo.rektfee = totalbets / 500;
}
mpz_clear(mpzTotalbets);
mpz_clear(mpzTotalprofits);
mpz_clear(mpzTotalcostbasis);
return 0;
}
else
return -3;
}
return (-1);
}
// pricesrekt rpc: anyone can rekt a bet at some block where losses reached limit, collecting fee
UniValue PricesRekt(int64_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 firstprice, lastprice = 0, positionsize;
int32_t firstheight;
int16_t leverage;
std::vector<uint16_t> vec; */
int64_t myfee = 0;
CPubKey pk, mypk, pricespk;
std::string rawtx;
char destaddr[64];
cp = CCinit(&C, EVAL_PRICES);
if (txfee == 0) // TODO: what did we want tot do with txfee in prices?
txfee = PRICES_TXFEE;
mypk = pubkey2pk(Mypubkey());
pricespk = GetUnspendable(cp, 0);
GetCCaddress(cp, destaddr, pricespk);
BetInfo betinfo;
int32_t retcode = prices_getbetinfo(bettxid, betinfo);
if (retcode < 0) {
if (retcode == -1) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant find bettxid or incorrect"));
}
else if (retcode == -2) {
throw std::runtime_error("tx still in mempool");
}
else if (retcode == -3)
{
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant decode opret"));
return(result);
}
else if (retcode == -4) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "error scanning chain"));
}
return(result);
}
int64_t totalbets = 0;
int64_t totalprofits = 0;
for (auto b : betinfo.bets) {
totalbets += b.positionsize;
totalprofits += b.profits;
}
if (!betinfo.isOpen) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position closed"));
return result;
}
prices_betjson(result, betinfo.bets, betinfo.leverage, betinfo.lastheight, betinfo.lastprice); // fill output
if (betinfo.isRekt)
{
myfee = betinfo.rektfee; // consolation fee for loss
}
if (myfee != 0)
{
int64_t CCchange = 0, inputsum;
mtx.vin.push_back(CTxIn(bettxid, NVOUT_CCMARKER, CScript())); // spend cc marker
if ((inputsum = AddPricesInputs(cp, mtx, destaddr, myfee + txfee, 64)) > myfee + txfee) // TODO: why do we take txfee from global addr and not from user's addr?
CCchange = (inputsum - myfee);
mtx.vout.push_back(CTxOut(myfee, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
if (CCchange >= txfee)
mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, pricespk));
/// mtx.vout.push_back(MakeCC1vout(cp->evalcode, bettx.vout[2].nValue - myfee - txfee, pricespk)); // change
rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_finalopret(bettxid, totalprofits, rektheight, mypk, betinfo.firstprice, 0, totalbets /*- positionsize*/, 0/*positionsize*/, betinfo.leverage));
return(prices_rawtxresult(result, rawtx, 0));
}
else
{
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position not rekt"));
return(result);
}
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant load or incorrect bettx"));
return(result);
}
// pricescashout rpc impl: bettor can cashout hit bet if it is not rekt
UniValue PricesCashout(int64_t txfee, uint256 bettxid)
{
int32_t nextheight = komodo_nextheight();
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ);
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight);
UniValue result(UniValue::VOBJ);
struct CCcontract_info *cp, C; char destaddr[64];
CTransaction bettx;
/* CTransaction bettx;
uint256 hashBlock, batontxid, tokenid;
int64_t CCchange = 0, positionsize, inputsum, firstprice, lastprice = 0;
int64_t positionsize, firstprice, lastprice = 0;
int32_t firstheight;
int16_t leverage;
std::vector<uint16_t> vec;
std::vector<uint16_t> vec;*/
int64_t CCchange = 0, inputsum;
CPubKey pk, mypk, pricespk;
std::string rawtx;
@ -1644,204 +1771,127 @@ UniValue PricesCashout(int64_t txfee, uint256 bettxid)
mypk = pubkey2pk(Mypubkey());
pricespk = GetUnspendable(cp, 0);
GetCCaddress(cp, destaddr, pricespk);
if (myGetTransaction(bettxid, bettx, hashBlock) != 0 && bettx.vout.size() > 3)
{
if (prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vec, tokenid) == 'B')
{
uint256 finaltxid;
int32_t vini;
int32_t finalheight, endheight;
std::vector<BetInfo> bets;
BetInfo bet1;
if (CCgetspenttxid(finaltxid, vini, finalheight, bettxid, N_CCMARKER) == 0) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position closed"));
return result;
}
bet1.amount = positionsize;
bet1.firstheight = firstheight;
bets.push_back(bet1);
prices_enumaddedbets(batontxid, bets, bettxid);
if (prices_scanchain(bets, leverage, vec, lastprice, endheight) < 0) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "error scanning chain"));
return(result);
}
int64_t totalbets = 0;
int64_t totalprofits = 0;
for (auto b : bets) {
totalbets += b.amount;
totalprofits += b.profits;
}
prices_betjson(result, bets, leverage, endheight, lastprice); // fill output json
int64_t equity = totalbets + totalprofits;
if (equity < 0)
{
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position rekt"));
return(result);
}
mtx.vin.push_back(CTxIn(bettxid, N_CCMARKER, CScript())); // spend cc marker
if ((inputsum = AddPricesInputs(cp, mtx, destaddr, equity + txfee, 64)) > equity + txfee)
CCchange = (inputsum - equity);
mtx.vout.push_back(CTxOut(equity, 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, totalprofits, nextheight - 1, mypk, firstprice, 0, totalbets-positionsize, positionsize, leverage));
return(prices_rawtxresult(result, rawtx, 0));
BetInfo betinfo;
int32_t retcode = prices_getbetinfo(bettxid, betinfo);
if (retcode < 0) {
if (retcode == -1) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant find bettxid or incorrect"));
}
else
else if (retcode == -2) {
throw std::runtime_error("tx still in mempool");
}
else if (retcode == -3)
{
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant decode opret"));
return(result);
}
else if (retcode == -4) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "error scanning chain"));
}
return(result);
}
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant load or incorrect bettx"));
return(result);
int64_t totalbets = 0;
int64_t totalprofits = 0;
for (auto b : betinfo.bets) {
totalbets += b.positionsize;
totalprofits += b.profits;
}
if (!betinfo.isOpen) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position closed"));
return result;
}
prices_betjson(result, betinfo.bets, betinfo.leverage, betinfo.lastheight, betinfo.lastprice); // fill output json
if (betinfo.isRekt)
{
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "position rekt"));
return(result);
}
mtx.vin.push_back(CTxIn(bettxid, NVOUT_CCMARKER, CScript())); // spend cc marker
if ((inputsum = AddPricesInputs(cp, mtx, destaddr, betinfo.equity + txfee, 64)) > betinfo.equity + txfee)
CCchange = (inputsum - betinfo.equity);
mtx.vout.push_back(CTxOut(betinfo.equity, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
if (CCchange >= txfee)
mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, pricespk));
// TODO: what should the opret param be:
rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_finalopret(bettxid, totalprofits, nextheight - 1, mypk, betinfo.firstprice, 0, totalbets/*- betinfo.positionsize*/, 0/*betinfo.positionsize*/, betinfo.leverage));
return(prices_rawtxresult(result, rawtx, 0));
}
// pricesinfo rpc impl
UniValue PricesInfo(uint256 bettxid, int32_t refheight)
{
UniValue result(UniValue::VOBJ);
CTransaction bettx;
/* CTransaction bettx;
uint256 hashBlock, batontxid, tokenid;
int64_t positionsize = 0, firstprice = 0, lastprice = 0;
int32_t firstheight = 0, endheight;
int16_t leverage = 0;
std::vector<uint16_t> vec;
CPubKey pk, mypk, pricespk;
std::string rawtx;
//uint256 costbasistxid;
std::string rawtx; */
if (myGetTransaction(bettxid, bettx, hashBlock) && bettx.vout.size() > 3)
{
if (hashBlock.IsNull())
BetInfo betinfo;
int32_t retcode = prices_getbetinfo(bettxid, betinfo);
if (retcode < 0) {
if( retcode == -1 ) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant find bettxid or incorrect"));
}
else if (retcode == -2) {
throw std::runtime_error("tx still in mempool");
if (prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vec, tokenid) == 'B')
}
else if (retcode == -3)
{
uint256 finaltxid;
int32_t vini;
int32_t finalheight, endheight;
std::vector<BetInfo> bets;
BetInfo bet1;
if (CCgetspenttxid(finaltxid, vini, finalheight, bettxid, N_CCMARKER) == 0)
result.push_back(Pair("status", "closed"));
else
result.push_back(Pair("status", "open"));
bet1.amount = positionsize;
bet1.firstheight = firstheight;
bets.push_back(bet1);
prices_enumaddedbets(batontxid, bets, bettxid);
if( prices_scanchain(bets, leverage, vec, lastprice, endheight) < 0 ) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "error scanning chain"));
return(result);
}
mpz_t mpzTotalbets;
mpz_t mpzTotalprofits;
mpz_t mpzTotalcostbasis;
mpz_init(mpzTotalbets);
mpz_init(mpzTotalprofits);
mpz_init(mpzTotalcostbasis);
int64_t totalbets = 0;
int64_t totalprofits = 0;
for (auto b : bets) {
mpz_t mpzProduct;
mpz_t mpzProfits;
mpz_init(mpzProduct);
mpz_init(mpzProfits);
//totalprofits += b.profits;
//dcostbasis += b.amount * (double)b.costbasis;
// costbasis += b.amount * (b.costbasis / PRICES_POINTFACTOR); // prevent int64 overflow (but we have underflow for 1/BTC)
// std::cerr << "PricesInfo() acc dcostbasis=" << dcostbasis << " b.amount=" << b.amount << " b.costbasis/PRICES_POINTFACTOR=" << (b.costbasis / PRICES_POINTFACTOR) << std::endl;
//std::cerr << "PricesInfo() acc dcostbasis=" << dcostbasis << " b.amount=" << b.amount << " b.costbasis/PRICES_POINTFACTOR=" << (b.costbasis / PRICES_POINTFACTOR) << std::endl;
mpz_set_ui(mpzProduct, b.costbasis);
mpz_mul_ui(mpzProduct, mpzProduct, (uint64_t)b.amount); // b.costbasis * b.amount
mpz_add(mpzTotalcostbasis, mpzTotalcostbasis, mpzProduct); //averageCostbasis += b.costbasis * b.amount;
mpz_add_ui(mpzTotalbets, mpzTotalbets, (uint64_t)b.amount); //totalbets += b.amount;
mpz_add(mpzTotalprofits, mpzTotalprofits, mpzProfits); //totalprofits += b.profits;
totalbets += b.amount;
totalprofits += b.profits;
mpz_clear(mpzProduct);
mpz_clear(mpzProfits);
}
int64_t equity = totalbets + totalprofits;
int64_t averageCostbasis = 0;
if (mpz_get_ui(mpzTotalbets) != 0) { //prevent zero div
mpz_t mpzAverageCostbasis;
mpz_init(mpzAverageCostbasis);
//averageCostbasis = totalcostbasis / totalbets;
mpz_mul_ui(mpzTotalcostbasis, mpzTotalcostbasis, SATOSHIDEN); // profits *= SATOSHIDEN normalization to prevent loss of significance while division
mpz_tdiv_q(mpzAverageCostbasis, mpzTotalcostbasis, mpzTotalbets);
mpz_tdiv_q_ui(mpzAverageCostbasis, mpzAverageCostbasis, SATOSHIDEN); // profits /= SATOSHIDEN de-normalization
averageCostbasis = mpz_get_ui(mpzAverageCostbasis);
mpz_clear(mpzAverageCostbasis);
}
int64_t liqprice = 0;
if (leverage != 0) {// prevent zero div
liqprice = averageCostbasis - averageCostbasis / leverage;
}
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant decode opret"));
return(result);
}
else if (retcode == -4) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "error scanning chain"));
}
return(result);
}
if (equity >= 0)
result.push_back(Pair("rekt", 0));
else
{
result.push_back(Pair("rekt", (int64_t)1));
result.push_back(Pair("rektfee", totalbets / 500));
result.push_back(Pair("rektheight", (int64_t)endheight));
}
if (!betinfo.isRekt)
result.push_back(Pair("rekt", 0));
else
{
result.push_back(Pair("rekt", (int64_t)1));
result.push_back(Pair("rektfee", betinfo.rektfee));
result.push_back(Pair("rektheight", betinfo.lastheight));
}
std::string expr = prices_getsourceexpression(vec);
result.push_back(Pair("expression", expr));
result.push_back(Pair("reduced", prices_getreducedexpr(expr)));
result.push_back(Pair("batontxid", batontxid.GetHex()));
result.push_back(Pair("costbasis", ValueFromAmount(averageCostbasis)));
std::string expr = prices_getsourceexpression(betinfo.parsed);
result.push_back(Pair("expression", expr));
result.push_back(Pair("reduced", prices_getreducedexpr(expr)));
// result.push_back(Pair("batontxid", batontxid.GetHex()));
result.push_back(Pair("costbasis", ValueFromAmount(betinfo.averageCostbasis)));
#ifdef TESTMODE
result.push_back(Pair("costbasis_test_period", 7));
result.push_back(Pair("costbasis_test_period", 7));
#endif
prices_betjson(result, bets, leverage, endheight, lastprice);
prices_betjson(result, betinfo.bets, betinfo.leverage, betinfo.lastheight, betinfo.lastprice);
result.push_back(Pair("LiquidationPrice", ValueFromAmount(liqprice)));
result.push_back(Pair("LiquidationPrice", ValueFromAmount(betinfo.liquidationprice)));
mpz_clear(mpzTotalbets);
mpz_clear(mpzTotalprofits);
mpz_clear(mpzTotalcostbasis);
return(result);
}
}
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "cant find bettxid or incorrect"));
return(result);
}
@ -1852,25 +1902,20 @@ UniValue PricesList(uint32_t filter, CPubKey mypk)
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex, addressIndexCC;
struct CCcontract_info *cp, C;
cp = CCinit(&C, EVAL_PRICES);
//pricespk = GetUnspendable(cp, 0);
// filters and outputs prices bet txid
auto priceslist = [&](std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it, int32_t nvout)
auto AddBetToList = [&](uint256 txid)
{
int64_t amount, firstprice;
int32_t height;
int16_t leverage;
uint256 txid, hashBlock, tokenid;
uint256 hashBlock, tokenid;
CPubKey pk, pricespk;
std::vector<uint16_t> vec;
CTransaction vintx;
txid = it->first.txhash;
if (nvout != it->first.index) // our marker vout
return;
if (GetTransaction(txid, vintx, hashBlock, false) != 0)
{
bool bAppend = false;
@ -1884,7 +1929,7 @@ UniValue PricesList(uint32_t filter, CPubKey mypk)
int32_t height;
uint256 finaltxid;
int32_t spent = CCgetspenttxid(finaltxid, vini, height, txid, N_CCMARKER);
int32_t spent = CCgetspenttxid(finaltxid, vini, height, txid, NVOUT_CCMARKER);
if (filter == 1 && spent < 0 || // open positions
filter == 2 && spent == 0) // closed positions
bAppend = true;
@ -1892,7 +1937,7 @@ UniValue PricesList(uint32_t filter, CPubKey mypk)
if (bAppend)
result.push_back(txid.GetHex());
}
std::cerr << "PricesList() " << " bettxid=" << txid.GetHex() << " mypk=" << HexStr(mypk) << " opretpk=" << HexStr(pk) << " filter=" << filter << " bAppend=" << bAppend << " index=" << it->first.index << " txindex=" << it->first.txindex << std::endl;
std::cerr << "PricesList() " << " bettxid=" << txid.GetHex() << " mypk=" << HexStr(mypk) << " opretpk=" << HexStr(pk) << " filter=" << filter << " bAppend=" << bAppend << std::endl;
}
};
@ -1900,7 +1945,8 @@ UniValue PricesList(uint32_t filter, CPubKey mypk)
SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++)
{
priceslist(it, 3);
if( it->first.txindex == NVOUT_NORMALMARKER )
AddBetToList(it->first.txhash);
}
/* for future when switch to cc marker only
@ -1911,4 +1957,33 @@ UniValue PricesList(uint32_t filter, CPubKey mypk)
}
*/
return(result);
}
void prices_addbookentry(uint256 txid)
{
BetInfo betinfo;
//if( prices_getbetinfo(txid, betinfo) == 0 )
}
// walk through uxtos on the global address
// calculate the balance:
// + rekt positions
// = opposite positions
// - unbalanced positions
UniValue PricesGetOrderbook()
{
UniValue result(UniValue::VARR);
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex, addressIndexCC;
struct CCcontract_info *cp, C;
cp = CCinit(&C, EVAL_PRICES);
SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++)
{
if (it->first.txindex == NVOUT_NORMALMARKER)
prices_addbookentry(it->first.txhash);
}
return result;
}

13
src/rpc/blockchain.cpp

@ -1439,6 +1439,19 @@ UniValue pricesrekt(const UniValue& params, bool fHelp)
return PricesRekt(txfee, bettxid, height);
}
// pricesrekt rpc implementation
UniValue pricesgetorderbook(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error("pricesgetorderbook\n");
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
if (ASSETCHAINS_CBOPRET == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
return PricesGetOrderbook();
}
UniValue gettxout(const UniValue& params, bool fHelp)
{

2
src/rpc/server.cpp

@ -470,6 +470,8 @@ static const CRPCCommand vRPCCommands[] =
{ "prices", "pricescashout", &pricescashout, true },
{ "prices", "pricesrekt", &pricesrekt, true },
{ "prices", "pricesaddfunding", &pricesaddfunding, true },
{ "prices", "pricesgetorderbook", &pricesgetorderbook, true },
// Pegs
{ "pegs", "pegsaddress", &pegsaddress, true },

2
src/rpc/server.h

@ -503,6 +503,8 @@ extern UniValue pricessetcostbasis(const UniValue& params, bool fHelp);
extern UniValue pricescashout(const UniValue& params, bool fHelp);
extern UniValue pricesrekt(const UniValue& params, bool fHelp);
extern UniValue pricesaddfunding(const UniValue& params, bool fHelp);
extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp);
#endif // BITCOIN_RPCSERVER_H

Loading…
Cancel
Save