From 16f5598f361a04e7faa7aaf3b9286420a871063b Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Mon, 26 Nov 2018 20:32:57 +0100 Subject: [PATCH] Gateways (#3) - Changed gateways withdrawal flow - Added txnotarizedconfirmed function to check if transaction is confirmed/notarized - Fixed max number of inputs when adding in varuous CC functions - Added TESTMODE to set CC confirmation tx to 2 blocks instead of 60 --- src/cc/CCGateways.h | 7 +- src/cc/CCassetstx.cpp | 16 +- src/cc/CCinclude.h | 11 +- src/cc/CCutils.cpp | 61 ++- src/cc/channels.cpp | 14 +- src/cc/dapps/oraclefeed.c | 236 +++++++--- src/cc/dice.cpp | 2 +- src/cc/gateways.cpp | 970 +++++++++++++++++++++++++------------- src/cc/oracles.cpp | 4 +- src/cc/prices.cpp | 2 +- src/komodo_structs.h | 7 +- src/rpc/misc.cpp | 27 ++ src/rpc/server.cpp | 9 +- src/rpc/server.h | 9 +- src/wallet/rpcwallet.cpp | 98 ++-- 15 files changed, 997 insertions(+), 476 deletions(-) diff --git a/src/cc/CCGateways.h b/src/cc/CCGateways.h index 0ccf21f44..2470665d4 100644 --- a/src/cc/CCGateways.h +++ b/src/cc/CCGateways.h @@ -25,10 +25,13 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vectorproof,CPubKey destpub,int64_t amount); std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount); std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount); +std::string GatewaysPartialSign(uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex); +std::string GatewaysCompleteSigning(uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex); +std::string GatewaysMarkDone(uint64_t txfee,uint256 withdrawtxid,std::string refcoin); UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin); -std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid,std::string refcoin,uint256 cointxid); +UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin); UniValue GatewaysMultisig(char *txidaddr); -std::string GatewaysPartialSign(uint64_t txfee,uint256 txidaddr,std::string refcoin, std::string hex); + // CCcustom UniValue GatewaysInfo(uint256 bindtxid); diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index 64b380900..b374f00d4 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -222,7 +222,7 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector des if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { /*n = outputs.size(); if ( n == amounts.size() ) @@ -257,7 +257,7 @@ std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector dest if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 ) { @@ -313,7 +313,7 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { mask = ~((1LL << mtx.vin.size()) - 1); if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 ) @@ -347,7 +347,7 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { mask = ~((1LL << mtx.vin.size()) - 1); if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 ) @@ -379,7 +379,7 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { mask = ~((1LL << mtx.vin.size()) - 1); if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 ) @@ -400,7 +400,7 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { mask = ~((1LL << mtx.vin.size()) - 1); if ( GetTransaction(asktxid,vintx,hashBlock,false) != 0 ) @@ -426,7 +426,7 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { mask = ~((1LL << mtx.vin.size()) - 1); if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 ) @@ -474,7 +474,7 @@ std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 askt if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { mask = ~((1LL << mtx.vin.size()) - 1); if ( GetTransaction(asktxid,vintx,hashBlock,false) != 0 ) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index fea3f7e48..5cf549706 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -57,9 +57,12 @@ extern char ASSETCHAINS_SYMBOL[]; 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; +#ifndef _BITS256 +#define _BITS256 + 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; +#endif + struct CC_utxo { @@ -167,7 +170,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); +bool komodo_txnotarizedconfirmed(uint256 txid); // CCtx bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey); std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index b6abd5474..93fddee67 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -13,11 +13,20 @@ * * ******************************************************************************/ -#include "CCinclude.h" - /* CCutils has low level functions that are universally useful for all contracts. */ +#include "CCinclude.h" +#include "komodo_structs.h" + +#ifdef TESTMODE + #define MIN_NON_NOTARIZED_CONFIRMS 2 +#else + #define MIN_NON_NOTARIZED_CONFIRMS 60 +#endif // TESTMODE +int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); +struct komodo_state *komodo_stateptr(char *symbol,char *dest); +extern uint32_t KOMODO_DPOWCONFS; void endiancpy(uint8_t *dest,uint8_t *src,int32_t len) { @@ -453,12 +462,50 @@ int64_t CCduration(int32_t &numblocks,uint256 txid) return(duration); } -bool isCCTxNotarizedConfirmed(uint256 txid) +bool komodo_txnotarizedconfirmed(uint256 txid) { - int32_t confirms; + char str[65]; + uint32_t confirms,notarized,txheight; + CTransaction tx; + uint256 hashBlock; + CBlockIndex *pindex; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - CCduration(confirms,txid); - if (confirms >= MIN_NOTARIZATION_CONFIRMS) + if ( myGetTransaction(txid,tx,hashBlock) == 0 ) + { + fprintf(stderr,"komodo_txnotarizedconfirmed cant find txid %s\n",txid.ToString().c_str()); + return(0); + } + else if ( hashBlock == zeroid ) + { + fprintf(stderr,"komodo_txnotarizedconfirmed no hashBlock for txid %s\n",txid.ToString().c_str()); + return(0); + } + else if ( (pindex= mapBlockIndex[hashBlock]) == 0 || (txheight= pindex->GetHeight()) <= 0 ) + { + fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d %p for txid %s\n",txheight,pindex,txid.ToString().c_str()); + return(0); + } + else if ( (pindex= chainActive.LastTip()) == 0 || pindex->GetHeight() < txheight ) + { + fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,(int32_t)pindex->GetHeight()); + return(0); + } + confirms=1 + pindex->GetHeight() - txheight; + if ( KOMODO_DPOWCONFS != 0 && txheight > 0 && confirms > 0 && (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + if ( (notarized=sp->NOTARIZED_HEIGHT) > 0 ) + { + if ( txheight >= sp->NOTARIZED_HEIGHT ) + confirms=1; + } + } +#ifdef TESTMODE + notarized=0; +#endif //TESTMODE + if (notarized>0 && confirms > 1) + return (true); + else if (notarized==0 && confirms >= MIN_NON_NOTARIZED_CONFIRMS) return (true); return (false); -} +} \ No newline at end of file diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 914ca4ebb..6ef09bfc5 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -199,7 +199,7 @@ 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 (isCCTxNotarizedConfirmed(opentxid) == 0) + if (komodo_txnotarizedconfirmed(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!"); @@ -261,7 +261,7 @@ 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 (isCCTxNotarizedConfirmed(opentxid) == 0) + if (komodo_txnotarizedconfirmed(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!"); @@ -304,9 +304,9 @@ 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 numpayments payment closetxid - if (isCCTxNotarizedConfirmed(opentxid) == 0) + if (komodo_txnotarizedconfirmed(opentxid) == 0) return eval->Invalid("channelOpen is not yet confirmed(notarised)!"); - else if (isCCTxNotarizedConfirmed(param3) == 0) + else if (komodo_txnotarizedconfirmed(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!"); @@ -479,7 +479,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 fprintf(stderr, "invalid channel open txid\n"); return (""); } - if (AddNormalinputs(mtx,mypk,2*txfee,1) > 0) + if (AddNormalinputs(mtx,mypk,2*txfee,3) > 0) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount-txfee)>=0) { @@ -595,7 +595,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) fprintf(stderr,"cannot close, you are not channel owner\n"); return(""); } - if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && funds-txfee>0) { @@ -658,7 +658,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) fprintf(stderr,"cannot refund, you are not the channel owenr\n"); return(""); } - if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && funds-txfee>0) { diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index a0930bae4..68c02310b 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -328,13 +328,18 @@ cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char { sprintf(cmdstr,"%s %s %s %s %s %s > %s\n",REFCOIN_CLI,method,arg0,arg1,arg2,arg3,fname); printf("ref.(%s) REFCOIN_CLI (%s)\n",refcoin,cmdstr); - } + } +#ifdef TESTMODE + fprintf(stderr,"cmd: %s\n",cmdstr); +#endif // TESTMODE system(cmdstr); *retstrp = 0; if ( (jsonstr= filestr(&fsize,fname)) != 0 ) { jsonstr[strlen(jsonstr)-1]='\0'; - //fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr); +#ifdef TESTMODE + fprintf(stderr,"jsonstr.(%s)\n",jsonstr); +#endif // TESTMODE if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 ) *retstrp = jsonstr; else free(jsonstr); @@ -483,6 +488,22 @@ cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr) return(0); } +cJSON *get_gatewaysprocessed(char *refcoin,char *acname,char *bindtxidstr) +{ + cJSON *retjson; char *retstr; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewaysprocessed",bindtxidstr,refcoin,"","")) != 0 ) + { + //printf("pending.(%s)\n",jprint(retjson,0)); + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"%s get_gatewaysprocessed.(%s) error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + cJSON *get_rawmempool(char *refcoin,char *acname) { cJSON *retjson; char *retstr; @@ -550,10 +571,12 @@ int32_t validateaddress(char *refcoin,char *acname,char *depositaddr, char* comp return (res); } -void importaddress(char *refcoin,char *acname,char *depositaddr) +void importaddress(char *refcoin,char *acname,char *depositaddr, char *label,int rescan) { - cJSON *retjson; char *retstr; - if ( (retjson= get_komodocli(refcoin,&retstr,acname,"importaddress",depositaddr,"","true","")) != 0 ) + cJSON *retjson; char *retstr; char rescanstr[10]; + if (rescan) strcpy(rescanstr,"true"); + else strcpy(rescanstr,"false"); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"importaddress",depositaddr,label,rescanstr,"")) != 0 ) { printf("importaddress.(%s)\n",jprint(retjson,0)); free_json(retjson); @@ -610,7 +633,7 @@ cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required) return(vins); } -char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signeraddr,char *withdrawaddr,int64_t satoshis) +char *createrawtx(char *refcoin,char *acname,char *depositaddr,char *withdrawaddr,char *txidaddr,int64_t satoshis) { char *retstr,*retstr2,array[128],*txstr = 0; cJSON *retjson2,*retjson,*vins,*vouts; int64_t txfee,total,change = 0; if ( strcmp(refcoin,"BTC") == 0 ) @@ -618,7 +641,7 @@ char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signerad else txfee = 10000; if ( satoshis < txfee ) { - printf("createmultisig satoshis %.8f < txfee %.8f\n",(double)satoshis/SATOSHIDEN,(double)txfee/SATOSHIDEN); + printf("createrawtx satoshis %.8f < txfee %.8f\n",(double)satoshis/SATOSHIDEN,(double)txfee/SATOSHIDEN); return(0); } satoshis -= txfee; @@ -631,8 +654,9 @@ char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signerad if ( total >= satoshis ) { vouts = cJSON_CreateObject(); - jaddnum(vouts,withdrawaddr,(double)satoshis/SATOSHIDEN); - if ( total > satoshis+txfee ) + jaddnum(vouts,withdrawaddr,(double)(satoshis-2*txfee)/SATOSHIDEN); + jaddnum(vouts,txidaddr,(double)txfee/SATOSHIDEN); + if ( total > satoshis) { change = (total - satoshis); jaddnum(vouts,depositaddr,(double)change/SATOSHIDEN); @@ -645,29 +669,30 @@ char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signerad sprintf(argB,"\'%s\'",tmpB); if ( (retjson2= get_komodocli(refcoin,&txstr,acname,"createrawtransaction",argA,argB,"","")) != 0 ) { - printf("createmultisig: unexpected JSON2.(%s)\n",jprint(retjson2,0)); + printf("createrawtx: unexpected JSON2.(%s)\n",jprint(retjson2,0)); free_json(retjson2); } else if ( txstr == 0 ) - printf("createmultisig: null txstr and JSON2\n"); + printf("createrawtx: null txstr and JSON2\n"); free(tmpA); free(tmpB); free(argA); free(argB); } + else printf("not enough funds to create withdraw tx\n"); } free_json(retjson); } else if ( retstr != 0 ) { - printf("createmultisig: unexpected null JSON, retstr.(%s)\n",retstr); + printf("createrawtx: unexpected null JSON, retstr.(%s)\n",retstr); free(retstr); } - else printf("createmultisig: null retstr and JSON\n"); + else printf("createrawtx: null retstr and JSON\n"); return(txstr); } -cJSON *addmultisignature(char *refcoin,char *acname,char *signeraddr,char *rawtx) +cJSON *addsignature(char *refcoin,char *acname,char *rawtx) { char *retstr,*hexstr; cJSON *retjson; if ( (retjson= get_komodocli(refcoin,&retstr,acname,"signrawtransaction",rawtx,"","","")) != 0 ) @@ -681,6 +706,11 @@ cJSON *addmultisignature(char *refcoin,char *acname,char *signeraddr,char *rawtx } free_json(retjson); } + else if ( retstr != 0 ) + { + printf("error parsing signrawtransaction.(%s)\n",retstr); + free(retstr); + } return(0); } @@ -696,6 +726,11 @@ char *get_gatewaysmultisig(char *refcoin,char *acname,char *txidaddr,int32_t *K) *K=jint(retjson,"number_of_signs"); free_json(retjson); } + else if ( retstr != 0 ) + { + printf("error parsing gatewaysmultisig.(%s)\n",retstr); + free(retstr); + } return(hex); } @@ -714,11 +749,27 @@ bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex) return (zeroid); } -void gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid,char *coin,bits256 cointxid) +void gatewayscompletesigning(char *refcoin,char *acname,bits256 withtxid,char *coin,char *hex) { char str[65],str2[65],*retstr; cJSON *retjson; printf("spend %s %s/v2 as marker\n",acname,bits256_str(str,withtxid)); - if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewaysmarkdone",bits256_str(str,withtxid),coin,bits256_str(str2,cointxid),"")) != 0 ) + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewayscompletesigning",bits256_str(str,withtxid),coin,hex,"")) != 0 ) + { + komodobroadcast(refcoin,acname,retjson); + free_json(retjson); + } + else if ( retstr != 0 ) + { + printf("error parsing gatewayscompletesigning.(%s)\n",retstr); + free(retstr); + } +} + +void gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid,char *coin) +{ + char str[65],str2[65],*retstr; cJSON *retjson; + printf("spend %s %s/v2 as marker\n",acname,bits256_str(str,withtxid)); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewaysmarkdone",bits256_str(str,withtxid),coin,"","")) != 0 ) { komodobroadcast(refcoin,acname,retjson); free_json(retjson); @@ -771,6 +822,22 @@ int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *M else return(0); } +int32_t tx_notarizedconfirmed(char *refcoin,char *acname,bits256 txid) +{ + char *retstr,str[65]; cJSON *retjson; int32_t result; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"txnotarizedconfirmed",bits256_str(str,txid),"","","")) != 0 ) + { + if (is_cJSON_True(jobj(retjson,"result")) != 0 ) result=1; + else result=0; + free_json(retjson); + } + else if ( retstr != 0 ) + { + printf("error parsing txnotarizedconfirmed.(%s)\n",retstr); + free(retstr); + } +} + int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinaddr) { cJSON *txobj,*vouts,*vout,*vins,*vin,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numarray,retval = 0, hasvout=0; @@ -788,8 +855,7 @@ int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinadd { addr = jstri(addresses,j); if ( strcmp(addr,coinaddr) == 0 ) - { - //fprintf(stderr,"found %s in %s v%d\n",coinaddr,bits256_str(str,txid),i); + { hasvout = 1; break; } @@ -798,23 +864,44 @@ int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinadd } if (hasvout==1) break; } - } - // if (hasvout==1 && (vins=jarray(&numarray,txobj,"vin"))!=0) - // { - // for (int i=0;i 0 ) + { + num = 1; + break; + } + } + } + free_json(array); + } + } + fprintf(stderr,"Num=%d\n",num); + return(num); + +} int32_t markerfromthisnodeorunconfirmed(char *refcoin,char *acname,char *coinaddr) { cJSON *array,*item,*rawtx,*vins,*vin; bits256 txid,tmptxid; int32_t i,n,m,num=0; char *retstr; @@ -887,54 +974,42 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t //process item.0 {"txid":"10ec8f4dad6903df6b249b361b879ac77b0617caad7629b97e10f29fa7e99a9b","txidaddr":"RMbite4TGugVmkGmu76ytPHDEQZQGSUjxz","withdrawaddr":"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc","amount":"1.00000000","depositaddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj","signeraddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj"} if ( (txidaddr= jstr(item,"txidaddr")) != 0 && (withdrawaddr= jstr(item,"withdrawaddr")) != 0 && (depositaddr= jstr(item,"depositaddr")) != 0 && (signeraddr= jstr(item,"signeraddr")) != 0 ) { - if ( (satoshis= jdouble(item,"amount")*SATOSHIDEN) != 0 && markerfromthisnodeorunconfirmed("KMD",acname,txidaddr) == 0) - { - // the actual withdraw + if ( (satoshis= jdouble(item,"amount")*SATOSHIDEN) != 0 && is_cJSON_True(jobj(item,"confirmed_or_notarized")) != 0 && markerfromthisnodeorunconfirmed("KMD",acname,txidaddr) == 0) + { if ( strcmp(depositaddr,signeraddr) == 0 ) - { - txid= sendtoaddress("KMD",acname,txidaddr,10000); - if (bits256_nonz(txid) != 0) + { + rawtx = createrawtx(refcoin,"",depositaddr,withdrawaddr,txidaddr,satoshis); + if ( rawtx != 0 ) { - cointxid = sendtoaddress(refcoin,"",withdrawaddr,satoshis); - if ( bits256_nonz(cointxid) != 0) - { - fprintf(stderr,"withdraw %s %s %s %.8f processed\n",refcoin,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN); - gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid); - processed++; + if ( (clijson= addsignature(refcoin,"",rawtx)) != 0 && is_cJSON_True(jobj(clijson,"complete")) != 0) + { + gatewayscompletesigning("KMD",acname,origtxid,refcoin,jstr(clijson,"hex")); + fprintf(stderr,"withdraw %.8f %s to %s processed\n",(double)satoshis/SATOSHIDEN,refcoin,withdrawaddr); + free_json(clijson); } - else - { - fprintf(stderr,"ERROR withdraw %s %s %s %.8f processed\n",refcoin,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN); - } - } - else - { - fprintf(stderr,"ERROR sending withdraw marker %s %s to %s %.8f processed\n",refcoin,bits256_str(str,cointxid),txidaddr,(double)10000/SATOSHIDEN); - } + processed++; + free(rawtx); + } else fprintf(stderr,"couldnt create rawtx\n"); } else { if ( (rawtx= get_gatewaysmultisig(refcoin,acname,txidaddr,&K)) == 0) { - rawtx = createmultisig(refcoin,"",depositaddr,signeraddr,withdrawaddr,satoshis); + rawtx = createrawtx(refcoin,"",depositaddr,withdrawaddr,txidaddr,satoshis); } if ( rawtx != 0 ) { - if ( (clijson= addmultisignature(refcoin,"",signeraddr,rawtx)) != 0 ) + if ( (clijson= addsignature(refcoin,"",rawtx)) != 0 ) { if ( is_cJSON_True(jobj(clijson,"complete")) != 0 ) - { - cointxid = komodobroadcast(refcoin,"",clijson); - if ( bits256_nonz(cointxid) != 0 ) - { - fprintf(stderr,"withdraw %s M.%d N.%d %s %s %.8f processed\n",refcoin,M,N,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN); - gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid); - } + { + gatewayscompletesigning("KMD",acname,origtxid,refcoin,jstr(clijson,"hex")); + fprintf(stderr,"withdraw %.8f %s M.%d N.%d to %s processed\n",(double)satoshis/SATOSHIDEN,refcoin,M,N,withdrawaddr); } else if ( jint(clijson,"partialtx") != 0 ) { txid=gatewayspartialsign(refcoin,acname,origtxid,jstr(clijson,"hex")); - fprintf(stderr,"%d of %d partialtx %s sent\n",K+1,N,bits256_str(str,txid)); + fprintf(stderr,"%d sign(s) %dof%d partialtx %s sent\n",K+1,M,N,bits256_str(str,txid)); } free_json(clijson); } @@ -949,6 +1024,33 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t } free_json(retjson); } + if ( (retjson= get_gatewaysprocessed("KMD",acname,bindtxidstr)) != 0 ) + { + if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 ) + { + if ( (pending=jarray(&n,retjson,"processed")) != 0 ) + { + for (i=0; i publishers,std::vectortxids,int32_t height,uint256 cointxid,std::string deposithex,std::vectorproof,CPubKey destpub,int64_t amount) -{ - CScript opret; uint8_t evalcode = EVAL_GATEWAYS; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << bindtxid << publishers << txids << height << cointxid << deposithex << proof << destpub << amount); - return(opret); -} - -uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey,std::string &coin,uint256 &bindtxid,std::vector&publishers,std::vector&txids,int32_t &height,uint256 &cointxid,std::string &deposithex,std::vector &proof,CPubKey &destpub,int64_t &amount) -{ - std::vector vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> coin; ss >> bindtxid; ss >> publishers; ss >> txids; ss >> height; ss >> cointxid; ss >> deposithex; ss >> proof; ss >> destpub; ss >> amount) != 0 ) - { - return(f); - } - return(0); -} - -uint8_t DecodeGatewaysPartialOpRet(const CScript &scriptPubKey,int32_t &K, CPubKey &signerpk, std::string &coin,std::string &hex) -{ - std::vector vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> K; ss >> signerpk; ss >> coin; ss >> hex) != 0 ) - { - return(f); - } - return(0); -} - -uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256 &assetid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount) -{ - std::vector vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 ) - { - return(f); - } - return(0); -} -uint8_t DecodeGatewaysMarkdoneOpRet(const CScript &scriptPubKey, std::string &refcoin, uint256 &cointxid) -{ - std::vector vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> refcoin; ss >> cointxid) != 0 ) - { - return(f); - } - return(0); -} - uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &tokenid,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &pubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2) { std::vector vopret; uint8_t *script,e,f; @@ -239,6 +185,133 @@ uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,st return(0); } +CScript EncodeGatewaysDepositOpRet(uint8_t funcid,std::string coin,uint256 bindtxid,std::vector publishers,std::vectortxids,int32_t height,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vectorproof,CPubKey destpub,int64_t amount) +{ + CScript opret; uint8_t evalcode = EVAL_GATEWAYS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << bindtxid << publishers << txids << height << cointxid << claimvout << deposithex << proof << destpub << amount); + return(opret); +} + +uint8_t DecodeGatewaysDepositOpRet(const CScript &scriptPubKey,std::string &coin,uint256 &bindtxid,std::vector&publishers,std::vector&txids,int32_t &height,uint256 &cointxid, int32_t &claimvout,std::string &deposithex,std::vector &proof,CPubKey &destpub,int64_t &amount) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> coin; ss >> bindtxid; ss >> publishers; ss >> txids; ss >> height; ss >> cointxid; ss >> claimvout; ss >> deposithex; ss >> proof; ss >> destpub; ss >> amount) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeGatewaysClaimOpRet(uint8_t funcid,uint256 assetid,std::string refcoin,uint256 bindtxid,uint256 deposittxid,CPubKey destpub,int64_t amount) +{ + CScript opret; uint8_t evalcode = EVAL_ASSETS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << bindtxid << deposittxid << destpub << amount); + return(opret); +} + +uint8_t DecodeGatewaysClaimOpRet(const CScript &scriptPubKey,uint256 &assetid,std::string &refcoin,uint256 &bindtxid,uint256 &deposittxid,CPubKey &destpub,int64_t &amount) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> bindtxid; ss >> deposittxid; ss >> destpub; ss >> amount) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeGatewaysWithdrawOpRet(uint8_t funcid,uint256 assetid, std::string refcoin, CPubKey withdrawpub, int64_t amount) +{ + CScript opret; uint8_t evalcode = EVAL_GATEWAYS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << withdrawpub << amount); + return(opret); +} + +uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256 &assetid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeGatewaysPartialOpRet(uint8_t funcid,int32_t K, CPubKey signerpk, std::string refcoin,std::string hex) +{ + CScript opret; uint8_t evalcode = EVAL_GATEWAYS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << K << signerpk << refcoin << hex); + return(opret); +} + +uint8_t DecodeGatewaysPartialOpRet(const CScript &scriptPubKey,int32_t &K, CPubKey &signerpk, std::string &refcoin,std::string &hex) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> K; ss >> signerpk; ss >> refcoin; ss >> hex) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeGatewaysCompleteSigningOpRet(uint8_t funcid,std::string refcoin,uint256 withdrawtxid,std::string hex) +{ + CScript opret; uint8_t evalcode = EVAL_GATEWAYS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << refcoin << withdrawtxid << hex); + return(opret); +} + +uint8_t DecodeGatewaysCompleteSigningOpRet(const CScript &scriptPubKey, std::string &refcoin, uint256 &withdrawtxid,std::string &hex) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> refcoin; ss >> withdrawtxid; ss >> hex) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeGatewaysMarkDoneOpRet(uint8_t funcid,std::string refcoin,uint256 withdrawtxid) +{ + CScript opret; uint8_t evalcode = EVAL_GATEWAYS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << refcoin << withdrawtxid); + return(opret); +} + +uint8_t DecodeGatewaysMarkDoneOpRet(const CScript &scriptPubKey, std::string &refcoin, uint256 &withdrawtxid) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> refcoin; ss >> withdrawtxid;) != 0 ) + { + return(f); + } + return(0); +} + +uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && (script[0] == EVAL_GATEWAYS || script[0] == EVAL_ASSETS) && E_UNMARSHAL(vopret,ss >> e; ss >> f) != 0 ) + { + if (f == 'B' && f == 'D' && f == 't' && f == 'W' && f == 'P' && f == 'M') + return(f); + } + return(0); +} + int64_t IsGatewaysvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) { char destaddr[64]; @@ -288,10 +361,160 @@ bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti else return(true); } +static int32_t myIs_coinaddr_inmempoolvout(char *coinaddr) +{ + int32_t i,n; char destaddr[64]; + BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + { + const CTransaction &tx = e.GetTx(); + if ( (n= tx.vout.size()) > 0 ) + { + const uint256 &txid = tx.GetHash(); + for (i=0; idata; + txid = zeroid; + char str[65]; + //fprintf(stderr,"start reverse scan %s\n",uint256_str(str,batontxid)); + while ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 ) + { + //fprintf(stderr,"check %s\n",uint256_str(str,batontxid)); + if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,bhash,pk,data) == 'D' && oracletxid == reforacletxid ) + { + //fprintf(stderr,"decoded %s\n",uint256_str(str,batontxid)); + if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height ) + { + len = oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size()); + len2 = oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size()); + char str2[65]; fprintf(stderr,"found merkleht.%d len.%d len2.%d %s %s\n",(int32_t)merkleht,len,len2,uint256_str(str,hash),uint256_str(str2,mhash)); + if ( len == sizeof(hash)+sizeof(int32_t) && len2 == 2*sizeof(mhash)+sizeof(int32_t) && mhash != zeroid ) + { + txid = batontxid; + //fprintf(stderr,"set txid\n"); + return(mhash); + } + else + { + //fprintf(stderr,"missing hash\n"); + return(zeroid); + } + } //else fprintf(stderr,"height.%d vs search ht.%d\n",(int32_t)merkleht,(int32_t)height); + batontxid = bhash; + //fprintf(stderr,"new hash %s\n",uint256_str(str,batontxid)); + } else break; + } + fprintf(stderr,"end of loop\n"); + return(zeroid); +} + +int32_t GatewaysCointxidExists(struct CCcontract_info *cp,uint256 cointxid) // dont forget to check mempool! +{ + char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock; + std::vector > addressIndex; + CCtxidaddr(txidaddr,cointxid); + SetCCtxids(addressIndex,txidaddr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) + { + return(-1); + } + return(myIs_coinaddr_inmempoolvout(txidaddr)); +} + +/* Get the block merkle root for a proof + * IN: proofData + * OUT: merkle root + * OUT: transaction IDS + */ +uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids) +{ + CMerkleBlock merkleBlock; + if (!E_UNMARSHAL(proofData, ss >> merkleBlock)) + return uint256(); + return merkleBlock.txn.ExtractMatches(txids); +} + +int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 cointxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub) +{ + std::vector txids; uint256 proofroot,hashBlock,txid = zeroid; CTransaction tx; std::string name,description,format; char destaddr[64],destpubaddr[64],claimaddr[64],str[65],str2[65]; int32_t i,numvouts; int64_t nValue = 0; + if ( myGetTransaction(oracletxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + fprintf(stderr,"GatewaysVerify cant find oracletxid %s\n",uint256_str(str,oracletxid)); + return(0); + } + if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' || name != refcoin ) + { + fprintf(stderr,"GatewaysVerify mismatched oracle name %s != %s\n",name.c_str(),refcoin.c_str()); + return(0); + } + proofroot = BitcoinGetProofMerkleRoot(proof,txids); + if ( proofroot != merkleroot ) + { + fprintf(stderr,"GatewaysVerify mismatched merkleroot %s != %s\n",uint256_str(str,proofroot),uint256_str(str2,merkleroot)); + return(0); + } + if ( DecodeHexTx(tx,deposithex) != 0 ) + { + Getscriptaddress(claimaddr,tx.vout[claimvout].scriptPubKey); + Getscriptaddress(destpubaddr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG); + if ( strcmp(claimaddr,destpubaddr) == 0 ) + { + for (i=0; i publishers; std::vectortxids; uint256 bindtxid,cointxid; std::vector proof; CPubKey claimpubkey; + if ( (numvouts= tx.vout.size()) > 0 ) + { + if ( DecodeGatewaysDepositOpRet(tx.vout[numvouts-1].scriptPubKey,coin,bindtxid,publishers,txids,height,cointxid,claimvout,deposithex,proof,claimpubkey,amount) == 'D' && claimpubkey == mypk ) + { + // coin, bindtxid, publishers + fprintf(stderr,"need to validate deposittxid more\n"); + return(amount); + } + } + return(0); +} + bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - std::vector > txids; + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks,height,claimvout; bool retval; uint8_t funcid,hash[32],M,N,taddr,prefix,prefix2; + char str[65],destaddr[64],depositaddr[65],validationError[512]; + std::vector txids; std::vector pubkeys,publishers,tmppublishers; std::vector proof; int64_t totalsupply,amount,tmpamount; + uint256 hashblock,txid,bindtxid,deposittxid,assetid,oracletxid,tokenid,cointxid,tmptxid,tmpxtxid2,merkleroot,mhash; CTransaction bindtx,deposittx,oracletx; + std::string refcoin,tmprefcoin,deposithex; CPubKey destpub,tmpdestpub; + fprintf(stderr,"return true without gateways validation\n"); return(true); numvins = tx.vin.size(); @@ -301,29 +524,151 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("no vouts"); else { - for (i=0; iInvalid("illegal normal vini"); - } - } + // for (i=0; iInvalid("illegal normal vini"); + // } + // } //fprintf(stderr,"check amounts\n"); - if ( GatewaysExactAmounts(cp,eval,tx,1,10000) == false ) - { - fprintf(stderr,"Gatewaysget invalid amount\n"); - return false; - } - else - { + // if ( GatewaysExactAmounts(cp,eval,tx,1,10000) == false ) + // { + // fprintf(stderr,"Gatewaysget invalid amount\n"); + // return false; + // } + // else + // { txid = tx.GetHash(); memcpy(hash,&txid,sizeof(hash)); + + if ( (funcid = DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey)) != 0) + { + switch ( funcid ) + { + case 'B': + //vin.0: normal input + //vout.0: CC vout txfee marker + //vout.n-1: opreturn - 'B' coin tokenid totalsupply oracletxid M N pubkeys taddr prefix prefix2 + return eval->Invalid("unexpected GatewaysValidate for gatewaysbind!"); + break; + case 'D': + //vin.0: normal input + //vout.0: CC vout txfee marker to destination pubkey + //vout.1: normal output txfee marker to txidaddr + //vout.n-1: opreturn - 'D' coin bindtxid publishers txids height cointxid deposithex proof destpub amount + return eval->Invalid("unexpected GatewaysValidate for gatewaysdeposit!"); + break; + case 't': + //vin.0: normal input + //vin.1: CC input of converted token to gateways eval code + //vin.2: CC input of marker from gatewaysdeposit tx + //vout.0: CC vout of total tokens from deposit amount to asset eval code + //(vout.1): CC vout if there is change of unused tokens back to owner of tokens (deposit amount less than available tokens) + //vout.n-1: opreturn - 't' assetid zeroid 0 mypubkey (NOTE: opreturn is with asset eval code) + if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysClaimOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,refcoin,bindtxid,deposittxid,destpub,amount)==0) + return eval->Invalid("invalid gatewaysclaim OP_RETURN data!"); + else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for gatewaysClaim!"); + else if ( IsCCInput(tx.vin[1].scriptSig) == 0 ) + return eval->Invalid("vin.1 is CC for gatewaysClaim!"); + else if ( IsCCInput(tx.vin[2].scriptSig) == 0 ) + return eval->Invalid("vin.2 is CC for gatewaysClaim!"); + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.0 is CC for gatewaysClaim!"); + else if ( numvouts > 2 && tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.1 is CC for gatewaysClaim!"); + else if (myGetTransaction(bindtxid,bindtx,hashblock) == 0) + return eval->Invalid("invalid gatewaysbind txid!"); + else if ((numvouts=bindtx.vout.size()) > 0 && DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 'B') + return eval->Invalid("invalid gatewaysbind OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different in bind tx"); + else if (tokenid!=assetid) + return eval->Invalid("assetid does not match tokenid from gatewaysbind"); + else if (komodo_txnotarizedconfirmed(bindtxid) == false) + return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); + else if (myGetTransaction(deposittxid,deposittx,hashblock) == 0) + return eval->Invalid("invalid gatewaysdeposittxid!"); + else if ((numvouts=deposittx.vout.size()) > 0 && DecodeGatewaysDepositOpRet(deposittx.vout[numvouts-1].scriptPubKey,tmprefcoin,tmptxid,tmppublishers,txids,height,cointxid,claimvout,deposithex,proof,tmpdestpub,tmpamount) != 'D') + return eval->Invalid("invalid gatewaysdeposit OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different in deposit tx"); + else if (bindtxid!=tmptxid) + return eval->Invalid("bindtxid does not match to bindtxid from gatewaysdeposit"); + else if (tmpamount>totalsupply) + return eval->Invalid("deposit amount greater then bind total supply"); + else if (komodo_txnotarizedconfirmed(deposittxid) == false) + return eval->Invalid("gatewaysdeposit tx is not yet confirmed(notarised)!"); + else if (amount>tmpamount) + return eval->Invalid("claimed amount greater then deposit amount"); + else if (destpub!=tmpdestpub) + return eval->Invalid("destination pubkey different than in deposit tx"); + else + { + int32_t m; + merkleroot = zeroid; + for (i=m=0; iInvalid(validationError); + } + if ( GatewaysCointxidExists(cp,cointxid) != 0 ) + { + sprintf(validationError,"cointxid.%s already exists\n",uint256_str(str,cointxid)); + return eval->Invalid(validationError); + } + if (GatewaysVerify(depositaddr,oracletxid,claimvout,tmprefcoin,cointxid,deposithex,proof,merkleroot,destpub)!=amount) + return eval->Invalid("deposittxid didnt validate\n"); + } + break; + case 'W': + //vin.0: normal input + //vin.1: CC input of converted token back to gateways eval code + //vout.0: CC vout of tokens back to gateways CC address + //vout.1: normal vout txfee marker to withdraw destination pubkey + //vout.2: CC vout txfee marker to gateways CC address + //vout.n-2: CC vout if there is change of unused tokens back to owner of tokens (withdraw amount less than owner available tokens) + //vout.n-1: opreturn - 'W' assetid refcoin withdrawpub amount + break; + case 'P': + //vin.0: normal input + //(vin.1): CC input form previous marker of gatewayspartialsign tx (if exists) + //vout.0: CC vout 5k sat marker to senders pubKey + //vout.n-1: opreturn - 'P' number_of_signs mypk refcoin hex + break; + case 'C': + //vin.0: CC input from gatewayswithdraw tx marker to gateways CC address + //vout.0: CC vout txfee marker to gateways CC address + //vout.n-1: opreturn - 'C' refcoin cointxid external_tx_hex + break; + case 'M': + //vin.0: CC input from gatewayscompletesigning tx marker to gateways CC address + //vout.0: opreturn - 'M' refcoin cointxid + break; + } + } + + retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); if ( retval != 0 ) fprintf(stderr,"Gatewaysget validated\n"); else fprintf(stderr,"Gatewaysget invalid\n"); return(retval); - } + // } } } // end of consensus code @@ -337,7 +682,7 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); threshold = total/(maxinputs+1); - fprintf(stderr,"check %s for gateway inputs\n",coinaddr); + //fprintf(stderr,"check %s for gateway inputs\n",coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; @@ -352,7 +697,7 @@ 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,"check %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); @@ -401,101 +746,6 @@ int32_t GatewaysBindExists(struct CCcontract_info *cp,CPubKey gatewayspk,uint256 return(0); } -static int32_t myIs_coinaddr_inmempoolvout(char *coinaddr) -{ - int32_t i,n; char destaddr[64]; - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - if ( (n= tx.vout.size()) > 0 ) - { - const uint256 &txid = tx.GetHash(); - for (i=0; i > addressIndex; - CCtxidaddr(txidaddr,cointxid); - SetCCtxids(addressIndex,txidaddr); - for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) - { - return(-1); - } - return(myIs_coinaddr_inmempoolvout(txidaddr)); -} - -UniValue GatewaysInfo(uint256 bindtxid) -{ - UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::string coin; char str[67],numstr[65],depositaddr[64],gatewaysassets[64]; uint8_t M,N; std::vector pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid,hashBlock; CTransaction tx; CMutableTransaction mtx; CPubKey Gatewayspk; struct CCcontract_info *cp,C; int32_t i; int64_t totalsupply,remaining; - result.push_back(Pair("result","success")); - result.push_back(Pair("name","Gateways")); - cp = CCinit(&C,EVAL_GATEWAYS); - Gatewayspk = GetUnspendable(cp,0); - _GetCCaddress(gatewaysassets,EVAL_GATEWAYS,Gatewayspk); - if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 ) - { - depositaddr[0] = 0; - if ( tx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,tx.vout[tx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 && M <= N && N > 0 ) - { - if ( N > 1 ) - { - result.push_back(Pair("M",M)); - result.push_back(Pair("N",N)); - for (i=0; i > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid,tokenid; CTransaction vintx; std::string coin; int64_t totalsupply; char str[65],depositaddr[64]; uint8_t M,N,taddr,prefix,prefix2; std::vector pubkeys; - cp = CCinit(&C,EVAL_GATEWAYS); - SetCCtxids(addressIndex,cp->unspendableCCaddr); - for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) - { - txid = it->first.txhash; - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) - { - if ( vintx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,vintx.vout[vintx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 ) - { - result.push_back(uint256_str(str,txid)); - } - } - } - return(result); -} - std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector pubkeys) { CMutableTransaction mtx; CTransaction oracletx; uint8_t taddr,prefix,prefix2; CPubKey mypk,gatewayspk; CScript opret; uint256 hashBlock; struct CCcontract_info *cp,C; std::string name,description,format; int32_t i,numvouts; int64_t fullsupply; char destaddr[64],coinaddr[64],str[65],*fstr; @@ -571,7 +821,7 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t fprintf(stderr,"Gateway bind.%s (%s) already exists\n",coin.c_str(),uint256_str(str,tokenid)); return(""); } - if ( AddNormalinputs(mtx,mypk,2*txfee,60) > 0 ) + if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,gatewayspk)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysBindOpRet('B',coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2))); @@ -581,119 +831,12 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t return(""); } -uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid) -{ - CTransaction tx; uint256 hash,mhash,bhash,hashBlock,oracletxid; int32_t len,len2,numvouts; int64_t val,merkleht; CPubKey pk; std::vectordata; - txid = zeroid; - char str[65]; - //fprintf(stderr,"start reverse scan %s\n",uint256_str(str,batontxid)); - while ( GetTransaction(batontxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) - { - //fprintf(stderr,"check %s\n",uint256_str(str,batontxid)); - if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,bhash,pk,data) == 'D' && oracletxid == reforacletxid ) - { - //fprintf(stderr,"decoded %s\n",uint256_str(str,batontxid)); - if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height ) - { - len = oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size()); - len2 = oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size()); - char str2[65]; fprintf(stderr,"found merkleht.%d len.%d len2.%d %s %s\n",(int32_t)merkleht,len,len2,uint256_str(str,hash),uint256_str(str2,mhash)); - if ( len == sizeof(hash)+sizeof(int32_t) && len2 == 2*sizeof(mhash)+sizeof(int32_t) && mhash != zeroid ) - { - txid = batontxid; - //fprintf(stderr,"set txid\n"); - return(mhash); - } - else - { - //fprintf(stderr,"missing hash\n"); - return(zeroid); - } - } //else fprintf(stderr,"height.%d vs search ht.%d\n",(int32_t)merkleht,(int32_t)height); - batontxid = bhash; - //fprintf(stderr,"new hash %s\n",uint256_str(str,batontxid)); - } else break; - } - fprintf(stderr,"end of loop\n"); - return(zeroid); -} - -/* Get the block merkle root for a proof - * IN: proofData - * OUT: merkle root - * OUT: transaction IDS - */ -uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids) -{ - CMerkleBlock merkleBlock; - if (!E_UNMARSHAL(proofData, ss >> merkleBlock)) - return uint256(); - return merkleBlock.txn.ExtractMatches(txids); -} - -int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 cointxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub) -{ - std::vector txids; uint256 proofroot,hashBlock,txid = zeroid; CTransaction tx; std::string name,description,format; char destaddr[64],destpubaddr[64],claimaddr[64],str[65],str2[65]; int32_t i,numvouts; int64_t nValue = 0; - if ( GetTransaction(oracletxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) - { - fprintf(stderr,"GatewaysVerify cant find oracletxid %s\n",uint256_str(str,oracletxid)); - return(0); - } - if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' || name != refcoin ) - { - fprintf(stderr,"GatewaysVerify mismatched oracle name %s != %s\n",name.c_str(),refcoin.c_str()); - return(0); - } - proofroot = BitcoinGetProofMerkleRoot(proof,txids); - if ( proofroot != merkleroot ) - { - fprintf(stderr,"GatewaysVerify mismatched merkleroot %s != %s\n",uint256_str(str,proofroot),uint256_str(str2,merkleroot)); - return(0); - } - if ( DecodeHexTx(tx,deposithex) != 0 ) - { - Getscriptaddress(claimaddr,tx.vout[claimvout].scriptPubKey); - Getscriptaddress(destpubaddr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG); - if ( strcmp(claimaddr,destpubaddr) == 0 ) - { - for (i=0; i publishers; std::vectortxids; uint256 bindtxid,cointxid; std::vector proof; CPubKey claimpubkey; - if ( (numvouts= tx.vout.size()) > 0 ) - { - if ( DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey,coin,bindtxid,publishers,txids,height,cointxid,deposithex,proof,claimpubkey,amount) == 'D' && claimpubkey == mypk ) - { - // coin, bindtxid, publishers - fprintf(stderr,"need to validate deposittxid more\n"); - return(amount); - } - } - return(0); -} - std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vectorproof,CPubKey destpub,int64_t amount) { - CMutableTransaction mtx; CTransaction bindtx; CPubKey mypk,gatewayspk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid; int64_t totalsupply; int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2; std::string coin; struct CCcontract_info *cp,C; std::vector pubkeys,publishers; std::vectortxids; char str[67],depositaddr[64],txidaddr[64]; + CMutableTransaction mtx; CTransaction bindtx; CPubKey mypk,gatewayspk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid; + int64_t totalsupply; int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2; std::string coin; struct CCcontract_info *cp,C; + std::vector pubkeys,publishers; std::vectortxids; char str[67],depositaddr[64],txidaddr[64]; + cp = CCinit(&C,EVAL_GATEWAYS); if ( txfee == 0 ) txfee = 10000; @@ -707,7 +850,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std:: } if ( DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 'B' || refcoin != coin ) { - fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); + fprintf(stderr,"invalid coin - bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); return(""); } n = (int32_t)pubkeys.size(); @@ -744,11 +887,11 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std:: fprintf(stderr,"deposittxid didnt validate\n"); return(""); } - if ( AddNormalinputs(mtx,mypk,3*txfee,60) > 0 ) + if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 ) { 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))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysDepositOpRet('D',coin,bindtxid,publishers,txids,height,cointxid,claimvout,deposithex,proof,destpub,amount))); } fprintf(stderr,"cant find enough inputs\n"); return(""); @@ -756,7 +899,11 @@ 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],destaddr[64]; + CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk,tmpdestpub; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2; + std::string coin, deposithex; std::vector msigpubkeys,publishers; int64_t totalsupply,depositamount,tmpamount,inputs,CCchange=0; + int32_t numvouts,claimvout,height; std::vector proof; + uint256 hashBlock,assetid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector txids; + cp = CCinit(&C,EVAL_GATEWAYS); if ( txfee == 0 ) txfee = 10000; @@ -769,33 +916,43 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui } if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin ) { - fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); + fprintf(stderr,"invalid coin - bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); return(""); } - if ( GetTransaction(deposittxid,tx,hashBlock,false) == 0 ) + if ( GetTransaction(deposittxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) { fprintf(stderr,"cant find deposittxid %s\n",uint256_str(str,bindtxid)); return(""); } + if (DecodeGatewaysDepositOpRet(tx.vout[numvouts-1].scriptPubKey,coin,tmptxid,publishers,txids,height,cointxid,claimvout,deposithex,proof,tmpdestpub,tmpamount) != 'D' || coin != refcoin) + { + fprintf(stderr,"invalid coin - deposittxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); + return(""); + } + if (tmpdestpub!=destpub) + { + fprintf(stderr,"different destination pubkey from desdeposittxid\n"); + return(""); + } if ( (depositamount= GatewaysDepositval(tx,mypk)) != amount ) { fprintf(stderr,"invalid Gateways deposittxid %s %.8f != %.8f\n",uint256_str(str,deposittxid),(double)depositamount/COIN,(double)amount/COIN); return(""); } //fprintf(stderr,"depositaddr.(%s) vs %s\n",depositaddr,cp->unspendableaddr2); - if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { if ( (inputs= AddGatewaysInputs(cp,mtx,gatewayspk,assetid,amount,60)) > 0 ) { if ( inputs > amount ) CCchange = (inputs - amount); _GetCCaddress(destaddr,EVAL_GATEWAYS,mypk); - printf("expecting deposittxid/v0 to be to %s\n",destaddr); + //printf("expecting deposittxid/v0 to be to %s\n",destaddr); mtx.vin.push_back(CTxIn(deposittxid,0,CScript())); // triggers EVAL_GATEWAYS validation mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,mypk)); // transfer back to normal token if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysClaimOpRet('t',assetid,refcoin,bindtxid,deposittxid,destpub,amount))); } } CCerror = strprintf("cant find enough inputs or mismatched total"); @@ -807,7 +964,7 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin { CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; - std::vector msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; CScript opret; + std::vector msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; cp = CCinit(&C,EVAL_GATEWAYS); if ( txfee == 0 ) txfee = 10000; @@ -823,7 +980,7 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); return(""); } - if ( AddNormalinputs(mtx,mypk,3*txfee,3) > 0 ) + if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 ) { if ( (inputs= AddGatewaysInputs(cp,mtx,mypk,assetid,amount,60)) > 0 ) { @@ -833,9 +990,8 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(withdrawpub)) << OP_CHECKSIG)); mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk)); if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk)); - opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'W' << assetid << refcoin << withdrawpub << amount); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysWithdrawOpRet('W',assetid,refcoin,withdrawpub,amount))); } } CCerror = strprintf("cant find enough inputs or mismatched total"); @@ -843,26 +999,76 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin return(""); } -std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid,std::string refcoin,uint256 cointxid) +std::string GatewaysPartialSign(uint64_t txfee,uint256 txid,std::string refcoin, std::string hex) { - CMutableTransaction mtx; CScript opret; CPubKey mypk; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,txidaddrpk,signerpk; struct CCcontract_info *cp,C; CTransaction tx; + std::vector > unspentOutputs; char txidaddr[65]; + int32_t maxK,K=0; uint256 tmptxid,parttxid,hashBlock; cp = CCinit(&C,EVAL_GATEWAYS); if ( txfee == 0 ) txfee = 5000; mypk = pubkey2pk(Mypubkey()); + txidaddrpk=CCtxidaddr(txidaddr,txid); + SetCCunspents(unspentOutputs,txidaddr); + maxK=0; + if (unspentOutputs.size()==0) + { + if (AddNormalinputs(mtx,mypk,2*txfee,3)==0) fprintf(stderr,"error adding funds for partialsign\n"); + } + else + { + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + tmptxid = it->first.txhash; + if (GetTransaction(tmptxid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && DecodeGatewaysPartialOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,K,signerpk,refcoin,hex) == 'P' && K>maxK ) + { + maxK=K; + parttxid=tmptxid; + } + } + if (maxK>0) + { + if (AddNormalinputs(mtx,mypk,txfee,3)==0) fprintf(stderr,"error adding funds for partialsign\n"); + mtx.vin.push_back(CTxIn(parttxid,0,CScript())); + } + else fprintf(stderr,"Error finding previous partial tx\n"); + } + + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,5000,txidaddrpk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysPartialOpRet('P',maxK+1,mypk,refcoin,hex))); +} + +std::string GatewaysCompleteSigning(uint64_t txfee,uint256 withdrawtxid,std::string refcoin,std::string hex) +{ + CMutableTransaction mtx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; char txidaddr[65]; + cp = CCinit(&C,EVAL_GATEWAYS); + mypk = pubkey2pk(Mypubkey()); + gatewayspk = GetUnspendable(cp,0); + if ( txfee == 0 ) + txfee = 10000; mtx.vin.push_back(CTxIn(withdrawtxid,2,CScript())); - mtx.vout.push_back(CTxOut(5000,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'M' << cointxid << refcoin); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysCompleteSigningOpRet('C',refcoin,withdrawtxid,hex))); +} + +std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string refcoin) +{ + CMutableTransaction mtx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; char txidaddr[65]; + cp = CCinit(&C,EVAL_GATEWAYS); + mypk = pubkey2pk(Mypubkey()); + if ( txfee == 0 ) + txfee = 10000; + mtx.vin.push_back(CTxIn(completetxid,0,CScript())); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysMarkDoneOpRet('M',refcoin,completetxid))); } UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) { - UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string coin,tmprefcoin; CPubKey mypk,gatewayspk,withdrawpub; std::vector msigpubkeys; - uint256 cointxid,hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; - char depositaddr[64],withmarker[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],signeraddr[64]; - int32_t i,n,numvouts,vout,numqueued,queueflag; int64_t totalsupply,amount,nValue; struct CCcontract_info *cp,C; + UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string tmprefcoin; CPubKey mypk,gatewayspk,withdrawpub; std::vector msigpubkeys; + uint256 hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; + char depositaddr[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],cctxidaddr[64],signeraddr[64]; + int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,amount,nValue; struct CCcontract_info *cp,C; std::vector > unspentOutputs; cp = CCinit(&C,EVAL_GATEWAYS); @@ -874,9 +1080,9 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); return(result); } - if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin ) + if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin ) { - fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); + fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str()); return(result); } n = msigpubkeys.size(); @@ -887,15 +1093,14 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) queueflag = 1; break; } - SetCCunspents(unspentOutputs,coinaddr); - numqueued = 0; + 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; nValue = (int64_t)it->second.satoshis; fprintf(stderr,"%s %d %ld\n",txid.ToString().c_str(),vout,(long)nValue); - if ( vout == 2 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) && + if ( vout == 2 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,tmprefcoin,withdrawpub,amount) == 'W' && myIsutxo_spentinmempool(txid,vout) == 0) { Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); @@ -904,11 +1109,12 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("txid",uint256_str(str,txid))); - CCtxidaddr(txidaddr,txid); - obj.push_back(Pair("txidaddr",txidaddr)); + _GetCCaddress(cctxidaddr,EVAL_GATEWAYS,CCtxidaddr(txidaddr,txid)); + obj.push_back(Pair("txidaddr",cctxidaddr)); obj.push_back(Pair("withdrawaddr",withaddr)); sprintf(numstr,"%.8f",(double)tx.vout[0].nValue/COIN); obj.push_back(Pair("amount",numstr)); + obj.push_back(Pair("confirmed_or_notarized",komodo_txnotarizedconfirmed(txid))); if ( queueflag != 0 ) { obj.push_back(Pair("depositaddr",depositaddr)); @@ -925,12 +1131,73 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) return(result); } -UniValue GatewaysMultisig(char *txidaddr) +UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin) +{ + UniValue result(UniValue::VOBJ),processed(UniValue::VARR); CTransaction tx; std::string tmprefcoin,hex; CPubKey mypk,gatewayspk,withdrawpub; std::vector msigpubkeys; + uint256 withdrawtxid,hashBlock,txid,assetid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; + char depositaddr[64],coinaddr[64],str[65],numstr[32],txidaddr[64],cctxidaddr[64],withaddr[64]; + int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,nValue,amount; struct CCcontract_info *cp,C; + std::vector > unspentOutputs; + + cp = CCinit(&C,EVAL_GATEWAYS); + mypk = pubkey2pk(Mypubkey()); + gatewayspk = GetUnspendable(cp,0); + _GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk); + if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); + return(result); + } + if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin ) + { + fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str()); + return(result); + } + n = msigpubkeys.size(); + queueflag = 0; + for (i=0; i >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second.satoshis; + //fprintf(stderr,"%s %d %ld\n",txid.ToString().c_str(),vout,(long)nValue); + if ( vout == 0 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && + DecodeGatewaysCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,tmprefcoin,withdrawtxid,hex) == 'C' && myIsutxo_spentinmempool(txid,vout) == 0) + { + if (GetTransaction(withdrawtxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,tmprefcoin,withdrawpub,amount) == 'W') + { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("txid",uint256_str(str,txid))); + obj.push_back(Pair("withdrawtxid",uint256_str(str,withdrawtxid))); + _GetCCaddress(cctxidaddr,EVAL_GATEWAYS,CCtxidaddr(txidaddr,withdrawtxid)); + obj.push_back(Pair("withdrawtxidaddr",cctxidaddr)); + Getscriptaddress(withaddr,tx.vout[1].scriptPubKey); + obj.push_back(Pair("withdrawaddr",withaddr)); + obj.push_back(Pair("confirmed_or_notarized",komodo_txnotarizedconfirmed(txid))); + obj.push_back(Pair("hex",hex)); + processed.push_back(obj); + } + } + } + result.push_back(Pair("coin",refcoin)); + result.push_back(Pair("processed",processed)); + result.push_back(Pair("queueflag",queueflag)); + return(result); +} + +UniValue GatewaysMultisig(char *cctxidaddr) { std::string parthex,hex,refcoin; uint256 txid,hashBlock; CTransaction tx; int32_t i,maxK,K,numvouts; CPubKey signerpk; std::vector > unspentOutputs; UniValue result(UniValue::VOBJ); - - SetCCunspents(unspentOutputs,txidaddr); + + SetCCunspents(unspentOutputs,cctxidaddr); maxK=0; for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { @@ -959,38 +1226,61 @@ UniValue GatewaysMultisig(char *txidaddr) return (result); } -std::string GatewaysPartialSign(uint64_t txfee,uint256 txid,std::string refcoin, std::string hex) +UniValue GatewaysList() { - CMutableTransaction mtx; CScript opret; CPubKey mypk,txidaddrpk,signerpk; struct CCcontract_info *cp,C; CTransaction tx; - std::vector > unspentOutputs; char txidaddr[65]; - int32_t maxK,K=0; uint256 tmptxid,parttxid,hashBlock; + UniValue result(UniValue::VARR); std::vector > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid,tokenid; CTransaction vintx; std::string coin; int64_t totalsupply; char str[65],depositaddr[64]; uint8_t M,N,taddr,prefix,prefix2; std::vector pubkeys; cp = CCinit(&C,EVAL_GATEWAYS); - if ( txfee == 0 ) - txfee = 5000; - mypk = pubkey2pk(Mypubkey()); - txidaddrpk=CCtxidaddr(txidaddr,txid); - SetCCunspents(unspentOutputs,txidaddr); - maxK=0; - if (unspentOutputs.size()==0) + SetCCtxids(addressIndex,cp->unspendableCCaddr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { - if (AddNormalinputs(mtx,mypk,2*txfee,2)==0) fprintf(stderr,"error adding funds for partialsign\n"); - } - else - { - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + txid = it->first.txhash; + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { - tmptxid = it->first.txhash; - if (GetTransaction(tmptxid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && DecodeGatewaysPartialOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,K,signerpk,refcoin,hex) == 'P' && K>maxK ) + if ( vintx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,vintx.vout[vintx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 ) { - maxK=K; - parttxid=tmptxid; + result.push_back(uint256_str(str,txid)); } } - if (maxK>0) mtx.vin.push_back(CTxIn(parttxid,0,CScript())); - else fprintf(stderr,"Error finding previous partial tx\n"); } - - mtx.vout.push_back(CTxOut(5000,CScript() << ParseHex(HexStr(txidaddrpk)) << OP_CHECKSIG)); - opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'P' << maxK+1 << mypk << refcoin << hex); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); + return(result); +} + +UniValue GatewaysInfo(uint256 bindtxid) +{ + UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::string coin; char str[67],numstr[65],depositaddr[64],gatewaysassets[64]; uint8_t M,N; std::vector pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid,hashBlock; CTransaction tx; CMutableTransaction mtx; CPubKey Gatewayspk; struct CCcontract_info *cp,C; int32_t i; int64_t totalsupply,remaining; + result.push_back(Pair("result","success")); + result.push_back(Pair("name","Gateways")); + cp = CCinit(&C,EVAL_GATEWAYS); + Gatewayspk = GetUnspendable(cp,0); + _GetCCaddress(gatewaysassets,EVAL_GATEWAYS,Gatewayspk); + if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 ) + { + depositaddr[0] = 0; + if ( tx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,tx.vout[tx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 && M <= N && N > 0 ) + { + if ( N > 1 ) + { + result.push_back(Pair("M",M)); + result.push_back(Pair("N",N)); + for (i=0; i 0 ) + if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(Oraclespk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesCreateOpRet('C',name,description,format))); @@ -778,7 +778,7 @@ std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,i txfee = 10000; mypk = pubkey2pk(Mypubkey()); markerpubkey = CCtxidaddr(markeraddr,oracletxid); - if ( AddNormalinputs(mtx,mypk,amount + 2*txfee,1) > 0 ) + if ( AddNormalinputs(mtx,mypk,amount + 2*txfee,64) > 0 ) { mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,publisher)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index be2d422d6..2ec19902e 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -229,7 +229,7 @@ std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletx return(""); } fprintf(stderr,"error check bettoken\n"); - if ( AddNormalinputs(mtx,mypk,3*txfee,3) > 0 ) + if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 ) { mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(pricespk)) << OP_CHECKSIG)); diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 3d8f50718..8595adc76 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -48,8 +48,11 @@ #define KOMODO_KVDURATION 1440 #define KOMODO_ASSETCHAIN_MAXLEN 65 -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; +#ifndef _BITS256 +#define _BITS256 + 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; +#endif union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; typedef union _bits320 bits320; diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 04be0ff74..26c273236 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -47,6 +47,7 @@ int32_t Jumblr_secretaddradd(char *secretaddr); uint64_t komodo_interestsum(); int32_t komodo_longestchain(); int32_t komodo_notarized_height(int32_t *prevhtp,uint256 *hashp,uint256 *txidp); +bool komodo_txnotarizedconfirmed(uint256 txid); uint32_t komodo_chainactive_timestamp(); int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; @@ -1295,6 +1296,32 @@ UniValue getspentinfo(const UniValue& params, bool fHelp) return obj; } +UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp) +{ + bool notarizedconfirmed; uint256 txid; + + if (fHelp || params.size() < 1 || params.size() > 1) + { + string msg = "txnotarizedconfirmed txid\n" + "\nReturns true if transaction is notarized on chain that has dPoW or if confirmation number is greater than 60 on chain taht does not have dPoW.\n" + + "\nArguments:\n" + "1. txid (string, required) Transaction id.\n" + + "\nResult:\n" + "{\n" + " true, (bool) The value the check.\n" + "}\n" + ; + throw runtime_error(msg); + } + txid = uint256S((char *)params[0].get_str().c_str()); + notarizedconfirmed=komodo_txnotarizedconfirmed(txid); + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result", notarizedconfirmed)); + return result; +} + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 70a124b8c..f95446a4c 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -437,10 +437,12 @@ static const CRPCCommand vRPCCommands[] = { "gateways", "gatewaysdeposit", &gatewaysdeposit, true }, { "gateways", "gatewaysclaim", &gatewaysclaim, true }, { "gateways", "gatewayswithdraw", &gatewayswithdraw, true }, - { "gateways", "gatewayspending", &gatewayspending, true }, - { "gateways", "gatewaysmultisig", &gatewaysmultisig, true }, - { "gateways", "gatewaysmarkdone", &gatewaysmarkdone, true }, { "gateways", "gatewayspartialsign", &gatewayspartialsign, true }, + { "gateways", "gatewayscompletesigning", &gatewayscompletesigning, true }, + { "gateways", "gatewaysmarkdone", &gatewaysmarkdone, true }, + { "gateways", "gatewayspending", &gatewayspending, true }, + { "gateways", "gatewaysprocessed", &gatewaysprocessed, true }, + { "gateways", "gatewaysmultisig", &gatewaysmultisig, true }, // dice { "dice", "dicelist", &dicelist, true }, @@ -481,6 +483,7 @@ static const CRPCCommand vRPCCommands[] = { "util", "createmultisig", &createmultisig, true }, { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ { "util", "verifymessage", &verifymessage, true }, + { "util", "txnotarizedconfirmed", &txnotarizedconfirmed, true }, { "util", "estimatefee", &estimatefee, true }, { "util", "estimatepriority", &estimatepriority, true }, { "util", "z_validateaddress", &z_validateaddress, true }, /* uses wallet if enabled */ diff --git a/src/rpc/server.h b/src/rpc/server.h index 65a36706e..6638024b8 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -265,10 +265,12 @@ extern UniValue gatewaysbind(const UniValue& params, bool fHelp); extern UniValue gatewaysdeposit(const UniValue& params, bool fHelp); extern UniValue gatewaysclaim(const UniValue& params, bool fHelp); extern UniValue gatewayswithdraw(const UniValue& params, bool fHelp); -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 gatewayspartialsign(const UniValue& params, bool fHelp); +extern UniValue gatewayscompletesigning(const UniValue& params, bool fHelp); +extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp); +extern UniValue gatewayspending(const UniValue& params, bool fHelp); +extern UniValue gatewaysprocessed(const UniValue& params, bool fHelp); +extern UniValue gatewaysmultisig(const UniValue& params, bool fHelp); extern UniValue channelsinfo(const UniValue& params, bool fHelp); extern UniValue channelsopen(const UniValue& params, bool fHelp); extern UniValue channelspayment(const UniValue& params, bool fHelp); @@ -337,6 +339,7 @@ extern UniValue walletpassphrasechange(const UniValue& params, bool fHelp); extern UniValue walletlock(const UniValue& params, bool fHelp); extern UniValue encryptwallet(const UniValue& params, bool fHelp); extern UniValue validateaddress(const UniValue& params, bool fHelp); +extern UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp); extern UniValue getinfo(const UniValue& params, bool fHelp); extern UniValue setpubkey(const UniValue& params, bool fHelp); extern UniValue getwalletinfo(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 31d355345..f3b344ecd 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5981,6 +5981,8 @@ UniValue gatewaysbind(const UniValue& params, bool fHelp) if ( params.size() < 6+i+1 ) throw runtime_error("not enough parameters for N pubkeys\n"); pubkey = ParseHex(params[6+i].get_str().c_str()); + if (pubkey.size()!= 33) + throw runtime_error("invalid destination pubkey"); pubkeys.push_back(pubkey2pk(pubkey)); } hex = GatewaysBind(0,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys); @@ -6013,6 +6015,8 @@ UniValue gatewaysdeposit(const UniValue& params, bool fHelp) amount = atof((char *)params[8].get_str().c_str()) * COIN + 0.00000000499999; if ( amount <= 0 || claimvout < 0 ) throw runtime_error("invalid param: amount, numpks or claimvout\n"); + if (destpub.size()!= 33) + throw runtime_error("invalid destination pubkey"); hex = GatewaysDeposit(0,bindtxid,height,coin,cointxid,claimvout,deposithex,proof,pubkey2pk(destpub),amount); RETURN_IF_ERROR(CCerror); @@ -6037,7 +6041,9 @@ UniValue gatewaysclaim(const UniValue& params, bool fHelp) coin = params[1].get_str(); deposittxid = Parseuint256((char *)params[2].get_str().c_str()); destpub = ParseHex(params[3].get_str()); - amount = atof((char *)params[4].get_str().c_str()) * COIN + 0.00000000499999; + amount = atof((char *)params[4].get_str().c_str()) * COIN + 0.00000000499999; + if (destpub.size()!= 33) + throw runtime_error("invalid destination pubkey"); hex = GatewaysClaim(0,bindtxid,coin,deposittxid,pubkey2pk(destpub),amount); RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) @@ -6060,7 +6066,9 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp) bindtxid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); withdrawpub = ParseHex(params[2].get_str()); - amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999; + amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999; + if (withdrawpub.size()!= 33) + throw runtime_error("invalid destination pubkey"); hex = GatewaysWithdraw(0,bindtxid,coin,pubkey2pk(withdrawpub),amount); RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) @@ -6071,19 +6079,61 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp) return(result); } -UniValue gatewaysmarkdone(const UniValue& params, bool fHelp) +UniValue gatewayspartialsign(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); uint256 withdrawtxid,cointxid; std::string hex,coin; + UniValue result(UniValue::VOBJ); std::string coin,parthex,hex; uint256 txid; if ( fHelp || params.size() != 3 ) - throw runtime_error("gatewaysmarkdone withdrawtxid coin cointxid\n"); + throw runtime_error("gatewayspartialsign txidaddr refcoin hex\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); + txid = Parseuint256((char *)params[0].get_str().c_str()); + coin = params[1].get_str(); + parthex = params[2].get_str(); + hex = GatewaysPartialSign(0,txid,coin,parthex); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex",hex)); + } else ERR_RESULT("couldnt gatewayspartialsign"); + return(result); +} + +UniValue gatewayscompletesigning(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 withdrawtxid; std::string txhex,hex,coin; + if ( fHelp || params.size() != 3 ) + throw runtime_error("gatewayscompletesigning withdrawtxid coin hex\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); withdrawtxid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); - cointxid = Parseuint256((char *)params[2].get_str().c_str()); - hex = GatewaysMarkdone(0,withdrawtxid,coin,cointxid); + txhex = params[2].get_str(); + hex = GatewaysCompleteSigning(0,withdrawtxid,coin,txhex); + RETURN_IF_ERROR(CCerror); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt gatewayscompletesigning"); + return(result); +} + +UniValue gatewaysmarkdone(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 completetxid; std::string hex,coin; + if ( fHelp || params.size() != 2 ) + throw runtime_error("gatewaysmarkdone completesigningtx coin\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); + completetxid = Parseuint256((char *)params[0].get_str().c_str()); + coin = params[1].get_str(); + hex = GatewaysMarkDone(0,completetxid,coin); RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) { @@ -6105,6 +6155,18 @@ UniValue gatewayspending(const UniValue& params, bool fHelp) return(GatewaysPendingWithdraws(bindtxid,coin)); } +UniValue gatewaysprocessed(const UniValue& params, bool fHelp) +{ + uint256 bindtxid; std::string coin; + if ( fHelp || params.size() != 2 ) + throw runtime_error("gatewaysprocessed bindtxid coin\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"); + bindtxid = Parseuint256((char *)params[0].get_str().c_str()); + coin = params[1].get_str(); + return(GatewaysProcessedWithdraws(bindtxid,coin)); +} + UniValue gatewaysmultisig(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); std::string hex; char *txidaddr; @@ -6118,28 +6180,6 @@ UniValue gatewaysmultisig(const UniValue& params, bool fHelp) return(GatewaysMultisig(txidaddr)); } -UniValue gatewayspartialsign(const UniValue& params, bool fHelp) -{ - UniValue result(UniValue::VOBJ); std::string coin,parthex,hex; uint256 txid; - if ( fHelp || params.size() != 3 ) - throw runtime_error("gatewayspartialsign txidaddr refcoin hex\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); - txid = Parseuint256((char *)params[0].get_str().c_str()); - coin = params[1].get_str(); - parthex = params[2].get_str(); - hex = GatewaysPartialSign(0,txid,coin,parthex); - RETURN_IF_ERROR(CCerror); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex",hex)); - } else ERR_RESULT("couldnt gatewaysmultisig"); - return(result); -} - UniValue oracleslist(const UniValue& params, bool fHelp) { if ( fHelp || params.size() > 0 )