Merge branch 'FSM' of https://github.com/jl777/komodo into jl777-FSM
xo
This commit is contained in:
@@ -226,8 +226,11 @@ bool priv2addr(char *coinaddr,uint8_t buf33[33],uint8_t priv32[32]);
|
||||
CPubKey buf2pk(uint8_t *buf33);
|
||||
void endiancpy(uint8_t *dest,uint8_t *src,int32_t len);
|
||||
uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv,int32_t entropyvout,int32_t usevout);
|
||||
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk, const std::vector<std::vector<unsigned char>>* vData = NULL);
|
||||
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2, const std::vector<std::vector<unsigned char>>* vData = NULL);
|
||||
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk, std::vector<std::vector<unsigned char>>* vData = NULL);
|
||||
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2, std::vector<std::vector<unsigned char>>* vData = NULL);
|
||||
int32_t has_opret(const CTransaction &tx, uint8_t evalcode);
|
||||
CScript getCCopret(const CScript &scriptPubKey);
|
||||
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData);
|
||||
CC *MakeCCcond1(uint8_t evalcode,CPubKey pk);
|
||||
CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2);
|
||||
CC* GetCryptoCondition(CScript const& scriptSig);
|
||||
|
||||
@@ -58,35 +58,70 @@ CC *MakeCCcond1(uint8_t evalcode,CPubKey pk)
|
||||
return CCNewThreshold(2, {condCC, Sig});
|
||||
}
|
||||
|
||||
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue, CPubKey pk, const std::vector<std::vector<unsigned char>>* vData)
|
||||
int32_t has_opret(const CTransaction &tx, uint8_t evalcode)
|
||||
{
|
||||
int i = 0;
|
||||
for ( auto vout : tx.vout )
|
||||
{
|
||||
if ( vout.scriptPubKey[0] == OP_RETURN && vout.scriptPubKey[1] == evalcode )
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CScript getCCopret(const CScript &scriptPubKey)
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
|
||||
CScript dummy; CScript opret;
|
||||
if ( scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) )
|
||||
{
|
||||
//opret << E_MARSHAL(ss << vParams[0]);
|
||||
opret = CScript(vParams[0].begin()+6, vParams[0].end());
|
||||
}
|
||||
//fprintf(stderr, "params_size.%li parmas_hexstr.%s\n", vParams.size(), HexStr(vParams[0].begin(),vParams[0].end()).c_str());
|
||||
//opret = CScript(vParams[0].begin(), vParams[0].end());
|
||||
return opret;
|
||||
}
|
||||
|
||||
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData)
|
||||
{
|
||||
if ( opret.empty() )
|
||||
return false;
|
||||
vData.push_back(std::vector<unsigned char>(opret.begin(), opret.end()));
|
||||
return true;
|
||||
}
|
||||
|
||||
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue, CPubKey pk, std::vector<std::vector<unsigned char>>* vData)
|
||||
{
|
||||
CTxOut vout;
|
||||
CC *payoutCond = MakeCCcond1(evalcode,pk);
|
||||
vout = CTxOut(nValue,CCPubKey(payoutCond));
|
||||
if ( vData )
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
|
||||
//std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
|
||||
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
|
||||
vPubKeys.push_back(pk);
|
||||
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 1, vPubKeys, vtmpData);
|
||||
//vPubKeys.push_back(pk);
|
||||
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 1, vPubKeys, ( * vData));
|
||||
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
|
||||
}
|
||||
cc_free(payoutCond);
|
||||
return(vout);
|
||||
}
|
||||
|
||||
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2, const std::vector<std::vector<unsigned char>>* vData)
|
||||
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2, std::vector<std::vector<unsigned char>>* vData)
|
||||
{
|
||||
CTxOut vout;
|
||||
CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2);
|
||||
vout = CTxOut(nValue,CCPubKey(payoutCond));
|
||||
if ( vData )
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
|
||||
//std::vector<std::vector<unsigned char>> vtmpData = std::vector<std::vector<unsigned char>>(vData->begin(), vData->end());
|
||||
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
|
||||
vPubKeys.push_back(pk1);
|
||||
vPubKeys.push_back(pk2);
|
||||
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 2, vPubKeys, vtmpData);
|
||||
// skip pubkeys. These need to maybe be optional and we need some way to get them out that is easy!
|
||||
//vPubKeys.push_back(pk1);
|
||||
//vPubKeys.push_back(pk2);
|
||||
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 2, vPubKeys, ( * vData));
|
||||
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
|
||||
}
|
||||
cc_free(payoutCond);
|
||||
@@ -114,8 +149,12 @@ bool IsCCInput(CScript const& scriptSig)
|
||||
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime)
|
||||
{
|
||||
LOCK(mempool.cs);
|
||||
CCoinsView dummy;
|
||||
CCoinsViewCache view(&dummy);
|
||||
int64_t interest; uint64_t valuein;
|
||||
CCoinsViewCache &view = *pcoinsTip;
|
||||
CCoinsViewMemPool viewMemPool(pcoinsTip, mempool);
|
||||
view.SetBackend(viewMemPool);
|
||||
valuein = view.GetValueIn(height,&interest,tx,blocktime);
|
||||
if ( valuein-tx.GetValueOut() > txfee )
|
||||
{
|
||||
@@ -584,7 +623,7 @@ bool komodo_txnotarizedconfirmed(uint256 txid)
|
||||
fprintf(stderr,"komodo_txnotarizedconfirmed no hashBlock for txid %s\n",txid.ToString().c_str());
|
||||
return(0);
|
||||
}
|
||||
else if ( (pindex= mapBlockIndex[hashBlock]) == 0 || (txheight= pindex->GetHeight()) <= 0 )
|
||||
else if ( (pindex= komodo_blockindex(hashBlock)) == 0 || (txheight= pindex->GetHeight()) <= 0 )
|
||||
{
|
||||
fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d %p for txid %s\n",txheight,pindex,txid.ToString().c_str());
|
||||
return(0);
|
||||
|
||||
@@ -250,10 +250,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarised)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelpayment!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for channelpayment!");
|
||||
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.2 is CC for channelpayment!");
|
||||
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" is CC for channelpayment!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelpayment!");
|
||||
else if ( ConstrainVout(tx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
@@ -283,8 +281,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,channeladdress,(p1-param2)*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid CC change amount for channelpayment!");
|
||||
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelpayment!");
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelpayment!");
|
||||
else if (param1+param2!=p1)
|
||||
return eval->Invalid("invalid payment depth!");
|
||||
else if (tx.vout[3].nValue > prevTx.vout[0].nValue)
|
||||
@@ -313,10 +311,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarised)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelclose!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for channelclose!");
|
||||
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.2 is CC for channelclose!");
|
||||
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" is CC for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,channeladdress,0)==0 )
|
||||
return eval->Invalid("vout.0 is CC for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
@@ -329,8 +325,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelclose!");
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelclose!");
|
||||
else if (tx.vout[0].nValue != prevTx.vout[0].nValue)
|
||||
return eval->Invalid("invalid CC amount, amount must match funds in channel");
|
||||
}
|
||||
@@ -358,10 +354,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
return eval->Invalid("channelClose is not yet confirmed(notarised)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelrefund!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for channelrefund!");
|
||||
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.2 is CC for channelrefund!");
|
||||
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" CC for channelrefund!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.0 is CC marker to srcpub or invalid amount for channelrefund!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
@@ -376,8 +370,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelrefund!");
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelrefund!");
|
||||
else if (tx.vout[2].nValue != prevTx.vout[0].nValue)
|
||||
return eval->Invalid("invalid amount, refund amount and funds in channel must match!");
|
||||
}
|
||||
|
||||
@@ -67,38 +67,26 @@ UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
// make op_return payload as normal.
|
||||
CScript opret = custom_opret('1',mypk);
|
||||
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
|
||||
vData.push_back(std::vector<unsigned char>(opret.begin(), opret.end()));
|
||||
// make vout0 with op_return included as payload.
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,mypk,&vData));
|
||||
fprintf(stderr, "vout size2.%li\n", mtx.vout.size());
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,CScript());
|
||||
return(custom_rawtxresult(result,rawtx,broadcastflag));
|
||||
if ( makeCCopret(opret, vData) )
|
||||
{
|
||||
// make vout0 with op_return included as payload.
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,mypk,&vData));
|
||||
fprintf(stderr, "vout size2.%li\n", mtx.vout.size());
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,CScript());
|
||||
return(custom_rawtxresult(result,rawtx,broadcastflag));
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
bool has_opret(const CTransaction &tx, uint8_t evalcode)
|
||||
{
|
||||
for ( auto vout : tx.vout )
|
||||
{
|
||||
if ( vout.scriptPubKey[0] == OP_RETURN && vout.scriptPubKey[1] == evalcode )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool custom_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
|
||||
{
|
||||
char expectedaddress[64]; CPubKey pk;
|
||||
CScript opret; int32_t numvout;
|
||||
if ( !has_opret(tx, EVAL_CUSTOM) )
|
||||
if ( has_opret(tx, EVAL_CUSTOM) == 0 )
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
|
||||
CScript dummy;
|
||||
if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && vParams.size() == 1 )
|
||||
{
|
||||
opret << E_MARSHAL(ss << vParams[0]);
|
||||
}
|
||||
opret = getCCopret(tx.vout[0].scriptPubKey);
|
||||
numvout = 1;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -592,7 +592,7 @@ void addmultisigaddress(char *refcoin,char *acname,int32_t M, char *pubkeys)
|
||||
|
||||
cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required)
|
||||
{
|
||||
cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,n,v; int64_t satoshis; bits256 txid;
|
||||
cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,j=0,n,v; int64_t satoshis; bits256 txid;
|
||||
*totalp = 0;
|
||||
if ( (n= cJSON_GetArraySize(unspents)) > 0 )
|
||||
{
|
||||
@@ -610,7 +610,10 @@ cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required)
|
||||
jaddi(vins,vin);
|
||||
*totalp += satoshis;
|
||||
if ( (*totalp) >= required )
|
||||
break;
|
||||
{
|
||||
if (j<3) j++;
|
||||
else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -910,10 +913,11 @@ void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxi
|
||||
processed++;
|
||||
}
|
||||
free(rawtx);
|
||||
} else fprintf(stderr,"couldnt create rawtx\n");
|
||||
} else fprintf(stderr,"couldnt create rawtx\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
rawtx=0;
|
||||
lasttxid = jbits256(item,"last_txid");
|
||||
if ( lasttxid.txid==withdrawtxid.txid)
|
||||
{
|
||||
@@ -921,24 +925,27 @@ void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxi
|
||||
}
|
||||
else rawtx=jstr(item,"hex");
|
||||
K=jint(item,"number_of_signs");
|
||||
if ( rawtx!=0 && (clijson=addsignature(refcoin,"",rawtx,M)) != 0 )
|
||||
if (rawtx!=0)
|
||||
{
|
||||
if ( is_cJSON_True(jobj(clijson,"complete")) != 0 )
|
||||
{
|
||||
txid=gatewayscompletesigning(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %dof%d\n",bits256_str(str,withdrawtxid),K+1,N);
|
||||
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
|
||||
}
|
||||
else if ( jint(clijson,"partialtx") != 0 )
|
||||
if ((clijson=addsignature(refcoin,"",rawtx,M)) != 0 )
|
||||
{
|
||||
txid=gatewayspartialsign(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %d/%dof%d\n",bits256_str(str,withdrawtxid),K+1,M,N);
|
||||
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
|
||||
}
|
||||
free_json(clijson);
|
||||
processed++;
|
||||
if ( lasttxid.txid==withdrawtxid.txid) free(rawtx);
|
||||
}
|
||||
if ( is_cJSON_True(jobj(clijson,"complete")) != 0 )
|
||||
{
|
||||
txid=gatewayscompletesigning(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %dof%d\n",bits256_str(str,withdrawtxid),K+1,N);
|
||||
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
|
||||
}
|
||||
else if ( jint(clijson,"partialtx") != 0 )
|
||||
{
|
||||
txid=gatewayspartialsign(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %d/%dof%d\n",bits256_str(str,withdrawtxid),K+1,M,N);
|
||||
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
|
||||
}
|
||||
free_json(clijson);
|
||||
processed++;
|
||||
if ( lasttxid.txid==withdrawtxid.txid) free(rawtx);
|
||||
}
|
||||
} else fprintf(stderr,"couldnt create rawtx or find previous partial signed tx\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,20 +628,25 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
return eval->Invalid("deposit amount greater then bind total supply");
|
||||
else if (komodo_txnotarizedconfirmed(deposittxid) == false)
|
||||
return eval->Invalid("gatewaysdeposit tx is not yet confirmed(notarised)!");
|
||||
else if (myGetTransaction(tx.vin[2].prevout.hash,tmptx,hashblock) == 0)
|
||||
return eval->Invalid("invalid gatewaysdeposittxid!");
|
||||
else if (IsCCInput(tx.vin[0].scriptSig) != 0)
|
||||
return eval->Invalid("vin.0 is normal for gatewaysclaim!");
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
else if (tx.vin.size()>2)
|
||||
{
|
||||
i=1;
|
||||
while (i<=tx.vin.size()-2)
|
||||
{
|
||||
if (IsCCInput(tx.vin[i].scriptSig)==0) return eval->Invalid("vin."+std::to_string(i)+" is CC for gatewaysclaim!");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewaysclaim or invalid marker amount!");
|
||||
else if (_GetCCaddress(destaddr,EVAL_TOKENS,pubkey)==0 || ConstrainVout(tx.vout[0],1,destaddr,amount)==0)
|
||||
return eval->Invalid("invalid vout tokens to destpub for gatewaysclaim!");
|
||||
else if (numvouts>2 && (myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || ConstrainVout(tx.vout[1],1,gatewaystokensaddr,tmptx.vout[tx.vin[1].prevout.n].nValue-amount)==0))
|
||||
else if (numvouts>2 && tx.vout[1].scriptPubKey.IsPayToCryptoCondition() && (myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || ConstrainVout(tx.vout[1],1,gatewaystokensaddr,tmptx.vout[tx.vin[1].prevout.n].nValue-amount)==0))
|
||||
return eval->Invalid("invalid CC change vout for gatewaysclaim!");
|
||||
else if (amount!=tmpamount)
|
||||
return eval->Invalid("claimed amount different then deposit amount");
|
||||
else if (tx.vout[0].nValue!=amount)
|
||||
return eval->Invalid("claim amount not matching amount in opret");
|
||||
return eval->Invalid("claimed amount different then deposit amount");
|
||||
else if (pubkey!=tmppubkey)
|
||||
return eval->Invalid("claim destination pubkey different than in deposit tx");
|
||||
else
|
||||
@@ -697,8 +702,6 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
return eval->Invalid("invalid marker vout for gatewaysWithdraw!");
|
||||
else if ( ConstrainVout(tmptx.vout[1],1,gatewaystokensaddr,amount)==0)
|
||||
return eval->Invalid("invalid tokens to gateways vout for gatewaysWithdraw!");
|
||||
else if (tmptx.vout[1].nValue!=amount)
|
||||
return eval->Invalid("amount in opret not matching tx tokens amount!");
|
||||
else if (komodo_txnotarizedconfirmed(withdrawtxid) == false)
|
||||
return eval->Invalid("gatewayswithdraw tx is not yet confirmed(notarised)!");
|
||||
else if (myGetTransaction(bindtxid,tmptx,hashblock) == 0)
|
||||
@@ -953,7 +956,7 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,2) > 0 )
|
||||
{
|
||||
if (AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, totalsupply, 64)>0)
|
||||
{
|
||||
@@ -1032,7 +1035,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,4) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,3) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,destpub));
|
||||
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,cointxid))) << OP_CHECKSIG));
|
||||
@@ -1104,7 +1107,7 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
|
||||
{
|
||||
if ((inputs=AddGatewaysInputs(cp, mtx, gatewayspk, bindtxid, amount, 60)) > 0)
|
||||
{
|
||||
@@ -1182,7 +1185,7 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
|
||||
}
|
||||
}
|
||||
}
|
||||
if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE, 4) > 0 )
|
||||
if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE, 2) > 0 )
|
||||
{
|
||||
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, amount, 60)) > 0)
|
||||
{
|
||||
@@ -1294,7 +1297,7 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refc
|
||||
return("");
|
||||
}
|
||||
}
|
||||
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
|
||||
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(tx.GetHash(),0,CScript()));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
|
||||
@@ -1393,7 +1396,7 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string
|
||||
return("");
|
||||
}
|
||||
}
|
||||
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
|
||||
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(lasttxid,0,CScript()));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
|
||||
@@ -1458,7 +1461,7 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
|
||||
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(completetxid,0,CScript()));
|
||||
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -193,11 +199,10 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 )
|
||||
return(eval->Invalid("negative values"));
|
||||
if ( !CheckTxFee(tx, PAYMENTS_TXFEE, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
|
||||
return eval->Invalid("txfee is too high");
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
//fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() );
|
||||
|
||||
if ( !CheckTxFee(tx, PAYMENTS_TXFEE+1, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
|
||||
return eval->Invalid("txfee is too high");
|
||||
// Get all the script pubkeys and allocations
|
||||
std::vector<int64_t> allocations;
|
||||
std::vector<CScript> scriptPubKeys;
|
||||
@@ -212,6 +217,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++;
|
||||
}
|
||||
@@ -247,7 +266,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
int64_t test = allocations[n];
|
||||
test *= checkamount;
|
||||
test /= totalallocations;
|
||||
if ( test != tx.vout[i].nValue )
|
||||
if ( test != tx.vout[i].nValue && test != tx.vout[i].nValue-1 )
|
||||
{
|
||||
fprintf(stderr, "vout.%i test.%li vs nVlaue.%li\n",i, test, tx.vout[i].nValue);
|
||||
return(eval->Invalid("amounts do not match"));
|
||||
@@ -277,18 +296,28 @@ 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.
|
||||
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
|
||||
if ( pblockindex->GetHeight() > ht-lockedblocks )
|
||||
// check the chain depth vs locked blocks requirement.
|
||||
CBlockIndex* pblockindex = komodo_blockindex(blockhash);
|
||||
if ( pblockindex == 0 || pblockindex->GetHeight() > ht-lockedblocks )
|
||||
{
|
||||
fprintf(stderr, "vin.%i is not elegible to be spent yet height.%i vs elegible_ht.%i\n", i, pblockindex->GetHeight(), ht-lockedblocks);
|
||||
fprintf(stderr, "vin.%i is not elegible to be spent yet height.%i vs elegible_ht.%i\n", i, pblockindex!=0?pblockindex->GetHeight():0, ht-lockedblocks);
|
||||
return(eval->Invalid("vin not elegible"));
|
||||
}
|
||||
} else return(eval->Invalid("cant get vin transaction"));
|
||||
@@ -340,8 +369,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;
|
||||
@@ -524,7 +563,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
newamount += (PAYMENTS_TXFEE - mtx.vout[i+1].nValue);
|
||||
mtx.vout[i+1].nValue = PAYMENTS_TXFEE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( (inputsum= AddPaymentsInputs(cp,mtx,txidpk,newamount+2*PAYMENTS_TXFEE,CC_MAXVINS/2,createtxid,latestheight)) >= newamount+2*PAYMENTS_TXFEE )
|
||||
{
|
||||
std::string rawtx;
|
||||
@@ -603,10 +642,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 +675,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 +922,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"));
|
||||
|
||||
Reference in New Issue
Block a user