diff --git a/.gitignore b/.gitignore index f6a9cbe17..c7962cf39 100755 --- a/.gitignore +++ b/.gitignore @@ -489,3 +489,7 @@ iguana/DB/PRICES/.tmpmarker iguana/DB/KMD/0/.tmpmarker *.swp + +iguana/myipaddr + +iguana/DB/UNSPENTS/.tmpmarker diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index 7c90807b1..1444658c9 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -2583,6 +2583,39 @@ int32_t iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *a return(vp->type); } +uint32_t iguana_vinscriptparse(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp,uint32_t *sigsizep,uint32_t *pubkeysizep,uint32_t *p2shsizep,uint32_t *userdatalenp,uint8_t *vinscript,int32_t scriptlen) +{ + uint32_t hashtype; uint8_t *userdata = 0; + *sigsizep = *pubkeysizep = *p2shsizep = *userdatalenp = 0; + if ( bitcoin_scriptget(taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0) < 0 ) + { + printf("iguana_vinscriptparse: error parsing vinscript?\n"); + return(-1); + } + if ( userdata != 0 && *userdatalenp > 0 ) + memcpy(vp->userdata,userdata,*userdatalenp); + if ( vp->type == IGUANA_SCRIPT_P2SH ) + { + *p2shsizep = vp->p2shlen + 1 + (vp->p2shlen >= 0xfd)*2; + //printf("P2SHSIZE.%d\n",*p2shsizep); + } + return(hashtype); +} + +/*char *iguana_scriptget(struct iguana_info *coin,char *scriptstr,char *asmstr,int32_t max,int32_t hdrsi,uint32_t unspentind,bits256 txid,int32_t vout,uint8_t *rmd160,int32_t type,uint8_t *pubkey33) +{ + int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; struct vin_info V,*vp = &V; + memset(vp,0,sizeof(*vp)); + scriptstr[0] = 0; + if ( asmstr != 0 ) + asmstr[0] = 0; + if ( pubkey33 != 0 && bitcoin_pubkeylen(pubkey33) > 0 ) + memcpy(vp->signers[0].pubkey,pubkey33,33); + scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,rmd160,type,(const struct vin_info *)vp,vout); + init_hexbytes_noT(scriptstr,script,scriptlen); + return(scriptstr); +}*/ + cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars) { int32_t i; cJSON *scriptjson,*array; diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 163408e7d..3bea50380 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -150,8 +150,8 @@ struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],r struct vin_info { struct iguana_msgvin vin; uint64_t amount; cJSON *extras; bits256 sigtxid; - int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,hashtype,userdatalen,suppress_pubkeys,ignore_cltverr; - uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65]; + int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,userdatalen,suppress_pubkeys,ignore_cltverr; + uint32_t sequence,unspentind,hashtype; struct vin_signer signers[16]; char coinaddr[65]; uint8_t rmd160[20],spendscript[10000],p2shscript[10000],userdata[10000]; }; diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 7de806d8a..f1b89a40b 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -17,7 +17,7 @@ // LP_nativeDEX.c // marketmaker // -// BCH signing +// BCH signing: FORKID_BCC = 0, FORKID_BTG = 79, // Atomic number AU // alice waiting for bestprice // MNZ getcoin strangeness // improve critical section detection when parallel trades @@ -679,6 +679,8 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) printf("%s ",activecoins[i]); LP_coinfind(activecoins[i]); LP_priceinfoadd(activecoins[i]); + //test_validate("02000000010e62f95ff5881de8853ce1a5ddbaad731a62879d719367f539103600f1895477010000006b483045022100c684a0871689519bd97f2e61275752124f0f1498360750c87cf99a8acf06fd8c022047e7e62a7bfd481599130e6f40c95833f6ed6f44aa8b6ead7b0ec86a738b98a041210361857e1ba609aadff520a2ca9886fe7548c7154fab2cbe108c3b0e1e7635eb1ffeffffff02a0860100000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac1e6f0700000000001976a9147f4b7113f9e26d84b150f2cc6d219baaf27f884488ace6b00700"); + //getchar(); if ( (coin= LP_coinfind(activecoins[i])) != 0 ) { if ( LP_getheight(coin) <= 0 ) @@ -889,7 +891,6 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu char *myipaddr=0,version[64]; long filesize,n; int32_t valid,timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx(); sprintf(version,"Marketmaker %s.%s %s rsize.%ld",LP_MAJOR_VERSION,LP_MINOR_VERSION,LP_BUILD_NUMBER,sizeof(struct basilisk_request)); printf("%s %u\n",version,calc_crc32(0,version,(int32_t)strlen(version))); - //test_validate("02000000010e62f95ff5881de8853ce1a5ddbaad731a62879d719367f539103600f1895477010000006b483045022100c684a0871689519bd97f2e61275752124f0f1498360750c87cf99a8acf06fd8c022047e7e62a7bfd481599130e6f40c95833f6ed6f44aa8b6ead7b0ec86a738b98a041210361857e1ba609aadff520a2ca9886fe7548c7154fab2cbe108c3b0e1e7635eb1ffeffffff02a0860100000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac1e6f0700000000001976a9147f4b7113f9e26d84b150f2cc6d219baaf27f884488ace6b00700"); if ( LP_MAXPRICEINFOS > 256 ) { printf("LP_MAXPRICEINFOS %d wont fit in a uint8_t, need to increase the width of the baseind and relind for struct LP_pubkey_quote\n",LP_MAXPRICEINFOS); @@ -1034,6 +1035,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu exit(-1); } LP_initcoins(ctx,pubsock,coinsjson); + G.waiting = 1; LP_passphrase_init(passphrase,jstr(argjson,"gui")); #ifndef FROM_JS diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index d1ad77b2d..bc73ee840 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -757,10 +757,10 @@ int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout) if ( (tx= LP_transactionfind(coin,txid)) != 0 ) { if ( vout < tx->numvouts && tx->height > 0 ) + { + printf("added missing utxo for SPV checking\n"); LP_address_utxoadd((uint32_t)time(NULL),"LP_validSPV",coin,coinaddr,txid,vout,tx->outpoints[vout].value,tx->height,-1); - if ( tx->SPV <= 0 ) - return(-1); - return(0); + } } } if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index c1c3ab5bb..d61940855 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -619,6 +619,100 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ return(complete); } +char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,char *rawtx,int32_t mempool,int32_t suppress_pubkeys,int32_t zcash) +{ + bits256 signedtxid; struct iguana_msgvin vin; cJSON *log,*vins,*vouts,*txobj,*retjson; char *signedtx; int32_t plen,height,finalized = 1,i,len,maxsize,numinputs,numoutputs,complete; struct vin_info *V; uint8_t *serialized,*serialized2; uint32_t sigsize,pubkeysize,p2shsize,suffixlen; int64_t inputsum,outputsum; struct iguana_msgvout vout; + char *symbol; uint8_t wiftaddr,taddr,pubtype,p2shtype,isPoS; + height = coin->longestchain; + symbol = coin->symbol; + wiftaddr = coin->wiftaddr; + taddr = coin->taddr; + pubtype = coin->pubtype; + p2shtype = coin->p2shtype; + isPoS = coin->isPoS; + retjson = cJSON_CreateObject(); + inputsum = outputsum = numinputs = numoutputs = 0; + if ( rawtx != 0 && rawtx[0] != 0 ) + { + if ( (strlen(rawtx) & 1) != 0 ) + return(clonestr("{\"error\":\"rawtx hex has odd length\"}")); + memset(msgtx,0,sizeof(*msgtx)); + if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&msgtx->txid,msgtx,rawtx,extraspace,extralen,0,0,suppress_pubkeys,zcash)) != 0 ) + { + maxsize = (int32_t)strlen(rawtx); + serialized = malloc(maxsize); + serialized2 = malloc(maxsize); + V = calloc(numinputs,sizeof(*V)); + if ( (vouts= jarray(&numoutputs,txobj,"vout")) > 0 ) + { + for (i=0; i 0 ) + outputsum += vout.value; + } + } + if ( (vins= jarray(&numinputs,txobj,"vin")) > 0 ) + { + len = 0; + for (i=0; ivins[i].spendscript = V[i].spendscript; + if ( (msgtx->vins[i].spendlen= V[i].spendlen) == 35 ) + { + if ( (plen= bitcoin_pubkeylen(msgtx->vins[i].spendscript+1)) > 0 ) + { + memcpy(V[i].signers[0].pubkey,msgtx->vins[i].spendscript+1,plen); + V[i].suppress_pubkeys = 1; + } + } + V[i].hashtype = iguana_vinscriptparse(taddr,pubtype,p2shtype,&V[i],&sigsize,&pubkeysize,&p2shsize,&suffixlen,msgtx->vins[i].vinscript,msgtx->vins[i].scriptlen); + if ( (V[i].signers[0].siglen= sigsize) > 0 ) + memcpy(V[i].signers[0].sig,msgtx->vins[i].vinscript+1,sigsize); + V[i].userdatalen = suffixlen; + memcpy(V[i].spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); + V[i].spendlen = msgtx->vins[i].spendlen; + if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL ) + finalized = 0; + if ( V[i].M == 0 ) + V[i].M = 1; + if ( V[i].N < V[i].M ) + V[i].N = V[i].M; + printf("V %dof%d %.8f (%s) spendscript.[%d] scriptlen.%d\n",V[i].M,V[i].N,dstr(V[i].amount),V[i].coinaddr,V[i].spendlen,V[i].spendlen); + } + complete = bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,&signedtxid,&signedtx,msgtx,serialized2,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys,LP_IS_BITCOINCASH); + msgtx->txid = signedtxid; + log = cJSON_CreateArray(); + if ( iguana_interpreter(ctx,log,0,V,numinputs) < 0 ) + jaddstr(retjson,"error","interpreter rejects tx"); + else complete = 1; + jadd(retjson,"interpreter",log); + jaddnum(retjson,"complete",complete); + free(serialized), free(serialized2); + if ( signedtx != 0 ) + free(signedtx); + free(V); + } + } + //char str[65]; printf("got txid.(%s)\n",bits256_str(str,txid)); + } + msgtx->inputsum = inputsum; + msgtx->numinputs = numinputs; + msgtx->outputsum = outputsum; + msgtx->numoutputs = numoutputs; + msgtx->txfee = (inputsum - outputsum); + return(jprint(retjson,1)); +} + +void test_validate(char *signedtx) +{ + char *retstr; uint8_t extraspace[8192]; int32_t mempool=0; struct iguana_msgtx msgtx; struct iguana_info *coin = LP_coinfind("BTC"); + retstr = iguana_validaterawtx(bitcoin_ctx(),coin,&msgtx,extraspace,sizeof(extraspace),signedtx,mempool,0,coin->zcash); + printf("validate test.(%s)\n",retstr); +} + char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t utxovout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys,int32_t zcash) { char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*obj,*vouts,*item,*privkeys; int32_t completed,spendlen,n,ignore_cltverr=1; struct vin_info V[8]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin; @@ -933,11 +1027,24 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ } } if ( dustcombine >= 1 && min0 != 0 && min0->U.value < LP_DUSTCOMBINE_THRESHOLD && (coin->electrum == 0 || min0->SPV > 0) ) - preselected[numpre++] = min0; + { + for (j=0; j= 2 && min1 != 0 && min1->U.value < LP_DUSTCOMBINE_THRESHOLD && (coin->electrum == 0 || min1->SPV > 0) ) - preselected[numpre++] = min1; + { + for (j=0; j