From be71d108b296df1a6ac540af90bee4996a3d947f Mon Sep 17 00:00:00 2001 From: dimxy Date: Mon, 7 Jan 2019 23:21:57 +0500 Subject: [PATCH] Added CCaddr1of2set and FinalizeCCtx modified to support it (small test CCerror code added - temp) --- src/cc/CCassetstx.cpp | 65 +++++++++++++++++++++++----------------- src/cc/CCinclude.h | 28 +++++++++++++---- src/cc/CCtx.cpp | 24 +++++++++++---- src/cc/CCutils.cpp | 8 +++++ src/cc/heir.cpp | 9 +++--- src/wallet/rpcwallet.cpp | 8 +++++ 6 files changed, 100 insertions(+), 42 deletions(-) diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index cae4b42bb..17c16bd6a 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -393,7 +393,7 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p uint64_t mask; int64_t inputs, CCchange; CScript opret; - struct CCcontract_info *cp,C; + struct CCcontract_info *cpTokens,C; //std::cerr << "CreateSell() askamount=" << askamount << " pricetotal=" << pricetotal << std::endl; @@ -402,16 +402,16 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p return(""); } - cp = CCinit(&C, EVAL_TOKENS); // NOTE: tokens is here + cpTokens = CCinit(&C, EVAL_TOKENS); // NOTE: tokens is here - if ( txfee == 0 ) + if (txfee == 0) txfee = 10000; mypk = pubkey2pk(Mypubkey()); if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - if ((inputs = AddTokenCCInputs(cp, mtx, mypk, assetid, askamount, 60)) > 0) + if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, askamount, 60)) > 0) { if (inputs < askamount) { //was: askamount = inputs; @@ -420,14 +420,14 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p return (""); } - mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,askamount, GetUnspendable(cp,0))); + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,askamount, GetUnspendable(cpTokens,0))); if (inputs > askamount) CCchange = (inputs - askamount); if (CCchange != 0) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); opret = EncodeAssetOpRet('s',assetid, zeroid, pricetotal, Mypubkey()); - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret)); + return(FinalizeCCTx(mask,cpTokens,mtx,mypk,txfee,opret)); } else { fprintf(stderr, "need some tokens to place ask\n"); @@ -439,6 +439,7 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p return(""); } +////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -497,7 +498,7 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a } return(""); -} +} ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// // unlocks coins std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) @@ -508,11 +509,11 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) uint256 hashBlock; int64_t bidamount; CPubKey mypk; - struct CCcontract_info *cp,C; + struct CCcontract_info *cpAssets, C; - cp = CCinit(&C, EVAL_ASSETS); + cpAssets = CCinit(&C, EVAL_ASSETS); - if ( txfee == 0 ) + if (txfee == 0) txfee = 10000; mypk = pubkey2pk(Mypubkey()); @@ -525,7 +526,7 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) bidamount = vintx.vout[0].nValue; mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeAssetOpRet('o', assetid, zeroid, 0, Mypubkey()))); + return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee, EncodeAssetOpRet('o', assetid, zeroid, 0, Mypubkey()))); } } return(""); @@ -536,11 +537,11 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t askamount; CPubKey mypk; - struct CCcontract_info *cp,C; + struct CCcontract_info *cpTokens, C; - cp = CCinit(&C, EVAL_TOKENS); + cpTokens = CCinit(&C, EVAL_TOKENS); - if ( txfee == 0 ) + if (txfee == 0) txfee = 10000; mypk = pubkey2pk(Mypubkey()); @@ -553,7 +554,7 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) askamount = vintx.vout[0].nValue; mtx.vin.push_back(CTxIn(asktxid, 0, CScript())); mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, mypk)); - return(FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeAssetOpRet('x', assetid, zeroid, 0, Mypubkey()))); + return(FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee, EncodeAssetOpRet('x', assetid, zeroid, 0, Mypubkey()))); } } return(""); @@ -570,16 +571,18 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f int32_t bidvout=0; uint64_t mask; int64_t origprice, bidamount, paid_amount, remaining_required, inputs, CCchange=0; - struct CCcontract_info *cp,C; + struct CCcontract_info *cpTokens, tokensC; + struct CCcontract_info *cpAssets, assetsC; if (fillamount < 0) { fprintf(stderr,"negative fillamount %lld\n", (long long)fillamount); return(""); } - cp = CCinit(&C, EVAL_TOKENS); + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + cpAssets = CCinit(&assetsC, EVAL_ASSETS); - if ( txfee == 0 ) + if (txfee == 0) txfee = 10000; mypk = pubkey2pk(Mypubkey()); @@ -594,7 +597,7 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f mtx.vin.push_back(CTxIn(bidtxid, bidvout, CScript())); - if ((inputs = AddTokenCCInputs(cp, mtx, mypk, assetid, fillamount, 60)) > 0) + if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fillamount, 60)) > 0) { if (inputs < fillamount) { std::cerr << "FillBuyOffer(): insufficient tokens to fill buy offer" << std::endl; @@ -607,16 +610,24 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f if (inputs > fillamount) CCchange = (inputs - fillamount); - mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, bidamount - paid_amount, GetUnspendable(cp,0))); // tokens + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, bidamount - paid_amount, GetUnspendable(cpTokens, NULL))); // tokens mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, fillamount, pubkey2pk(origpubkey))); // coins + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, fillamount, pubkey2pk(origpubkey))); // coins on assets if (CCchange != 0) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); // coins + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); // coins on assets fprintf(stderr,"remaining %llu -> origpubkey\n", (long long)remaining_required); - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee, EncodeAssetOpRet('B', assetid, zeroid, remaining_required, origpubkey))); + // add additional unspendable addr from Assets: + char unspendableAssetsAddr[64]; + uint8_t unspendableAssetsPrivkey[32]; + + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk); + CCaddr2set(cpTokens, EVAL_ASSETS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); + + return(FinalizeCCTx(mask,cpTokens,mtx,mypk,txfee, EncodeAssetOpRet('B', assetid, zeroid, remaining_required, origpubkey))); } else return("dont have any assets to fill bid\n"); } } @@ -694,16 +705,16 @@ std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 askt if (assetid2 != zeroid && inputs > paid_nValue) CCchange = (inputs - paid_nValue); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, orig_assetoshis - received_assetoshis, GetUnspendable(cpAssets, NULL))); // coins + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, orig_assetoshis - received_assetoshis, GetUnspendable(cpAssets, NULL))); // coins in Assets cc addr mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, received_assetoshis, mypk)); // tokens if (assetid2 != zeroid) - mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, paid_nValue, origpubkey)); // tokens (not implemented correctly) + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, paid_nValue, origpubkey)); // tokens... (swap is not implemented yet) else - mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); // coins + mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); // coins normal if (CCchange != 0) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); // coins + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); // coins in Assets cc addr return(FinalizeCCTx(mask,cpTokens,mtx,mypk,txfee,EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid, assetid2, remaining_nValue, origpubkey))); } else { diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 56c4b27d5..ec1557e2b 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -86,12 +86,27 @@ struct CC_meta struct CCcontract_info { - char unspendableCCaddr[64],CChexstr[72],normaladdr[64],unspendableaddr2[64],unspendableaddr3[64]; - uint8_t CCpriv[32],unspendablepriv2[32],unspendablepriv3[32]; - CPubKey unspendablepk2,unspendablepk3; - bool (*validate)(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); - bool (*ismyvin)(CScript const& scriptSig); - uint8_t evalcode,evalcode2,evalcode3,didinit; + // this is for spending from 'unspendable' CC address + uint8_t evalcode; + char unspendableCCaddr[64], CChexstr[72], normaladdr[64]; + uint8_t CCpriv[32]; + + // this for 1of2 key spending condition (for this evalcode) + // NOTE: only one evalcode is allowed at this time + char unspendable1of2addr[64]; + CPubKey unspendable1of2pk[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): + uint8_t evalcode2, evalcode3; + char unspendableaddr2[64], unspendableaddr3[64]; + uint8_t unspendablepriv2[32], unspendablepriv3[32]; + CPubKey unspendablepk2, unspendablepk3; + + bool (*validate)(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); // cc contract tx validation callback + bool (*ismyvin)(CScript const& scriptSig); // checks if evalcode is present in the scriptSig param + + uint8_t didinit; }; struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode); @@ -164,6 +179,7 @@ CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2); 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); bool IsCCInput(CScript const& scriptSig); int32_t unstringbits(char *buf,uint64_t bits); uint64_t stringbits(char *str); diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 57a2a327b..dc8b4788e 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -44,7 +44,10 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=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]; - uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*othercond2=0,*othercond3=0,*cond; CPubKey unspendablepk; + uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; + CC *mycond=0, *othercond=0, *othercond2=0, *othercond3=0, *othercond1of2=NULL, *cond; + CPubKey unspendablepk; + n = mtx.vout.size(); for (i=0; iunspendableaddr2) == 0) { //fprintf(stderr,"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) - 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); + if ( othercond2 == 0 ) //&& cp->evalcode != EVAL_CHANNELS && cp->evalcode != EVAL_HEIR && cp->evalcode != EVAL_ASSETS && cp->evalcode != EVAL_TOKENS) + 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); @@ -158,6 +163,15 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran othercond3 = MakeCCcond1(cp->evalcode3,cp->unspendablepk3); cond = othercond3; } + // check if this is spending from 1of2 cc addr: + else if (strcmp(cp->unspendable1of2addr, destaddr) == 0) + { + //fprintf(stderr,"matched %s unspendable1of2!\n",cp->unspendable1of2addr); + privkey = myprivkey; + if (othercond1of2 == 0) + othercond1of2 = MakeCCcond1of2(cp->evalcode, cp->unspendable1of2pk[0], cp->unspendable1of2pk[1]); + cond = othercond1of2; + } else { fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index ed16805d7..c0fea0c9f 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -195,6 +195,14 @@ void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t * strcpy(cp->unspendableaddr3,coinaddr); } +// 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); +} + bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) { CTxDestination address; txnouttype whichType; diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index 81318ad1e..90557d7ac 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -1061,11 +1061,12 @@ template UniValue HeirClaim(uint256 fundingtxid, uint64_t txfee GetCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); Myprivkey(myprivkey); - //fprintf(stderr,"HeirClaim() before setting unspendable CC addr2= (%s) addr3= (%s)\n", cp->unspendableaddr2, cp->unspendableaddr3); - CCaddr2set(cp, Helper::getMyEval(), ownerPubkey, myprivkey, coinaddr); - CCaddr3set(cp, Helper::getMyEval(), heirPubkey, myprivkey, coinaddr); + ////fprintf(stderr,"HeirClaim() before setting unspendable CC addr2= (%s) addr3= (%s)\n", cp->unspendableaddr2, cp->unspendableaddr3); + //CCaddr2set(cp, Helper::getMyEval(), ownerPubkey, myprivkey, coinaddr); + //CCaddr3set(cp, Helper::getMyEval(), heirPubkey, myprivkey, coinaddr); + ////fprintf(stderr, "HeirClaim() after setting unspendable CC addr2=(%s) addr3=(%s)\n", cp->unspendableaddr2, cp->unspendableaddr3); - fprintf(stderr, "HeirClaim() after setting unspendable CC addr2=(%s) addr3=(%s)\n", cp->unspendableaddr2, cp->unspendableaddr3); + CCaddr1of2set(cp, ownerPubkey, heirPubkey, coinaddr); // add opreturn 'C' and sign tx: // this txfee will be ignored std::string rawhextx = FinalizeCCTx(0, cp, mtx, myPubkey, txfee, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b39a19668..1320da61c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6952,12 +6952,20 @@ UniValue tokenlist(const UniValue& params, bool fHelp) UniValue tokeninfo(const UniValue& params, bool fHelp) { +#ifdef TESTMODE + std::cerr << "is CCerror clear? CCerror=" << CCerror << std::endl; +#endif uint256 tokenid; if ( fHelp || params.size() != 1 ) throw runtime_error("tokeninfo tokenid\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); tokenid = Parseuint256((char *)params[0].get_str().c_str()); + +#ifdef TESTMODE + CCerror = "test error"; +#endif + return(AssetInfo(tokenid)); }