From 1f77927e6250b9fe98f7a4df782fe82a0d73724a Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 24 Sep 2018 07:19:21 -1100 Subject: [PATCH 01/35] Keep mining rewards indefinitely --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 8908e811e..bf2ae23fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1876,7 +1876,7 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) return(100000000 * COIN); // ICO allocation else if ( nHeight < KOMODO_ENDOFERA ) //komodo_moneysupply(nHeight) < MAX_MONEY ) return(3 * COIN); - else return(0); + else return(COIN); } else { From 9f59de78b2e48687e9971d99f754f0cd2ff4f691 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 24 Sep 2018 07:22:32 -1100 Subject: [PATCH 02/35] Ramp down blockreward over 30 years --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index bf2ae23fd..0aadc130c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1874,8 +1874,10 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) { if ( nHeight == 1 ) return(100000000 * COIN); // ICO allocation - else if ( nHeight < KOMODO_ENDOFERA ) //komodo_moneysupply(nHeight) < MAX_MONEY ) + else if ( nHeight < KOMODO_ENDOFERA ) return(3 * COIN); + else if ( nHeight < 2*KOMODO_ENDOFERA ) + return(2 * COIN); else return(COIN); } else From 22f4e6fd145c82d6a348d93abd6db8c36a3fdf70 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 24 Sep 2018 20:25:35 -1100 Subject: [PATCH 03/35] Dispflag for PoW diff --- src/komodo_bitcoind.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 13501d2a9..86ed8f7b3 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1284,7 +1284,7 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc) { - int32_t oldflag = 0; + int32_t oldflag = 0,dispflag = 0; CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val; *percPoSp = percPoS = 0; if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) ) @@ -1303,23 +1303,23 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he { n++; percPoS++; - if ( ASSETCHAINS_STAKED < 100 ) + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) fprintf(stderr,"0"); } else { - if ( ASSETCHAINS_STAKED < 100 ) + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) fprintf(stderr,"1"); sum += UintToArith256(pindex->GetBlockHash()); m++; } } - if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) fprintf(stderr," %d, ",percPoS); } if ( m+n < 100 ) percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; - if ( ASSETCHAINS_STAKED < 100 ) + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); *percPoSp = percPoS; if ( m > 0 ) @@ -1332,12 +1332,10 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he percPoS = 1; if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget { - //if ( oldflag != 0 ) - // bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc); if ( oldflag != 0 ) bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); else bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); - if ( ASSETCHAINS_STAKED < 100 ) + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) { for (i=31; i>=24; i--) fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); @@ -1355,7 +1353,6 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he if ( oldflag != 0 ) { bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); - //bnTarget = (bnTarget * arith_uint256(percPoS * percPoS * percPoS)) / arith_uint256(goalperc * goalperc); bnTarget = (bnTarget / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); } else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); @@ -1367,7 +1364,7 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he if ( bnTarget < ave ) bnTarget = ave; } - if ( 1 ) + if ( dispflag != 0 ) { for (i=31; i>=24; i--) fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); From c9f93c2c95be56f2cf443daf549a03cb227f2696 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 24 Sep 2018 20:41:38 -1100 Subject: [PATCH 04/35] +print --- src/cc/gateways.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index a0b3a7210..3db4a56e2 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -311,14 +311,14 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { Getscriptaddress(destaddr,vintx.vout[vout].scriptPubKey); - //fprintf(stderr,"%s vout.%d %.8f %.8f\n",destaddr,vout,(double)vintx.vout[vout].nValue/COIN,(double)it->second.satoshis/COIN); + fprintf(stderr,"check %s vout.%d %.8f %.8f\n",destaddr,vout,(double)vintx.vout[vout].nValue/COIN,(double)it->second.satoshis/COIN); 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 ) { 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); + 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 ) { //fprintf(stderr,"total %llu maxinputs.%d %.8f\n",(long long)total,maxinputs,(double)it->second.satoshis/COIN); From f9f8f4ec67ee01a7004b033e2aacc575039ef2ab Mon Sep 17 00:00:00 2001 From: jl777 Date: Tue, 25 Sep 2018 00:38:11 -1100 Subject: [PATCH 05/35] Fix gatewaysmarkdone --- src/cc/CCcustom.cpp | 2 +- src/wallet/rpcwallet.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index d9a793ddd..71644686b 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -214,7 +214,7 @@ uint8_t PaymentsCCpriv[32] = { 0x03, 0xc9, 0x73, 0xc2, 0xb8, 0x30, 0x3d, 0xbd, 0 #define FUNCNAME IsGatewaysInput #define EVALCODE EVAL_GATEWAYS const char *GatewaysCCaddr = "RKWpoK6vTRtq5b9qrRBodLkCzeURHeEk33"; -const char *GatewaysNormaladdr = "RGJKV97ZN1wBfunuMt1tebiiHENNEq73Yh"; +const char *GatewaysNormaladdr = "RGJKV97ZN1wBfunuMt1tebiiHENNEq73Yh"; // wif UxJFYqEvLAjWPPRvn8NN1fRWscBxQZXZB5BBgc3HiapKVQBYNcmo char GatewaysCChexstr[67] = { "03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40" }; uint8_t GatewaysCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0x89, 0xb1, 0xcb, 0xb9, 0xe6, 0x9c, 0x2c, 0x70, 0x85, 0x37, 0xdd, 0x00, 0x7a, 0x67, 0xff, 0x7c, 0x62, 0x1b, 0xe2, 0xfb, 0x04, 0x8f, 0x85, 0xbf }; #include "CCcustom.inc" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index cf86a0ba5..8f64d093d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5554,7 +5554,7 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp) UniValue gatewaysmarkdone(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); uint256 withdrawtxid,cointxid; std::string hex,coin; - if ( fHelp || params.size() != 1 ) + if ( fHelp || params.size() != 3 ) throw runtime_error("gatewaysmarkdone withdrawtxid coin cointxid\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"); From 72968af153b1813c68b51201eefa59969932fbc3 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 27 Sep 2018 23:40:35 -1100 Subject: [PATCH 06/35] Prices --- src/cc/oracles.cpp | 2 +- src/cc/prices.cpp | 52 ++++++++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 6af1453ce..255b7f034 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -804,7 +804,7 @@ std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector da mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,batonpk)); mtx.vout.push_back(CTxOut(datafee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesData('D',oracletxid,batontxid,mypk,data))); - } else fprintf(stderr,"couldnt find enough oracle inputs, limit 1 per utxo\n"); + } else fprintf(stderr,"couldnt find enough oracle inputs %s, limit 1 per utxo\n",coinaddr); } else fprintf(stderr,"couldnt add normal inputs\n"); return(""); } diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index ca945d02f..6ee0364e2 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -55,6 +55,8 @@ exposure address, funds address + + */ // start of consensus code @@ -138,7 +140,7 @@ int64_t AddTokensInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && vout < vintx.vout.size() ) { // need to verify assetid - if ( (nValue= vintx.vout[vout].nValue) > 10000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + if ( (nValue= vintx.vout[vout].nValue) >= 10000 && myIsutxo_spentinmempool(txid,vout) == 0 ) { if ( total != 0 && maxinputs != 0 ) mtx.vin.push_back(CTxIn(txid,vout,CScript())); @@ -179,7 +181,7 @@ UniValue PricesList() // bettoken std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletxid,uint64_t margin,uint64_t mode,uint256 longtoken,uint256 shorttoken,int32_t maxleverage,int64_t funding,std::vector pubkeys) { - CMutableTransaction mtx; CTransaction oracletx; int64_t fullsupply,inputs,CCchange=0; uint256 hashBlock; char str[65],coinaddr[64],houseaddr[64]; CPubKey mypk,pricespk; int32_t i,N,numvouts; struct CCcontract_info *cp,C,*assetscp,C2; + CMutableTransaction mtx; CTransaction oracletx; int64_t fullsupply,inputs,CCchange=0; uint256 hashBlock; char str[65],coinaddr[64],houseaddr[64]; CPubKey mypk,pricespk; int32_t i,N,numvouts; struct CCcontract_info *cp,C; if ( funding < 100*COIN || maxleverage <= 0 || maxleverage > 10000 ) { CCerror = "invalid parameter error"; @@ -187,7 +189,6 @@ std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletx return(""); } cp = CCinit(&C,EVAL_PRICES); - assetscp = CCinit(&C2,EVAL_ASSETS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); @@ -243,9 +244,8 @@ std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletx UniValue PricesInfo(uint256 fundingtxid) { - UniValue result(UniValue::VOBJ),a(UniValue::VARR); CPubKey pricespk,planpk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction vintx; int64_t balance,supply,exposure; uint64_t funding,mode; int32_t i,margin,maxleverage; char numstr[65],houseaddr[64],exposureaddr[64],str[65]; std::vectorpubkeys; struct CCcontract_info *cp,C,*assetscp,C2; + UniValue result(UniValue::VOBJ),a(UniValue::VARR); CPubKey pricespk,planpk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction vintx; int64_t balance,supply,exposure; uint64_t funding,mode; int32_t i,margin,maxleverage; char numstr[65],houseaddr[64],exposureaddr[64],str[65]; std::vectorpubkeys; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_PRICES); - assetscp = CCinit(&C2,EVAL_ASSETS); pricespk = GetUnspendable(cp,0); if ( GetTransaction(fundingtxid,vintx,hashBlock,false) == 0 ) { @@ -266,8 +266,8 @@ UniValue PricesInfo(uint256 fundingtxid) for (i=0; ipubkeys; + CMutableTransaction mtx; struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,CCchange = 0; uint64_t funding,mode; int32_t margin,maxleverage; char houseaddr[64],myaddr[64]; std::vectorpubkeys; if ( amount < 10000 ) { CCerror = "amount must be positive"; @@ -300,12 +300,11 @@ std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingt return(""); } cp = CCinit(&C,EVAL_PRICES); - assetscp = CCinit(&C2,EVAL_ASSETS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); pricespk = GetUnspendable(cp,0); - GetCCaddress(assetscp,myaddr,mypk); + GetCCaddress(cp,myaddr,mypk); if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 ) { fprintf(stderr,"cant find fundingtxid\n"); @@ -313,16 +312,16 @@ std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingt } if ( tx.vout.size() > 0 && DecodePricesFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' && bettoken == refbettoken ) { - GetCCaddress1of2(assetscp,houseaddr,pricespk,planpk); + GetCCaddress1of2(cp,houseaddr,pricespk,planpk); if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { - if ( (inputs= AddTokensInputs(assetscp,mtx,myaddr,bettoken,amount,60)) >= amount ) + if ( (inputs= AddTokensInputs(cp,mtx,myaddr,bettoken,amount,60)) >= amount ) { - mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,amount,pricespk,planpk)); + mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,amount,pricespk,planpk)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(planpk)) << OP_CHECKSIG)); if ( inputs > amount+txfee ) CCchange = (inputs - amount); - mtx.vout.push_back(MakeCC1vout(assetscp->evalcode,CCchange,mypk)); + mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,mypk)); // add addr2 return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',bettoken,zeroid,0,Mypubkey()))); } @@ -343,19 +342,18 @@ std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingt std::string PricesBet(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount,int32_t leverage) { - CMutableTransaction mtx; struct CCcontract_info *cp,C,*assetscp,C2; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,tokenid,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,inputs2,longexposure,netexposure,shortexposure,CCchange = 0,CCchange2 = 0; uint64_t funding,mode; int32_t dir,margin,maxleverage; char houseaddr[64],myaddr[64],exposureaddr[64]; std::vectorpubkeys; + CMutableTransaction mtx; struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,tokenid,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,inputs2,longexposure,netexposure,shortexposure,CCchange = 0,CCchange2 = 0; uint64_t funding,mode; int32_t dir,margin,maxleverage; char houseaddr[64],myaddr[64],exposureaddr[64]; std::vectorpubkeys; if ( amount < 0 ) { amount = -amount; dir = -1; } else dir = 1; cp = CCinit(&C,EVAL_PRICES); - assetscp = CCinit(&C2,EVAL_ASSETS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); pricespk = GetUnspendable(cp,0); - GetCCaddress(assetscp,myaddr,mypk); + GetCCaddress(cp,myaddr,mypk); if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 ) { fprintf(stderr,"cant find fundingtxid\n"); @@ -368,8 +366,8 @@ std::string PricesBet(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int fprintf(stderr,"illegal leverage\n"); return(""); } - GetCCaddress1of2(assetscp,houseaddr,pricespk,planpk); - GetCCaddress1of2(assetscp,exposureaddr,pricespk,pricespk); + GetCCaddress1of2(cp,houseaddr,pricespk,planpk); + GetCCaddress1of2(cp,exposureaddr,pricespk,pricespk); if ( dir < 0 ) tokenid = shorttoken; else tokenid = longtoken; @@ -387,22 +385,22 @@ std::string PricesBet(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int } if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { - if ( (inputs= AddTokensInputs(assetscp,mtx,houseaddr,tokenid,exposure,30)) >= exposure ) + if ( (inputs= AddTokensInputs(cp,mtx,houseaddr,tokenid,exposure,30)) >= exposure ) { - if ( (inputs2= AddTokensInputs(assetscp,mtx,myaddr,bettoken,amount,30)) >= amount ) + if ( (inputs2= AddTokensInputs(cp,mtx,myaddr,bettoken,amount,30)) >= amount ) { - mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,amount,pricespk,planpk)); - mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,exposure,pricespk,pricespk)); + mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,amount,pricespk,planpk)); + mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,exposure,pricespk,pricespk)); if ( inputs > exposure+txfee ) CCchange = (inputs - exposure); if ( inputs2 > amount+txfee ) CCchange2 = (inputs2 - amount); - mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,CCchange,pricespk,planpk)); - mtx.vout.push_back(MakeCC1vout(assetscp->evalcode,CCchange2,mypk)); + mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,CCchange,pricespk,planpk)); + mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange2,mypk)); // add addr2 and addr3 - //return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,EncodePricesExtra('T',tokenid,bettoken,zeroid,dir*leverage))); + //return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesExtra('T',tokenid,bettoken,zeroid,dir*leverage))); CScript opret; - return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,opret)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } else { From bd59ecd6cd8a903f4164d75da145ae5005ca4dbf Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 1 Oct 2018 02:37:21 -1100 Subject: [PATCH 07/35] Require tokenid for remaining --- src/cc/gateways.cpp | 2 +- src/rpcrawtransaction.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 3db4a56e2..5c82b789d 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -426,7 +426,7 @@ UniValue GatewaysInfo(uint256 bindtxid) result.push_back(Pair("tokenid",uint256_str(str,tokenid))); sprintf(numstr,"%.8f",(double)totalsupply/COIN); result.push_back(Pair("totalsupply",numstr)); - remaining = CCaddress_balance(gatewaysassets); + remaining = CCtoken_balance(gatewaysassets,tokenid); sprintf(numstr,"%.8f",(double)remaining/COIN); result.push_back(Pair("remaining",numstr)); sprintf(numstr,"%.8f",(double)(totalsupply - remaining)/COIN); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 798b991d7..9471abf0a 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -477,7 +477,7 @@ int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid uint256 hashBlock; if ( GetTransaction(txid,tx,hashBlock,false) == 0 ) return(-1); - else if ( n <= tx.vout.size() ) // vout.size() seems off by 1 + else if ( n < tx.vout.size() ) { ptr = (uint8_t *)tx.vout[n].scriptPubKey.data(); m = tx.vout[n].scriptPubKey.size(); From 450c5f7115f1832915b7ac878414906bb5e81f29 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 1 Oct 2018 02:47:25 -1100 Subject: [PATCH 08/35] Test --- src/cc/oracles.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 255b7f034..5a352afeb 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -666,6 +666,7 @@ int64_t AddOracleInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); + fprintf(stderr,"addoracleinputs from (%s)\n",coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; From 93cfcaa7efeb6251cddda6afe3f01fe747ce97eb Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Fri, 14 Sep 2018 15:03:44 +0200 Subject: [PATCH 09/35] - Modified AddChannelsInputs to uses inputs from CC channel for payment - Inital validate skeleton - Defined OP_RETURN format --- src/cc/channels.cpp | 326 ++++++++++++++++++++++++++++++++------------ 1 file changed, 239 insertions(+), 87 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index dc1a3f291..0ecd6a1be 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -111,11 +111,101 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti else return(true); } +CScript EncodeChannelsOpRet(uint8_t funcid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) +{ + CScript opret; uint8_t evalcode = EVAL_CHANNELS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << opentxid << srcpub << destpub << numpayments << payment << hashchain); + return(opret); +} + +uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) +{ + std::vector vopret; uint8_t *script,e,f,funcid; + GetOpReturnData(scriptPubKey, vopret); + if ( vopret.size() > 2 ) + { + script = (uint8_t *)vopret.data(); + if ( script[0] == EVAL_CHANNELS ) + { + funcid = script[1]; + //fprintf(stderr,"decode.[%c]\n",funcid); + switch ( funcid ) + { + case 'c': + return(funcid); + break; + default: + if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> opentxid; ss >> srcpub; ss >> destpub; ss >> numpayments; ss >> payment; ss >> hashchain) != 0 ) + { + return(f); + } + break; + } + } else fprintf(stderr,"script[0] %02x != EVAL_CHANNELS\n",script[0]); + } else fprintf(stderr,"not enough opret.[%d]\n",(int32_t)vopret.size()); + return(0); +} + +CScript EncodeChannelsPaymentOpRet(uint8_t funcid,uint256 opentxid,uint256 prevtxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) +{ + CScript opret; uint8_t evalcode = EVAL_CHANNELS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << opentxid << prevtxid << srcpub << destpub << numpayments << payment << hashchain); + return(opret); +} + +uint8_t DecodeChannelsPaymentOpRet(const CScript &scriptPubKey,uint256 &opentxid,uint256 &prevtxid,CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) +{ + std::vector vopret; uint8_t *script,e,f,funcid; + GetOpReturnData(scriptPubKey, vopret); + if ( vopret.size() > 2 ) + { + script = (uint8_t *)vopret.data(); + if ( script[0] == EVAL_CHANNELS ) + { + if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> opentxid; ss >> srcpub; ss >> destpub; ss >> numpayments; ss >> payment; ss >> hashchain) != 0 ) + { + return(f); + } + } else fprintf(stderr,"script[0] %02x != EVAL_CHANNELS\n",script[0]); + } else fprintf(stderr,"not enough opret.[%d]\n",(int32_t)vopret.size()); + return(0); +} + +//bool GetChannelOpenTx(struct CCcontract_info *cp, CTransaction &channelOpenTx, CPubKey srcpub, CPubKey destpub, int32_t &numpayments, int64_t &payment, uint256 &hashchain) +//{ +// uint256 txid, hashBlock, origtxid; +// char CCaddr[64]; +// std::vector > txids; +// uint8_t funcid; +// CPubKey opensrcpub, opendestpub; +// int32_t numvouts; +// +// GetCCaddress1of2(cp,CCaddr,srcpub,destpub); +// SetCCtxids(txids,CCaddr); +// +// for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) +// { +// txid=it->first.txhash; +// if (GetTransaction(txid,channelOpenTx,hashBlock,false) != 0 && (numvouts= channelOpenTx.vout.size()) > 0) +// { +// if (((funcid = DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,origtxid,opensrcpub,opendestpub,numpayments,payment,hashchain)) != 0) && (funcid == 'O') && (srcpub==opensrcpub && (destpub==opendestpub))) +// { +// return true; +// } +// } +// } +// +// return false; +//} + bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,param1,numpayments; bool retval; uint256 txid,hashblock,param3,hashchain,opentxid,prevtxid; uint8_t funcid, hash[32]; char str[65],destaddr[64]; + int64_t param2,payment; + CPubKey srcpub, destpub; std::vector > txids; + CTransaction channelOpenTx; + numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; @@ -140,6 +230,43 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & { txid = tx.GetHash(); memcpy(hash,&txid,sizeof(hash)); + + if ( (funcid = DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, opentxid, srcpub, destpub, param1, param2, param3)) != 0) + { + switch ( funcid ) + { + case 'O': + if ( IsCCInput(tx.vin[0].scriptSig) == 0 ) + return eval->Invalid("vin.0 is normal for channelOpen"); + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.0 is CC for channelOpen"); + else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.1 is CC for channelOpen"); + else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.2 is CC for channelOpen"); + else if ( numpayments > 1000) + return eval->Invalid("too many payment increments"); + else if ( tx.vout[0].nValue != param1 * param2) + return eval->Invalid("tx funds do not match sum of payments"); + break; + case 'C': + break; + case 'P': + DecodeChannelsPaymentOpRet(tx.vout[numvouts-1].scriptPubKey, opentxid, prevtxid, srcpub, destpub, param1, param2, param3); + if ( IsCCInput(tx.vin[0].scriptSig) == 0 ) + return eval->Invalid("vin.0 is normal for channelOpen"); + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.0 is CC for channelOpen"); + + if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) + { + return (false); + } + break; + case 'R': + break; + } + } retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); if ( retval != 0 ) fprintf(stderr,"Channelsget validated\n"); @@ -152,57 +279,57 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & // helper functions for rpc calls in rpcwallet.cpp -CScript EncodeChannelsOpRet(uint8_t funcid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) +int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, uint256 prevtxid) { - CScript opret; uint8_t evalcode = EVAL_CHANNELS; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << srcpub << destpub << numpayments << payment << hashchain); - return(opret); -} - -uint8_t DecodeChannelsOpRet(uint256 txid,const CScript &scriptPubKey,CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) -{ - std::vector vopret; uint8_t *script,e,f,funcid; - GetOpReturnData(scriptPubKey, vopret); - if ( vopret.size() > 2 ) - { - script = (uint8_t *)vopret.data(); - if ( script[0] == EVAL_CHANNELS ) - { - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> srcpub; ss >> destpub; ss >> numpayments; ss >> payment; ss >> hashchain) != 0 ) - { - return(f); - } - } else fprintf(stderr,"script[0] %02x != EVAL_CHANNELS\n",script[0]); - } else fprintf(stderr,"not enough opret.[%d]\n",(int32_t)vopret.size()); - return(0); -} - -int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) -{ - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; + char coinaddr[64]; int64_t param2,totalinputs = 0; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t funcid,param1,numvouts,vout; std::vector > unspentOutputs; - GetCCaddress(cp,coinaddr,pk); + CPubKey srcpub,destpub; + + GetCCaddress1of2(cp,coinaddr,srcpub,destpub); SetCCunspents(unspentOutputs,coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - // no need to prevent dup - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0) { - if ( (nValue= IsChannelsvout(cp,vintx,vout)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) - { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) != 0 && prevtxid==tmp_txid) + if ( (totalinputs=IsChannelsvout(cp,tx,vout)) > 0) + { + txid = it->first.txhash; + vout = 0; break; + } + } + } + + if (myIsutxo_spentinmempool(txid,vout) != 0) + { + txid=zeroid; + int32_t mindepth=1000; + + BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) + { + const CTransaction &txmempool = e.GetTx(); + const uint256 &hash = tx.GetHash(); + if ((numvouts=txmempool.vout.size()) > 0 && + (funcid=DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)) != 0 && + funcid=='P' && param1 < mindepth) + { + txid=hash; + vout=0; + totalinputs=txmempool.vout[vout].nValue; + mindepth=param1; + } } } - return(totalinputs); + + if (txid != zeroid) + { + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + return totalinputs; + } + else return 0; } std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment) @@ -232,12 +359,74 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',mypk,destpub,numpayments,payment,hashchain))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',zeroid,mypk,destpub,numpayments,payment,hashchain))); } return(""); } -std::string ChannelStop(uint64_t txfee,CPubKey destpub,uint256 origtxid) +std::string ChannelPayment(uint64_t txfee,uint256 prevtxid,uint256 opentxid,int32_t numpayments) +{ + CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,secret,hashblock,entropy,hentropy,param3; + struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,param1; + int64_t param2,payment,change,funds; + uint8_t hash[32],hashdest[32]; + CTransaction channelOpenTx,prevTx; + + if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) + { + if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsPaymentOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, txid, srcpub, destpub, param1, param2, param3)) != 0) && (funcid == 'O' || funcid == 'P')) + { + if (mypk != srcpub || mypk != destpub) + { + fprintf(stderr,"this is not our channel\n"); + return(""); + } + + prevdepth=param1; + payment=param2; + } + else + { + fprintf(stderr,"invalid previous txid\n"); + return(""); + } + + if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) + { + hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < prevdepth-numpayments; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & secret, hashdest, 32); + } + else + { + fprintf(stderr,"invalid channel open txid\n"); + return(""); + } + } + // verify lasttxid and origtxid match and src is me + // also verify hashchain depth and amount, set prevdepth + cp = CCinit(&C,EVAL_CHANNELS); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + { + if ((funds=AddChannelsInputs(cp,mtx,prevtxid)) != 0 && (change=funds-numpayments*payment)>=0) { + mtx.vout.push_back(CTxOut(numpayments * payment, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS, txfee, mypk)); + mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); + return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsPaymentOpRet('P', opentxid, prevtxid, mypk, destpub, prevdepth - numpayments, payment, secret))); + } + } + return(""); +} + +std::string ChannelClose(uint64_t txfee,uint256 prevtxid,uint256 opentxid,CPubKey destpub) { CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; // verify this is one of our outbound channels @@ -248,49 +437,12 @@ std::string ChannelStop(uint64_t txfee,CPubKey destpub,uint256 origtxid) if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) { mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('S',mypk,destpub,0,0,zeroid))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('S',opentxid,mypk,destpub,0,0,zeroid))); } return(""); } -std::string ChannelPayment(uint64_t txfee,uint256 prevtxid,uint256 origtxid,int32_t n,int64_t amount) -{ - CMutableTransaction mtx; CPubKey mypk,destpub; uint256 secret; struct CCcontract_info *cp,C; int32_t prevdepth; - // verify lasttxid and origtxid match and src is me - // also verify hashchain depth and amount, set prevdepth - cp = CCinit(&C,EVAL_CHANNELS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) - { - // add locked funds inputs - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('P',mypk,destpub,prevdepth-n,amount,secret))); - } - return(""); -} - -std::string ChannelCollect(uint64_t txfee,uint256 paytxid,uint256 origtxid,int32_t n,int64_t amount) -{ - CMutableTransaction mtx; CPubKey mypk,senderpub; struct CCcontract_info *cp,C; int32_t prevdepth; - // verify paytxid and origtxid match and dest is me - // also verify hashchain depth and amount - cp = CCinit(&C,EVAL_CHANNELS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) - { - // add locked funds inputs - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); - mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',senderpub,mypk,prevdepth-n,amount,paytxid))); - } - return(""); -} - -std::string ChannelRefund(uint64_t txfee,uint256 stoptxid,uint256 origtxid) +std::string ChannelRefund(uint64_t txfee,uint256 closetxid,uint256 opentxid) { CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; int64_t amount; // verify stoptxid and origtxid match and are mine @@ -302,14 +454,14 @@ std::string ChannelRefund(uint64_t txfee,uint256 stoptxid,uint256 origtxid) { mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',mypk,mypk,0,0,stoptxid))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,mypk,0,0,closetxid))); } return(""); } UniValue ChannelsInfo() { - UniValue result(UniValue::VOBJ); CTransaction tx; uint256 txid,hashBlock,hashchain; struct CCcontract_info *cp,C; uint8_t funcid; char myCCaddr[64]; int32_t vout,numvouts,numpayments; int64_t nValue,payment; CPubKey srcpub,destpub,mypk; + UniValue result(UniValue::VOBJ); CTransaction tx; uint256 txid,hashBlock,hashchain,opentxid; struct CCcontract_info *cp,C; uint8_t funcid; char myCCaddr[64]; int32_t vout,numvouts,numpayments; int64_t nValue,payment; CPubKey srcpub,destpub,mypk; std::vector > txids; result.push_back(Pair("result","success")); result.push_back(Pair("name","Channels")); @@ -325,7 +477,7 @@ UniValue ChannelsInfo() nValue = (int64_t)it->second; if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - if ( DecodeChannelsOpRet(txid,tx.vout[numvouts-1].scriptPubKey,srcpub,destpub,numpayments,payment,hashchain) == 'O' || funcid == 'P' ) + if ( DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'O' || funcid == 'P' ) { char str[67],str2[67]; fprintf(stderr,"%s func.%c %s -> %s %.8f num.%d of %.8f\n",mypk == srcpub ? "send" : "recv",funcid,pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),(double)tx.vout[0].nValue/COIN,numpayments,(double)payment/COIN); From c2fa2759d61cc39a7e55b3365eed7a7b7cc20642 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Fri, 14 Sep 2018 22:36:10 +0200 Subject: [PATCH 10/35] Small fixes --- src/cc/CCchannels.h | 7 ++-- src/cc/channels.cpp | 78 +++++++++++++++++++++++++++++----------- src/rpcserver.cpp | 3 +- src/rpcserver.h | 4 +-- src/wallet/rpcwallet.cpp | 58 +++++++++--------------------- 5 files changed, 80 insertions(+), 70 deletions(-) diff --git a/src/cc/CCchannels.h b/src/cc/CCchannels.h index 26057457f..ba31883a2 100644 --- a/src/cc/CCchannels.h +++ b/src/cc/CCchannels.h @@ -22,10 +22,9 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment); -std::string ChannelStop(uint64_t txfee,CPubKey destpub,uint256 origtxid); -std::string ChannelPayment(uint64_t txfee,uint256 prevtxid,uint256 origtxid,int32_t n,int64_t amount); -std::string ChannelCollect(uint64_t txfee,uint256 paytxid,uint256 origtxid,int32_t n,int64_t amount); -std::string ChannelRefund(uint64_t txfee,uint256 stoptxid,uint256 origtxid); +std::string ChannelPayment(uint64_t txfee,uint256 opentxid,uint256 prevtxid,int64_t amount); +std::string ChannelClose(uint64_t txfee,uint256 opentxid); +std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid); // CCcustom UniValue ChannelsInfo(); diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 0ecd6a1be..01a422715 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -244,7 +244,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vout.1 is CC for channelOpen"); else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("vout.2 is CC for channelOpen"); - else if ( numpayments > 1000) + else if ( numpayments > CHANNELS_MAXPAYMENTS) return eval->Invalid("too many payment increments"); else if ( tx.vout[0].nValue != param1 * param2) return eval->Invalid("tx funds do not match sum of payments"); @@ -287,7 +287,6 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, u GetCCaddress1of2(cp,coinaddr,srcpub,destpub); SetCCunspents(unspentOutputs,coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0) @@ -301,12 +300,10 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, u } } } - if (myIsutxo_spentinmempool(txid,vout) != 0) { txid=zeroid; int32_t mindepth=1000; - BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) { const CTransaction &txmempool = e.GetTx(); @@ -323,7 +320,6 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, u } } } - if (txid != zeroid) { mtx.vin.push_back(CTxIn(txid,vout,CScript())); @@ -344,6 +340,8 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 cp = CCinit(&C,EVAL_CHANNELS); if ( txfee == 0 ) txfee = 10000; + if (numpayments>CHANNELS_MAXPAYMENTS) + return (""); mypk = pubkey2pk(Mypubkey()); funds = numpayments * payment; if ( AddNormalinputs(mtx,mypk,funds+3*txfee,64) > 0 ) @@ -364,38 +362,78 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 return(""); } -std::string ChannelPayment(uint64_t txfee,uint256 prevtxid,uint256 opentxid,int32_t numpayments) +std::string ChannelPayment(uint64_t txfee,uint256 opentxid,uint256 prevtxid,int64_t amount) { CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,secret,hashblock,entropy,hentropy,param3; - struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,param1; + struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments,param1; int64_t param2,payment,change,funds; uint8_t hash[32],hashdest[32]; CTransaction channelOpenTx,prevTx; - if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) + if (opentxid==prevtxid) { - if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsPaymentOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, txid, srcpub, destpub, param1, param2, param3)) != 0) && (funcid == 'O' || funcid == 'P')) + if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) { - if (mypk != srcpub || mypk != destpub) + if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) != 0) && funcid == 'O') + { + if (mypk == srcpub || mypk == destpub) + { + prevdepth=param1; + payment=param2; + } + else + { + fprintf(stderr,"this is not our channel\n"); + return(""); + } + } + else + { + fprintf(stderr,"invalid previous txid\n"); + return(""); + } + if (amount % payment != 0) + return (""); + numpayments=amount/payment; + hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < numpayments; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & secret, hashdest, 32); + + } + } + else if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) + { + if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsPaymentOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, txid, srcpub, destpub, param1, param2, param3)) != 0) && funcid == 'P') + { + if (mypk == srcpub || mypk == destpub) + { + prevdepth=param1; + payment=param2; + } + else { fprintf(stderr,"this is not our channel\n"); return(""); } - - prevdepth=param1; - payment=param2; } else { fprintf(stderr,"invalid previous txid\n"); return(""); } - + if ((numpayments=amount % payment) != 0) + return (""); + numpayments=amount/payment; if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) { hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < prevdepth-numpayments; i++) + for (i = 0; i < numpayments; i++) { vcalc_sha256(0, hashdest, hash, 32); memcpy(hash, hashdest, 32); @@ -416,8 +454,8 @@ std::string ChannelPayment(uint64_t txfee,uint256 prevtxid,uint256 opentxid,int3 mypk = pubkey2pk(Mypubkey()); if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) { - if ((funds=AddChannelsInputs(cp,mtx,prevtxid)) != 0 && (change=funds-numpayments*payment)>=0) { - mtx.vout.push_back(CTxOut(numpayments * payment, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); + if ((funds=AddChannelsInputs(cp,mtx,prevtxid)) != 0 && (change=funds-amount)>=0) { + mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS, txfee, mypk)); mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsPaymentOpRet('P', opentxid, prevtxid, mypk, destpub, prevdepth - numpayments, payment, secret))); @@ -426,7 +464,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 prevtxid,uint256 opentxid,int3 return(""); } -std::string ChannelClose(uint64_t txfee,uint256 prevtxid,uint256 opentxid,CPubKey destpub) +std::string ChannelClose(uint64_t txfee,uint256 opentxid) { CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; // verify this is one of our outbound channels @@ -437,12 +475,12 @@ std::string ChannelClose(uint64_t txfee,uint256 prevtxid,uint256 opentxid,CPubKe if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) { mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('S',opentxid,mypk,destpub,0,0,zeroid))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('S',opentxid,mypk,mypk,0,0,zeroid))); } return(""); } -std::string ChannelRefund(uint64_t txfee,uint256 closetxid,uint256 opentxid) +std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) { CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; int64_t amount; // verify stoptxid and origtxid match and are mine diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 8934ae717..7d2eab1e3 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -383,8 +383,7 @@ static const CRPCCommand vRPCCommands[] = { "channels", "channelsinfo", &channelsinfo, true }, { "channels", "channelsopen", &channelsopen, true }, { "channels", "channelspayment", &channelspayment, true }, - { "channels", "channelscollect", &channelscollect, true }, - { "channels", "channelsstop", &channelsstop, true }, + { "channels", "channelsclose", &channelsclose, true }, { "channels", "channelsrefund", &channelsrefund, true }, /* Oracles */ diff --git a/src/rpcserver.h b/src/rpcserver.h index f4c502d63..a78f1b6fc 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -254,11 +254,9 @@ extern UniValue gatewayspending(const UniValue& params, bool fHelp); extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp); extern UniValue gatewaysmultisig(const UniValue& params, bool fHelp); extern UniValue channelsinfo(const UniValue& params, bool fHelp); -extern UniValue channelsbind(const UniValue& params, bool fHelp); extern UniValue channelsopen(const UniValue& params, bool fHelp); extern UniValue channelspayment(const UniValue& params, bool fHelp); -extern UniValue channelscollect(const UniValue& params, bool fHelp); -extern UniValue channelsstop(const UniValue& params, bool fHelp); +extern UniValue channelsclose(const UniValue& params, bool fHelp); extern UniValue channelsrefund(const UniValue& params, bool fHelp); //extern UniValue tokenswapask(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8f64d093d..c105b4872 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5153,42 +5153,21 @@ UniValue channelsopen(const UniValue& params, bool fHelp) return(result); } -UniValue channelsstop(const UniValue& params, bool fHelp) -{ - UniValue result(UniValue::VOBJ); std::vector destpub; struct CCcontract_info *cp,C; std::string hex; uint256 origtxid; - cp = CCinit(&C,EVAL_CHANNELS); - if ( fHelp || params.size() != 2 ) - throw runtime_error("channelsstop destpubkey origtxid\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"); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - destpub = ParseHex(params[0].get_str().c_str()); - origtxid = Parseuint256((char *)params[1].get_str().c_str()); - hex = ChannelStop(0,pubkey2pk(destpub),origtxid); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else ERR_RESULT("couldnt create channelsstop transaction"); - return(result); -} - UniValue channelspayment(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 origtxid,prevtxid; int32_t n; int64_t amount; + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,prevtxid; int32_t n; int64_t amount; cp = CCinit(&C,EVAL_CHANNELS); if ( fHelp || params.size() != 4 ) - throw runtime_error("channelspayment prevtxid origtxid n amount\n"); + throw runtime_error("channelspayment opentxid prevtxid amount\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"); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); - prevtxid = Parseuint256((char *)params[0].get_str().c_str()); - origtxid = Parseuint256((char *)params[1].get_str().c_str()); + opentxid = Parseuint256((char *)params[0].get_str().c_str()); + prevtxid = Parseuint256((char *)params[1].get_str().c_str()); n = atoi((char *)params[2].get_str().c_str()); amount = atoi((char *)params[3].get_str().c_str()); - hex = ChannelPayment(0,prevtxid,origtxid,n,amount); + hex = ChannelPayment(0,opentxid,prevtxid,amount); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); @@ -5197,42 +5176,39 @@ UniValue channelspayment(const UniValue& params, bool fHelp) return(result); } -UniValue channelscollect(const UniValue& params, bool fHelp) +UniValue channelsclose(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 origtxid,paytxid; int32_t n; int64_t amount; + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid; cp = CCinit(&C,EVAL_CHANNELS); - if ( fHelp || params.size() != 4 ) - throw runtime_error("channelscollect paytxid origtxid n amount\n"); + if ( fHelp || params.size() != 2 ) + throw runtime_error("channelsclose opentxid\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"); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); - paytxid = Parseuint256((char *)params[0].get_str().c_str()); - origtxid = Parseuint256((char *)params[1].get_str().c_str()); - n = atoi((char *)params[2].get_str().c_str()); - amount = atoi((char *)params[3].get_str().c_str()); - hex = ChannelCollect(0,paytxid,origtxid,n,amount); + opentxid = Parseuint256((char *)params[1].get_str().c_str()); + hex = ChannelClose(0,opentxid); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else ERR_RESULT("couldnt create channelscollect transaction"); + } else ERR_RESULT("couldnt create channelsstop transaction"); return(result); } UniValue channelsrefund(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 origtxid,stoptxid; + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,closetxid; cp = CCinit(&C,EVAL_CHANNELS); if ( fHelp || params.size() != 2 ) - throw runtime_error("channelsrefund stoptxid origtxid\n"); + throw runtime_error("channelsrefund opentxid closetxid\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"); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); - stoptxid = Parseuint256((char *)params[0].get_str().c_str()); - origtxid = Parseuint256((char *)params[1].get_str().c_str()); - hex = ChannelRefund(0,stoptxid,origtxid); + opentxid = Parseuint256((char *)params[0].get_str().c_str()); + closetxid = Parseuint256((char *)params[1].get_str().c_str()); + hex = ChannelRefund(0,opentxid,closetxid); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); From 5aa6428feba6f92cf4fa204e5ed476d88f5c0390 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sat, 15 Sep 2018 11:22:48 +0200 Subject: [PATCH 11/35] - Fixes --- src/cc/channels.cpp | 150 ++++++++++++++++++++++----------------- src/wallet/rpcwallet.cpp | 4 +- 2 files changed, 85 insertions(+), 69 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 01a422715..744c223d1 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -128,10 +128,9 @@ uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubK if ( script[0] == EVAL_CHANNELS ) { funcid = script[1]; - //fprintf(stderr,"decode.[%c]\n",funcid); switch ( funcid ) { - case 'c': + case 'O': return(funcid); break; default: @@ -171,37 +170,12 @@ uint8_t DecodeChannelsPaymentOpRet(const CScript &scriptPubKey,uint256 &opentxid return(0); } -//bool GetChannelOpenTx(struct CCcontract_info *cp, CTransaction &channelOpenTx, CPubKey srcpub, CPubKey destpub, int32_t &numpayments, int64_t &payment, uint256 &hashchain) -//{ -// uint256 txid, hashBlock, origtxid; -// char CCaddr[64]; -// std::vector > txids; -// uint8_t funcid; -// CPubKey opensrcpub, opendestpub; -// int32_t numvouts; -// -// GetCCaddress1of2(cp,CCaddr,srcpub,destpub); -// SetCCtxids(txids,CCaddr); -// -// for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) -// { -// txid=it->first.txhash; -// if (GetTransaction(txid,channelOpenTx,hashBlock,false) != 0 && (numvouts= channelOpenTx.vout.size()) > 0) -// { -// if (((funcid = DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,origtxid,opensrcpub,opendestpub,numpayments,payment,hashchain)) != 0) && (funcid == 'O') && (srcpub==opensrcpub && (destpub==opendestpub))) -// { -// return true; -// } -// } -// } -// -// return false; -//} - bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,param1,numpayments; bool retval; uint256 txid,hashblock,param3,hashchain,opentxid,prevtxid; uint8_t funcid, hash[32]; char str[65],destaddr[64]; - int64_t param2,payment; + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,param1,depth; bool retval; + uint256 txid,hashblock,param3,opentxid,prevtxid,entropy,hentropy,secret,gensecret,genhashchain; + uint8_t funcid,hash[32],hashdest[32]; + int64_t param2,numpayments; CPubKey srcpub, destpub; std::vector > txids; CTransaction channelOpenTx; @@ -236,34 +210,72 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & switch ( funcid ) { case 'O': - if ( IsCCInput(tx.vin[0].scriptSig) == 0 ) - return eval->Invalid("vin.0 is normal for channelOpen"); - else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.0 is CC for channelOpen"); - else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.1 is CC for channelOpen"); - else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.2 is CC for channelOpen"); - else if ( numpayments > CHANNELS_MAXPAYMENTS) - return eval->Invalid("too many payment increments"); - else if ( tx.vout[0].nValue != param1 * param2) - return eval->Invalid("tx funds do not match sum of payments"); - break; - case 'C': + //vin.0: normal input + //vout.0: CC vout for channel funding on CC1of2 pubkey + //vout.1: CC vout marker to senders pubKey + //vout.2: CC vout marker to receiver pubkey + //vout.3: opreturn - 'O' zerotxid senderspubkey receiverspubkey totalnumberofpayments paymentamount hashchain + return eval->Invalid("unexpected ChannelsValidate for channelopen"); break; case 'P': - DecodeChannelsPaymentOpRet(tx.vout[numvouts-1].scriptPubKey, opentxid, prevtxid, srcpub, destpub, param1, param2, param3); - if ( IsCCInput(tx.vin[0].scriptSig) == 0 ) - return eval->Invalid("vin.0 is normal for channelOpen"); - else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.0 is CC for channelOpen"); - - if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) + //vin.0: normal input + //vin.1: CC input from channel funding + //vout.0: normal output of payment amount to receiver pubkey + //vout.1: CC vout change to CC1of2 pubkey + //vout.n-2: CC vout marker to payment issuer + //vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret + if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for channelPayment"); + else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) + return eval->Invalid("vin.1 is CC for channelPayment"); + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 ) + return eval->Invalid("vout.0 is normal for channelPayment"); + else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.1 is CC for channelPayment"); + else if ( tx.vout.size() == 4 && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.2 is CC for channelPayment"); + else if (DecodeChannelsPaymentOpRet(tx.vout[numvouts-1].scriptPubKey, opentxid, prevtxid, srcpub, destpub, depth, numpayments, secret) != 'P') + return eval->Invalid("invalid OP_RETURN data"); + else if ( tx.vout[0].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) + return eval->Invalid("payment funds do not go to receiver"); + else if ( param2 > CHANNELS_MAXPAYMENTS) + return eval->Invalid("too many payment increments"); + else { - return (false); + if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) + { + if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, opentxid, srcpub, destpub, param1, param2, param3)) != 0 && funcid!='O') + return eval->Invalid("invalid channelopen OP_RETURN data"); + hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < param1; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + if (i==depth) endiancpy((uint8_t * ) & gensecret, hashdest, 32); + } + endiancpy((uint8_t * ) & genhashchain, hashdest, 32); + + if (secret!=gensecret) + return eval->Invalid("invalid secret for payment"); + else if (param3!=genhashchain) + return eval->Invalid("invalid secret for payment, does not reach final hashchain"); + else if (tx.vout[0].nValue != numpayments*param2) + return eval->Invalid("vout amount does not match numberofpayments*payment"); + } } break; + case 'C': + //vin.0: normal input for 2*txfee (normal fee and marker) + //vout.0: CC vout marker to senders pubKey + //vout.1: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 + return eval->Invalid("unexpected ChannelsValidate for channelclose"); case 'R': + //vin.0: normal input + //vin.1: CC input from channel funding + //vout.0: normal output of CC input to senders pubkey + //vout.1: CC vout marker to senders pubKey + //vout.2: opreturn - 'R' opentxid senderspubkey receiverspubkey 0 0 closetxid break; } } @@ -333,18 +345,16 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 CMutableTransaction mtx; uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy; CPubKey mypk; struct CCcontract_info *cp,C; if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS ) { - CCerror = strprintf("invalid ChannelsFund param numpayments.%d max.%d payment.%lld\n",numpayments,CHANNELS_MAXPAYMENTS,(long long)payment); + CCerror = strprintf("invalid ChannelOpen param numpayments.%d max.%d payment.%lld\n",numpayments,CHANNELS_MAXPAYMENTS,(long long)payment); fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } cp = CCinit(&C,EVAL_CHANNELS); if ( txfee == 0 ) txfee = 10000; - if (numpayments>CHANNELS_MAXPAYMENTS) - return (""); mypk = pubkey2pk(Mypubkey()); funds = numpayments * payment; - if ( AddNormalinputs(mtx,mypk,funds+3*txfee,64) > 0 ) + if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) { hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash); endiancpy(hash,(uint8_t *)&hentropy,32); @@ -355,8 +365,6 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 } endiancpy((uint8_t *)&hashchain,hashdest,32); mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub)); - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',zeroid,mypk,destpub,numpayments,payment,hashchain))); } return(""); @@ -393,7 +401,10 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,uint256 prevtxid,int6 return(""); } if (amount % payment != 0) + { + fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); return (""); + } numpayments=amount/payment; hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); @@ -426,14 +437,17 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,uint256 prevtxid,int6 fprintf(stderr,"invalid previous txid\n"); return(""); } - if ((numpayments=amount % payment) != 0) + if (amount % payment != 0) + { + fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); return (""); + } numpayments=amount/payment; if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) { hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < numpayments; i++) + for (i = 0; i < prevdepth-numpayments; i++) { vcalc_sha256(0, hashdest, hash, 32); memcpy(hash, hashdest, 32); @@ -452,15 +466,19 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,uint256 prevtxid,int6 if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) { if ((funds=AddChannelsInputs(cp,mtx,prevtxid)) != 0 && (change=funds-amount)>=0) { mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS, txfee, mypk)); mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsPaymentOpRet('P', opentxid, prevtxid, mypk, destpub, prevdepth - numpayments, payment, secret))); + } else + { + fprintf(stderr,"error adding CC inputs\n"); + return(""); } } + fprintf(stderr,"error adding normal inputs\n"); return(""); } @@ -472,9 +490,8 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) { - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('S',opentxid,mypk,mypk,0,0,zeroid))); } return(""); @@ -488,9 +505,8 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) { - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,mypk,0,0,closetxid))); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c105b4872..3aa736a16 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5157,7 +5157,7 @@ UniValue channelspayment(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,prevtxid; int32_t n; int64_t amount; cp = CCinit(&C,EVAL_CHANNELS); - if ( fHelp || params.size() != 4 ) + if ( fHelp || params.size() != 3 ) throw runtime_error("channelspayment opentxid prevtxid amount\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"); @@ -5180,7 +5180,7 @@ UniValue channelsclose(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid; cp = CCinit(&C,EVAL_CHANNELS); - if ( fHelp || params.size() != 2 ) + if ( fHelp || params.size() != 1 ) throw runtime_error("channelsclose opentxid\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"); From f2cf63f98b238ca8c20d66c019ea608bdb9c02a1 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sat, 15 Sep 2018 11:42:21 +0200 Subject: [PATCH 12/35] fix --- src/wallet/rpcwallet.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3aa736a16..a126c780e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5165,8 +5165,7 @@ UniValue channelspayment(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); opentxid = Parseuint256((char *)params[0].get_str().c_str()); prevtxid = Parseuint256((char *)params[1].get_str().c_str()); - n = atoi((char *)params[2].get_str().c_str()); - amount = atoi((char *)params[3].get_str().c_str()); + amount = atoi((char *)params[2].get_str().c_str()); hex = ChannelPayment(0,opentxid,prevtxid,amount); if ( hex.size() > 0 ) { From 93346f25d9341f83af6e41c86a786d363b5b0d9e Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sun, 16 Sep 2018 22:44:08 +0200 Subject: [PATCH 13/35] - Fixing payment, open, validate .... --- src/cc/CCchannels.h | 2 +- src/cc/CCinclude.h | 1 + src/cc/CCtx.cpp | 6 +- src/cc/channels.cpp | 409 ++++++++++++++++++--------------------- src/wallet/rpcwallet.cpp | 9 +- 5 files changed, 200 insertions(+), 227 deletions(-) diff --git a/src/cc/CCchannels.h b/src/cc/CCchannels.h index ba31883a2..6988b5913 100644 --- a/src/cc/CCchannels.h +++ b/src/cc/CCchannels.h @@ -22,7 +22,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment); -std::string ChannelPayment(uint64_t txfee,uint256 opentxid,uint256 prevtxid,int64_t amount); +std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount); std::string ChannelClose(uint64_t txfee,uint256 opentxid); std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 7ac0bfb98..2c3c6f5e6 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -125,6 +125,7 @@ uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv); CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk); CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2); CC *MakeCCcond1(uint8_t evalcode,CPubKey pk); +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); diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index a9d3f68e7..f1ee0b309 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -119,12 +119,14 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran cond = othercond; //fprintf(stderr,"unspendable CC addr.(%s)\n",unspendable); } - else if ( strcmp(destaddr,cp->unspendableaddr2) == 0 ) + else if ( strcmp(destaddr,cp->unspendableaddr2) == 0) { //fprintf(stderr,"matched %s unspendable2!\n",cp->unspendableaddr2); privkey = cp->unspendablepriv2; - if ( othercond2 == 0 ) + if ( othercond2 == 0 && cp->evalcode != EVAL_CHANNELS) othercond2 = MakeCCcond1(cp->evalcode2,cp->unspendablepk2); + else if ( othercond2 == 0 && cp->evalcode == EVAL_CHANNELS) + othercond2 = MakeCCcond1of2(cp->evalcode2,cp->unspendablepk2,cp->unspendablepk3); cond = othercond2; } else if ( strcmp(destaddr,cp->unspendableaddr3) == 0 ) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 744c223d1..21249a7e9 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -62,55 +62,19 @@ Possible third iteration: // start of consensus code -int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub, CPubKey destpub,int32_t v) { - char destaddr[64]; + char destaddr[64],channeladdr[64]; + + GetCCaddress1of2(cp,channeladdr,srcpub,destpub); if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,channeladdr) == 0 ) return(tx.vout[v].nValue); } return(0); } -bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) -{ - static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - //fprintf(stderr,"vini.%d check mempool\n",i); - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - //fprintf(stderr,"vini.%d check hash and vout\n",i); - if ( hashBlock == zerohash ) - return eval->Invalid("cant Channels from mempool"); - if ( (assetoshis= IsChannelsvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) - inputs += assetoshis; - } - } - } - for (i=0; iInvalid("mismatched inputs != outputs + txfee"); - } - else return(true); -} - CScript EncodeChannelsOpRet(uint8_t funcid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) { CScript opret; uint8_t evalcode = EVAL_CHANNELS; @@ -119,40 +83,6 @@ CScript EncodeChannelsOpRet(uint8_t funcid,uint256 opentxid,CPubKey srcpub,CPubK } uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) -{ - std::vector vopret; uint8_t *script,e,f,funcid; - GetOpReturnData(scriptPubKey, vopret); - if ( vopret.size() > 2 ) - { - script = (uint8_t *)vopret.data(); - if ( script[0] == EVAL_CHANNELS ) - { - funcid = script[1]; - switch ( funcid ) - { - case 'O': - return(funcid); - break; - default: - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> opentxid; ss >> srcpub; ss >> destpub; ss >> numpayments; ss >> payment; ss >> hashchain) != 0 ) - { - return(f); - } - break; - } - } else fprintf(stderr,"script[0] %02x != EVAL_CHANNELS\n",script[0]); - } else fprintf(stderr,"not enough opret.[%d]\n",(int32_t)vopret.size()); - return(0); -} - -CScript EncodeChannelsPaymentOpRet(uint8_t funcid,uint256 opentxid,uint256 prevtxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) -{ - CScript opret; uint8_t evalcode = EVAL_CHANNELS; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << opentxid << prevtxid << srcpub << destpub << numpayments << payment << hashchain); - return(opret); -} - -uint8_t DecodeChannelsPaymentOpRet(const CScript &scriptPubKey,uint256 &opentxid,uint256 &prevtxid,CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) { std::vector vopret; uint8_t *script,e,f,funcid; GetOpReturnData(scriptPubKey, vopret); @@ -170,12 +100,61 @@ uint8_t DecodeChannelsPaymentOpRet(const CScript &scriptPubKey,uint256 &opentxid return(0); } +bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) +{ + static uint256 zerohash; + uint256 txid,param3; + CPubKey srcpub,destpub; + int32_t param1; int64_t param2; uint8_t funcid; + CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; + numvins = tx.vin.size(); + numvouts = tx.vout.size(); + + if ((numvouts=tx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) !=0) + { + for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) + { + //fprintf(stderr,"vini.%d check mempool\n",i); + if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + else + { + //fprintf(stderr,"vini.%d check hash and vout\n",i); + if ( hashBlock == zerohash ) + return eval->Invalid("cant Channels from mempool"); + if ( (assetoshis= IsChannelsvout(cp,vinTx,srcpub,destpub,tx.vin[i].prevout.n)) != 0 ) + inputs += assetoshis; + } + } + } + } + else + { + return eval->Invalid("invalid op_return data"); + } + for (i=0; iInvalid("mismatched inputs != outputs + txfee"); + } + else return(true); +} + bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,param1,depth; bool retval; - uint256 txid,hashblock,param3,opentxid,prevtxid,entropy,hentropy,secret,gensecret,genhashchain; + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,param1; bool retval; + uint256 txid,hashblock,param3,opentxid,tmp_txid,entropy,hentropy,gensecret,genhashchain,hashchain; uint8_t funcid,hash[32],hashdest[32]; - int64_t param2,numpayments; + int64_t param2,payment; CPubKey srcpub, destpub; std::vector > txids; CTransaction channelOpenTx; @@ -183,17 +162,11 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; + fprintf(stderr,"validateCC\n"); if ( numvouts < 1 ) return eval->Invalid("no vouts"); else { - for (i=0; iInvalid("illegal normal vini"); - } - } //fprintf(stderr,"check amounts\n"); if ( ChannelsExactAmounts(cp,eval,tx,1,10000) == false ) { @@ -214,7 +187,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.0: CC vout for channel funding on CC1of2 pubkey //vout.1: CC vout marker to senders pubKey //vout.2: CC vout marker to receiver pubkey - //vout.3: opreturn - 'O' zerotxid senderspubkey receiverspubkey totalnumberofpayments paymentamount hashchain + //vout.n-2: normal change + //vout.n-1: opreturn - 'O' zerotxid senderspubkey receiverspubkey totalnumberofpayments paymentamount hashchain return eval->Invalid("unexpected ChannelsValidate for channelopen"); break; case 'P': @@ -222,45 +196,48 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vin.1: CC input from channel funding //vout.0: normal output of payment amount to receiver pubkey //vout.1: CC vout change to CC1of2 pubkey - //vout.n-2: CC vout marker to payment issuer + //vout.2: CC vout marker to payment issuer + //vout.n-2: normal change //vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for channelPayment"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) return eval->Invalid("vin.1 is CC for channelPayment"); - else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 ) - return eval->Invalid("vout.0 is normal for channelPayment"); - else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.1 is CC for channelPayment"); - else if ( tx.vout.size() == 4 && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.2 is CC for channelPayment"); - else if (DecodeChannelsPaymentOpRet(tx.vout[numvouts-1].scriptPubKey, opentxid, prevtxid, srcpub, destpub, depth, numpayments, secret) != 'P') - return eval->Invalid("invalid OP_RETURN data"); - else if ( tx.vout[0].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) - return eval->Invalid("payment funds do not go to receiver"); - else if ( param2 > CHANNELS_MAXPAYMENTS) + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.0 is CC for channelPayment"); + else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() != 0 ) + return eval->Invalid("vout.1 is normal for channelPayment"); +// else if ( tx.vout.size() == 4 && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) +// return eval->Invalid("vout.2 is CC for channelPayment"); + else if ( tx.vout[1].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) + return eval->Invalid("payment funds do not go to receiver -"); + else if ( param1 > CHANNELS_MAXPAYMENTS) return eval->Invalid("too many payment increments"); else { if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) { - if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, opentxid, srcpub, destpub, param1, param2, param3)) != 0 && funcid!='O') + if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') return eval->Invalid("invalid channelopen OP_RETURN data"); hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < param1; i++) + for (i = 0; i < numpayments; i++) { vcalc_sha256(0, hashdest, hash, 32); memcpy(hash, hashdest, 32); - if (i==depth) endiancpy((uint8_t * ) & gensecret, hashdest, 32); + if (i==param1-1) + { + endiancpy((uint8_t*)&gensecret,hashdest,32); + } } - endiancpy((uint8_t * ) & genhashchain, hashdest, 32); + endiancpy((uint8_t*)&genhashchain,hashdest,32); - if (secret!=gensecret) + fprintf(stderr,"gensecret=%s secret=%s genhashchain=%s hashchain=%s\n",gensecret.ToString().c_str(),param3.ToString().c_str(),genhashchain.ToString().c_str(),hashchain.ToString().c_str()); + if (param3!=gensecret) return eval->Invalid("invalid secret for payment"); - else if (param3!=genhashchain) + else if (hashchain!=genhashchain) return eval->Invalid("invalid secret for payment, does not reach final hashchain"); - else if (tx.vout[0].nValue != numpayments*param2) + else if (tx.vout[0].nValue != param1*payment) return eval->Invalid("vout amount does not match numberofpayments*payment"); } } @@ -291,31 +268,58 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & // helper functions for rpc calls in rpcwallet.cpp -int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, uint256 prevtxid) +int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid) { - char coinaddr[64]; int64_t param2,totalinputs = 0; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t funcid,param1,numvouts,vout; + char coinaddr[64]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t funcid,param1; std::vector > unspentOutputs; CPubKey srcpub,destpub; + uint8_t myprivkey[32]; + + //fprintf(stderr,"numvouts=%d decode=%c\n",numvouts=openTx.vout.size(),DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)); + + if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)=='O') + { + GetCCaddress1of2(cp,coinaddr,srcpub,destpub); + SetCCunspents(unspentOutputs,coinaddr); + Myprivkey(myprivkey); + CCaddr2set(cp,EVAL_CHANNELS,srcpub,myprivkey,coinaddr); + CCaddr3set(cp,EVAL_CHANNELS,destpub,myprivkey,coinaddr); + } + else + { + fprintf(stderr,"invalid open tx id\n"); + return 0; + } - GetCCaddress1of2(cp,coinaddr,srcpub,destpub); - SetCCunspents(unspentOutputs,coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0) + fprintf(stderr,"txhash: %d\n",it->first.txhash); + if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) != 0 && prevtxid==tmp_txid) - if ( (totalinputs=IsChannelsvout(cp,tx,vout)) > 0) - { - txid = it->first.txhash; - vout = 0; - break; - } + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) + { + txid = it->first.txhash; + break; + } } } - if (myIsutxo_spentinmempool(txid,vout) != 0) + +// fprintf(stderr,"prevtxid=%s , GetTX=%d\n",prevtxid.ToString().c_str(),GetTransaction(prevtxid,tx,hashBlock,false)); +// if (GetTransaction(prevtxid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) +// { +// fprintf(stderr,"prevtxid=%s decode=%c total=%d\n",prevtxid.ToString().c_str(),DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3),IsChannelsvout(cp,tx,srcpub,destpub,0)); +// if ((funcid=DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)) != 0 && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)) > 0) +// { +// //if (funcid='P') DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,tmp_txid,srcpub,destpub,param1,param2,param3) +// txid=prevtxid; +// fprintf(stderr,"found utxo, txid=%d, funds=%d\n",txid,totalinputs); +// } +// } + if (myIsutxo_spentinmempool(txid,0) != 0) { + fprintf(stderr,"spent in mempool\n"); txid=zeroid; - int32_t mindepth=1000; + int32_t mindepth=CHANNELS_MAXPAYMENTS; BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) { const CTransaction &txmempool = e.GetTx(); @@ -325,24 +329,25 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, u funcid=='P' && param1 < mindepth) { txid=hash; - vout=0; - totalinputs=txmempool.vout[vout].nValue; + totalinputs=txmempool.vout[0].nValue; mindepth=param1; } } } + else fprintf(stderr,"not spent in mempool\n"); if (txid != zeroid) { - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - return totalinputs; + prevtxid=txid; + mtx.vin.push_back(CTxIn(txid,0,CScript())); + return totalinputs; } else return 0; } std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment) { - CMutableTransaction mtx; uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy; CPubKey mypk; struct CCcontract_info *cp,C; + CMutableTransaction mtx; uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy; CPubKey mypk,channelspk; struct CCcontract_info *cp,C; if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS ) { CCerror = strprintf("invalid ChannelOpen param numpayments.%d max.%d payment.%lld\n",numpayments,CHANNELS_MAXPAYMENTS,(long long)payment); @@ -370,111 +375,77 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 return(""); } -std::string ChannelPayment(uint64_t txfee,uint256 opentxid,uint256 prevtxid,int64_t amount) +std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) { - CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,secret,hashblock,entropy,hentropy,param3; - struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments,param1; - int64_t param2,payment,change,funds; + CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,secret,hashblock,entropy,hentropy,prevtxid; + struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments; + int64_t payment,change,funds; uint8_t hash[32],hashdest[32]; CTransaction channelOpenTx,prevTx; - if (opentxid==prevtxid) - { - if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) - { - if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) != 0) && funcid == 'O') - { - if (mypk == srcpub || mypk == destpub) - { - prevdepth=param1; - payment=param2; - } - else - { - fprintf(stderr,"this is not our channel\n"); - return(""); - } - } - else - { - fprintf(stderr,"invalid previous txid\n"); - return(""); - } - if (amount % payment != 0) - { - fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); - return (""); - } - numpayments=amount/payment; - hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < numpayments; i++) - { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); - } - endiancpy((uint8_t * ) & secret, hashdest, 32); - - } - } - else if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) - { - if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsPaymentOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, txid, srcpub, destpub, param1, param2, param3)) != 0) && funcid == 'P') - { - if (mypk == srcpub || mypk == destpub) - { - prevdepth=param1; - payment=param2; - } - else - { - fprintf(stderr,"this is not our channel\n"); - return(""); - } - } - else - { - fprintf(stderr,"invalid previous txid\n"); - return(""); - } - if (amount % payment != 0) - { - fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); - return (""); - } - numpayments=amount/payment; - if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) - { - hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < prevdepth-numpayments; i++) - { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); - } - endiancpy((uint8_t * ) & secret, hashdest, 32); - } - else - { - fprintf(stderr,"invalid channel open txid\n"); - return(""); - } - } - // verify lasttxid and origtxid match and src is me - // also verify hashchain depth and amount, set prevdepth cp = CCinit(&C,EVAL_CHANNELS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + + if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - if ((funds=AddChannelsInputs(cp,mtx,prevtxid)) != 0 && (change=funds-amount)>=0) { - mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); - mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); - return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsPaymentOpRet('P', opentxid, prevtxid, mypk, destpub, prevdepth - numpayments, payment, secret))); - } else + fprintf(stderr, "invalid channel open txid\n"); + return (""); + } + + if (AddNormalinputs(mtx,mypk,txfee,1) > 0) + { + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) { - fprintf(stderr,"error adding CC inputs\n"); + fprintf(stderr,"prevtxid=%s\n",prevtxid.ToString().c_str()); + if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) + { + if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, payment, hashchain)) != 0) && (funcid == 'P' || funcid=='O')) + { + if (mypk != srcpub && mypk != destpub) + { + fprintf(stderr,"this is not our channel\n"); + return(""); + } + else if (amount % payment != 0) + { + fprintf(stderr,"invalid amount, not a magnitude of payment size - %d %d\n",amount,payment); + return (""); + } + } + else + { + fprintf(stderr,"invalid previous tx\n"); + return(""); + } + + numpayments=amount/payment; + + hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < prevdepth-numpayments; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & secret, hashdest, 32); + } + else + { + fprintf(stderr, "cannot find previous tx (channel open or payment)\n"); + return (""); + } + // verify lasttxid and origtxid match and src is me + // also verify hashchain depth and amount, set prevdepth + + mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); + mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); + return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', opentxid, mypk, destpub, prevdepth - numpayments, payment, secret))); + } + else + { + fprintf(stderr,"error adding CC inputs: funds=%d change=%d\n",funds,change); return(""); } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a126c780e..1e342fc84 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5157,16 +5157,15 @@ UniValue channelspayment(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,prevtxid; int32_t n; int64_t amount; cp = CCinit(&C,EVAL_CHANNELS); - if ( fHelp || params.size() != 3 ) - throw runtime_error("channelspayment opentxid prevtxid amount\n"); + if ( fHelp || params.size() != 2 ) + throw runtime_error("channelspayment opentxid amount\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"); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); opentxid = Parseuint256((char *)params[0].get_str().c_str()); - prevtxid = Parseuint256((char *)params[1].get_str().c_str()); - amount = atoi((char *)params[2].get_str().c_str()); - hex = ChannelPayment(0,opentxid,prevtxid,amount); + amount = atoi((char *)params[1].get_str().c_str()); + hex = ChannelPayment(0,opentxid,amount); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); From acd84a38985130811fb3e69a9c3799f56d693d5b Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sun, 16 Sep 2018 22:47:47 +0200 Subject: [PATCH 14/35] fix --- src/cc/channels.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 21249a7e9..a064cefa6 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -293,7 +293,6 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - fprintf(stderr,"txhash: %d\n",it->first.txhash); if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) { if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) @@ -410,7 +409,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) } else if (amount % payment != 0) { - fprintf(stderr,"invalid amount, not a magnitude of payment size - %d %d\n",amount,payment); + fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); return (""); } } From 352856b87faca48ebe6c38202fdbc69dfabd5b69 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sun, 16 Sep 2018 22:50:54 +0200 Subject: [PATCH 15/35] fix --- src/cc/channels.cpp | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index a064cefa6..dcbeefc2a 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -232,7 +232,6 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & } endiancpy((uint8_t*)&genhashchain,hashdest,32); - fprintf(stderr,"gensecret=%s secret=%s genhashchain=%s hashchain=%s\n",gensecret.ToString().c_str(),param3.ToString().c_str(),genhashchain.ToString().c_str(),hashchain.ToString().c_str()); if (param3!=gensecret) return eval->Invalid("invalid secret for payment"); else if (hashchain!=genhashchain) @@ -275,8 +274,6 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C CPubKey srcpub,destpub; uint8_t myprivkey[32]; - //fprintf(stderr,"numvouts=%d decode=%c\n",numvouts=openTx.vout.size(),DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)); - if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)=='O') { GetCCaddress1of2(cp,coinaddr,srcpub,destpub); @@ -302,18 +299,6 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C } } } - -// fprintf(stderr,"prevtxid=%s , GetTX=%d\n",prevtxid.ToString().c_str(),GetTransaction(prevtxid,tx,hashBlock,false)); -// if (GetTransaction(prevtxid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) -// { -// fprintf(stderr,"prevtxid=%s decode=%c total=%d\n",prevtxid.ToString().c_str(),DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3),IsChannelsvout(cp,tx,srcpub,destpub,0)); -// if ((funcid=DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)) != 0 && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)) > 0) -// { -// //if (funcid='P') DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,tmp_txid,srcpub,destpub,param1,param2,param3) -// txid=prevtxid; -// fprintf(stderr,"found utxo, txid=%d, funds=%d\n",txid,totalinputs); -// } -// } if (myIsutxo_spentinmempool(txid,0) != 0) { fprintf(stderr,"spent in mempool\n"); @@ -397,7 +382,6 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) { - fprintf(stderr,"prevtxid=%s\n",prevtxid.ToString().c_str()); if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) { if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, payment, hashchain)) != 0) && (funcid == 'P' || funcid=='O')) @@ -444,7 +428,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) } else { - fprintf(stderr,"error adding CC inputs: funds=%d change=%d\n",funds,change); + fprintf(stderr,"error adding CC inputs\n"); return(""); } } From 294b79f6bd66dcfd0d1b0f1fa8a820019d5f97b5 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sun, 16 Sep 2018 22:59:00 +0200 Subject: [PATCH 16/35] fix --- src/cc/channels.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index dcbeefc2a..396be12bc 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -220,21 +220,15 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') return eval->Invalid("invalid channelopen OP_RETURN data"); hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < numpayments; i++) + endiancpy(hash, (uint8_t * ) & param3, 32); + for (i = 0; i < numpayments-param1; i++) { vcalc_sha256(0, hashdest, hash, 32); memcpy(hash, hashdest, 32); - if (i==param1-1) - { - endiancpy((uint8_t*)&gensecret,hashdest,32); - } } endiancpy((uint8_t*)&genhashchain,hashdest,32); - if (param3!=gensecret) - return eval->Invalid("invalid secret for payment"); - else if (hashchain!=genhashchain) + if (hashchain!=genhashchain) return eval->Invalid("invalid secret for payment, does not reach final hashchain"); else if (tx.vout[0].nValue != param1*payment) return eval->Invalid("vout amount does not match numberofpayments*payment"); From e741f587f5bfcc7691732d174649dfc7fa3a2f49 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sun, 16 Sep 2018 23:13:06 +0200 Subject: [PATCH 17/35] fix deadlock --- src/cc/channels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 396be12bc..298430b1a 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -215,7 +215,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("too many payment increments"); else { - if (GetTransaction(opentxid,channelOpenTx,hashblock,false) != 0) + if (myGetTransaction(opentxid,channelOpenTx,hashblock) != 0) { if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') return eval->Invalid("invalid channelopen OP_RETURN data"); From dd3bcadec44aae7f316c548084d1c359680a81ad Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 20 Sep 2018 17:42:24 +0200 Subject: [PATCH 18/35] - adding markers for transactions --- src/cc/channels.cpp | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 298430b1a..de2227c1b 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -189,14 +189,15 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.2: CC vout marker to receiver pubkey //vout.n-2: normal change //vout.n-1: opreturn - 'O' zerotxid senderspubkey receiverspubkey totalnumberofpayments paymentamount hashchain - return eval->Invalid("unexpected ChannelsValidate for channelopen"); + return eval->Invalid("unexpected ChannelsValidate for channelsopen"); break; case 'P': //vin.0: normal input //vin.1: CC input from channel funding - //vout.0: normal output of payment amount to receiver pubkey - //vout.1: CC vout change to CC1of2 pubkey - //vout.2: CC vout marker to payment issuer + //vout.0: CC vout change to CC1of2 pubkey + //vout.1: CC vout marker to senders pubKey + //vout.2: CC vout marker to receiver pubkey + //vout.3: normal output of payment amount to receiver pubkey //vout.n-2: normal change //vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) @@ -205,11 +206,13 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vin.1 is CC for channelPayment"); else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("vout.0 is CC for channelPayment"); - else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() != 0 ) + else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.1 is CC for channelPayment (marker to srcPub)"); + else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.1 is CC for channelPayment (marker to dstPub)"); + else if ( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) return eval->Invalid("vout.1 is normal for channelPayment"); -// else if ( tx.vout.size() == 4 && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) -// return eval->Invalid("vout.2 is CC for channelPayment"); - else if ( tx.vout[1].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) + else if ( tx.vout[3].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) return eval->Invalid("payment funds do not go to receiver -"); else if ( param1 > CHANNELS_MAXPAYMENTS) return eval->Invalid("too many payment increments"); @@ -239,13 +242,14 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vin.0: normal input for 2*txfee (normal fee and marker) //vout.0: CC vout marker to senders pubKey //vout.1: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 - return eval->Invalid("unexpected ChannelsValidate for channelclose"); + return eval->Invalid("unexpected ChannelsValidate for channelsclose"); case 'R': //vin.0: normal input //vin.1: CC input from channel funding //vout.0: normal output of CC input to senders pubkey //vout.1: CC vout marker to senders pubKey //vout.2: opreturn - 'R' opentxid senderspubkey receiverspubkey 0 0 closetxid + return eval->Invalid("unexpected ChannelsValidate for channelsrefund"); break; } } @@ -337,7 +341,7 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 txfee = 10000; mypk = pubkey2pk(Mypubkey()); funds = numpayments * payment; - if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) + if ( AddNormalinputs(mtx,mypk,funds+3*txfee,64) > 0 ) { hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash); endiancpy(hash,(uint8_t *)&hentropy,32); @@ -348,6 +352,8 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 } endiancpy((uint8_t *)&hashchain,hashdest,32); mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',zeroid,mypk,destpub,numpayments,payment,hashchain))); } return(""); @@ -372,7 +378,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) return (""); } - if (AddNormalinputs(mtx,mypk,txfee,1) > 0) + if (AddNormalinputs(mtx,mypk,3*txfee,1) > 0) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) { @@ -417,6 +423,8 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) // also verify hashchain depth and amount, set prevdepth mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', opentxid, mypk, destpub, prevdepth - numpayments, payment, secret))); } @@ -463,7 +471,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) UniValue ChannelsInfo() { - UniValue result(UniValue::VOBJ); CTransaction tx; uint256 txid,hashBlock,hashchain,opentxid; struct CCcontract_info *cp,C; uint8_t funcid; char myCCaddr[64]; int32_t vout,numvouts,numpayments; int64_t nValue,payment; CPubKey srcpub,destpub,mypk; + UniValue result(UniValue::VOBJ); CTransaction tx; uint256 txid,hashBlock,hashchain,opentxid; struct CCcontract_info *cp,C; char myCCaddr[64]; int32_t vout,numvouts,numpayments; int64_t nValue,payment; CPubKey srcpub,destpub,mypk; std::vector > txids; result.push_back(Pair("result","success")); result.push_back(Pair("name","Channels")); @@ -479,10 +487,15 @@ UniValue ChannelsInfo() nValue = (int64_t)it->second; if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - if ( DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'O' || funcid == 'P' ) + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'O') { char str[67],str2[67]; - fprintf(stderr,"%s func.%c %s -> %s %.8f num.%d of %.8f\n",mypk == srcpub ? "send" : "recv",funcid,pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),(double)tx.vout[0].nValue/COIN,numpayments,(double)payment/COIN); + fprintf(stderr,"%s %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelOpen",pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'P') + { + char str[67],str2[67]; + fprintf(stderr,"%s (%s) %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelPayment",opentxid.ToString().c_str(),pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); } } } From 0e7a9780129b95f68aef42d0a436e4d430ef12f9 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 20 Sep 2018 17:45:28 +0200 Subject: [PATCH 19/35] - fix --- src/cc/channels.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index de2227c1b..1aaf2612f 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -490,12 +490,12 @@ UniValue ChannelsInfo() if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'O') { char str[67],str2[67]; - fprintf(stderr,"%s %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelOpen",pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); + fprintf(stderr,"%s %s -> %s %\" PRId64 \"sat num.%d of %.8lldsat\n","ChannelOpen",pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); } else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'P') { char str[67],str2[67]; - fprintf(stderr,"%s (%s) %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelPayment",opentxid.ToString().c_str(),pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); + fprintf(stderr,"%s (%s) %s -> %s %\" PRId64 \"sat num.%d of %.8lldsat\n","ChannelPayment",opentxid.ToString().c_str(),pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); } } } From 7394c6247432e62bc1a8c11828b3ee0185be768c Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 20 Sep 2018 17:47:47 +0200 Subject: [PATCH 20/35] - fix --- src/cc/channels.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 1aaf2612f..7086f9cf9 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -490,12 +490,12 @@ UniValue ChannelsInfo() if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'O') { char str[67],str2[67]; - fprintf(stderr,"%s %s -> %s %\" PRId64 \"sat num.%d of %.8lldsat\n","ChannelOpen",pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); + fprintf(stderr,"%s %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelOpen",pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),(long long)tx.vout[0].nValue,numpayments,(long long)payment); } else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'P') { char str[67],str2[67]; - fprintf(stderr,"%s (%s) %s -> %s %\" PRId64 \"sat num.%d of %.8lldsat\n","ChannelPayment",opentxid.ToString().c_str(),pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),tx.vout[0].nValue,numpayments,payment); + fprintf(stderr,"%s (%s) %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelPayment",opentxid.ToString().c_str(),pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),(long long)tx.vout[0].nValue,numpayments,(long long)payment); } } } From 7340ace3b15f9bf87bb371ee639653f15ad3436f Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 20 Sep 2018 22:14:10 +0200 Subject: [PATCH 21/35] test --- src/cc/channels.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 7086f9cf9..a30b04a30 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -168,7 +168,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & else { //fprintf(stderr,"check amounts\n"); - if ( ChannelsExactAmounts(cp,eval,tx,1,10000) == false ) + if ( 0) //ChannelsExactAmounts(cp,eval,tx,1,10000) == false ) { fprintf(stderr,"Channelsget invalid amount\n"); return false; @@ -274,15 +274,13 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)=='O') { + GetCCaddress1of2(cp,coinaddr,srcpub,destpub); SetCCunspents(unspentOutputs,coinaddr); - Myprivkey(myprivkey); - CCaddr2set(cp,EVAL_CHANNELS,srcpub,myprivkey,coinaddr); - CCaddr3set(cp,EVAL_CHANNELS,destpub,myprivkey,coinaddr); } else { - fprintf(stderr,"invalid open tx id\n"); + fprintf(stderr,"invalid open txid\n"); return 0; } @@ -317,11 +315,13 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C } } } - else fprintf(stderr,"not spent in mempool\n"); if (txid != zeroid) { prevtxid=txid; mtx.vin.push_back(CTxIn(txid,0,CScript())); + Myprivkey(myprivkey); + CCaddr2set(cp,EVAL_CHANNELS,srcpub,myprivkey,coinaddr); + CCaddr3set(cp,EVAL_CHANNELS,destpub,myprivkey,coinaddr); return totalinputs; } else return 0; @@ -329,7 +329,7 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment) { - CMutableTransaction mtx; uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy; CPubKey mypk,channelspk; struct CCcontract_info *cp,C; + CMutableTransaction mtx; uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy; CPubKey mypk; struct CCcontract_info *cp,C; if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS ) { CCerror = strprintf("invalid ChannelOpen param numpayments.%d max.%d payment.%lld\n",numpayments,CHANNELS_MAXPAYMENTS,(long long)payment); From 5628e37d9eea1efe3f480e35b4f705a8571d7b6f Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Fri, 21 Sep 2018 21:01:00 +0200 Subject: [PATCH 22/35] -fix --- src/cc/channels.cpp | 140 ++++++++++++++++++++++++++++++--------- src/wallet/rpcwallet.cpp | 2 +- 2 files changed, 109 insertions(+), 33 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index a30b04a30..62b3612d4 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -233,7 +233,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if (hashchain!=genhashchain) return eval->Invalid("invalid secret for payment, does not reach final hashchain"); - else if (tx.vout[0].nValue != param1*payment) + else if (tx.vout[0].nValue != param2*payment) return eval->Invalid("vout amount does not match numberofpayments*payment"); } } @@ -241,15 +241,16 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & case 'C': //vin.0: normal input for 2*txfee (normal fee and marker) //vout.0: CC vout marker to senders pubKey - //vout.1: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 + //vout.1: CC vout marker to receiver pubkey + //vout.2: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 return eval->Invalid("unexpected ChannelsValidate for channelsclose"); case 'R': //vin.0: normal input //vin.1: CC input from channel funding - //vout.0: normal output of CC input to senders pubkey + //vout.0: CC vout marker to senders pubKey //vout.1: CC vout marker to senders pubKey - //vout.2: opreturn - 'R' opentxid senderspubkey receiverspubkey 0 0 closetxid - return eval->Invalid("unexpected ChannelsValidate for channelsrefund"); + //vout.2: normal output of CC input to senders pubkey + //vout.3: opreturn - 'R' opentxid senderspubkey receiverspubkey 0 0 closetxid break; } } @@ -269,12 +270,13 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { char coinaddr[64]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t funcid,param1; std::vector > unspentOutputs; - CPubKey srcpub,destpub; + CPubKey srcpub,destpub,mypk; uint8_t myprivkey[32]; + mypk = pubkey2pk(Mypubkey()); + if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)=='O') { - GetCCaddress1of2(cp,coinaddr,srcpub,destpub); SetCCunspents(unspentOutputs,coinaddr); } @@ -288,7 +290,9 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && + tmp_txid==openTx.GetHash() && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) + { txid = it->first.txhash; break; @@ -306,12 +310,11 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C const uint256 &hash = tx.GetHash(); if ((numvouts=txmempool.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)) != 0 && - funcid=='P' && param1 < mindepth) + funcid=='P' && tmp_txid==openTx.GetHash() && param1 < mindepth) { txid=hash; totalinputs=txmempool.vout[0].nValue; mindepth=param1; - } } } @@ -371,13 +374,11 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { fprintf(stderr, "invalid channel open txid\n"); return (""); } - if (AddNormalinputs(mtx,mypk,3*txfee,1) > 0) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) @@ -402,9 +403,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) fprintf(stderr,"invalid previous tx\n"); return(""); } - numpayments=amount/payment; - hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); for (i = 0; i < prevdepth-numpayments; i++) @@ -421,12 +420,11 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) } // verify lasttxid and origtxid match and src is me // also verify hashchain depth and amount, set prevdepth - mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); - return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', opentxid, mypk, destpub, prevdepth - numpayments, payment, secret))); + return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', opentxid, mypk, destpub, prevdepth-numpayments, numpayments, secret))); } else { @@ -440,41 +438,103 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) std::string ChannelClose(uint64_t txfee,uint256 opentxid) { - CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C; + CTransaction channelOpenTx; + uint256 hashblock,tmp_txid,param3; + int32_t numvouts,param1; + int64_t param2,funds; + // verify this is one of our outbound channels cp = CCinit(&C,EVAL_CHANNELS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('S',opentxid,mypk,mypk,0,0,zeroid))); + fprintf(stderr, "invalid channel open tx\n"); + return (""); + } + if ((numvouts=channelOpenTx.vout.size()) < 1 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!='O') + { + fprintf(stderr, "invalid channel open tx\n"); + return (""); + } + if ( AddNormalinputs(mtx,mypk,3*txfee,1) > 0 ) + { + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,0,0,zeroid))); } return(""); } std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) { - CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; int64_t amount; + CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,change,payment,param2; + int32_t i,numpayments,numvouts,param1; + uint256 hashchain,hashblock,txid,prevtxid,param3,entropy,hentropy,secret; + CTransaction channelOpenTx,prevTx; + CPubKey srcpub,destpub; + uint8_t funcid,hash[32],hashdest[32];; + // verify stoptxid and origtxid match and are mine cp = CCinit(&C,EVAL_CHANNELS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,mypk,0,0,closetxid))); + fprintf(stderr, "invalid channel open tx\n"); + return (""); + } + if ((numvouts=channelOpenTx.vout.size()) < 1 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,numpayments,payment,hashchain)!='O') + { + fprintf(stderr, "invalid channel open tx\n"); + return (""); + } + if ( AddNormalinputs(mtx,mypk,3*txfee,1) > 0 ) + { + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0) + { + if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) + { + if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) != 0) && (funcid == 'P' || funcid=='O')) + { + if (mypk != srcpub) + { + fprintf(stderr,"this channel is not in our ownership\n"); + return(""); + } + } + hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < param1; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & secret, hashdest, 32); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); + mtx.vout.push_back(CTxOut(funds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,destpub,numpayments-param1,payment,secret))); + } + } + else + { + fprintf(stderr,"error adding CC inputs\n"); + return(""); + } } return(""); } UniValue ChannelsInfo() { - UniValue result(UniValue::VOBJ); CTransaction tx; uint256 txid,hashBlock,hashchain,opentxid; struct CCcontract_info *cp,C; char myCCaddr[64]; int32_t vout,numvouts,numpayments; int64_t nValue,payment; CPubKey srcpub,destpub,mypk; + UniValue result(UniValue::VOBJ); CTransaction tx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain; struct CCcontract_info *cp,C; char myCCaddr[64],addr[64],str1[100],str2[100]; int32_t vout,numvouts,param1,numpayments; int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk; std::vector > txids; result.push_back(Pair("result","success")); - result.push_back(Pair("name","Channels")); + result.push_back(Pair("name","Channel Info")); cp = CCinit(&C,EVAL_CHANNELS); mypk = pubkey2pk(Mypubkey()); GetCCaddress(cp,myCCaddr,mypk); @@ -485,17 +545,33 @@ UniValue ChannelsInfo() txid = it->first.txhash; vout = (int32_t)it->first.index; nValue = (int64_t)it->second; - if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) + if ( (vout==0 || vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'O') + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O') { - char str[67],str2[67]; - fprintf(stderr,"%s %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelOpen",pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),(long long)tx.vout[0].nValue,numpayments,(long long)payment); + GetCCaddress1of2(cp,addr,srcpub,destpub); + sprintf(str1,"Channel - %s",addr); + result.push_back(Pair(str1,"Open")); } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,numpayments,payment,hashchain) == 'P') + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'P') { - char str[67],str2[67]; - fprintf(stderr,"%s (%s) %s -> %s %lldsat num.%d of %.8lldsat\n","ChannelPayment",opentxid.ToString().c_str(),pubkey33_str(str,(uint8_t *)&srcpub),pubkey33_str(str2,(uint8_t *)&destpub),(long long)tx.vout[0].nValue,numpayments,(long long)payment); + if (GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') + sprintf(str1,"Channel - %s",addr); + sprintf(str2,"Payment -> %s %lld payments of %lld",destpub.GetHash().ToString().c_str(),param2,payment); + result.push_back(Pair(str1,str2)); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C') + { + GetCCaddress1of2(cp,addr,srcpub,destpub); + sprintf(str1,"Channel - %s",addr); + result.push_back(Pair(str1,"Close")); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C') + { + GetCCaddress1of2(cp,addr,srcpub,destpub); + sprintf(str1,"Channel - %s",addr); + sprintf(str2,"Refund -> %s %lld payments of %lld",srcpub.GetHash().ToString().c_str(),param1,param2); + result.push_back(Pair(str1,"Refund")); } } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1e342fc84..83a65f0f0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5184,7 +5184,7 @@ UniValue channelsclose(const UniValue& params, bool fHelp) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); - opentxid = Parseuint256((char *)params[1].get_str().c_str()); + opentxid = Parseuint256((char *)params[0].get_str().c_str()); hex = ChannelClose(0,opentxid); if ( hex.size() > 0 ) { From e5e3d065f3e0b0b370249b8539cb128feb28f79f Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Fri, 21 Sep 2018 21:03:49 +0200 Subject: [PATCH 23/35] -fix --- src/cc/channels.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 62b3612d4..ff94b77e0 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -557,7 +557,7 @@ UniValue ChannelsInfo() { if (GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') sprintf(str1,"Channel - %s",addr); - sprintf(str2,"Payment -> %s %lld payments of %lld",destpub.GetHash().ToString().c_str(),param2,payment); + sprintf(str2,"Payment -> %s %lld payments of %lld",destpub.GetHash().ToString().c_str(),(long long)param2,(long long)payment); result.push_back(Pair(str1,str2)); } else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C') @@ -570,7 +570,7 @@ UniValue ChannelsInfo() { GetCCaddress1of2(cp,addr,srcpub,destpub); sprintf(str1,"Channel - %s",addr); - sprintf(str2,"Refund -> %s %lld payments of %lld",srcpub.GetHash().ToString().c_str(),param1,param2); + sprintf(str2,"Refund -> %s %lld payments of %lld",srcpub.GetHash().ToString().c_str(),(long long)param1,(long long)param2); result.push_back(Pair(str1,"Refund")); } } From 21eb7fa7d283e6e4c996d2d9c7aad9eaf2479d91 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Fri, 21 Sep 2018 21:32:15 +0200 Subject: [PATCH 24/35] -fix --- src/cc/channels.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index ff94b77e0..550a4cbd3 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -233,8 +233,11 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if (hashchain!=genhashchain) return eval->Invalid("invalid secret for payment, does not reach final hashchain"); - else if (tx.vout[0].nValue != param2*payment) + else if (tx.vout[3].nValue != param2*payment) + { + fprintf(stderr,"%lld=%lld*%lld\n",(long long)tx.vout[3].nValue,(long long)param2,(long long)payment); return eval->Invalid("vout amount does not match numberofpayments*payment"); + } } } break; @@ -290,8 +293,8 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && - tmp_txid==openTx.GetHash() && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && fprintf(stderr,"%s - %s\n",tmp_txid.ToString().c_str(),openTx.GetHash().ToString().c_str()) && + (tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) { txid = it->first.txhash; @@ -308,9 +311,10 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { const CTransaction &txmempool = e.GetTx(); const uint256 &hash = tx.GetHash(); + if ((numvouts=txmempool.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)) != 0 && - funcid=='P' && tmp_txid==openTx.GetHash() && param1 < mindepth) + funcid=='P' && (tmp_txid==openTx.GetHash() || txmempool.GetHash()==openTx.GetHash()) && param1 < mindepth) { txid=hash; totalinputs=txmempool.vout[0].nValue; From fea4c38edddae6e00d85e909a222429baffb1520 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sat, 22 Sep 2018 11:53:31 +0200 Subject: [PATCH 25/35] -fix --- src/cc/channels.cpp | 70 ++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 550a4cbd3..16460e8c0 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -223,21 +223,17 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') return eval->Invalid("invalid channelopen OP_RETURN data"); hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & param3, 32); + endiancpy(hash, (uint8_t * ) & hentropy, 32); for (i = 0; i < numpayments-param1; i++) { vcalc_sha256(0, hashdest, hash, 32); memcpy(hash, hashdest, 32); } endiancpy((uint8_t*)&genhashchain,hashdest,32); - if (hashchain!=genhashchain) - return eval->Invalid("invalid secret for payment, does not reach final hashchain"); + return eval->Invalid("invalid secret for payment, does not reach final hashchain!"); else if (tx.vout[3].nValue != param2*payment) - { - fprintf(stderr,"%lld=%lld*%lld\n",(long long)tx.vout[3].nValue,(long long)param2,(long long)payment); - return eval->Invalid("vout amount does not match numberofpayments*payment"); - } + return eval->Invalid("vout amount does not match number_of_payments*payment"); } } break; @@ -368,9 +364,9 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) { - CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,secret,hashblock,entropy,hentropy,prevtxid; + CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,secret,hashblock,entropy,hentropy,prevtxid,param3; struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments; - int64_t payment,change,funds; + int64_t payment,change,funds,param2; uint8_t hash[32],hashdest[32]; CTransaction channelOpenTx,prevTx; @@ -387,43 +383,46 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) { - if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) + if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, numpayments, payment, hashchain)=='O') { - if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, payment, hashchain)) != 0) && (funcid == 'P' || funcid=='O')) + + if (mypk != srcpub && mypk != destpub) { - if (mypk != srcpub && mypk != destpub) + fprintf(stderr,"this is not our channel\n"); + return(""); + } + else if (amount % payment != 0) + { + fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); + return (""); + } + + numpayments=amount/payment; + + if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 && + ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) && + (funcid == 'P' || funcid=='O')) + { + hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < prevdepth-numpayments; i++) { - fprintf(stderr,"this is not our channel\n"); - return(""); - } - else if (amount % payment != 0) - { - fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); - return (""); + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); } + endiancpy((uint8_t * ) & secret, hashdest, 32); } else { fprintf(stderr,"invalid previous tx\n"); return(""); } - numpayments=amount/payment; - hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < prevdepth-numpayments; i++) - { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); - } - endiancpy((uint8_t * ) & secret, hashdest, 32); } else { - fprintf(stderr, "cannot find previous tx (channel open or payment)\n"); + fprintf(stderr, "invalid channel open tx\n"); return (""); } - // verify lasttxid and origtxid match and src is me - // also verify hashchain depth and amount, set prevdepth mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); @@ -455,7 +454,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) mypk = pubkey2pk(Mypubkey()); if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - fprintf(stderr, "invalid channel open tx\n"); + fprintf(stderr, "invalid channel open txid\n"); return (""); } if ((numvouts=channelOpenTx.vout.size()) < 1 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!='O') @@ -463,6 +462,11 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) fprintf(stderr, "invalid channel open tx\n"); return (""); } + if (mypk != srcpub) + { + fprintf(stderr,"this channel is not in our ownership\n"); + return(""); + } if ( AddNormalinputs(mtx,mypk,3*txfee,1) > 0 ) { mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); @@ -488,7 +492,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) mypk = pubkey2pk(Mypubkey()); if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - fprintf(stderr, "invalid channel open tx\n"); + fprintf(stderr, "invalid channel open txid\n"); return (""); } if ((numvouts=channelOpenTx.vout.size()) < 1 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,numpayments,payment,hashchain)!='O') From b32b682ae969366dade85d7aaa919aae85ffa001 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Sat, 22 Sep 2018 12:18:41 +0200 Subject: [PATCH 26/35] -fix --- src/cc/channels.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 16460e8c0..7bc1d8d5a 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -152,7 +152,7 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,param1; bool retval; - uint256 txid,hashblock,param3,opentxid,tmp_txid,entropy,hentropy,gensecret,genhashchain,hashchain; + uint256 txid,hashblock,param3,opentxid,tmp_txid,genhashchain,hashchain; uint8_t funcid,hash[32],hashdest[32]; int64_t param2,payment; CPubKey srcpub, destpub; @@ -222,8 +222,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & { if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') return eval->Invalid("invalid channelopen OP_RETURN data"); - hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & hentropy, 32); + endiancpy(hash, (uint8_t * ) & param3, 32); for (i = 0; i < numpayments-param1; i++) { vcalc_sha256(0, hashdest, hash, 32); From d68350535dc3ed7b9abc1d803ac3070c600e8977 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 27 Sep 2018 10:46:45 +0200 Subject: [PATCH 27/35] - updated validation - added secret parameter to payment - reused marker for sender to validate creator of tx --- src/cc/CCchannels.h | 2 +- src/cc/channels.cpp | 217 +++++++++++++++++++++++++++------------ src/wallet/rpcwallet.cpp | 12 ++- 3 files changed, 163 insertions(+), 68 deletions(-) diff --git a/src/cc/CCchannels.h b/src/cc/CCchannels.h index 6988b5913..4754ae44e 100644 --- a/src/cc/CCchannels.h +++ b/src/cc/CCchannels.h @@ -22,7 +22,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment); -std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount); +std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret); std::string ChannelClose(uint64_t txfee,uint256 opentxid); std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid); diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 7bc1d8d5a..4d5d8934a 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -152,12 +152,12 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,param1; bool retval; - uint256 txid,hashblock,param3,opentxid,tmp_txid,genhashchain,hashchain; + uint256 txid,hashblock,param3,opentxid,closetxid,tmp_txid,genhashchain,hashchain; uint8_t funcid,hash[32],hashdest[32]; int64_t param2,payment; CPubKey srcpub, destpub; std::vector > txids; - CTransaction channelOpenTx; + CTransaction channelOpenTx,channelCloseTx; numvins = tx.vin.size(); numvouts = tx.vout.size(); @@ -189,11 +189,10 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.2: CC vout marker to receiver pubkey //vout.n-2: normal change //vout.n-1: opreturn - 'O' zerotxid senderspubkey receiverspubkey totalnumberofpayments paymentamount hashchain - return eval->Invalid("unexpected ChannelsValidate for channelsopen"); - break; + return eval->Invalid("unexpected ChannelsValidate for channelsopen!"); case 'P': //vin.0: normal input - //vin.1: CC input from channel funding + //vin.1: CC input from channel funding and src marker //vout.0: CC vout change to CC1of2 pubkey //vout.1: CC vout marker to senders pubKey //vout.2: CC vout marker to receiver pubkey @@ -201,21 +200,21 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.n-2: normal change //vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) - return eval->Invalid("vin.0 is normal for channelPayment"); + return eval->Invalid("vin.0 is normal for channelPayment!"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) - return eval->Invalid("vin.1 is CC for channelPayment"); + return eval->Invalid("vin.1 is CC for channelPayment!"); else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.0 is CC for channelPayment"); + return eval->Invalid("vout.0 is CC for channelPayment!"); else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.1 is CC for channelPayment (marker to srcPub)"); + return eval->Invalid("vout.1 is CC for channelPayment (marker to srcPub)!"); else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("vout.1 is CC for channelPayment (marker to dstPub)"); + return eval->Invalid("vout.1 is CC for channelPayment (marker to dstPub)!"); else if ( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) - return eval->Invalid("vout.1 is normal for channelPayment"); + return eval->Invalid("vout.1 is normal for channelPayment!"); else if ( tx.vout[3].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) - return eval->Invalid("payment funds do not go to receiver -"); + return eval->Invalid("payment funds do not go to receiver!"); else if ( param1 > CHANNELS_MAXPAYMENTS) - return eval->Invalid("too many payment increments"); + return eval->Invalid("too many payment increments!"); else { if (myGetTransaction(opentxid,channelOpenTx,hashblock) != 0) @@ -232,23 +231,71 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if (hashchain!=genhashchain) return eval->Invalid("invalid secret for payment, does not reach final hashchain!"); else if (tx.vout[3].nValue != param2*payment) - return eval->Invalid("vout amount does not match number_of_payments*payment"); + return eval->Invalid("invalid amount, does not match number_of_payments*payment!"); } } break; case 'C': - //vin.0: normal input for 2*txfee (normal fee and marker) - //vout.0: CC vout marker to senders pubKey - //vout.1: CC vout marker to receiver pubkey - //vout.2: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 - return eval->Invalid("unexpected ChannelsValidate for channelsclose"); + //vin.0: normal input + //vin.1: CC input from channel funding and src marker + //vout.0: CC vout for channel funding + //vout.1: CC vout marker to senders pubKey + //vout.2: CC vout marker to receiver pubkey + //vout.n-2: normal change + //vout.n-1: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 + if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for channelClose!"); + else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) + return eval->Invalid("vin.1 is CC for channelClose!"); + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.0 is CC for channelClose!"); + else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.1 is CC for channelClose (marker to srcPub)!"); + else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.2 is CC for channelClose (marker to dstPub)!"); + else if ( param1 > CHANNELS_MAXPAYMENTS) + return eval->Invalid("too many payment increments!"); + else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) + return eval->Invalid("invalid open txid!"); + else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) == 'O') + return eval->Invalid("invalid channelopen OP_RETURN data"); + else if (tx.vout[0].nValue != param2*payment) + return eval->Invalid("vout amount does not match number_of_payments*payment!"); + break; case 'R': //vin.0: normal input //vin.1: CC input from channel funding //vout.0: CC vout marker to senders pubKey - //vout.1: CC vout marker to senders pubKey + //vout.1: CC vout marker to receiver pubKey //vout.2: normal output of CC input to senders pubkey - //vout.3: opreturn - 'R' opentxid senderspubkey receiverspubkey 0 0 closetxid + //vout.n-2: normal change + //vout.n-1: opreturn - 'R' opentxid senderspubkey receiverspubkey numpaymewnts payment closetxid + if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for channelRefund!"); + else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) + return eval->Invalid("vin.1 is CC for channelRefund!"); + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.0 is CC for channelRefund (marker to srcPub)!"); + else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.1 is CC for channelRefund (marker to dstPub)!"); + else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 ) + return eval->Invalid("vout.2 is normal for channelRefund!"); + else if ( tx.vout[2].scriptPubKey!=CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG) + return eval->Invalid("payment funds do not go to sender!"); + else if ( param1 > CHANNELS_MAXPAYMENTS) + return eval->Invalid("too many payment increments!"); + else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) + return eval->Invalid("invalid open txid!"); + else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) == 'O') + return eval->Invalid("invalid channelopen OP_RETURN data"); + else if (tx.vout[2].nValue != param2*payment) + return eval->Invalid("vout amount does not match number_of_payments*payment!"); + else if (myGetTransaction(param3,channelCloseTx,hashblock) == 0) + return eval->Invalid("invalid close txid!"); + else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, param1, param2, param3) == 'C') + return eval->Invalid("invalid channelclose OP_RETURN data"); + else if (tmp_txid!=opentxid) + return eval->Invalid("invalid close tx, opentxid do not match on close and refund!"); break; } } @@ -268,11 +315,9 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { char coinaddr[64]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t funcid,param1; std::vector > unspentOutputs; - CPubKey srcpub,destpub,mypk; + CPubKey srcpub,destpub; uint8_t myprivkey[32]; - mypk = pubkey2pk(Mypubkey()); - if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)=='O') { GetCCaddress1of2(cp,coinaddr,srcpub,destpub); @@ -288,9 +333,9 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && fprintf(stderr,"%s - %s\n",tmp_txid.ToString().c_str(),openTx.GetHash().ToString().c_str()) && - (tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) - + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && + (tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && + (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)+IsChannelsvout(cp,tx,srcpub,destpub,1))>0) { txid = it->first.txhash; break; @@ -309,10 +354,10 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C if ((numvouts=txmempool.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)) != 0 && - funcid=='P' && (tmp_txid==openTx.GetHash() || txmempool.GetHash()==openTx.GetHash()) && param1 < mindepth) + (tmp_txid==openTx.GetHash() || txmempool.GetHash()==openTx.GetHash()) && param1 < mindepth) { txid=hash; - totalinputs=txmempool.vout[0].nValue; + totalinputs=txmempool.vout[0].nValue+txmempool.vout[1].nValue; mindepth=param1; } } @@ -361,10 +406,10 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 return(""); } -std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) +std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret) { - CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,secret,hashblock,entropy,hentropy,prevtxid,param3; - struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments; + CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3; + struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments,totalnumpayments; int64_t payment,change,funds,param2; uint8_t hash[32],hashdest[32]; CTransaction channelOpenTx,prevTx; @@ -378,11 +423,11 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) fprintf(stderr, "invalid channel open txid\n"); return (""); } - if (AddNormalinputs(mtx,mypk,3*txfee,1) > 0) + if (AddNormalinputs(mtx,mypk,2*txfee,1) > 0) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount-2*txfee)>=0) { - if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, numpayments, payment, hashchain)=='O') + if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O') { if (mypk != srcpub && mypk != destpub) @@ -399,17 +444,35 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount) numpayments=amount/payment; if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 && - ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) && - (funcid == 'P' || funcid=='O')) + ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) && + (funcid == 'P' || funcid=='O')) { - hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < prevdepth-numpayments; i++) + if (secret!=zeroid) { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); + hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < prevdepth-numpayments; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & secret, hashdest, 32); + } + else + { + endiancpy(hash, (uint8_t * ) & secret, 32); + for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & gensecret, hashdest, 32); + if (gensecret!=hashchain) + { + fprintf(stderr,"invalid secret supplied\n"); + return(""); + } } - endiancpy((uint8_t * ) & secret, hashdest, 32); } else { @@ -442,7 +505,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) { CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C; CTransaction channelOpenTx; - uint256 hashblock,tmp_txid,param3; + uint256 hashblock,tmp_txid,prevtxid,param3; int32_t numvouts,param1; int64_t param2,funds; @@ -456,7 +519,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) fprintf(stderr, "invalid channel open txid\n"); return (""); } - if ((numvouts=channelOpenTx.vout.size()) < 1 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!='O') + if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!='O') { fprintf(stderr, "invalid channel open tx\n"); return (""); @@ -466,21 +529,31 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) fprintf(stderr,"this channel is not in our ownership\n"); return(""); } - if ( AddNormalinputs(mtx,mypk,3*txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) { - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,0,0,zeroid))); + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0) + { + mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,0,0,zeroid))); + } + else + { + fprintf(stderr,"error adding CC inputs\n"); + return(""); + } } + fprintf(stderr,"error adding normal inputs\n"); return(""); } std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) { - CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,change,payment,param2; + CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,payment,param2; int32_t i,numpayments,numvouts,param1; uint256 hashchain,hashblock,txid,prevtxid,param3,entropy,hentropy,secret; - CTransaction channelOpenTx,prevTx; + CTransaction channelOpenTx,channelCloseTx,prevTx; CPubKey srcpub,destpub; uint8_t funcid,hash[32],hashdest[32];; @@ -489,30 +562,43 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); + if (GetTransaction(closetxid,channelCloseTx,hashblock,false) == 0) + { + fprintf(stderr, "invalid channel close txid\n"); + return (""); + } + if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,param1,param2,param3)!='C') + { + fprintf(stderr, "invalid channel close tx\n"); + return (""); + } + if (txid!=opentxid) + { + fprintf(stderr,"%s - %s\n",txid.ToString().c_str(),opentxid.ToString().c_str()); + fprintf(stderr, "open and close txid are not from same channel\n"); + return (""); + } if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { fprintf(stderr, "invalid channel open txid\n"); return (""); } - if ((numvouts=channelOpenTx.vout.size()) < 1 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,numpayments,payment,hashchain)!='O') + if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,numpayments,payment,hashchain)!='O') { fprintf(stderr, "invalid channel open tx\n"); return (""); } - if ( AddNormalinputs(mtx,mypk,3*txfee,1) > 0 ) + if (mypk != srcpub) + { + fprintf(stderr,"this channel is not in our ownership\n"); + return(""); + } + if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0) { - if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0) + if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) != 0) && (funcid == 'P' || funcid=='O')) { - if ((numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) != 0) && (funcid == 'P' || funcid=='O')) - { - if (mypk != srcpub) - { - fprintf(stderr,"this channel is not in our ownership\n"); - return(""); - } - } hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); for (i = 0; i < param1; i++) @@ -524,7 +610,12 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); mtx.vout.push_back(CTxOut(funds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,destpub,numpayments-param1,payment,secret))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,destpub,param1,payment,closetxid))); + } + else + { + fprintf(stderr,"previous tx is invalid\n"); + return(""); } } else diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 83a65f0f0..ff910f2c9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5155,17 +5155,21 @@ UniValue channelsopen(const UniValue& params, bool fHelp) UniValue channelspayment(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,prevtxid; int32_t n; int64_t amount; + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,secret=zeroid; int32_t n; int64_t amount; cp = CCinit(&C,EVAL_CHANNELS); if ( fHelp || params.size() != 2 ) - throw runtime_error("channelspayment opentxid amount\n"); + throw runtime_error("channelspayment opentxid amount [secret]\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"); const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); opentxid = Parseuint256((char *)params[0].get_str().c_str()); amount = atoi((char *)params[1].get_str().c_str()); - hex = ChannelPayment(0,opentxid,amount); + if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty()) + { + secret = Parseuint256((char *)params[2].get_str().c_str()); + } + hex = ChannelPayment(0,opentxid,amount,secret); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); @@ -5190,7 +5194,7 @@ UniValue channelsclose(const UniValue& params, bool fHelp) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else ERR_RESULT("couldnt create channelsstop transaction"); + } else ERR_RESULT("couldnt create channelsclose transaction"); return(result); } From 5e1984d0d219c65d78881f3469dbd2c80199edb7 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 27 Sep 2018 16:24:55 +0200 Subject: [PATCH 28/35] -fix --- src/cc/CCinclude.h | 3 ++- src/cc/CCtx.cpp | 2 +- src/cc/CCutils.cpp | 9 +++++++ src/cc/channels.cpp | 66 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 2c3c6f5e6..8be4bce29 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -54,6 +54,7 @@ extern uint32_t ASSETCHAINS_CC; extern std::string CCerror; #define SMALLVAL 0.000000000000001 +#define MIN_NOTARIZATION_CONFIRMS 2 union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; typedef union _bits256 bits256; @@ -149,7 +150,7 @@ bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); std::vector Mypubkey(); bool Myprivkey(uint8_t myprivkey[]); int64_t CCduration(int32_t &numblocks,uint256 txid); - +bool isCCTxNotarizedConfirmed(uint256 txid); // CCtx std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret); void SetCCunspents(std::vector > &unspentOutputs,char *coinaddr); diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index f1ee0b309..4e8561b20 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -111,7 +111,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran { privkey = myprivkey; cond = mycond; - //fprintf(stderr,"my CC addr.(%s)\n",myaddr); + fprintf(stderr,"my CC addr.(%s)\n",myaddr); } else if ( strcmp(destaddr,unspendable) == 0 ) { diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index e03564971..c149be03f 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -410,3 +410,12 @@ int64_t CCduration(int32_t &numblocks,uint256 txid) return(duration); } +bool isCCTxNotarizedConfirmed(uint256 txid) +{ + int32_t confirms; + + CCduration(confirms,txid); + if (confirms >= MIN_NOTARIZATION_CONFIRMS) + return (true); + return (false); +} diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 4d5d8934a..460f2b91d 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -84,7 +84,7 @@ CScript EncodeChannelsOpRet(uint8_t funcid,uint256 opentxid,CPubKey srcpub,CPubK uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) { - std::vector vopret; uint8_t *script,e,f,funcid; + std::vector vopret; uint8_t *script,e,f; GetOpReturnData(scriptPubKey, vopret); if ( vopret.size() > 2 ) { @@ -151,13 +151,13 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,param1; bool retval; - uint256 txid,hashblock,param3,opentxid,closetxid,tmp_txid,genhashchain,hashchain; + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,p1,param1; bool retval; + uint256 txid,hashblock,p3,param3,opentxid,tmp_txid,genhashchain,hashchain; uint8_t funcid,hash[32],hashdest[32]; - int64_t param2,payment; + int64_t p2,param2,payment; CPubKey srcpub, destpub; std::vector > txids; - CTransaction channelOpenTx,channelCloseTx; + CTransaction channelOpenTx,channelCloseTx,prevTx; numvins = tx.vin.size(); numvouts = tx.vout.size(); @@ -199,7 +199,9 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.3: normal output of payment amount to receiver pubkey //vout.n-2: normal change //vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret - if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + if (isCCTxNotarizedConfirmed(opentxid) == 0) + return eval->Invalid("channelOpen is not yet confirmed(notarised)!"); + else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for channelPayment!"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) return eval->Invalid("vin.1 is CC for channelPayment!"); @@ -220,7 +222,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if (myGetTransaction(opentxid,channelOpenTx,hashblock) != 0) { if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') - return eval->Invalid("invalid channelopen OP_RETURN data"); + return eval->Invalid("invalid channelopen OP_RETURN data!"); endiancpy(hash, (uint8_t * ) & param3, 32); for (i = 0; i < numpayments-param1; i++) { @@ -233,6 +235,17 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & else if (tx.vout[3].nValue != param2*payment) return eval->Invalid("invalid amount, does not match number_of_payments*payment!"); } + if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) + { + if ((numvouts=prevTx.vout.size()) > 0 && (DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3)) != 0) + return eval->Invalid("invalid previous tx OP_RETURN data!"); + else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) + return eval->Invalid("invalid destination for sender marker!"); + else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey) + return eval->Invalid("invalid destination for receiver marker!"); + else if (param1!=p1-p2) + return eval->Invalid("invalid payment depth!"); + } } break; case 'C': @@ -243,7 +256,9 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.2: CC vout marker to receiver pubkey //vout.n-2: normal change //vout.n-1: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 - if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + if (isCCTxNotarizedConfirmed(opentxid) == 0) + return eval->Invalid("channelOpen is not yet confirmed(notarised)!"); + else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for channelClose!"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) return eval->Invalid("vin.1 is CC for channelClose!"); @@ -258,9 +273,20 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) return eval->Invalid("invalid open txid!"); else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) == 'O') - return eval->Invalid("invalid channelopen OP_RETURN data"); + return eval->Invalid("invalid channelopen OP_RETURN data!"); else if (tx.vout[0].nValue != param2*payment) return eval->Invalid("vout amount does not match number_of_payments*payment!"); + else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) + { + if ((numvouts=prevTx.vout.size()) > 0 && (DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3)) != 0) + return eval->Invalid("invalid previous tx OP_RETURN data!"); + else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) + return eval->Invalid("invalid destination for sender marker!"); + else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey) + return eval->Invalid("invalid destination for receiver marker!"); + else if (tx.vout[0].nValue != prevTx.vout[0].nValue) + return eval->Invalid("invalid CC amount, input!=output!"); + } break; case 'R': //vin.0: normal input @@ -270,7 +296,11 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.2: normal output of CC input to senders pubkey //vout.n-2: normal change //vout.n-1: opreturn - 'R' opentxid senderspubkey receiverspubkey numpaymewnts payment closetxid - if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + if (isCCTxNotarizedConfirmed(opentxid) == 0) + return eval->Invalid("channelOpen is not yet confirmed(notarised)!"); + else if (isCCTxNotarizedConfirmed(param3) == 0) + return eval->Invalid("channelClose is not yet confirmed(notarised)!"); + else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for channelRefund!"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) return eval->Invalid("vin.1 is CC for channelRefund!"); @@ -287,15 +317,26 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) return eval->Invalid("invalid open txid!"); else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) == 'O') - return eval->Invalid("invalid channelopen OP_RETURN data"); + return eval->Invalid("invalid channelopen OP_RETURN data!"); else if (tx.vout[2].nValue != param2*payment) return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(param3,channelCloseTx,hashblock) == 0) return eval->Invalid("invalid close txid!"); else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, param1, param2, param3) == 'C') - return eval->Invalid("invalid channelclose OP_RETURN data"); + return eval->Invalid("invalid channelclose OP_RETURN data!"); else if (tmp_txid!=opentxid) return eval->Invalid("invalid close tx, opentxid do not match on close and refund!"); + else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) + { + if ((numvouts=prevTx.vout.size()) > 0 && (DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3)) != 0) + return eval->Invalid("invalid previous tx OP_RETURN data!"); + else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) + return eval->Invalid("invalid destination for sender marker!"); + else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey) + return eval->Invalid("invalid destination for receiver marker!"); + else if (tx.vout[2].nValue != prevTx.vout[0].nValue) + return eval->Invalid("invalid refund amount, must transfer all funds!"); + } break; } } @@ -366,6 +407,7 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { prevtxid=txid; mtx.vin.push_back(CTxIn(txid,0,CScript())); + mtx.vin.push_back(CTxIn(txid,1,CScript())); Myprivkey(myprivkey); CCaddr2set(cp,EVAL_CHANNELS,srcpub,myprivkey,coinaddr); CCaddr3set(cp,EVAL_CHANNELS,destpub,myprivkey,coinaddr); From 001d7ea10188063f5372c24d95fd1b14d84266ee Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 27 Sep 2018 18:41:33 +0200 Subject: [PATCH 29/35] -fix --- src/cc/CCutils.cpp | 1 - src/cc/channels.cpp | 64 +++++++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index c149be03f..cbf574532 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -63,7 +63,6 @@ CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2) CTxOut vout; CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2); vout = CTxOut(nValue,CCPubKey(payoutCond)); - fprintf(stderr,"payoutCond: %s\n",cc_conditionToJSONString(payoutCond)); cc_free(payoutCond); return(vout); } diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 460f2b91d..2635fe494 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -156,7 +156,6 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & uint8_t funcid,hash[32],hashdest[32]; int64_t p2,param2,payment; CPubKey srcpub, destpub; - std::vector > txids; CTransaction channelOpenTx,channelCloseTx,prevTx; numvins = tx.vin.size(); @@ -192,7 +191,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("unexpected ChannelsValidate for channelsopen!"); case 'P': //vin.0: normal input - //vin.1: CC input from channel funding and src marker + //vin.1: CC input from channel funding + //vin.2: CC input from src marker //vout.0: CC vout change to CC1of2 pubkey //vout.1: CC vout marker to senders pubKey //vout.2: CC vout marker to receiver pubkey @@ -205,6 +205,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vin.0 is normal for channelPayment!"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) return eval->Invalid("vin.1 is CC for channelPayment!"); + else if ( IsCCInput(tx.vin[2].scriptSig) == 0 ) + return eval->Invalid("vin.1 is CC for channelPayment!"); else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("vout.0 is CC for channelPayment!"); else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) @@ -237,20 +239,21 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & } if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { - if ((numvouts=prevTx.vout.size()) > 0 && (DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3)) != 0) + if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) return eval->Invalid("invalid previous tx OP_RETURN data!"); else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) return eval->Invalid("invalid destination for sender marker!"); else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey) return eval->Invalid("invalid destination for receiver marker!"); - else if (param1!=p1-p2) + else if (param1+param2!=p1) return eval->Invalid("invalid payment depth!"); } } break; case 'C': //vin.0: normal input - //vin.1: CC input from channel funding and src marker + //vin.1: CC input from channel funding + //vin.2: CC input from src marker //vout.0: CC vout for channel funding //vout.1: CC vout marker to senders pubKey //vout.2: CC vout marker to receiver pubkey @@ -262,6 +265,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vin.0 is normal for channelClose!"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) return eval->Invalid("vin.1 is CC for channelClose!"); + else if ( IsCCInput(tx.vin[2].scriptSig) == 0 ) + return eval->Invalid("vin.2 is CC for channelClose!"); else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("vout.0 is CC for channelClose!"); else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) @@ -278,7 +283,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { - if ((numvouts=prevTx.vout.size()) > 0 && (DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3)) != 0) + if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) return eval->Invalid("invalid previous tx OP_RETURN data!"); else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) return eval->Invalid("invalid destination for sender marker!"); @@ -291,6 +296,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & case 'R': //vin.0: normal input //vin.1: CC input from channel funding + //vin.2: CC input from src marker //vout.0: CC vout marker to senders pubKey //vout.1: CC vout marker to receiver pubKey //vout.2: normal output of CC input to senders pubkey @@ -304,6 +310,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vin.0 is normal for channelRefund!"); else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) return eval->Invalid("vin.1 is CC for channelRefund!"); + else if ( IsCCInput(tx.vin[2].scriptSig) == 0 ) + return eval->Invalid("vin.2 is CC for channelRefund!"); else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("vout.0 is CC for channelRefund (marker to srcPub)!"); else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) @@ -328,7 +336,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("invalid close tx, opentxid do not match on close and refund!"); else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { - if ((numvouts=prevTx.vout.size()) > 0 && (DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3)) != 0) + if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) return eval->Invalid("invalid previous tx OP_RETURN data!"); else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) return eval->Invalid("invalid destination for sender marker!"); @@ -391,11 +399,10 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) { const CTransaction &txmempool = e.GetTx(); - const uint256 &hash = tx.GetHash(); + const uint256 &hash = txmempool.GetHash(); - if ((numvouts=txmempool.vout.size()) > 0 && - (funcid=DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)) != 0 && - (tmp_txid==openTx.GetHash() || txmempool.GetHash()==openTx.GetHash()) && param1 < mindepth) + if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) != 0 && + tmp_txid==openTx.GetHash() && param1 < mindepth) { txid=hash; totalinputs=txmempool.vout[0].nValue+txmempool.vout[1].nValue; @@ -467,7 +474,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 } if (AddNormalinputs(mtx,mypk,2*txfee,1) > 0) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount-2*txfee)>=0) + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) { if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O') { @@ -482,14 +489,28 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); return (""); } - numpayments=amount/payment; - if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) && (funcid == 'P' || funcid=='O')) { if (secret!=zeroid) + { + endiancpy(hash, (uint8_t * ) & secret, 32); + for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & gensecret, hashdest, 32); + fprintf(stderr, "%d %d %d %s %s\n",(int)(totalnumpayments-(prevdepth-numpayments)),(int)prevdepth,(int)numpayments,gensecret.ToString().c_str(),hashchain.ToString().c_str()); + if (gensecret!=hashchain) + { + fprintf(stderr,"invalid secret supplied\n"); + return(""); + } + } + else { hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); @@ -500,21 +521,6 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 } endiancpy((uint8_t * ) & secret, hashdest, 32); } - else - { - endiancpy(hash, (uint8_t * ) & secret, 32); - for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++) - { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); - } - endiancpy((uint8_t * ) & gensecret, hashdest, 32); - if (gensecret!=hashchain) - { - fprintf(stderr,"invalid secret supplied\n"); - return(""); - } - } } else { From 2ca1bcbe215022b97557e99b5567c33f624fef8e Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 27 Sep 2018 18:52:03 +0200 Subject: [PATCH 30/35] -fix --- src/cc/channels.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 2635fe494..b525d557e 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -277,10 +277,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("too many payment increments!"); else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) return eval->Invalid("invalid open txid!"); - else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) == 'O') + else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') return eval->Invalid("invalid channelopen OP_RETURN data!"); - else if (tx.vout[0].nValue != param2*payment) - return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) @@ -324,13 +322,13 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("too many payment increments!"); else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) return eval->Invalid("invalid open txid!"); - else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) == 'O') + else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') return eval->Invalid("invalid channelopen OP_RETURN data!"); else if (tx.vout[2].nValue != param2*payment) return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(param3,channelCloseTx,hashblock) == 0) return eval->Invalid("invalid close txid!"); - else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, param1, param2, param3) == 'C') + else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, param1, param2, param3) != 'C') return eval->Invalid("invalid channelclose OP_RETURN data!"); else if (tmp_txid!=opentxid) return eval->Invalid("invalid close tx, opentxid do not match on close and refund!"); From bd632043f2b184bf287483c070629771b68dbf1d Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 27 Sep 2018 20:06:21 +0200 Subject: [PATCH 31/35] -fix --- src/cc/channels.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index b525d557e..72f995e55 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -235,7 +235,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if (hashchain!=genhashchain) return eval->Invalid("invalid secret for payment, does not reach final hashchain!"); else if (tx.vout[3].nValue != param2*payment) - return eval->Invalid("invalid amount, does not match number_of_payments*payment!"); + return eval->Invalid("vout amount does not match number_of_payments*payment!"); } if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { @@ -247,6 +247,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("invalid destination for receiver marker!"); else if (param1+param2!=p1) return eval->Invalid("invalid payment depth!"); + else if (tx.vout[3].nValue > prevTx.vout[0].nValue) + return eval->Invalid("not enough funds in channel for that amount!"); } } break; @@ -279,6 +281,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("invalid open txid!"); else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') return eval->Invalid("invalid channelopen OP_RETURN data!"); + else if (tx.vout[0].nValue != param1*payment) + return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) @@ -288,7 +292,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey) return eval->Invalid("invalid destination for receiver marker!"); else if (tx.vout[0].nValue != prevTx.vout[0].nValue) - return eval->Invalid("invalid CC amount, input!=output!"); + return eval->Invalid("invalid CC amount, amount must match funds in channel"); } break; case 'R': @@ -299,7 +303,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //vout.1: CC vout marker to receiver pubKey //vout.2: normal output of CC input to senders pubkey //vout.n-2: normal change - //vout.n-1: opreturn - 'R' opentxid senderspubkey receiverspubkey numpaymewnts payment closetxid + //vout.n-1: opreturn - 'R' opentxid senderspubkey receiverspubkey numpayments payment closetxid if (isCCTxNotarizedConfirmed(opentxid) == 0) return eval->Invalid("channelOpen is not yet confirmed(notarised)!"); else if (isCCTxNotarizedConfirmed(param3) == 0) @@ -324,24 +328,24 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("invalid open txid!"); else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') return eval->Invalid("invalid channelopen OP_RETURN data!"); - else if (tx.vout[2].nValue != param2*payment) - return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(param3,channelCloseTx,hashblock) == 0) return eval->Invalid("invalid close txid!"); else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, param1, param2, param3) != 'C') return eval->Invalid("invalid channelclose OP_RETURN data!"); else if (tmp_txid!=opentxid) return eval->Invalid("invalid close tx, opentxid do not match on close and refund!"); + else if (tx.vout[2].nValue != param1*payment) + return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) return eval->Invalid("invalid previous tx OP_RETURN data!"); - else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) + else if (tx.vout[0].scriptPubKey != prevTx.vout[1].scriptPubKey) return eval->Invalid("invalid destination for sender marker!"); - else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey) + else if (tx.vout[1].scriptPubKey != prevTx.vout[2].scriptPubKey) return eval->Invalid("invalid destination for receiver marker!"); else if (tx.vout[2].nValue != prevTx.vout[0].nValue) - return eval->Invalid("invalid refund amount, must transfer all funds!"); + return eval->Invalid("invalid amount, refund amount and funds in channel must match!"); } break; } @@ -551,9 +555,9 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) { CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C; CTransaction channelOpenTx; - uint256 hashblock,tmp_txid,prevtxid,param3; - int32_t numvouts,param1; - int64_t param2,funds; + uint256 hashblock,tmp_txid,prevtxid,hashchain; + int32_t numvouts,numpayments; + int64_t payment,funds; // verify this is one of our outbound channels cp = CCinit(&C,EVAL_CHANNELS); @@ -565,7 +569,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) fprintf(stderr, "invalid channel open txid\n"); return (""); } - if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!='O') + if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O') { fprintf(stderr, "invalid channel open tx\n"); return (""); @@ -582,7 +586,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,0,0,zeroid))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,funds/payment,payment,zeroid))); } else { @@ -643,7 +647,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0) { - if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 && ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) != 0) && (funcid == 'P' || funcid=='O')) + if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3) != 0) { hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); endiancpy(hash, (uint8_t * ) & hentropy, 32); From 7f0ed443f1e051d98fbcfe444c0ce60cd5b8b1b9 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Mon, 1 Oct 2018 18:24:14 +0200 Subject: [PATCH 32/35] -modified ChannelsExactAmount -fixes --- src/cc/CCchannels.h | 2 +- src/cc/CCtx.cpp | 2 +- src/cc/channels.cpp | 171 +++++++++++++++++++++++---------------- src/wallet/rpcwallet.cpp | 8 +- 4 files changed, 109 insertions(+), 74 deletions(-) diff --git a/src/cc/CCchannels.h b/src/cc/CCchannels.h index 4754ae44e..29b35d0e6 100644 --- a/src/cc/CCchannels.h +++ b/src/cc/CCchannels.h @@ -27,6 +27,6 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid); std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid); // CCcustom -UniValue ChannelsInfo(); +UniValue ChannelsInfo(char *); #endif diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 4e8561b20..abe65199d 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -111,7 +111,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran { privkey = myprivkey; cond = mycond; - fprintf(stderr,"my CC addr.(%s)\n",myaddr); + } else if ( strcmp(destaddr,unspendable) == 0 ) { diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 72f995e55..de2657dc4 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -75,6 +75,19 @@ int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey return(0); } +int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub,int32_t v) +{ + char destaddr[64],ccaddr[64]; + + GetCCaddress(cp,ccaddr,srcpub); + if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) + { + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,ccaddr) == 0 ) + return(tx.vout[v].nValue); + } + return(0); +} + CScript EncodeChannelsOpRet(uint8_t funcid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) { CScript opret; uint8_t evalcode = EVAL_CHANNELS; @@ -110,24 +123,15 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti numvins = tx.vin.size(); numvouts = tx.vout.size(); - if ((numvouts=tx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)) !=0) + if ((numvouts=tx.vout.size()) > 0 && DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)!=0) { for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) + if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + else { - //fprintf(stderr,"vini.%d check mempool\n",i); - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - //fprintf(stderr,"vini.%d check hash and vout\n",i); - if ( hashBlock == zerohash ) - return eval->Invalid("cant Channels from mempool"); - if ( (assetoshis= IsChannelsvout(cp,vinTx,srcpub,destpub,tx.vin[i].prevout.n)) != 0 ) - inputs += assetoshis; - } + inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; } } } @@ -137,9 +141,7 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti } for (i=0; iInvalid("no vouts"); else { - //fprintf(stderr,"check amounts\n"); - if ( 0) //ChannelsExactAmounts(cp,eval,tx,1,10000) == false ) + if (ChannelsExactAmounts(cp,eval,tx,1,10000) == false ) { fprintf(stderr,"Channelsget invalid amount\n"); return false; @@ -364,7 +365,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid) { - char coinaddr[64]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t funcid,param1; + char coinaddr[64]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t param1; std::vector > unspentOutputs; CPubKey srcpub,destpub; uint8_t myprivkey[32]; @@ -386,14 +387,14 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && - (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)+IsChannelsvout(cp,tx,srcpub,destpub,1))>0) + (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)+IsChannelsMarkervout(cp,tx,srcpub,1))>0) { txid = it->first.txhash; break; } } } - if (myIsutxo_spentinmempool(txid,0) != 0) + if (txid!=zeroid && myIsutxo_spentinmempool(txid,0) != 0) { fprintf(stderr,"spent in mempool\n"); txid=zeroid; @@ -476,7 +477,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 } if (AddNormalinputs(mtx,mypk,2*txfee,1) > 0) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount)>=0) + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount-txfee)>=0) { if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O') { @@ -505,7 +506,6 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 memcpy(hash, hashdest, 32); } endiancpy((uint8_t * ) & gensecret, hashdest, 32); - fprintf(stderr, "%d %d %d %s %s\n",(int)(totalnumpayments-(prevdepth-numpayments)),(int)prevdepth,(int)numpayments,gensecret.ToString().c_str(),hashchain.ToString().c_str()); if (gensecret!=hashchain) { fprintf(stderr,"invalid secret supplied\n"); @@ -515,13 +515,17 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 else { hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash); - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < prevdepth-numpayments; i++) + if (prevdepth-numpayments) { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < prevdepth-numpayments; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & secret, hashdest, 32); } - endiancpy((uint8_t * ) & secret, hashdest, 32); + else endiancpy((uint8_t * ) & secret, (uint8_t * ) & hentropy, 32); } } else @@ -581,9 +585,9 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) } if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0) + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && funds-txfee>0) { - mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub)); + mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds-txfee, mypk, destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,funds/payment,payment,zeroid))); @@ -645,7 +649,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) } if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0) + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && funds-txfee>0) { if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3) != 0) { @@ -659,7 +663,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) endiancpy((uint8_t * ) & secret, hashdest, 32); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - mtx.vout.push_back(CTxOut(funds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + mtx.vout.push_back(CTxOut(funds-txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,destpub,param1,payment,closetxid))); } else @@ -677,52 +681,79 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) return(""); } -UniValue ChannelsInfo() +UniValue ChannelsInfo(char *CCaddr) { - UniValue result(UniValue::VOBJ); CTransaction tx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain; struct CCcontract_info *cp,C; char myCCaddr[64],addr[64],str1[100],str2[100]; int32_t vout,numvouts,param1,numpayments; int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk; + UniValue result(UniValue::VOBJ); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid; + struct CCcontract_info *cp,C; char myCCaddr[64],addr[64],str1[256],str2[64]; int32_t vout,numvouts,param1,numpayments; + int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk; std::vector > txids; + result.push_back(Pair("result","success")); - result.push_back(Pair("name","Channel Info")); cp = CCinit(&C,EVAL_CHANNELS); mypk = pubkey2pk(Mypubkey()); - GetCCaddress(cp,myCCaddr,mypk); - SetCCtxids(txids,myCCaddr); - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + if (strcmp(CCaddr,"")==0) { - //int height = it->first.blockHeight; - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second; - if ( (vout==0 || vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) + result.push_back(Pair("name","Channels Info")); + GetCCaddress(cp,myCCaddr,mypk); + SetCCtxids(txids,myCCaddr); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O') + //int height = it->first.blockHeight; + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second; + if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - GetCCaddress1of2(cp,addr,srcpub,destpub); - sprintf(str1,"Channel - %s",addr); - result.push_back(Pair(str1,"Open")); - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'P') - { - if (GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') - sprintf(str1,"Channel - %s",addr); - sprintf(str2,"Payment -> %s %lld payments of %lld",destpub.GetHash().ToString().c_str(),(long long)param2,(long long)payment); - result.push_back(Pair(str1,str2)); - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C') - { - GetCCaddress1of2(cp,addr,srcpub,destpub); - sprintf(str1,"Channel - %s",addr); - result.push_back(Pair(str1,"Close")); - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C') - { - GetCCaddress1of2(cp,addr,srcpub,destpub); - sprintf(str1,"Channel - %s",addr); - sprintf(str2,"Refund -> %s %lld payments of %lld",srcpub.GetHash().ToString().c_str(),(long long)param1,(long long)param2); - result.push_back(Pair(str1,"Refund")); + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O') + { + GetCCaddress1of2(cp,addr,srcpub,destpub); + sprintf(str1,"%s - %lld payments of %lld satoshi",addr,(long long)param1,(long long)param2); + result.push_back(Pair("Channel", str1)); + } } } } + else + { + sprintf(str1,"Channel %s",CCaddr); + result.push_back(Pair("name",str1)); + strcpy(myCCaddr,CCaddr); + SetCCtxids(txids,myCCaddr); + prevtxid=zeroid; + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + { + //int height = it->first.blockHeight; + txid = it->first.txhash; + nValue = (int64_t)it->second; + if (txid!=prevtxid && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) + { + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O') + { + sprintf(str1,"%lld payments of %lld satoshi",(long long)param1,(long long)param2); + result.push_back(Pair("Open", str1)); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'P') + { + if (GetTransaction(opentxid,opentx,hashBlock,false) != 0 && (numvouts=opentx.vout.size()) > 0 && DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') + { + Getscriptaddress(str2,tx.vout[3].scriptPubKey); + sprintf(str1,"%lld satoshi to %s, %lld payments left",(long long)(param2*payment),str2,(long long)param1); + result.push_back(Pair("Payment",str1)); + } + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C') + { + result.push_back(Pair("Close","channel")); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'R') + { + Getscriptaddress(str2,tx.vout[2].scriptPubKey); + sprintf(str1,"%lld satoshi back to %s",(long long)(param1*param2),str2); + result.push_back(Pair("Refund",str1)); + } + } + prevtxid=txid; + } + } return(result); -} - +} \ No newline at end of file diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ff910f2c9..d4a83d83a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5124,11 +5124,15 @@ UniValue tokenaddress(const UniValue& params, bool fHelp) UniValue channelsinfo(const UniValue& params, bool fHelp) { - if ( fHelp || params.size() != 0 ) + char addr[100]; + if ( fHelp || params.size() > 1 ) throw runtime_error("channelsinfo\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"); - return(ChannelsInfo()); + strcpy(addr,""); + if (params.size() > 0 && !params[0].isNull() && !params[0].get_str().empty()) + strcpy(addr,params[0].get_str().c_str()); + return(ChannelsInfo(addr)); } UniValue channelsopen(const UniValue& params, bool fHelp) From 78086bc3bf538f763caea411a7306616b348b645 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Mon, 1 Oct 2018 18:52:21 +0200 Subject: [PATCH 33/35] - fix --- src/cc/CCchannels.h | 2 +- src/cc/CCutils.cpp | 2 +- src/cc/channels.cpp | 74 +++++++++++++++++++++------------------- src/wallet/rpcwallet.cpp | 10 +++--- 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/cc/CCchannels.h b/src/cc/CCchannels.h index 29b35d0e6..f67ef9a6c 100644 --- a/src/cc/CCchannels.h +++ b/src/cc/CCchannels.h @@ -27,6 +27,6 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid); std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid); // CCcustom -UniValue ChannelsInfo(char *); +UniValue ChannelsInfo(uint256 opentxid); #endif diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index cbf574532..491798a98 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -405,7 +405,7 @@ int64_t CCduration(int32_t &numblocks,uint256 txid) } numblocks = (pindex->nHeight - txheight); duration = (pindex->nTime - txtime); - fprintf(stderr,"duration %d (%u - %u) numblocks %d (%d - %d)\n",(int32_t)duration,(uint32_t)pindex->nTime,txtime,numblocks,pindex->nHeight,txheight); + //fprintf(stderr,"duration %d (%u - %u) numblocks %d (%d - %d)\n",(int32_t)duration,(uint32_t)pindex->nTime,txtime,numblocks,pindex->nHeight,txheight); return(duration); } diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index de2657dc4..236f28e03 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -681,7 +681,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) return(""); } -UniValue ChannelsInfo(char *CCaddr) +UniValue ChannelsInfo(uint256 channeltxid) { UniValue result(UniValue::VOBJ); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid; struct CCcontract_info *cp,C; char myCCaddr[64],addr[64],str1[256],str2[64]; int32_t vout,numvouts,param1,numpayments; @@ -691,7 +691,7 @@ UniValue ChannelsInfo(char *CCaddr) result.push_back(Pair("result","success")); cp = CCinit(&C,EVAL_CHANNELS); mypk = pubkey2pk(Mypubkey()); - if (strcmp(CCaddr,"")==0) + if (channeltxid==zeroid) { result.push_back(Pair("name","Channels Info")); GetCCaddress(cp,myCCaddr,mypk); @@ -704,10 +704,10 @@ UniValue ChannelsInfo(char *CCaddr) nValue = (int64_t)it->second; if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O') + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O') { GetCCaddress1of2(cp,addr,srcpub,destpub); - sprintf(str1,"%s - %lld payments of %lld satoshi",addr,(long long)param1,(long long)param2); + sprintf(str1,"%s - %lld payments of %lld satoshi - %s",addr,(long long)param1,(long long)param2,tx.GetHash().ToString().c_str()); result.push_back(Pair("Channel", str1)); } } @@ -715,44 +715,48 @@ UniValue ChannelsInfo(char *CCaddr) } else { - sprintf(str1,"Channel %s",CCaddr); - result.push_back(Pair("name",str1)); - strcpy(myCCaddr,CCaddr); - SetCCtxids(txids,myCCaddr); - prevtxid=zeroid; - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + if (GetTransaction(channeltxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && + (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O')) { - //int height = it->first.blockHeight; - txid = it->first.txhash; - nValue = (int64_t)it->second; - if (txid!=prevtxid && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) + GetCCaddress1of2(cp,addr,srcpub,destpub); + sprintf(str1,"Channel %s",addr); + result.push_back(Pair("name",str1)); + SetCCtxids(txids,addr); + prevtxid=zeroid; + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O') + + txid = it->first.txhash; + nValue = (int64_t)it->second; + if (txid!=prevtxid && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - sprintf(str1,"%lld payments of %lld satoshi",(long long)param1,(long long)param2); - result.push_back(Pair("Open", str1)); - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'P') - { - if (GetTransaction(opentxid,opentx,hashBlock,false) != 0 && (numvouts=opentx.vout.size()) > 0 && DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O' && tx.GetHash()==channeltxid) { - Getscriptaddress(str2,tx.vout[3].scriptPubKey); - sprintf(str1,"%lld satoshi to %s, %lld payments left",(long long)(param2*payment),str2,(long long)param1); - result.push_back(Pair("Payment",str1)); + sprintf(str1,"%lld payments of %lld satoshi",(long long)param1,(long long)param2); + result.push_back(Pair("Open", str1)); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'P' && opentxid==channeltxid) + { + if (GetTransaction(opentxid,opentx,hashBlock,false) != 0 && (numvouts=opentx.vout.size()) > 0 && DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') + { + Getscriptaddress(str2,tx.vout[3].scriptPubKey); + sprintf(str1,"%lld satoshi to %s, %lld payments left",(long long)(param2*payment),str2,(long long)param1); + result.push_back(Pair("Payment",str1)); + } + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C' && opentxid==channeltxid) + { + result.push_back(Pair("Close","channel")); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'R' && opentxid==channeltxid) + { + Getscriptaddress(str2,tx.vout[2].scriptPubKey); + sprintf(str1,"%lld satoshi back to %s",(long long)(param1*param2),str2); + result.push_back(Pair("Refund",str1)); } } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C') - { - result.push_back(Pair("Close","channel")); - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'R') - { - Getscriptaddress(str2,tx.vout[2].scriptPubKey); - sprintf(str1,"%lld satoshi back to %s",(long long)(param1*param2),str2); - result.push_back(Pair("Refund",str1)); - } + prevtxid=txid; } - prevtxid=txid; } } return(result); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d4a83d83a..d97df5b3a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5124,15 +5124,15 @@ UniValue tokenaddress(const UniValue& params, bool fHelp) UniValue channelsinfo(const UniValue& params, bool fHelp) { - char addr[100]; + uint256 opentxid; if ( fHelp || params.size() > 1 ) - throw runtime_error("channelsinfo\n"); + throw runtime_error("channelsinfo [opentxid]\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"); - strcpy(addr,""); + opentxid=zeroid; if (params.size() > 0 && !params[0].isNull() && !params[0].get_str().empty()) - strcpy(addr,params[0].get_str().c_str()); - return(ChannelsInfo(addr)); + opentxid = Parseuint256((char *)params[0].get_str().c_str()); + return(ChannelsInfo(opentxid)); } UniValue channelsopen(const UniValue& params, bool fHelp) From 0cb59663e2194b52ac6519a0c1e8831856358a1e Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Tue, 2 Oct 2018 15:06:55 +0200 Subject: [PATCH 34/35] - Updated channel CC docs --- src/cc/CC made easy | 55 ++++++++++++++++++++++++++++++++++++++++++++- src/cc/channels.cpp | 1 - 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/cc/CC made easy b/src/cc/CC made easy index 895d84404..158c2907a 100644 --- a/src/cc/CC made easy +++ b/src/cc/CC made easy @@ -490,8 +490,61 @@ Now we can make the payment based on the hashvalue revealed at a specified depth Payments at the speed of the mempool, protected by dPoW! -
+RPC calls +channelsopen: + Used to open channel between two pub keys (sender and receiver). Parameters: destination_pubkey, total_number_of_payments, payment_denomination. + Example - channelsopen 03a8fe537de2ace0d9c210b0ff945085c9192c9abf56ea22f22ce7998f289bb7bb 10 10000000 +channelspayment: + Sending payment to receiver. Condition is that the channel open tx is confirmed/notarised. Parameters: open_tx_id, payment_amount, [secret] (optional, used when receiver needs to make a payment which secret has already been revealed by sender). + Example - channelspayment b9c141facc8cb71306d0de8e525b3de1450e93e17fc8799c8fda5ed52fd14440 20000000 +channelsclose: + Marking channel as closed. This RPC only creates a tx which says that the channel is closed and will be used in refund RPC to withdraw funds from closed channel. This also notifies receiver that channel fund could be withdrawn, but the payment RPC is still available until all funds are withdrawn. Parameters: open_tx_id. + Example - channelsclose b9c141facc8cb71306d0de8e525b3de1450e93e17fc8799c8fda5ed52fd14440 +channelsrefund: + Withdrawing funds back to senders address. Refund can be issued only when channel close tx is confirmed/notarised. Parameters: open_tx_id, close_tx_id + Example - channelsrefund b9c141facc8cb71306d0de8e525b3de1450e93e17fc8799c8fda5ed52fd14440 bb0ea34f846247642684c7c541c435b06ee79e47893640e5d2e51023841677fd +channelsinfo: + Getting info about channels in which the issuer is involved, either as sender or receiver. Call without parameters give the list of available channels. Parameters: [open_tx_id] (optional - used to get info about specific channel) +VIN/VOUT allocation +Open: + vin.0: normal input + vout.0: CC vout for channel funding on CC1of2 pubkey + vout.1: CC vout marker to senders pubKey + vout.2: CC vout marker to receiver pubkey + vout.n-2: normal change + vout.n-1: opreturn - 'O' zerotxid senderspubkey receiverspubkey totalnumberofpayments paymentamount hashchain + +Payment + vin.0: normal input + vin.1: CC input from channel funding + vin.2: CC input from src marker + vout.0: CC vout change to channel funding on CC1of2 pubkey + vout.1: CC vout marker to senders pubKey + vout.2: CC vout marker to receiver pubkey + vout.3: normal output of payment amount to receiver pubkey + vout.n-2: normal change + vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret + +Close: + vin.0: normal input + vin.1: CC input from channel funding + vin.2: CC input from src marker + vout.0: CC vout for channel funding + vout.1: CC vout marker to senders pubKey + vout.2: CC vout marker to receiver pubkey + vout.n-2: normal change + vout.n-1: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0 + +Refund: + vin.0: normal input + vin.1: CC input from channel funding + vin.2: CC input from src marker + vout.0: CC vout marker to senders pubKey + vout.1: CC vout marker to receiver pubKey + vout.2: normal output of CC input to senders pubkey + vout.n-2: normal change + vout.n-1: opreturn - 'R' opentxid senderspubkey receiverspubkey numpayments payment closetxid Chapter 11 - oracles example Oracles CC is an example where it ended up being simpler than I first expected, but at the same time a lot more powerful. It is one of the smaller CC, but it enables creation of an arbitrary number of data markets, in a performant way. diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 236f28e03..f6133d575 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -727,7 +727,6 @@ UniValue ChannelsInfo(uint256 channeltxid) { txid = it->first.txhash; - nValue = (int64_t)it->second; if (txid!=prevtxid && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O' && tx.GetHash()==channeltxid) From 374dbd844c2399ae82ab3b44027b7cf8a8045ccd Mon Sep 17 00:00:00 2001 From: jl777 Date: Tue, 2 Oct 2018 02:23:29 -1100 Subject: [PATCH 35/35] Fix destination confusion --- src/cc/CCtx.cpp | 2 +- src/cc/dapps/oraclefeed.c | 4 ++-- src/cc/gateways.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index abe65199d..f29fd05e8 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -139,7 +139,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran } else { - fprintf(stderr,"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); continue; } uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL, utxovalues[i],consensusBranchId, &txdata); diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index 297b92a01..eaf488a34 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -464,10 +464,10 @@ int32_t get_coinheader(char *refcoin,char *acname,bits256 *blockhashp,bits256 *m return(0); } -cJSON *get_gatewayspending(char *refcoin,char *acname,char *oraclestxidstr) +cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr) { cJSON *retjson; char *retstr; - if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewayspending",oraclestxidstr,refcoin,"","")) != 0 ) + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewayspending",bindtxidstr,refcoin,"","")) != 0 ) { //printf("pending.(%s)\n",jprint(retjson,0)); return(retjson); diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 5c82b789d..b9c78a612 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -704,7 +704,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std:: } if ( AddNormalinputs(mtx,mypk,3*txfee,60) > 0 ) { - mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk)); + mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,destpub)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,cointxid))) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysOpRet('D',coin,bindtxid,publishers,txids,height,cointxid,deposithex,proof,destpub,amount))); } @@ -714,7 +714,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std:: std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount) { - CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector msigpubkeys; int64_t totalsupply,depositamount,inputs,CCchange=0; int32_t numvouts; uint256 hashBlock,assetid,oracletxid; char str[65],depositaddr[64],coinaddr[64]; + CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector msigpubkeys; int64_t totalsupply,depositamount,inputs,CCchange=0; int32_t numvouts; uint256 hashBlock,assetid,oracletxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; cp = CCinit(&C,EVAL_GATEWAYS); if ( txfee == 0 ) txfee = 10000; @@ -747,6 +747,8 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui { 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 if ( CCchange != 0 )