Browse Source

MakeTokensCC1of2vout MakeTokensCCcond1of2 test code added

gateways partially adapted for tokens
pull/4/head
dimxy 5 years ago
parent
commit
1f6d62e7c8
  1. 18
      src/cc/CCinclude.h
  2. 10
      src/cc/CCtokens.cpp
  3. 1
      src/cc/CCtokens.h
  4. 31
      src/cc/CCtx.cpp
  5. 47
      src/cc/CCutils.cpp
  6. 153
      src/cc/gateways.cpp
  7. 2
      src/cc/heir.cpp

18
src/cc/CCinclude.h

@ -91,10 +91,14 @@ struct CCcontract_info
char unspendableCCaddr[64], CChexstr[72], normaladdr[64];
uint8_t CCpriv[32];
// this for 1of2 key spending condition (for this evalcode)
// this for 1of2 keys coins cryptocondition (for this evalcode)
// NOTE: only one evalcode is allowed at this time
char unspendable1of2addr[64];
CPubKey unspendable1of2pk[2];
char coins1of2addr[64];
CPubKey coins1of2pk[2];
// the same for tokens 1of2 keys cc
char tokens1of2addr[64];
CPubKey tokens1of2pk[2];
// this is for spending from two additional 'unspendable' CC addresses of other eval codes
// (that is, for spending from several cc contract 'unspendable' addresses):
@ -153,15 +157,15 @@ uint256 OraclesBatontxid(uint256 oracletxid,CPubKey pk);
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs);
int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, std::vector<uint8_t> &origpubkey, const CTransaction& tx, int32_t v, uint256 reftokenid, std::vector<CPubKey> vinPubkeys);
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 tokenid, uint256 assetid2, int64_t price, std::vector<CPubKey> voutPubkeys, std::vector<uint8_t> origpubkey);
bool DecodeAssetCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description);
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey, uint8_t &evalCodeInOpret, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector<uint8_t> &origpubkey);
CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload);
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description);
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCode, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra);
//uint8_t DecodeAssetOpRet(const CScript &scriptPubKey, uint8_t &evalCode, uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey);
uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector <uint8_t>&data);
int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen);
@ -182,6 +186,10 @@ CC* GetCryptoCondition(CScript const& scriptSig);
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr);
void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr);
void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr);
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2);
CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2);
bool IsCCInput(CScript const& scriptSig);
int32_t unstringbits(char *buf,uint64_t bits);
uint64_t stringbits(char *str);

10
src/cc/CCtokens.cpp

@ -51,7 +51,7 @@ CScript EncodeTokenCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,st
}
// this is for other contracts which use tokens and build customized extra payloads to token's opret:
CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys)
CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload)
{
CScript opret;
uint8_t ccType = 0;
@ -63,10 +63,14 @@ CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 t
//uint8_t tokenFuncId = (isTransferrable) ? (uint8_t)'t' : (uint8_t)'l';
//opret << OP_RETURN << E_MARSHAL(ss << evalCodeInOpret << tokenFuncId << tokenid << payload);
opret << OP_RETURN << E_MARSHAL(ss << evalCodeInOpret << tokenFuncId << tokenid << ccType; if (ccType >= 1) ss << voutPubkeys[0]; if (ccType == 2) ss << voutPubkeys[1];);
opret << OP_RETURN << E_MARSHAL(ss << evalCodeInOpret << tokenFuncId << tokenid << ccType; \
if(ccType >= 1) ss << voutPubkeys[0]; \
if(ccType == 2) ss << voutPubkeys[1]; \
if(payload.size() > 0) ss << payload);
return(opret);
}
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description)
{
std::vector<uint8_t> vopret; uint8_t dummyEvalcode, funcid, *script;
@ -578,7 +582,7 @@ std::string TokenTransfer(int64_t txfee, uint256 assetid, std::vector<uint8_t> d
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(pubkey2pk(destpubkey)); // dest pubkey for validating vout
return(FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeTokenOpRet('t', EVAL_TOKENS, assetid, voutTokenPubkeys))); // By setting EVAL_TOKENS we're getting out from assets validation code
return(FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeTokenOpRet('t', EVAL_TOKENS, assetid, voutTokenPubkeys, CScript()))); // By setting EVAL_TOKENS we're getting out from assets validation code
}
else {
fprintf(stderr, "not enough CC token inputs for %.8f\n", (double)total / COIN);

1
src/cc/CCtokens.h

@ -31,7 +31,6 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t
//int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, std::vector<uint8_t> &origpubkey, const CTransaction& tx, int32_t v, uint256 reftokenid, std::vector<CPubKey> vinPubkeys);
std::string CreateToken(int64_t txfee, int64_t assetsupply, std::string name, std::string description);
std::string TokenTransfer(int64_t txfee, uint256 assetid, std::vector<uint8_t> destpubkey, int64_t total);
CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys);
//this is in CCinclude.h int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs);

