From 287a373a05b83f18d884d70813445c0250c4d3a7 Mon Sep 17 00:00:00 2001 From: jl777 Date: Tue, 21 Aug 2018 08:20:32 -1100 Subject: [PATCH] +channels --- src/Makefile.am | 1 + src/cc/CCChannels.h | 27 +++++ src/cc/CCcustom.cpp | 25 ++++- src/cc/channels.cpp | 210 +++++++++++++++++++++++++++++++++++++++ src/main.cpp | 4 +- src/rpcserver.cpp | 3 + src/rpcserver.h | 1 + src/wallet/rpcwallet.cpp | 13 +++ 8 files changed, 278 insertions(+), 6 deletions(-) create mode 100644 src/cc/CCChannels.h create mode 100644 src/cc/channels.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 5d7685980..5d6ee93c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -268,6 +268,7 @@ libbitcoin_server_a_SOURCES = \ cc/lotto.cpp \ cc/fsm.cpp \ cc/MofN.cpp \ + cc/channels.cpp \ cc/auction.cpp \ cc/betprotocol.cpp \ chain.cpp \ diff --git a/src/cc/CCChannels.h b/src/cc/CCChannels.h new file mode 100644 index 000000000..c628cc918 --- /dev/null +++ b/src/cc/CCChannels.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright © 2014-2018 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + + +#ifndef CC_CHANNELS_H +#define CC_CHANNELS_H + +#include "CCinclude.h" + +bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); + +// CCcustom +UniValue ChannelsInfo(); + +#endif diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 54b11d495..0aeb24792 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -22,6 +22,7 @@ #include "CClotto.h" #include "CCfsm.h" #include "CCMofN.h" +#include "CCChannels.h" /* CCcustom has most of the functions that need to be extended to create a new CC contract. @@ -45,10 +46,7 @@ Make sure both the CC coins and normal coins are preserved and follow the rules that make sense. It is a good idea to define specific roles for specific vins and vouts to reduce the complexity of validation. */ -//BTCD Address: RAssetsAtGnvwgK9gVHBbAU4sVTah1hAm5 -//BTCD Privkey: UvtvQVgVScXEYm4J3r4nE4nbFuGXSVM5pKec8VWXwgG9dmpWBuDh -//BTCD Address: RSavingsEYcivt2DFsxsKeCjqArV6oVtVZ -//BTCD Privkey: Ux6XQekTxokko6gZHz24B7PUsmUQtWFzG2W9nUA8jba7UoVbPBF4 +// to create a new CCaddr, add to rpcwallet the CCaddress and start with -pubkey= with the pubkey of the new address, with its wif already imported. set normaladdr and CChexstr. run CCaddress and it will print the privkey along with autocorrect the CCaddress. which should then update the CCaddr here // Assets, aka Tokens #define FUNCNAME IsAssetsInput @@ -140,6 +138,17 @@ uint8_t MofNCCpriv[32] = { 0x9d, 0xa1, 0xf8, 0xf7, 0xba, 0x0a, 0x91, 0x36, 0x89, #undef FUNCNAME #undef EVALCODE +// Channels +#define FUNCNAME IsChannelsInput +#define EVALCODE EVAL_CHANNELS +const char *ChannelsCCaddr = "RDVHcSekmXgeYBqRupNTmqo3Rn8QRXNduy"; +const char *ChannelsNormaladdr = "RQUuT8zmkvDfXqECH4m3VD3SsHZAfnoh1v"; +char ChannelsCChexstr[67] = { "035debdb19b1c98c615259339500511d6216a3ffbeb28ff5655a7ef5790a12ab0b" }; +uint8_t ChannelsCCpriv[32] = { 0x9d, 0xa1, 0xf8, 0xf7, 0xba, 0x0a, 0x91, 0x36, 0x89, 0x9a, 0x86, 0x30, 0x63, 0x20, 0xd7, 0xdf, 0xaa, 0x35, 0xe3, 0x99, 0x32, 0x2b, 0x63, 0xc0, 0x66, 0x9c, 0x93, 0xc4, 0x5e, 0x9d, 0xb9, 0xce }; +#include "CCcustom.inc" +#undef FUNCNAME +#undef EVALCODE + struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode) { cp->evalcode = evalcode; @@ -209,6 +218,14 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode) cp->validate = MofNValidate; cp->ismyvin = IsMofNInput; break; + case EVAL_CHANNELS: + strcpy(cp->unspendableCCaddr,ChannelsCCaddr); + strcpy(cp->normaladdr,ChannelsNormaladdr); + strcpy(cp->CChexstr,ChannelsCChexstr); + memcpy(cp->CCpriv,ChannelsCCpriv,32); + cp->validate = ChannelsValidate; + cp->ismyvin = IsChannelsInput; + break; } return(cp); } diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp new file mode 100644 index 000000000..7a4cdd886 --- /dev/null +++ b/src/cc/channels.cpp @@ -0,0 +1,210 @@ +/****************************************************************************** + * Copyright © 2014-2018 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include "CCChannels.h" + +/* +*/ + +// start of consensus code + +int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +{ + char destaddr[64]; + if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) + { + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 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); +} + +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); + std::vector > txids; + numvins = tx.vin.size(); + numvouts = tx.vout.size(); + preventCCvins = preventCCvouts = -1; + 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 ) + { + fprintf(stderr,"Channelsget invalid amount\n"); + return false; + } + else + { + txid = tx.GetHash(); + memcpy(hash,&txid,sizeof(hash)); + retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); + if ( retval != 0 ) + fprintf(stderr,"Channelsget validated\n"); + else fprintf(stderr,"Channelsget invalid\n"); + return(retval); + } + } +} +// end of consensus code + +// helper functions for rpc calls in rpcwallet.cpp + +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; + std::vector > unspentOutputs; + GetCCaddress(cp,coinaddr,pk); + 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 ( (nValue= IsChannelsvout(cp,vintx,vout)) > 1000000 && 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) ) + break; + } + } + } + return(totalinputs); +} + +std::string ChannelsGet(uint64_t txfee,int64_t nValue) +{ + CMutableTransaction mtx,tmpmtx; CPubKey mypk,Channelspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; + cp = CCinit(&C,EVAL_CHANNELS); + if ( txfee == 0 ) + txfee = 10000; + Channelspk = GetUnspendable(cp,0); + mypk = pubkey2pk(Mypubkey()); + if ( (inputs= AddChannelsInputs(cp,mtx,Channelspk,nValue+txfee,60)) > 0 ) + { + if ( inputs > nValue ) + CCchange = (inputs - nValue - txfee); + if ( CCchange != 0 ) + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CCchange,Channelspk)); + mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + fprintf(stderr,"start at %u\n",(uint32_t)time(NULL)); + j = rand() & 0xfffffff; + for (i=0; i<1000000; i++,j++) + { + tmpmtx = mtx; + rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_CHANNELS << (uint8_t)'G' << j)); + if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) + { + len >>= 1; + decode_hex(buf,len,(char *)rawhex.c_str()); + hash = bits256_doublesha256(0,buf,len); + if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) + { + fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL)); + return(rawhex); + } + //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); + } + } + fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL)); + return(""); + } else fprintf(stderr,"cant find Channels inputs\n"); + return(""); +} + +std::string ChannelsFund(uint64_t txfee,int64_t funds) +{ + CMutableTransaction mtx; CPubKey mypk,Channelspk; CScript opret; struct CCcontract_info *cp,C; + cp = CCinit(&C,EVAL_CHANNELS); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + Channelspk = GetUnspendable(cp,0); + if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) + { + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,funds,Channelspk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); + } + return(""); +} + +UniValue ChannelsInfo() +{ + UniValue result(UniValue::VOBJ); char numstr[64]; + CMutableTransaction mtx; CPubKey Channelspk; struct CCcontract_info *cp,C; int64_t funding; + result.push_back(Pair("result","success")); + result.push_back(Pair("name","Channels")); + cp = CCinit(&C,EVAL_CHANNELS); + Channelspk = GetUnspendable(cp,0); + funding = AddChannelsInputs(cp,mtx,Channelspk,0,0); + sprintf(numstr,"%.8f",(double)funding/COIN); + result.push_back(Pair("funding",numstr)); + return(result); +} + diff --git a/src/main.cpp b/src/main.cpp index 3726546e4..ec5ae036e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4185,11 +4185,11 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C } if ( rejects == 0 || rejects == lastrejects ) { - if ( lastrejects != 0 ) + if ( 0 && lastrejects != 0 ) fprintf(stderr,"lastrejects.%d -> all tx in mempool\n",lastrejects); break; } - fprintf(stderr,"addtomempool ht.%d for CC checking: n.%d rejects.%d last.%d\n",height,(int32_t)block.vtx.size(),rejects,lastrejects); + //fprintf(stderr,"addtomempool ht.%d for CC checking: n.%d rejects.%d last.%d\n",height,(int32_t)block.vtx.size(),rejects,lastrejects); lastrejects = rejects; rejects = 0; } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 156783f85..98212dc85 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -373,6 +373,9 @@ static const CRPCCommand vRPCCommands[] = /* MofN */ { "MofN", "mofnaddress", &mofnaddress, true }, + + /* Channels */ + { "channels", "channelsaddress", &channelsaddress, true }, /* dice */ { "dice", "dicelist", &dicelist, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index be404982c..fbc1c99f6 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -222,6 +222,7 @@ extern UniValue tokenask(const UniValue& params, bool fHelp); extern UniValue tokencancelask(const UniValue& params, bool fHelp); extern UniValue tokenfillask(const UniValue& params, bool fHelp); extern UniValue mofnaddress(const UniValue& params, bool fHelp); +extern UniValue channelsaddress(const UniValue& params, bool fHelp); //extern UniValue tokenswapask(const UniValue& params, bool fHelp); //extern UniValue tokenfillswap(const UniValue& params, bool fHelp); extern UniValue faucetfund(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0e5554134..62e97d058 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4882,6 +4882,19 @@ UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector pubkey; + cp = CCinit(&C,EVAL_CHANNELS); + if ( fHelp || params.size() > 1 ) + throw runtime_error("channelsaddress [pubkey]\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"); + if ( params.size() == 1 ) + pubkey = ParseHex(params[0].get_str().c_str()); + return(CCaddress(cp,(char *)"Channels",pubkey)); +} + UniValue mofnaddress(const UniValue& params, bool fHelp) { struct CCcontract_info *cp,C; std::vector pubkey;