add validation for OP_RETURN to payments CC. Enable ccvoutopret for payments fund.

This commit is contained in:
blackjok3r
2019-04-20 19:29:16 +08:00
parent d12fb49e80
commit fea2b66581
4 changed files with 135 additions and 53 deletions

View File

@@ -16,6 +16,12 @@
#include "CCPayments.h"
/*
-earlytxid is not an -ac_param, so it doesnt affect the chain magics
extra data after the normal CCvout is whatever data we want and can represent whatever we want
so -ac_script=<payments CC vout + useearlytxid>
in the validation if you see the useearlytxid in the opreturn data or extra data, you use the earlytxid as the txid that specifies the payment
0) txidopret <- allocation, scriptPubKey, opret
1) create <- locked_blocks, minrelease, list of txidopret
@@ -212,6 +218,20 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
allocations.push_back(allocation);
//fprintf(stderr, "i.%i scriptpubkey.%s allocation.%li\n",i,scriptPubKeys[i].ToString().c_str(),allocation);
checkallocations += allocation;
// if we have an op_return to pay to need to check it exists and is paying the correct opret.
if ( !opret.empty() )
{
if ( !fHasOpret )
{
fprintf(stderr, "missing opret.%s in payments release.\n",HexStr(opret.begin(), opret.end()).c_str());
return(eval->Invalid("missing opret in payments release"));
}
else if ( CScript(opret.begin(),opret.end()) != tx.vout[tx.vout.size()-1].scriptPubKey )
{
fprintf(stderr, "opret.%s vs opret.%s\n",HexStr(opret.begin(), opret.end()).c_str(), HexStr(tx.vout[tx.vout.size()-1].scriptPubKey.begin(), tx.vout[tx.vout.size()-1].scriptPubKey.end()).c_str());
return(eval->Invalid("pays incorrect opret"));
}
}
}
i++;
}
@@ -277,14 +297,24 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
Getscriptaddress(destaddr,txin.vout[vin.prevout.n].scriptPubKey);
if ( strcmp(destaddr,coinaddr) != 0 )
{
std::vector<uint8_t> scriptPubKey,opret; uint256 checktxid;
if ( txin.vout.size() < 2 || DecodePaymentsFundOpRet(txin.vout[txin.vout.size()-1].scriptPubKey,checktxid) != 'F' || checktxid != createtxid )
CScript opret; uint256 checktxid; int32_t opret_ind;
if ( (opret_ind= has_opret(txin, EVAL_PAYMENTS)) == 0 )
{
// get op_return from CCvout
opret = getCCopret(txin.vout[0].scriptPubKey);
}
else
{
// get op_return from the op_return
opret = txin.vout[opret_ind].scriptPubKey;
} // else return(eval->Invalid("vin has wrong amount of vouts")); // dont think this is needed?
if ( DecodePaymentsFundOpRet(opret,checktxid) != 'F' || checktxid != createtxid )
{
fprintf(stderr, "vin.%i is not a payments CC vout: txid.%s\n", i, txin.GetHash().ToString().c_str());
return(eval->Invalid("vin is not paymentsCC type"));
} //else fprintf(stderr, "vin.%i opret type txid.%s\n", i, txin.GetHash().ToString().c_str());
}
}
// check the chain depth vs locked blcoks requirement.
// check the chain depth vs locked blocks requirement.
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
if ( pblockindex->GetHeight() > ht-lockedblocks )
{
@@ -340,8 +370,18 @@ int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
}
if ( iter == 0 )
{
std::vector<uint8_t> scriptPubKey,opret;
if ( myGetTransaction(txid,tx,hashBlock) == 0 || tx.vout.size() < 2 || DecodePaymentsFundOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,checktxid) != 'F' || checktxid != createtxid )
CScript opret; uint256 checktxid; int32_t opret_ind;
if ( (opret_ind= has_opret(vintx, EVAL_PAYMENTS)) == 0 )
{
// get op_return from CCvout
opret = getCCopret(vintx.vout[0].scriptPubKey);
}
else
{
// get op_return from the op_return
opret = vintx.vout[opret_ind].scriptPubKey;
}
if ( myGetTransaction(txid,tx,hashBlock) == 0 || DecodePaymentsFundOpRet(opret,checktxid) != 'F' || checktxid != createtxid )
{
fprintf(stderr,"bad opret %s vs %s\n",checktxid.GetHex().c_str(),createtxid.GetHex().c_str());
continue;
@@ -603,10 +643,16 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
}
else
{
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,amount,Paymentspk));
opret = EncodePaymentsFundOpRet(txid);
fprintf(stderr, "opret.%s\n", HexStr(opret.begin(), opret.end()).c_str());
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
if ( makeCCopret(opret, vData) )
{
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,amount,Paymentspk,&vData));
fprintf(stderr, "params_size.%li parmas_hexstr.%s\n", vData.size(), HexStr(vData[0].begin(),vData[0].end()).c_str());
}
}
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,opret);
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,CScript());
if ( params != 0 )
free_json(params);
return(payments_rawtxresult(result,rawtx,1));
@@ -630,24 +676,34 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); UniValue result(UniValue::VOBJ); CPubKey mypk; std::string rawtx;
std::vector<uint8_t> scriptPubKey,opret; int32_t allocation,n,retval0,retval1=0;
std::vector<uint8_t> scriptPubKey,opret; int32_t n,retval0,retval1=0; int64_t allocation;
cJSON *params = payments_reparse(&n,jsonstr);
mypk = pubkey2pk(Mypubkey());
if ( params != 0 && n > 1 && n <= 3 )
{
allocation = juint(jitem(params,0),0);
allocation = (int64_t)jint(jitem(params,0),0);
retval0 = payments_parsehexdata(scriptPubKey,jitem(params,1),0);
if ( n == 3 )
retval1 = payments_parsehexdata(opret,jitem(params,2),0);
if ( allocation > 0 && retval0 == 0 && retval1 == 0 && AddNormalinputs(mtx,mypk,PAYMENTS_TXFEE,10) > 0 )
CScript test = CScript(scriptPubKey.begin(),scriptPubKey.end());
txnouttype whichType;
if (!::IsStandard(test, whichType))
{
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,EncodePaymentsTxidOpRet(allocation,scriptPubKey,opret));
if ( params != 0 )
free_json(params);
return(payments_rawtxresult(result,rawtx,1));
result.push_back(Pair("result","error"));
result.push_back(Pair("error","scriptPubkey is not valid payment."));
}
else
{
if ( n == 3 )
retval1 = payments_parsehexdata(opret,jitem(params,2),0);
if ( allocation > 0 && retval0 == 0 && retval1 == 0 && AddNormalinputs(mtx,mypk,PAYMENTS_TXFEE*2,10) > 0 )
{
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,EncodePaymentsTxidOpRet(allocation,scriptPubKey,opret));
if ( params != 0 )
free_json(params);
return(payments_rawtxresult(result,rawtx,1));
}
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid params or cant find txfee"));
}
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid params or cant find txfee"));
}
else
{
@@ -867,7 +923,7 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
funds = CCaddress_balance(fundsaddr,1);
result.push_back(Pair(fundsaddr,ValueFromAmount(funds)));
GetCCaddress(cp,fundsopretaddr,Paymentspk);
fundsopret = CCaddress_balance(fundsopretaddr,1);
fundsopret = CCaddress_balance(fundsopretaddr,1); // Shows balance for ALL payments plans, not just the one asked for!
result.push_back(Pair(fundsopretaddr,ValueFromAmount(fundsopret)));
result.push_back(Pair("totalfunds",ValueFromAmount(funds+fundsopret)));
result.push_back(Pair("result","success"));