MakeTokensCC1of2vout MakeTokensCCcond1of2 test code added

gateways partially adapted for tokens
This commit is contained in:
dimxy
2019-01-10 13:40:21 +05:00
parent 884c58e3cf
commit 1f6d62e7c8
7 changed files with 182 additions and 80 deletions

View File

@@ -91,10 +91,14 @@ struct CCcontract_info
char unspendableCCaddr[64], CChexstr[72], normaladdr[64]; char unspendableCCaddr[64], CChexstr[72], normaladdr[64];
uint8_t CCpriv[32]; 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 // NOTE: only one evalcode is allowed at this time
char unspendable1of2addr[64]; char coins1of2addr[64];
CPubKey unspendable1of2pk[2]; 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 // this is for spending from two additional 'unspendable' CC addresses of other eval codes
// (that is, for spending from several cc contract 'unspendable' addresses): // (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 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); 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); 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); 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); 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); 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 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 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); 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); 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 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 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); 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); bool IsCCInput(CScript const& scriptSig);
int32_t unstringbits(char *buf,uint64_t bits); int32_t unstringbits(char *buf,uint64_t bits);
uint64_t stringbits(char *str); uint64_t stringbits(char *str);

View File

@@ -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: // 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; CScript opret;
uint8_t ccType = 0; 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'; //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 << 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); return(opret);
} }
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description) 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; 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; std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(pubkey2pk(destpubkey)); // dest pubkey for validating vout 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 { else {
fprintf(stderr, "not enough CC token inputs for %.8f\n", (double)total / COIN); fprintf(stderr, "not enough CC token inputs for %.8f\n", (double)total / COIN);

View File

@@ -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); //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 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); 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); //this is in CCinclude.h int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs);

View File