31
src/cc/CCtx.cpp

@ -45,7 +45,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0;
int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64];
uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0;
CC *mycond=0, *othercond=0, *othercond2=0, *othercond3=0, *othercond1of2=NULL, *cond;
CC *mycond=0, *othercond=0, *othercond2=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond;
CPubKey unspendablepk;
n = mtx.vout.size();
@ -130,7 +130,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
else
{
Getscriptaddress(destaddr,vintx.vout[utxovout].scriptPubKey);
//fprintf(stderr,"vin.%d is CC %.8f -> (%s)\n",i,(double)utxovalues[i]/COIN,destaddr);
//fprintf(stderr,"FinalizeCCTx() vin.%d is CC %.8f -> (%s)\n",i,(double)utxovalues[i]/COIN,destaddr);
if ( strcmp(destaddr,myaddr) == 0 )
{
privkey = myprivkey;
@ -140,37 +140,44 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
{
privkey = unspendablepriv;
cond = othercond;
//fprintf(stderr,"unspendable CC addr.(%s)\n",unspendable);
//fprintf(stderr,"FinalizeCCTx() unspendable CC addr.(%s)\n",unspendable);
}
// check if this is the 2nd additional evalcode + 'unspendable' cc addr:
else if ( strcmp(destaddr,cp->unspendableaddr2) == 0)
{
//fprintf(stderr,"matched %s unspendable2!\n",cp->unspendableaddr2);
//fprintf(stderr,"FinalizeCCTx() matched %s unspendable2!\n",cp->unspendableaddr2);
privkey = cp->unspendablepriv2;
if ( othercond2 == 0 ) //&& cp->evalcode != EVAL_CHANNELS && cp->evalcode != EVAL_HEIR && cp->evalcode != EVAL_ASSETS && cp->evalcode != EVAL_TOKENS)
if ( othercond2 == 0 )
othercond2 = MakeCCcond1(cp->evalcode2, cp->unspendablepk2);
//else if ( othercond2 == 0 && (cp->evalcode == EVAL_CHANNELS || cp->evalcode == EVAL_HEIR || cp->evalcode == EVAL_ASSETS || cp->evalcode == EVAL_TOKENS) )
// othercond2 = MakeCCcond1of2(cp->evalcode2,cp->unspendablepk2,cp->unspendablepk3);
cond = othercond2;
}
// check if this is 3rd additional evalcode + 'unspendable' cc addr:
else if ( strcmp(destaddr,cp->unspendableaddr3) == 0 )
{
//fprintf(stderr,"matched %s unspendable3!\n",cp->unspendableaddr3);
//fprintf(stderr,"FinalizeCCTx() matched %s unspendable3!\n",cp->unspendableaddr3);
privkey = cp->unspendablepriv3;
if ( othercond3 == 0 )
othercond3 = MakeCCcond1(cp->evalcode3,cp->unspendablepk3);
cond = othercond3;
}
// check if this is spending from 1of2 cc addr:
else if (strcmp(cp->unspendable1of2addr, destaddr) == 0)
// check if this is spending from 1of2 cc coins addr:
else if (strcmp(cp->coins1of2addr, destaddr) == 0)
{
//fprintf(stderr,"matched %s unspendable1of2!\n",cp->unspendable1of2addr);
fprintf(stderr,"FinalizeCCTx() matched %s unspendable1of2!\n",cp->coins1of2addr);
privkey = myprivkey;
if (othercond1of2 == 0)
othercond1of2 = MakeCCcond1of2(cp->evalcode, cp->unspendable1of2pk[0], cp->unspendable1of2pk[1]);
othercond1of2 = MakeCCcond1of2(cp->evalcode, cp->coins1of2pk[0], cp->coins1of2pk[1]);
cond = othercond1of2;
}
// check if this is spending from 1of2 cc tokens addr:
else if (strcmp(cp->tokens1of2addr, destaddr) == 0)
{
fprintf(stderr,"FinalizeCCTx() matched %s cp->tokens1of2addr!\n", cp->tokens1of2addr);
privkey = myprivkey;
if (othercond1of2tokens == 0)
othercond1of2tokens = MakeTokensCCcond1of2(cp->evalcode, cp->tokens1of2pk[0], cp->tokens1of2pk[1]);
cond = othercond1of2tokens;
}
else
{
fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr);

47
src/cc/CCutils.cpp

@ -76,6 +76,39 @@ CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2)
return(vout);
}
CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2)
{
// make 1of2 sigs cond
std::vector<CC*> pks;
pks.push_back(CCNewSecp256k1(pk1));
pks.push_back(CCNewSecp256k1(pk2));
CC *condEvalCC = CCNewEval(E_MARSHAL(ss << evalcode)); // this is eval cc
CC *cond1of2Sig = CCNewThreshold(1, pks); // this is 1 of 2 sigs cc
CC *cond1of2Threshold = CCNewThreshold(2, { condEvalCC, cond1of2Sig });
// make token cond
struct CCcontract_info *cpTokens, tokensC;
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
CPubKey unspendableTokensPk = GetUnspendable(cpTokens, NULL);
std::vector<CC*> pksTokens;
pks.push_back(CCNewSecp256k1(unspendableTokensPk));
CC *condEvalTokensCC = CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS)); // this is eval cc
CC *condUnspendableSig = CCNewThreshold(1, pksTokens); // this is 1 of 2 sigs cc
CC *condTopThreshold = CCNewThreshold(2, { condEvalTokensCC, condUnspendableSig });
return CCNewThreshold(2, { cond1of2Threshold, condTopThreshold });
}
CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2)
{
CTxOut vout;
CC *payoutCond = MakeTokensCCcond1of2(evalcode, pk1, pk2);
vout = CTxOut(nValue, CCPubKey(payoutCond));
cc_free(payoutCond);
return(vout);
}
CC* GetCryptoCondition(CScript const& scriptSig)
{
auto pc = scriptSig.begin();
@ -198,9 +231,17 @@ void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *
// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 cryptocondition vout:
void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr)
{
cp->unspendable1of2pk[0] = pk1;
cp->unspendable1of2pk[1] = pk2;
strcpy(cp->unspendable1of2addr, coinaddr);
cp->coins1of2pk[0] = pk1;
cp->coins1of2pk[1] = pk2;
strcpy(cp->coins1of2addr, coinaddr);
}
// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 tokens cryptocondition vout:
void CCaddr1of2setTokens(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr)
{
cp->tokens1of2pk[0] = pk1;
cp->tokens1of2pk[1] = pk2;
strcpy(cp->tokens1of2addr, coinaddr);
}
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)

