first validation code added

This commit is contained in:
dimxy
2019-04-16 23:08:39 +05:00
parent e0fa061cc9
commit efaedac711

View File

@@ -126,8 +126,212 @@ uint8_t prices_finalopretdecode(CScript scriptPubKey,uint256 &bettxid,int64_t &p
return(0); return(0);
} }
bool CheckPricesOpret(const CTransaction & tx, vscript_t &opret)
{
return (tx.vout.size() == 0 || !GetOpReturnData(tx.vout.back().scriptPubKey, opret) || opret.size() < 3 || opret.begin()[0] != EVAL_PRICES) || opret.begin()[1] == 0;
}
bool ValidateBetTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & bettx)
{
uint256 tokenid;
int64_t positionsize, firstprice;
int32_t firstheight;
int16_t leverage;
CPubKey pk, pricespk;
std::vector<uint16_t> vec;
if (bettx.vout.size() < 5 || bettx.vout.size() > 6)
return eval->Invalid("incorrect vout number for bet tx");
vscript_t opret;
if( prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vec, tokenid) != 'B')
return eval->Invalid("cannot decode opreturn for bet tx");
pricespk = GetUnspendable(cp, 0);
if (MakeCC1vout(cp->evalcode, bettx.vout[0].nValue, pk) != bettx.vout[0])
return eval->Invalid("cannot validate vout0 in bet tx with pk from opreturn");
if (MakeCC1vout(cp->evalcode, bettx.vout[1].nValue, pricespk) != bettx.vout[1])
return eval->Invalid("cannot validate vout1 in bet tx with global pk");
if( MakeCC1of2vout(cp->evalcode, bettx.vout[2].nValue, pk, pricespk) != bettx.vout[2] )
return eval->Invalid("cannot validate 1of2 vout2 in bet tx with pk from opreturn");
return true;
}
bool ValidateAddFundingTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & addfundingtx)
{
uint256 bettxid;
int64_t amount;
CPubKey pk, pricespk;
if (addfundingtx.vout.size() < 3 || addfundingtx.vout.size() > 4)
return eval->Invalid("incorrect vout number for add funding tx");
vscript_t opret;
if (prices_addopretdecode(addfundingtx.vout.back().scriptPubKey, bettxid, pk, amount) != 'A')
return eval->Invalid("cannot decode opreturn for add funding tx");
pricespk = GetUnspendable(cp, 0);
if (MakeCC1vout(cp->evalcode, addfundingtx.vout[0].nValue, pk) != addfundingtx.vout[0])
return eval->Invalid("cannot validate vout0 in add funding tx with pk from opreturn");
if (MakeCC1vout(cp->evalcode, addfundingtx.vout[1].nValue, pricespk) != addfundingtx.vout[1])
return eval->Invalid("cannot validate vout1 in add funding tx with global pk");
return true;
}
bool ValidateCostbasisTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & costbasistx, const CTransaction & bettx)
{
uint256 bettxid;
int64_t amount;
CPubKey pk, pricespk;
int32_t height;
// check basic structure:
if (costbasistx.vout.size() < 3 || costbasistx.vout.size() > 4)
return eval->Invalid("incorrect vout number for add funding tx");
vscript_t opret;
if (prices_costbasisopretdecode(costbasistx.vout.back().scriptPubKey, bettxid, pk, height, amount) != 'C')
return eval->Invalid("cannot decode opreturn for setcostbasis tx");
pricespk = GetUnspendable(cp, 0);
if (MakeCC1vout(cp->evalcode, costbasistx.vout[0].nValue, pk) != costbasistx.vout[0])
return eval->Invalid("cannot validate vout0 in add funding tx with pk from opreturn");
if (MakeCC1vout(cp->evalcode, costbasistx.vout[1].nValue, pricespk) != costbasistx.vout[1])
return eval->Invalid("cannot validate vout1 in add funding tx with global pk");
if (bettx.vout.size() < 1) // maybe this is already checked outside, but it is safe to check here too and have encapsulated check
return eval->Invalid("incorrect bettx");
// check costbasis rules:
if (costbasistx.vout[0].nValue > bettx.vout[1].nValue / 10)
return eval->Invalid("costbasis myfee too big");
uint256 tokenid;
int64_t positionsize, firstprice;
int32_t firstheight;
int16_t leverage;
std::vector<uint16_t> vec;
if (prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vec, tokenid) != 'B')
return eval->Invalid("cannot decode opreturn for bet tx");
if( firstheight + PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH > chainActive.Height() )
return eval->Invalid("cannot calculate costbasis yet");
return true;
}
bool ValidateFinalTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & finaltx)
{
uint256 bettxid;
int64_t amount;
CPubKey pk, pricespk;
int64_t profits;
int32_t height;
int64_t firstprice, costbasis, addedbets, positionsize;
int16_t leverage;
if (finaltx.vout.size() < 2 || finaltx.vout.size() > 3)
return eval->Invalid("incorrect vout number for final tx");
vscript_t opret;
if (prices_finalopretdecode(finaltx.vout.back().scriptPubKey, bettxid, profits, height, pk, firstprice, costbasis, addedbets, positionsize, leverage) != 'F')
return eval->Invalid("cannot decode opreturn for final tx");
pricespk = GetUnspendable(cp, 0);
if (MakeCC1vout(cp->evalcode, finaltx.vout[0].nValue, pk) != finaltx.vout[0])
return eval->Invalid("cannot validate vout0 in final tx with pk from opreturn");
if( finaltx.vout.size() == 3 && MakeCC1vout(cp->evalcode, finaltx.vout[1].nValue, pricespk) != finaltx.vout[1] )
return eval->Invalid("cannot validate vout1 in final tx with global pk");
return true;
}
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{ {
vscript_t vopret;
// check basic opret rules:
if (CheckPricesOpret(tx, vopret))
return eval->Invalid("tx has no prices opreturn");
uint8_t funcId = vopret.begin()[1];
CTransaction vintx;
vscript_t vintxOpret;
int32_t ccVinCount = 0;
int32_t prevoutN = 0;
// load vintx:
for (auto vin : tx.vin)
if (cp->ismyvin(vin.scriptSig)) {
uint256 hashBlock;
if (myGetTransaction(vin.prevout.hash, vintx, hashBlock))
return eval->Invalid("cannot load vin tx");
prevoutN = vin.prevout.n;
ccVinCount++;
}
if (ccVinCount != 1) // must be only one cc vintx
return eval->Invalid("incorrect cc vin txns num");
if (!CheckPricesOpret(vintx, vintxOpret))
return eval->Invalid("cannot find prices opret in vintx");
if (vintxOpret.begin()[1] == 'B' && prevoutN == 3) { // check basic spending rules
return eval->Invalid("cannot spend bet marker");
}
switch (funcId) {
case 'B': // bet
return eval->Invalid("unexpected validate for bet funcid");
case 'A': // add funding
// check tx structure:
if (!ValidateAddFundingTx(cp, eval, tx))
return false; // invalid state is already set in the func
if (vintxOpret.begin()[1] == 'B') {
if (!ValidateBetTx(cp, eval, vintx)) // check tx structure
return false;
}
else if (vintxOpret.begin()[1] == 'A') {
// no need to validate the previous addfunding tx (it was validated when added)
}
if (prevoutN != 0) { // check spending rules
return eval->Invalid("incorrect vout to spend");
}
break;
case 'C': // set costbasis
if (!ValidateBetTx(cp, eval, vintx)) // first check bet tx
return false;
if (!ValidateCostbasisTx(cp, eval, tx, vintx))
return false;
if (prevoutN != 1) { // check spending rules
return eval->Invalid("incorrect vout to spend");
}
break;
case 'F': // final tx
if (!ValidateBetTx(cp, eval, vintx)) // first check bet tx
return false;
if (!ValidateFinalTx(cp, eval, tx))
return false;
if (prevoutN != 2) { // check spending rules
return eval->Invalid("incorrect vout to spend");
}
break;
default:
return eval->Invalid("invalid funcid");
}
return true; return true;
} }
// end of consensus code // end of consensus code
@@ -138,6 +342,7 @@ int64_t AddPricesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char
{ {
int64_t nValue, price, totalinputs = 0; uint256 txid, hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout, n = 0; 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; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
SetCCunspents(unspentOutputs, destaddr); SetCCunspents(unspentOutputs, destaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++)
{ {
@@ -174,8 +379,12 @@ UniValue prices_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcast
RelayTransaction(tx); RelayTransaction(tx);
result.push_back(Pair("txid", tx.GetHash().ToString())); result.push_back(Pair("txid", tx.GetHash().ToString()));
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
} else result.push_back(Pair("error","decode hex")); }
} else result.push_back(Pair("error","couldnt finalize CCtx")); else
result.push_back(Pair("error", "decode hex"));
}
else
result.push_back(Pair("error", "couldnt finalize CCtx"));
return(result); return(result);
} }
@@ -446,6 +655,7 @@ int64_t prices_costbasis(CTransaction bettx)
uint256 txidCostbasis; uint256 txidCostbasis;
int32_t vini; int32_t vini;
int32_t height; int32_t height;
if (CCgetspenttxid(txidCostbasis, vini, height, bettx.GetHash(), 1) < 0) { if (CCgetspenttxid(txidCostbasis, vini, height, bettx.GetHash(), 1) < 0) {
std::cerr << "prices_costbasis() no costbasis txid found" << std::endl; std::cerr << "prices_costbasis() no costbasis txid found" << std::endl;
return 0; return 0;
@@ -509,9 +719,11 @@ UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector<
{ {
int32_t nextheight = komodo_nextheight(); 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; CPubKey pricespk, mypk; int64_t betamount, firstprice; struct CCcontract_info *cp, C;
CPubKey pricespk, mypk;
int64_t betamount, firstprice;
std::vector<uint16_t> vec; std::vector<uint16_t> vec;
char myaddr[64]; //char myaddr[64];
std::string rawtx; std::string rawtx;
if (leverage > PRICES_MAXLEVERAGE || leverage < -PRICES_MAXLEVERAGE) if (leverage > PRICES_MAXLEVERAGE || leverage < -PRICES_MAXLEVERAGE)
@@ -525,7 +737,7 @@ UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector<
txfee = PRICES_TXFEE; txfee = PRICES_TXFEE;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
pricespk = GetUnspendable(cp, 0); pricespk = GetUnspendable(cp, 0);
GetCCaddress(cp, myaddr, mypk); //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) 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("result", "error"));