@@ -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; 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]; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64];
uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; 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; CPubKey unspendablepk;
n = mtx.vout.size(); n = mtx.vout.size();
@@ -130,7 +130,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
else else
{ {
Getscriptaddress(destaddr,vintx.vout[utxovout].scriptPubKey); 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 ) if ( strcmp(destaddr,myaddr) == 0 )
{ {
privkey = myprivkey; privkey = myprivkey;
@@ -140,37 +140,44 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
{ {
privkey = unspendablepriv; privkey = unspendablepriv;
cond = othercond; 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: // check if this is the 2nd additional evalcode + 'unspendable' cc addr:
else if ( strcmp(destaddr,cp->unspendableaddr2) == 0) 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; 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); 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; cond = othercond2;
} }
// check if this is 3rd additional evalcode + 'unspendable' cc addr: // check if this is 3rd additional evalcode + 'unspendable' cc addr:
else if ( strcmp(destaddr,cp->unspendableaddr3) == 0 ) 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; privkey = cp->unspendablepriv3;
if ( othercond3 == 0 ) if ( othercond3 == 0 )
othercond3 = MakeCCcond1(cp->evalcode3,cp->unspendablepk3); othercond3 = MakeCCcond1(cp->evalcode3,cp->unspendablepk3);
cond = othercond3; cond = othercond3;
} }
// check if this is spending from 1of2 cc addr: // check if this is spending from 1of2 cc coins addr:
else if (strcmp(cp->unspendable1of2addr, destaddr) == 0) 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; privkey = myprivkey;
if (othercond1of2 == 0) 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; 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 else
{ {
fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr);

View File

@@ -76,6 +76,39 @@ CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2)
return(vout); 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) CC* GetCryptoCondition(CScript const& scriptSig)
{ {
auto pc = scriptSig.begin(); 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: // 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) void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr)
{ {
cp->unspendable1of2pk[0] = pk1; cp->coins1of2pk[0] = pk1;
cp->unspendable1of2pk[1] = pk2; cp->coins1of2pk[1] = pk2;
strcpy(cp->unspendable1of2addr, coinaddr); 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) bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)

View File

@@ -132,13 +132,17 @@
Implementation Issues: 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. -- 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.
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.
++ The gatewaysclaim automatically transfers the deposit amount of tokens to depositor's address (within EVAL_TOKENS).
The gatewaysclaim automatically converts the deposit amount of tokens back to EVAL_ASSETS.
*/ */
@@ -204,38 +208,42 @@ uint8_t DecodeGatewaysDepositOpRet(const CScript &scriptPubKey,std::string &coin
return(0); 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; CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << bindtxid << deposittxid << destpub << amount);
opret << OP_RETURN << E_MARSHAL(ss << funcid << refcoin << bindtxid << deposittxid << destpub << amount);
return(opret); 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; std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret); GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data(); 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(f);
} }
return(0); 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; CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << withdrawpub << amount); opret << OP_RETURN << E_MARSHAL(ss << funcid << refcoin << withdrawpub << amount);
return(opret); 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; std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret); GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data(); 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); return(f);
} }
@@ -304,7 +312,7 @@ uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey)
std::vector<uint8_t> vopret; uint8_t *script,e,f; std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret); GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data(); 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') if (f == 'B' && f == 'D' && f == 't' && f == 'W' && f == 'P' && f == 'M')
return(f); 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; 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]; 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; 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; std::string refcoin,tmprefcoin,deposithex; CPubKey destpub,tmpdestpub;
fprintf(stderr,"return true without gateways validation\n"); 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 //vin.2: CC input of marker from gatewaysdeposit tx
//vout.0: CC vout of total tokens from deposit amount to asset eval code //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.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) //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,assetid,refcoin,bindtxid,deposittxid,destpub,amount)==0) 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!"); return eval->Invalid("invalid gatewaysclaim OP_RETURN data!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for gatewaysClaim!"); 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!"); return eval->Invalid("vout.1 is CC for gatewaysClaim!");
else if (myGetTransaction(bindtxid,bindtx,hashblock) == 0) else if (myGetTransaction(bindtxid,bindtx,hashblock) == 0)
return eval->Invalid("invalid gatewaysbind txid!"); 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!"); return eval->Invalid("invalid gatewaysbind OP_RETURN data!");
else if (tmprefcoin!=refcoin) else if (tmprefcoin!=refcoin)
return eval->Invalid("refcoin different in bind tx"); return eval->Invalid("refcoin different in bind tx");
else if (tokenid!=assetid) else if (tokenidClaim!=tokenidBind)
return eval->Invalid("assetid does not match tokenid from gatewaysbind"); return eval->Invalid("tokenid does not match tokenid from gatewaysbind");
else if (komodo_txnotarizedconfirmed(bindtxid) == false) else if (komodo_txnotarizedconfirmed(bindtxid) == false)
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
else if (myGetTransaction(deposittxid,deposittx,hashblock) == 0) 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.1: normal vout txfee marker to withdraw destination pubkey
//vout.2: CC vout txfee marker to gateways CC address //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-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; break;
case 'P': case 'P':
//vin.0: normal input //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 // 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; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk); GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr); 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 ) if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 )
continue; continue;
GetOpReturnData(vintx.vout[vintx.vout.size()-1].scriptPubKey, vopret); 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); tokenid = revuint256(tokenid);
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); 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 ( assetid == refassetid && funcid == 't' && (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) 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); //fprintf(stderr,"total %llu maxinputs.%d %.8f\n",(long long)total,maxinputs,(double)it->second.satoshis/COIN);
if ( total != 0 && maxinputs != 0 ) 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; 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; 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; 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); cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 ) 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)); fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return(""); 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()); fprintf(stderr,"invalid coin - bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
return(""); 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); //fprintf(stderr,"depositaddr.(%s) vs %s\n",depositaddr,cp->unspendableaddr2);
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) 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 ) if ( inputs > amount )
CCchange = (inputs - amount); CCchange = (inputs - amount);
_GetCCaddress(destaddr,EVAL_GATEWAYS,mypk); _GetCCaddress(destaddr,EVAL_GATEWAYS,mypk);
//printf("expecting deposittxid/v0 to be to %s\n",destaddr); //printf("expecting deposittxid/v0 to be to %s\n",destaddr);
mtx.vin.push_back(CTxIn(deposittxid,0,CScript())); // triggers EVAL_GATEWAYS validation 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 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk)); mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysClaimOpRet('t',assetid,refcoin,bindtxid,deposittxid,destpub,amount)));
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"); 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) std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount)
{ {
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; CTransaction tx;
uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; 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]; 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 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0); gatewayspk = GetUnspendable(cpGateways, 0);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
if( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{ {
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return(""); 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()); fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
return(""); 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 ) if ( inputs > amount )
CCchange = (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(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 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysWithdrawOpRet('W',assetid,refcoin,withdrawpub,amount)));
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() ); fprintf(stderr,"%s\n", CCerror.c_str() );
return(""); return("");
} }
@@ -1073,7 +1116,7 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) 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; 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]; 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; int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,amount,nValue; struct CCcontract_info *cp,C;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; 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)); fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return(result); 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()); fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str());
return(result); return(result);
@@ -1108,7 +1151,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
nValue = (int64_t)it->second.satoshis; nValue = (int64_t)it->second.satoshis;
fprintf(stderr,"%s %d %ld\n",txid.ToString().c_str(),vout,(long)nValue); 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 && 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(destaddr,tx.vout[0].scriptPubKey);
Getscriptaddress(withaddr,tx.vout[1].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 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; 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]; 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; int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,nValue,amount; struct CCcontract_info *cp,C;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; 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)); fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return(result); 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()); fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str());
return(result); 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 && 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) 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); UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("txid",uint256_str(str,txid))); obj.push_back(Pair("txid",uint256_str(str,txid)));

View File

@@ -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 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(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() // add a marker for finding all plans in HeirList()
CPubKey HeirContractPubKey = GetUnspendable(cp, 0); CPubKey HeirContractPubKey = GetUnspendable(cp, 0);