153
src/cc/gateways.cpp

@ -132,14 +132,18 @@
Implementation Issues:
When thinking about validation, it is clear that we cant use EVAL_ASSETS for the locked coins as there wont be any enforcement of the gateways locking. This means we need a way to transfer assets into gateways outputs and back. It seems a tokenconvert rpc will be needed and hopefully that will be enough to make it all work properly.
-- When thinking about validation, it is clear that we cant use EVAL_ASSETS for the locked coins as there wont be any enforcement of the gateways locking.
-- This means we need a way to transfer assets into gateways outputs and back. It seems a tokenconvert rpc will be needed and hopefully that will be enough to make it all work properly.
++ The use of tokenconvert has been changed to the use of the new Tokens contract which can enforce other contracts validation by forwarding eval->validate call to GatewaysValidate
++ So all tokens remain within that Tokens contract eval code.
Care must be taken so that tokens are not lost and can be converted back.
This changes the usage to require tokenconvert before doing the bind and also tokenconvert before doing a withdraw. EVAL_GATEWAYS has evalcode of 241
The gatewaysclaim automatically converts the deposit amount of tokens back to EVAL_ASSETS.
-- Care must be taken so that tokens are not lost and can be converted back.
-- This changes the usage to require tokenconvert before doing the bind and also tokenconvert before doing a withdraw. EVAL_GATEWAYS has evalcode of 241
++ tokenconvert now returns 'not implemented', no need to use it at all.
-- The gatewaysclaim automatically converts the deposit amount of tokens back to EVAL_ASSETS.
++ The gatewaysclaim automatically transfers the deposit amount of tokens to depositor's address (within EVAL_TOKENS).
*/
@ -204,38 +208,42 @@ uint8_t DecodeGatewaysDepositOpRet(const CScript &scriptPubKey,std::string &coin
return(0);
}
CScript EncodeGatewaysClaimOpRet(uint8_t funcid,uint256 assetid,std::string refcoin,uint256 bindtxid,uint256 deposittxid,CPubKey destpub,int64_t amount)
// encodes payload for the token opret (needs to be added to the tail of it)
CScript EncodeGatewaysClaimOpRet(uint8_t funcid, std::string refcoin, uint256 bindtxid, uint256 deposittxid, CPubKey destpub, int64_t amount)
{
CScript opret; uint8_t evalcode = EVAL_ASSETS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << bindtxid << deposittxid << destpub << amount);
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << funcid << refcoin << bindtxid << deposittxid << destpub << amount);
return(opret);
}
uint8_t DecodeGatewaysClaimOpRet(const CScript &scriptPubKey,uint256 &assetid,std::string &refcoin,uint256 &bindtxid,uint256 &deposittxid,CPubKey &destpub,int64_t &amount)
uint8_t DecodeGatewaysClaimOpRet(const CScript &scriptPubKey,uint256 &tokenid,std::string &refcoin,uint256 &bindtxid,uint256 &deposittxid,CPubKey &destpub,int64_t &amount)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> bindtxid; ss >> deposittxid; ss >> destpub; ss >> amount) != 0 )
if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> tokenid; ss >> refcoin; ss >> bindtxid; ss >> deposittxid; ss >> destpub; ss >> amount) != 0 )
{
return(f);
}
return(0);
}
CScript EncodeGatewaysWithdrawOpRet(uint8_t funcid,uint256 assetid, std::string refcoin, CPubKey withdrawpub, int64_t amount)
CScript EncodeGatewaysWithdrawOpRet(uint8_t funcid, std::string refcoin, CPubKey withdrawpub, int64_t amount)
{
CScript opret; uint8_t evalcode = EVAL_GATEWAYS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << withdrawpub << amount);
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << funcid << refcoin << withdrawpub << amount);
return(opret);
}
uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256 &assetid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount)
uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256 &tokenid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 )
if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> tokenid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 )
{
return(f);
}
@ -304,7 +312,7 @@ uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey)
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && (script[0] == EVAL_GATEWAYS || script[0] == EVAL_ASSETS) && E_UNMARSHAL(vopret,ss >> e; ss >> f) != 0 )
if ( vopret.size() > 2 && (script[0] == EVAL_GATEWAYS || script[0] == EVAL_TOKENS) && E_UNMARSHAL(vopret,ss >> e; ss >> f) != 0 )
{
if (f == 'B' && f == 'D' && f == 't' && f == 'W' && f == 'P' && f == 'M')
return(f);
@ -512,7 +520,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks,height,claimvout; bool retval; uint8_t funcid,hash[32],M,N,taddr,prefix,prefix2;
char str[65],destaddr[64],depositaddr[65],validationError[512];
std::vector<uint256> txids; std::vector<CPubKey> pubkeys,publishers,tmppublishers; std::vector<uint8_t> proof; int64_t totalsupply,amount,tmpamount;
uint256 hashblock,txid,bindtxid,deposittxid,assetid,oracletxid,tokenid,cointxid,tmptxid,tmpxtxid2,merkleroot,mhash; CTransaction bindtx,deposittx,oracletx;
uint256 hashblock,txid,bindtxid,deposittxid,tokenidClaim,oracletxid,tokenidBind,cointxid,tmptxid,tmpxtxid2,merkleroot,mhash; CTransaction bindtx,deposittx,oracletx;
std::string refcoin,tmprefcoin,deposithex; CPubKey destpub,tmpdestpub;
fprintf(stderr,"return true without gateways validation\n");
@ -565,8 +573,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
//vin.2: CC input of marker from gatewaysdeposit tx
//vout.0: CC vout of total tokens from deposit amount to asset eval code
//(vout.1): CC vout if there is change of unused tokens back to owner of tokens (deposit amount less than available tokens)
//vout.n-1: opreturn - 't' assetid zeroid 0 mypubkey (NOTE: opreturn is with asset eval code)
if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysClaimOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,refcoin,bindtxid,deposittxid,destpub,amount)==0)
//vout.n-1: opreturn - 't' tokenid zeroid 0 mypubkey (NOTE: opreturn is with asset eval code)
if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysClaimOpRet(tx.vout[numvouts-1].scriptPubKey,tokenidClaim,refcoin,bindtxid,deposittxid,destpub,amount)==0)
return eval->Invalid("invalid gatewaysclaim OP_RETURN data!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for gatewaysClaim!");
@ -580,12 +588,12 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
return eval->Invalid("vout.1 is CC for gatewaysClaim!");
else if (myGetTransaction(bindtxid,bindtx,hashblock) == 0)
return eval->Invalid("invalid gatewaysbind txid!");
else if ((numvouts=bindtx.vout.size()) > 0 && DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 'B')
else if ((numvouts=bindtx.vout.size()) > 0 && DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenidBind,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 'B')
return eval->Invalid("invalid gatewaysbind OP_RETURN data!");
else if (tmprefcoin!=refcoin)
return eval->Invalid("refcoin different in bind tx");
else if (tokenid!=assetid)
return eval->Invalid("assetid does not match tokenid from gatewaysbind");
else if (tokenidClaim!=tokenidBind)
return eval->Invalid("tokenid does not match tokenid from gatewaysbind");
else if (komodo_txnotarizedconfirmed(bindtxid) == false)
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
else if (myGetTransaction(deposittxid,deposittx,hashblock) == 0)
@ -642,7 +650,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
//vout.1: normal vout txfee marker to withdraw destination pubkey
//vout.2: CC vout txfee marker to gateways CC address
//vout.n-2: CC vout if there is change of unused tokens back to owner of tokens (withdraw amount less than owner available tokens)
//vout.n-1: opreturn - 'W' assetid refcoin withdrawpub amount
//vout.n-1: opreturn - 'W' tokenid refcoin withdrawpub amount
break;
case 'P':
//vin.0: normal input
@ -675,9 +683,9 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
// helper functions for rpc calls in rpcwallet.cpp
int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 refassetid,int64_t total,int32_t maxinputs)
int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 reftokenid,int64_t total,int32_t maxinputs)
{
char coinaddr[64],destaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 assetid,txid,hashBlock; std::vector<uint8_t> origpubkey; std::vector<uint8_t> vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid;
char coinaddr[64],destaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 tokenid,txid,hashBlock; std::vector<uint8_t> origpubkey; std::vector<uint8_t> vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
@ -701,11 +709,11 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 )
continue;
GetOpReturnData(vintx.vout[vintx.vout.size()-1].scriptPubKey, vopret);
if ( E_UNMARSHAL(vopret,ss >> evalcode; ss >> funcid; ss >> assetid) != 0 )
if ( E_UNMARSHAL(vopret,ss >> evalcode; ss >> funcid; ss >> tokenid) != 0 )
{
assetid = revuint256(assetid);
char str[65],str2[65]; fprintf(stderr,"vout.%d %d:%d (%c) check for refassetid.%s vs %s %.8f\n",vout,evalcode,cp->evalcode,funcid,uint256_str(str,refassetid),uint256_str(str2,assetid),(double)vintx.vout[vout].nValue/COIN);
if ( assetid == refassetid && funcid == 't' && (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
tokenid = revuint256(tokenid);
char str[65],str2[65]; fprintf(stderr,"vout.%d %d:%d (%c) check for reftokenid.%s vs %s %.8f\n",vout,evalcode,cp->evalcode,funcid,uint256_str(str,reftokenid),uint256_str(str2,tokenid),(double)vintx.vout[vout].nValue/COIN);
if ( tokenid == reftokenid && funcid == 't' && (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
{
//fprintf(stderr,"total %llu maxinputs.%d %.8f\n",(long long)total,maxinputs,(double)it->second.satoshis/COIN);
if ( total != 0 && maxinputs != 0 )
@ -905,7 +913,7 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
CTransaction tx; CPubKey mypk,gatewayspk,tmpdestpub; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2;
std::string coin, deposithex; std::vector<CPubKey> msigpubkeys,publishers; int64_t totalsupply,depositamount,tmpamount,inputs,CCchange=0;
int32_t numvouts,claimvout,height; std::vector<uint8_t> proof;
uint256 hashBlock,assetid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector<uint256> txids;
uint256 hashBlock,tokenid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector<uint256> txids;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
@ -917,7 +925,7 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
{
fprintf(stderr,"invalid coin - bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
return("");
@ -945,17 +953,24 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
//fprintf(stderr,"depositaddr.(%s) vs %s\n",depositaddr,cp->unspendableaddr2);
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
{
if ( (inputs= AddGatewaysInputs(cp,mtx,gatewayspk,assetid,amount,60)) > 0 )
///////// if ( (inputs= AddGatewaysInputs(cp,mtx,gatewayspk,tokenid,amount,60)) > 0 )
if ((inputs = AddTokenCCInputs(cp, mtx, gatewayspk, tokenid, amount, 60)) > 0)
{
if ( inputs > amount )
CCchange = (inputs - amount);
_GetCCaddress(destaddr,EVAL_GATEWAYS,mypk);
//printf("expecting deposittxid/v0 to be to %s\n",destaddr);
mtx.vin.push_back(CTxIn(deposittxid,0,CScript())); // triggers EVAL_GATEWAYS validation
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,mypk)); // transfer back to normal token
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,amount,mypk)); // transfer back to normal token
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysClaimOpRet('t',assetid,refcoin,bindtxid,deposittxid,destpub,amount)));
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk));
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(mypk); // the pubkey where tokens are going (vout[0])
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,
EncodeTokenOpRet('t', EVAL_GATEWAYS, tokenid, voutTokenPubkeys,
EncodeGatewaysClaimOpRet('t', refcoin, bindtxid, deposittxid, destpub, amount)))); // yes, 't' is passed twice
}
}
CCerror = strprintf("cant find enough inputs or mismatched total");
@ -966,39 +981,67 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C;
uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin;
CTransaction tx;
CPubKey mypk, gatewayspk;
uint256 tokenid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin;
std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65],coinaddr[64];
cp = CCinit(&C,EVAL_GATEWAYS);
struct CCcontract_info *cpGateways, gatewaysC;
struct CCcontract_info *cpTokens, tokensC;
cpGateways = CCinit(&gatewaysC, EVAL_GATEWAYS);
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
gatewayspk = GetUnspendable(cpGateways, 0);
if( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
if( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
{
fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
return("");
}
if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 )
if( AddNormalinputs(mtx, mypk, 3*txfee, 4) > 0 )
{
if ( (inputs= AddGatewaysInputs(cp,mtx,mypk,assetid,amount,60)) > 0 )
/////if ( (inputs= AddGatewaysInputs(cp,mtx,mypk,tokenid,amount,60)) > 0 )
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, amount, 60)) > 0)
{
if ( inputs > amount )
CCchange = (inputs - amount);
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,amount,gatewayspk));
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, amount, gatewayspk));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(withdrawpub)) << OP_CHECKSIG));
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk));
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS, txfee, gatewayspk));
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysWithdrawOpRet('W',assetid,refcoin,withdrawpub,amount)));
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk));
char unspendableGatewaysAddr[64];
GetCCaddress(cpGateways, unspendableGatewaysAddr, gatewayspk);
uint8_t unspendableGatewaysPrivkey[32];
GetUnspendable(cpGateways, unspendableGatewaysPrivkey);
// add additional unspendable addr from Gateways:
CCaddr2set(cpTokens, EVAL_GATEWAYS, gatewayspk, unspendableGatewaysPrivkey, unspendableGatewaysAddr);
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(gatewayspk); // the pubkey where tokens are going vout[0] (and for checking the 'change' the Tokens contract will find pubkeys itself)
return(FinalizeCCTx(0, cpTokens, mtx, mypk, txfee,
EncodeTokenOpRet('t', EVAL_GATEWAYS, tokenid, voutTokenPubkeys,
EncodeGatewaysWithdrawOpRet('W', refcoin, withdrawpub, amount))));
}
CCerror = strprintf("cant find enough token inputs or mismatched total");
fprintf(stderr, "%s\n", CCerror.c_str());
return("");
}
CCerror = strprintf("cant find enough inputs or mismatched total");
CCerror = strprintf("cant find enough normal inputs or mismatched total");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
@ -1073,7 +1116,7 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
{
UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string tmprefcoin; CPubKey mypk,gatewayspk,withdrawpub; std::vector<CPubKey> msigpubkeys;
uint256 hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2;
uint256 hashBlock,tokenid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2;
char depositaddr[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],cctxidaddr[64],signeraddr[64];
int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,amount,nValue; struct CCcontract_info *cp,C;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
@ -1087,7 +1130,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin )
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin )
{
fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str());
return(result);
@ -1108,7 +1151,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
nValue = (int64_t)it->second.satoshis;
fprintf(stderr,"%s %d %ld\n",txid.ToString().c_str(),vout,(long)nValue);
if ( vout == 2 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 &&
DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,tmprefcoin,withdrawpub,amount) == 'W' && myIsutxo_spentinmempool(txid,vout) == 0)
DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmprefcoin,withdrawpub,amount) == 'W' && myIsutxo_spentinmempool(txid,vout) == 0)
{
Getscriptaddress(destaddr,tx.vout[0].scriptPubKey);
Getscriptaddress(withaddr,tx.vout[1].scriptPubKey);
@ -1141,7 +1184,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
{
UniValue result(UniValue::VOBJ),processed(UniValue::VARR); CTransaction tx; std::string tmprefcoin,hex; CPubKey mypk,gatewayspk,withdrawpub; std::vector<CPubKey> msigpubkeys;
uint256 withdrawtxid,hashBlock,txid,assetid,oracletxid; uint8_t M,N,taddr,prefix,prefix2;
uint256 withdrawtxid,hashBlock,txid,tokenid,oracletxid; uint8_t M,N,taddr,prefix,prefix2;
char depositaddr[64],coinaddr[64],str[65],numstr[32],txidaddr[64],cctxidaddr[64],withaddr[64];
int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,nValue,amount; struct CCcontract_info *cp,C;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
@ -1155,7 +1198,7 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin )
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin )
{
fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str());
return(result);
@ -1178,7 +1221,7 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
if ( vout == 0 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 &&
DecodeGatewaysCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,tmprefcoin,withdrawtxid,hex) == 'C' && myIsutxo_spentinmempool(txid,vout) == 0)
{
if (GetTransaction(withdrawtxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,tmprefcoin,withdrawpub,amount) == 'W')
if (GetTransaction(withdrawtxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmprefcoin,withdrawpub,amount) == 'W')
{
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("txid",uint256_str(str,txid)));

2
src/cc/heir.cpp

@ -690,7 +690,7 @@ template <typename Helper> std::string HeirFund(uint64_t txfee, int64_t amount,
if ((inputs=Helper::addOwnerInputs(cp, tokenid, mtx, myPubkey, amount, (int32_t)64)) > 0) { // 2 x txfee: 1st for marker vout, 2nd to miners
//mtx.vout.push_back(MakeCC1vout(EVAL_HEIR,amount,HeirCCpk));
mtx.vout.push_back(MakeCC1of2vout(Helper::getMyEval(), amount, myPubkey, heirPubkey)); // add cryptocondition to spend amount for either pk
mtx.vout.push_back(MakeTokensCC1of2vout(/*Helper::getMyEval()*/EVAL_HEIR, amount, myPubkey, heirPubkey)); // add cryptocondition to spend amount for either pk
// add a marker for finding all plans in HeirList()
CPubKey HeirContractPubKey = GetUnspendable(cp, 0);

Loading…
Cancel
Save