diff --git a/crypto777/Makefile b/crypto777/Makefile index 1b2cba457..ba83510c4 100644 --- a/crypto777/Makefile +++ b/crypto777/Makefile @@ -13,7 +13,8 @@ TARGET = crypto777 EXTRA= -D__PNACL -O2 -include $(NACL_SDK_ROOT)/tools/common.mk +#include $(NACL_SDK_ROOT)/tools/common.mk +include tools/common.mk CHROME_ARGS += --allow-nacl-socket-api=127.0.0.1 DEPS = nacl_io diff --git a/deprecated/obsolete.h b/deprecated/obsolete.h index 5b3239105..91f0fc8b3 100644 --- a/deprecated/obsolete.h +++ b/deprecated/obsolete.h @@ -13091,5 +13091,106 @@ len = 0; } return(clonestr("{\"error\":\"need pubkey\"}")); }*/ + + int32_t bitcoin_outputscript(struct iguana_info *coin,char *pubkeys[],int32_t *scriptlenp,uint8_t *scriptspace,bits256 txid,int32_t vout) + { + struct iguana_txid T,*tx; int32_t height,numpubs = 1; char asmstr[8192]; struct iguana_msgvout v; + if ( 0 ) + { + *scriptlenp = 0; + if ( (tx= iguana_txidfind(coin,&height,&T,txid)) != 0 ) + { + *scriptlenp = iguana_voutset(coin,scriptspace,asmstr,height,&v,tx,vout); + return(numpubs); + } + } + //char *str = "2103506a52e95cdfbb9d17d702af6259ba7de8b7a604007999e0266edbf6e4bb6974ac"; + char *str = "76a914010966776006953d5567439e5e39f86a0d273bee88ac"; + *scriptlenp = (int32_t)strlen(str) >> 1; + decode_hex(scriptspace,*scriptlenp,str); + //pubkeys[0] = clonestr("03506a52e95cdfbb9d17d702af6259ba7de8b7a604007999e0266edbf6e4bb6974"); + pubkeys[0] = clonestr("0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6"); + return(numpubs); + } + + cJSON *bitcoin_txjson(struct iguana_info *coin,struct iguana_msgtx *msgtx,struct vin_info *V) + { + char vpnstr[2]; int32_t n; uint8_t *serialized; bits256 txid; cJSON *json = cJSON_CreateObject(); + vpnstr[0] = 0; + serialized = malloc(IGUANA_MAXPACKETSIZE); + if ( (n= iguana_rwmsgtx(coin,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&txid,vpnstr,V)) < 0 ) + { + printf("bitcoin_txtest: n.%d\n",n); + } + free(serialized); + return(json); + } + + /*{ + for (i=0; inuminputs; i++) + strcpy(T->inputs[i].sigs,"00"); + strcpy(vin->sigs,redeemscript); + vin->sequence = (uint32_t)-1; + T->nlocktime = 0; + //disp_cointx(&T); + emit_cointx(&hash2,data,sizeof(data),T,oldtx_format,SIGHASH_ALL); + //printf("HASH2.(%llx)\n",(long long)hash2.txid); + if ( bp_sign(&key,hash2.bytes,sizeof(hash2),&sig,&siglen) != 0 ) + { + memcpy(sigbuf,sig,siglen); + sigbuf[siglen++] = SIGHASH_ALL; + init_hexbytes_noT(sigs[privkeyind],sigbuf,(int32_t)siglen); + strcpy(vin->sigs,"00"); + for (i=0; isigs + strlen(vin->sigs),"%02x%s",(int32_t)strlen(sigs[i])>>1,sigs[i]); + //printf("(%s).%ld ",sigs[i],strlen(sigs[i])); + } + } + len = (int32_t)(strlen(redeemscript)/2); + if ( len >= 0xfd ) + sprintf(&vin->sigs[strlen(vin->sigs)],"4d%02x%02x",len & 0xff,(len >> 8) & 0xff); + else sprintf(&vin->sigs[strlen(vin->sigs)],"4c%02x",len); + sprintf(&vin->sigs[strlen(vin->sigs)],"%s",redeemscript); + //printf("after A.(%s) othersig.(%s) siglen.%02lx -> (%s)\n",hexstr,othersig != 0 ? othersig : "",siglen,vin->sigs); + //printf("vinsigs.(%s) %ld\n",vin->sigs,strlen(vin->sigs)); + _emit_cointx(hexstr,sizeof(hexstr),T,oldtx_format); + //disp_cointx(&T); + free(T); + return(clonestr(hexstr)); + } + else printf("error signing\n"); + free(T); + }*/ + + /*cJSON *iguana_txjson(struct iguana_info *coin,struct iguana_txid *tx,int32_t height,struct vin_info *V) + { + struct iguana_msgvin vin; struct iguana_msgvout vout; int32_t i; char asmstr[512],str[65]; uint8_t space[8192]; + cJSON *vouts,*vins,*json; + json = cJSON_CreateObject(); + jaddstr(json,"txid",bits256_str(str,tx->txid)); + if ( height >= 0 ) + jaddnum(json,"height",height); + jaddnum(json,"version",tx->version); + jaddnum(json,"timestamp",tx->timestamp); + jaddnum(json,"locktime",tx->locktime); + vins = cJSON_CreateArray(); + vouts = cJSON_CreateArray(); + for (i=0; inumvouts; i++) + { + iguana_voutset(coin,space,asmstr,height,&vout,tx,i); + jaddi(vouts,iguana_voutjson(coin,&vout,i,tx->txid)); + } + jadd(json,"vout",vouts); + for (i=0; inumvins; i++) + { + iguana_vinset(coin,height,&vin,tx,i); + jaddi(vins,iguana_vinjson(coin,&vin,V != 0 ? &V[i] : 0)); + } + jadd(json,"vin",vins); + return(json); + }*/ #endif diff --git a/iguana/Makefile b/iguana/Makefile index 1eba19ce6..26c323a8c 100644 --- a/iguana/Makefile +++ b/iguana/Makefile @@ -13,7 +13,8 @@ TARGET = iguana EXTRA= -D__PNACL -DNN_DISABLE_GETADDRINFO_A=1 -DNN_USE_LITERAL_IFADDR=1 -DNN_HAVE_STDINT=1 -DNN_HAVE_MSG_CONTROL=0 -DNN_HAVE_SEMAPHORE=1 -DNN_HAVE_POLL=1 -DNN_HAVE_SOCKETPAIR=1 -DNN_USE_POLL=1 -include $(NACL_SDK_ROOT)/tools/common.mk +#include $(NACL_SDK_ROOT)/tools/common.mk +include tools/common.mk include iguana.sources include ../crypto777/crypto777.sources @@ -21,7 +22,9 @@ CHROME_ARGS += --allow-nacl-socket-api=127.0.0.1 DEPS = nacl_io #LIBS = curl ssl crypto z glibc-compat nacl_spawn ppapi nacl_io ppapi_cpp ppapi_simple # cli_main -LIBS = crypto777 curl ssl crypto z pthread ppapi nacl_io +#LIBS = crypto777 curl ssl crypto z pthread ppapi nacl_io +#DEPS = nacl_io +LIBS = crypto777 curl ssl crypto z glibc-compat nacl_spawn ppapi nacl_io ppapi_simple # cli_main ppapi_cpp ppapi_simple CFLAGS = -Wall -O2 -fno-strict-aliasing $(EXTRA) LFLAGS = libs diff --git a/iguana/SuperNET.h b/iguana/SuperNET.h index 728cc2a50..3fef1fb84 100644 --- a/iguana/SuperNET.h +++ b/iguana/SuperNET.h @@ -84,10 +84,27 @@ struct supernet_info int32_t LBsock,PUBsock,reqsock,subsock,networktimeout,maxdelay; uint16_t LBport,PUBport,reqport,subport; struct nn_pollfd pfd[SUPERNET_MAXAGENTS]; //struct relay_info active; - struct supernet_agent agents[SUPERNET_MAXAGENTS]; queue_t acceptQ; int32_t numagents,numexchanges; + struct supernet_agent agents[SUPERNET_MAXAGENTS]; queue_t acceptQ,acceptableQ; + int32_t numagents,numexchanges; struct exchange_info *tradingexchanges[SUPERNET_MAXEXCHANGES]; char handle[1024]; }; +#define NXT_ASSETID ('N' + ((uint64_t)'X'<<8) + ((uint64_t)'T'<<16)) // 5527630 +#define INSTANTDEX_ACCT "4383817337783094122" +union _NXT_tx_num { int64_t amountNQT; int64_t quantityQNT; }; +struct NXT_tx +{ + bits256 refhash,sighash,fullhash; + uint64_t senderbits,recipientbits,assetidbits,txid,priceNQT,quoteid; + int64_t feeNQT; + union _NXT_tx_num U; + int32_t deadline,type,subtype,verify,number; + uint32_t timestamp; + char comment[4096]; +}; +uint64_t set_NXTtx(struct supernet_info *myinfo,struct NXT_tx *tx,uint64_t assetidbits,int64_t amount,uint64_t other64bits,int32_t feebits); +cJSON *gen_NXT_tx_json(struct supernet_info *myinfo,char *fullhash,struct NXT_tx *utx,char *reftxid,double myshare); +int32_t calc_raw_NXTtx(struct supernet_info *myinfo,char *fullhash,char *utxbytes,char *sighash,uint64_t assetidbits,int64_t amount,uint64_t other64bits); /*struct supernet_endpoint { @@ -166,6 +183,7 @@ double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *s void SuperNET_setkeys(struct supernet_info *myinfo,void *pass,int32_t passlen,int32_t dosha256); char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *data,int32_t len,char *remoteaddr); +double instantdex_acceptable(struct supernet_info *myinfo,cJSON *array,char *refstr,char *base,char *rel,double volume); #endif diff --git a/iguana/exchanges/bitcoin.c b/iguana/exchanges/bitcoin.c index a0e3a82a9..cd094d3b9 100755 --- a/iguana/exchanges/bitcoin.c +++ b/iguana/exchanges/bitcoin.c @@ -31,6 +31,15 @@ static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijk #define IGUANA_SCRIPT_DATA 11 #define IGUANA_SCRIPT_STRANGE 15 +int32_t bitcoin_pubkeylen(const uint8_t *pubkey) +{ + if ( pubkey[0] == 2 || pubkey[0] == 3 ) + return(33); + else if ( pubkey[0] == 4 ) + return(65); + else return(-1); +} + void bn_mpi2bn(BIGNUM *vo,uint8_t *data,int32_t datalen) { uint8_t vch2[64 + 4]; uint32_t i,vch2_len = (int32_t)datalen + 4; @@ -137,7 +146,8 @@ int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr) be_sz = (uint32_t)len + (uint32_t)zeroes; memset(data,0,be_sz); for (i=0; i= 4 ) { // validate with trailing hash, then remove hash hash = bits256_doublesha256(0,buf,len - 4); + *addrtypep = *buf; + memcpy(rmd160,buf+1,20); if ( (buf[len - 4]&0xff) == hash.bytes[31] && (buf[len - 3]&0xff) == hash.bytes[30] &&(buf[len - 2]&0xff) == hash.bytes[29] &&(buf[len - 1]&0xff) == hash.bytes[28] ) { - *addrtypep = buf[0]; - memcpy(rmd160,buf+1,20); - return(20); + //printf("coinaddr.(%s) valid checksum\n",coinaddr); } else { - char str[65]; printf("checkhash mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x (%s)\n",buf[len - 4]&0xff,buf[len - 3]&0xff,buf[len - 2]&0xff,buf[len - 1]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28],bits256_str(str,hash)); + int32_t i; char hexaddr[64]; + btc_convaddr(hexaddr,coinaddr); + for (i=0; iM; + for (i=0; iN; i++) { if ( (plen= bitcoin_pubkeylen(vp->signers[i].pubkey)) < 0 ) return(-1); memcpy(&script[n],vp->signers[i].pubkey,plen); n += plen; } - script[n++] = 0x50 + N; + script[n++] = 0x50 + vp->N; script[n++] = SCRIPT_OP_CHECKMULTISIG; vcalc_sha256(0,sha256,script,n); calc_rmd160(0,p2sh_rmd160,sha256,sizeof(sha256)); return(n); } -char *create_atomictx_cltvspend(char *scriptstr,uint8_t *rmd160A,uint8_t *rmd160B,uint32_t locktime) +int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,const int32_t p2shlen) +{ + if ( p2shlen >= 0xfd ) + { + script[n++] = 0x4d; + script[n++] = (p2shlen & 0xff); + script[n++] = ((p2shlen >> 8) & 0xff); + } + else + { + script[n++] = 0x4c; + script[n++] = p2shlen; + } + memcpy(&script[n],p2shscript,p2shlen), n += p2shlen; + return(n); +} + +int32_t bitcoin_scriptsig(uint8_t *script,int32_t n,const struct vin_info *vp) +{ + int32_t i,siglen; + if ( vp->N > 1 ) + script[n++] = SCRIPT_OP_NOP; + for (i=0; iN; i++) + { + if ( (siglen= vp->signers[i].siglen) != 0 ) + { + script[n++] = siglen; + memcpy(&script[n],vp->signers[i].sig,siglen), n += siglen; + } + } + if ( vp->type == IGUANA_SCRIPT_P2SH ) + n = bitcoin_p2shscript(script,n,vp->p2shscript,vp->p2shlen); + return(n); +} + +int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,char *senderaddr,char *destaddr,uint32_t locktime) { // OP_IF // OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG // OP_ELSE // OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG // standard spend // OP_ENDIF - uint8_t hex[4096]; int32_t n = 0; - hex[n++] = SCRIPT_OP_IF; - n = bitcoin_checklocktimeverify(hex,n,locktime); - n = bitcoin_standardspend(hex,n,rmd160A); - hex[n++] = SCRIPT_OP_ELSE; - n = bitcoin_standardspend(hex,n,rmd160B); - hex[n++] = SCRIPT_OP_ENDIF; - init_hexbytes_noT(scriptstr,hex,n); - return(scriptstr); + uint8_t sha256[32],rmd160A[20],rmd160B[20],addrtypeA,addrtypeB; + bitcoin_addr2rmd160(&addrtypeA,rmd160A,senderaddr); + bitcoin_addr2rmd160(&addrtypeB,rmd160B,destaddr); + script[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(script,n,locktime); + n = bitcoin_standardspend(script,n,rmd160A); + script[n++] = SCRIPT_OP_ELSE; + n = bitcoin_standardspend(script,n,rmd160B); + script[n++] = SCRIPT_OP_ENDIF; + vcalc_sha256(0,sha256,script,n); + calc_rmd160(0,p2sh_rmd160,sha256,sizeof(sha256)); + bitcoin_address(ps2h_coinaddr,p2shtype,p2sh_rmd160,20); + return(n); } -int32_t iguana_scriptgen(struct iguana_info *coin,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,int32_t txi,struct vin_info *vp) +int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi) { - uint8_t addrtype; char rmd160str[41]; int32_t i,m,n,flag = 0,scriptlen = 0; + uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t i,m,n,flag = 0,scriptlen = 0; m = n = 1; if ( type == IGUANA_SCRIPT_76A988AC || type == IGUANA_SCRIPT_76AC || type == IGUANA_SCRIPT_P2SH ) { @@ -376,7 +429,6 @@ int32_t iguana_scriptgen(struct iguana_info *coin,char *coinaddr,uint8_t *script init_hexbytes_noT(rmd160str,rmd160,20); btc_convrmd160(coinaddr,addrtype,rmd160); } - //printf("addrtype.%d\n",addrtype); switch ( type ) { case IGUANA_SCRIPT_NULL: @@ -385,8 +437,10 @@ int32_t iguana_scriptgen(struct iguana_info *coin,char *coinaddr,uint8_t *script coinaddr[0] = 0; break; case IGUANA_SCRIPT_76AC: - sprintf(asmstr,"OP_DUP %s OP_CHECKSIG // %s",rmd160str,coinaddr); - scriptlen = bitcoin_pubkeyspend(script,0,vp->signers[0].pubkey); + init_hexbytes_noT(pubkeystr,(uint8_t *)vp->signers[0].pubkey,bitcoin_pubkeylen(vp->signers[0].pubkey)); + sprintf(asmstr,"OP_DUP %s OP_CHECKSIG // %s",pubkeystr,coinaddr); + scriptlen = bitcoin_pubkeyspend(script,0,(uint8_t *)vp->signers[0].pubkey); + //printf("[%02x] scriptlen.%d (%s)\n",vp->signers[0].pubkey[0],scriptlen,asmstr); break; case IGUANA_SCRIPT_76A988AC: sprintf(asmstr,"OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG // %s",rmd160str,coinaddr); @@ -418,11 +472,11 @@ int32_t iguana_scriptgen(struct iguana_info *coin,char *coinaddr,uint8_t *script } if ( n > 1 ) { - scriptlen = bitcoin_MofN(rmd160,script,0,vp,m,n); + scriptlen = bitcoin_MofNspendscript(rmd160,script,0,vp); sprintf(asmstr,"%d ",m); for (i=0; isigners[i].pubkey,bitcoin_pubkeylen(vp->signers[i].pubkey)); + init_hexbytes_noT(asmstr + strlen(asmstr),(uint8_t *)vp->signers[i].pubkey,bitcoin_pubkeylen(vp->signers[i].pubkey)); strcat(asmstr," "); } sprintf(asmstr + strlen(asmstr),"%d // M.%d of N.%d [",n,m,n); @@ -431,8 +485,9 @@ int32_t iguana_scriptgen(struct iguana_info *coin,char *coinaddr,uint8_t *script strcat(asmstr,"]\n"); } if ( flag != 0 && vp->spendlen > 0 ) - init_hexbytes_noT(asmstr + strlen(asmstr),vp->spendscript,vp->spendlen); - return(0); + init_hexbytes_noT(asmstr + strlen(asmstr),(uint8_t *)vp->spendscript,vp->spendlen); + *Mp = m, *nump = n; + return(scriptlen); } int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) @@ -552,19 +607,6 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) return(type); } - -/* - struct vin_signer { bits256 privkey; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; }; - - struct vin_info - { - struct iguana_msgvin vin; - int32_t M,N,validmask,spendlen,p2shflag; - struct vin_signer signers[16]; - uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; - }; - */ - int32_t iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp,uint8_t *pk_script,int32_t pk_scriptlen,bits256 debugtxid,int32_t vout,uint32_t sequence) { int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; char asmstr[IGUANA_MAXSCRIPTSIZE*3]; @@ -573,10 +615,9 @@ int32_t iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp,uint8_t * vp->spendlen = pk_scriptlen; vp->vin.sequence = sequence; memcpy(vp->spendscript,pk_script,pk_scriptlen); - vp->vin.script = vp->spendscript, vp->vin.prev_vout = pk_scriptlen; if ( (vp->type= _iguana_calcrmd160(coin,vp)) >= 0 ) { - scriptlen = iguana_scriptgen(coin,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,vout,vp); + scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout); if ( scriptlen != pk_scriptlen || memcmp(script,pk_script,scriptlen) != 0 ) { printf("iguana_calcrmd160 type.%d error regenerating scriptlen.%d vs %d\n",vp->type,scriptlen,pk_scriptlen); @@ -614,7 +655,7 @@ int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t vin->prev_hash = jbits256(vinobj,"txid"); vin->prev_vout = jint(vinobj,"vout"); if ( (sigjson= jobj(vinobj,"scriptSig")) != 0 ) - hexstr = jstr(sigjson,"redeemScript"); + hexstr = jstr(sigjson,"hex"); } if ( hexstr != 0 ) { @@ -631,46 +672,42 @@ int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t return(len); } -//{"result":{"txid":"a2b81b9894205ced12dfe276cbe27c05308976b5a2e12789ccd167fe6c3217f7","version":1,"time":1433295027,"locktime":0,"vin":[{"txid":"cf8f5e26e29a74c4fb867338213c02059b975fcfeae993926edbad8aba1cfedb","vout":1,"scriptSig":{"asm":"3045022100f86ab6815d1c22bf9f0fb6c389b558eb644159462054039d393cdba6e480a952022079b7f804c48a0ef5de68bc4be4c18cd5ea947763f4d5f6d415092f8dc00ee1aa01","hex":"483045022100f86ab6815d1c22bf9f0fb6c389b558eb644159462054039d393cdba6e480a952022079b7f804c48a0ef5de68bc4be4c18cd5ea947763f4d5f6d415092f8dc00ee1aa01"},"sequence":4294967295},{"txid":"cfcaef36853be671a5247c1ccb2a54a59d8b4628d0d63726dcdc8dbf73116ae3","vout":2,"scriptSig":{"asm":"3045022100a84f56626e4558e13911290e72d498796ba0bc70a0c9eb59b20d50f6ed94cee30220734c94ab1e89dfe26b3cc1b519a5a6f37863829e9eccdb246843e76577b4040f01","hex":"483045022100a84f56626e4558e13911290e72d498796ba0bc70a0c9eb59b20d50f6ed94cee30220734c94ab1e89dfe26b3cc1b519a5a6f37863829e9eccdb246843e76577b4040f01"},"sequence":4294967295}],"vout":[{"value":0.00000000,"n":0,"scriptPubKey":{"asm":"","type":"nonstandard"}},{"value":1036.57541260,"n":1,"scriptPubKey":{"asm":"03506a52e95cdfbb9d17d702af6259ba7de8b7a604007999e0266edbf6e4bb6974 OP_CHECKSIG","reqSigs":1,"type":"pubkey","addresses":["RJyYWRKSK7cMg5EeW9aHAaT3hHVEkAXnP9"]}}],"blockhash":"6863f2bab8cd9b69dd7a446aa63281f9e5301520f9ba02ca3acc892866872fe4","confirmations":374485},"error":null,"id":"jl777"} - -//{"result":{"version":1,"timestamp":1433295027,"vin":[{"sequence":4294967295,"txid":"cf8f5e26e29a74c4fb867338213c02059b975fcfeae993926edbad8aba1cfedb","vout":1,"hex":"483045022100f86ab6815d1c22bf9f0fb6c389b558eb644159462054039d393cdba6e480a952022079b7f804c48a0ef5de68bc4be4c18cd5ea947763f4d5f6d415092f8dc00ee1aa01"}, {"sequence":4294967295,"txid":"cfcaef36853be671a5247c1ccb2a54a59d8b4628d0d63726dcdc8dbf73116ae3","vout":2,"hex":"483045022100a84f56626e4558e13911290e72d498796ba0bc70a0c9eb59b20d50f6ed94cee30220734c94ab1e89dfe26b3cc1b519a5a6f37863829e9eccdb246843e76577b4040f01"}],"numvins":2,"vout":[{"value":0,"n":0,"scriptPubKey":{"asm":"coinbase","addresses":[]}}, {"value":1036.57541260,"n":1,"scriptPubKey":{"asm":"OP_DUP 6a5ad2f911f1bfd7c018c95154e2c049accd04da OP_CHECKSIG","addresses":["RJyYWRKSK7cMg5EeW9aHAaT3hHVEkAXnP9"],"hex":"2103506a52e95cdfbb9d17d702af6259ba7de8b7a604007999e0266edbf6e4bb6974ac"}}],"numvouts":2,"locktime":0,"size":295,"txid":"a2b81b9894205ced12dfe276cbe27c05308976b5a2e12789ccd167fe6c3217f7"},"height":555555,"confirmations":333945,"blockhash":"6863f2bab8cd9b69dd7a446aa63281f9e5301520f9ba02ca3acc892866872fe4","tag":"731886559821890929"} - cJSON *iguana_voutjson(struct iguana_info *coin,struct iguana_msgvout *vout,int32_t txi,bits256 txid) { // 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG - char scriptstr[8192+1],coinaddr[65],asmstr[16384]; int32_t i,asmtype; struct vin_info V; - uint8_t addrtype,space[8192]; - cJSON *addrs,*skey,*json = cJSON_CreateObject(); + char scriptstr[8192+1],asmstr[16384]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp; + uint8_t space[8192]; cJSON *addrs,*skey,*json = cJSON_CreateObject(); + vp = calloc(1,sizeof(*vp)); jaddnum(json,"value",dstr(vout->value)); jaddnum(json,"n",txi); //"scriptPubKey":{"asm":"OP_DUP OP_HASH160 5f69cb73016264270dae9f65c51f60d0e4d6fd44 OP_EQUALVERIFY OP_CHECKSIG","reqSigs":1,"type":"pubkeyhash","addresses":["RHyh1V9syARTf2pyxibz7v27D5paBeWza5"]} if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) ) { - memset(&V,0,sizeof(V)); - if ( (asmtype= iguana_calcrmd160(coin,&V,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) + memset(vp,0,sizeof(*vp)); + if ( (asmtype= iguana_calcrmd160(coin,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) { skey = cJSON_CreateObject(); - addrtype = iguana_scriptgen(coin,V.coinaddr,space,asmstr,V.rmd160,asmtype,txi,&V); + scriptlen = iguana_scriptgen(coin,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi); if ( asmstr[0] != 0 ) jaddstr(skey,"asm",asmstr); addrs = cJSON_CreateArray(); - if ( V.M == 0 ) + if ( vp->N == 1 ) { if ( asmtype == 2 ) { jaddnum(skey,"reqSigs",1); jaddstr(skey,"type","pubkeyhash"); } - if ( coinaddr[0] != 0 ) - jaddistr(addrs,coinaddr); + if ( vp->coinaddr[0] != 0 ) + jaddistr(addrs,vp->coinaddr); } else { - jaddnum(skey,"reqSigs",V.M); - for (i=0; iM); + for (i=0; iN; i++) { - btc_convrmd160(coinaddr,coin->chain->pubtype,V.signers[i].pubkey); - jaddistr(addrs,coinaddr); + //btc_convrmd160(coinaddr,coin->chain->pubtype,V.signers[i].pubkey); + jaddistr(addrs,vp->signers[i].coinaddr); } } jadd(skey,"addresses",addrs); @@ -697,41 +734,13 @@ cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin) jaddstr(json,"txid",bits256_str(str,vin->prev_hash)); jaddnum(json,"vout",vout); sigjson = cJSON_CreateObject(); - jaddstr(sigjson,"redeemScript",scriptstr); + jaddstr(sigjson,"hex",scriptstr); jadd(json,"scriptSig",sigjson); } return(json); } -cJSON *iguana_txjson(struct iguana_info *coin,struct iguana_txid *tx,int32_t height) -{ - struct iguana_msgvin vin; struct iguana_msgvout vout; int32_t i; char asmstr[512],str[65]; uint8_t space[8192]; - cJSON *vouts,*vins,*json; - json = cJSON_CreateObject(); - jaddstr(json,"txid",bits256_str(str,tx->txid)); - if ( height >= 0 ) - jaddnum(json,"height",height); - jaddnum(json,"version",tx->version); - jaddnum(json,"timestamp",tx->timestamp); - jaddnum(json,"locktime",tx->locktime); - vins = cJSON_CreateArray(); - vouts = cJSON_CreateArray(); - for (i=0; inumvouts; i++) - { - iguana_voutset(coin,space,asmstr,height,&vout,tx,i); - jaddi(vouts,iguana_voutjson(coin,&vout,i,tx->txid)); - } - jadd(json,"vout",vouts); - for (i=0; inumvins; i++) - { - iguana_vinset(coin,height,&vin,tx,i); - jaddi(vins,iguana_vinjson(coin,&vin)); - } - jadd(json,"vin",vins); - return(json); -} - -int32_t iguana_vinparse(int32_t rwflag,uint8_t *serialized,struct iguana_msgvin *msg) +int32_t iguana_vinparse(struct iguana_info *coin,int32_t rwflag,uint8_t *serialized,struct iguana_msgvin *msg) { int32_t len = 0; len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->prev_hash),msg->prev_hash.bytes); @@ -803,7 +812,7 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t rwflag,cJSON *json,uint8 { for (i=0; itx_in; i++) { - len += iguana_vinparse(rwflag,&serialized[len],&msg->vins[i]); + len += iguana_vinparse(coin,rwflag,&serialized[len],&msg->vins[i]); if ( array != 0 ) jaddi(array,iguana_vinjson(coin,&msg->vins[i])); } @@ -880,7 +889,7 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t rwflag,cJSON *json,uint8 return(len); } -bits256 iguana_parsetxobj(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,cJSON *txobj) +bits256 iguana_parsetxobj(struct iguana_info *coin,int32_t *txstartp,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,cJSON *txobj) // json -> serialized + (msg,V) { int32_t i,numvins,numvouts,len = 0; cJSON *array=0; bits256 txid; char vpnstr[64]; memset(msg,0,sizeof(*msg)); @@ -916,125 +925,166 @@ bits256 iguana_parsetxobj(struct iguana_info *coin,uint8_t *serialized,int32_t m } msg->lock_time = juint(txobj,"locktime"); msg->txid = jbits256(txobj,"txid"); + *txstartp = len; msg->allocsize = iguana_rwmsgtx(coin,1,0,&serialized[len],maxsize-len,msg,&txid,vpnstr); //char str[65]; printf("json -> %s\n",bits256_str(str,txid)); return(txid); } -char *iguana_rawtxbytes(struct iguana_info *coin,uint8_t *serialized,int32_t datalen,cJSON *json,struct iguana_msgtx *msgtx) +char *iguana_rawtxbytes(struct iguana_info *coin,cJSON *json,struct iguana_msgtx *msgtx) { - int32_t n; char *txbytes,vpnstr[64]; + int32_t n; char *txbytes = 0,vpnstr[64]; uint8_t *serialized; + serialized = malloc(IGUANA_MAXPACKETSIZE); vpnstr[0] = 0; //char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid)); - if ( (n= iguana_rwmsgtx(coin,1,json,serialized,datalen,msgtx,&msgtx->txid,vpnstr)) > 0 ) + if ( (n= iguana_rwmsgtx(coin,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr)) > 0 ) { txbytes = malloc(n*2+1); init_hexbytes_noT(txbytes,serialized,n); - return(txbytes); } - return(0); + free(serialized); + return(txbytes); } -cJSON *bitcoin_txjson(struct iguana_info *coin,struct iguana_msgtx *msgtx) +/* + struct vin_signer { bits256 privkey; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; }; + + struct vin_info + { + struct iguana_msgvin vin; + int32_t M,N,validmask,spendlen,p2shflag; + struct vin_signer signers[16]; + uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; + }; + */ + +int32_t bitcoin_scriptget(struct iguana_info *coin,int32_t *hashtypep,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t type) { - char vpnstr[2]; int32_t n; uint8_t *serialized; bits256 txid; cJSON *json = cJSON_CreateObject(); - vpnstr[0] = 0; - serialized = malloc(IGUANA_MAXPACKETSIZE); - if ( (n= iguana_rwmsgtx(coin,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&txid,vpnstr)) < 0 ) + char asmstr[IGUANA_MAXSCRIPTSIZE*3]; int32_t j,n,siglen,plen; uint8_t sha256[32]; + j = n = 0; + *hashtypep = SIGHASH_ALL; + while ( (siglen= scriptsig[n]) >= 70 && siglen <= 73 && n+siglen+1 < len && j < 16 ) { - printf("bitcoin_txtest: n.%d\n",n); + vp->signers[j].siglen = siglen; + memcpy(vp->signers[j].sig,&scriptsig[n+1],siglen); + if ( j == 0 ) + *hashtypep = vp->signers[j].sig[siglen-1]; + n += (siglen + 1); + j++; + if ( type == 0 && j > 1 ) + type = IGUANA_SCRIPT_MSIG; } - free(serialized); - return(json); -} - -int32_t bitcoin_outputscript(struct iguana_info *coin,char *pubkeys[],int32_t *scriptlenp,uint8_t *scriptspace,bits256 txid,int32_t vout) -{ - struct iguana_txid T,*tx; int32_t height,numpubs = 1; char asmstr[8192]; struct iguana_msgvout v; - if ( 0 ) + vp->type = type; + j = 0; + while ( ((plen= scriptsig[n]) == 33 || plen == 65 ) && j < 16 ) { - *scriptlenp = 0; - if ( (tx= iguana_txidfind(coin,&height,&T,txid)) != 0 ) - { - *scriptlenp = iguana_voutset(coin,scriptspace,asmstr,height,&v,tx,vout); - return(numpubs); - } + memcpy(vp->signers[j].pubkey,&scriptsig[n+1],plen); + vcalc_sha256(0,sha256,vp->signers[j].pubkey,plen); + calc_rmd160(0,vp->signers[j].rmd160,sha256,sizeof(sha256)); + if ( j == 0 ) + memcpy(vp->rmd160,vp->signers[j].rmd160,20); + n += (plen + 1); + j++; } - //char *str = "2103506a52e95cdfbb9d17d702af6259ba7de8b7a604007999e0266edbf6e4bb6974ac"; - char *str = "76a914010966776006953d5567439e5e39f86a0d273bee88ac"; - *scriptlenp = (int32_t)strlen(str) >> 1; - decode_hex(scriptspace,*scriptlenp,str); - //pubkeys[0] = clonestr("03506a52e95cdfbb9d17d702af6259ba7de8b7a604007999e0266edbf6e4bb6974"); - pubkeys[0] = clonestr("0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6"); - return(numpubs); -} - -int32_t bitcoin_hashtype(uint8_t *script,int32_t scriptlen,uint8_t *pk_script,int32_t pk_scriptlen) -{ - return(SIGHASH_ALL); + if ( n < len && (scriptsig[n] == 0x4c || scriptsig[n] == 0x4d) ) + { + if ( scriptsig[n] == 0x4c ) + vp->p2shlen = scriptsig[n+1], n += 2; + else vp->p2shlen = ((uint32_t)scriptsig[n+1] + ((uint32_t)scriptsig[n+2] << 8)), n += 3; + memcpy(vp->p2shscript,&scriptsig[n],vp->p2shlen); + vp->type = IGUANA_SCRIPT_P2SH; + } + /*if ( len == 0 ) + { + // txid.(eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2).v1 + decode_hex(vp->rmd160,20,"010966776006953d5567439e5e39f86a0d273bee");//3564a74f9ddb4372301c49154605573d7d1a88fe"); + vp->type = IGUANA_SCRIPT_76A988AC; + }*/ + vp->spendlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,vp->spendscript,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vp->vin.prev_vout); + //printf("type.%d asmstr.(%s) spendlen.%d\n",vp->type,asmstr,vp->spendlen); + return(vp->spendlen); } -int32_t bitcoin_verifyvins(struct iguana_info *coin,int32_t *scriptlens,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,bits256 myprivkey) +int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,int32_t *scriptlens,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V) { - char txidstr[128],bigstr[2560],coinaddr[64],vpnstr[64],str[65],*pubkeys[16]; - uint8_t *sig,mypubkey[128],pubkey[128],sigspace[8192],*saveinput,scriptspace[8192]; - bits256 txid,sigtxid,revsigtxid,mypub; - int32_t n2,i,j,numpubs,plen,scriptlen,vini=0,siglen,numvins,hashtype,myvin = 1; + bits256 txid,sigtxid,revsigtxid; char txidstr[128],bigstr[2560],coinaddr[64],vpnstr[64],str[65]; + uint8_t *sig,*pubkey,*saveinput; struct vin_info *vp; + int32_t n2,i,j,k,plen,vini=0,flag,numvins,hashtype,retval,siglen,asmtype; vpnstr[0] = 0; - memset(pubkeys,0,sizeof(pubkeys)); + *signedtx = 0; + memset(signedtxidp,0,sizeof(*signedtxidp)); numvins = msgtx->tx_in; - mypub = bitcoin_pubkey(mypubkey,myprivkey); + retval = -numvins; for (vini=0; vinivins[vini].script; + vp = &V[vini]; for (i=0; ivins[i].scriptlen = 0; - saveinput = msgtx->vins[vini].script; sig = &msgtx->vins[vini].script[1]; - siglen = msgtx->vins[vini].script[0]; - numpubs = bitcoin_outputscript(coin,pubkeys,&scriptlen,scriptspace,msgtx->vins[vini].prev_hash,msgtx->vins[vini].prev_vout); - msgtx->vins[vini].scriptlen = scriptlen; - msgtx->vins[vini].script = scriptspace; - for (j=0; jvins[vini].script[0] - 1; + vp->vin = msgtx->vins[vini]; + flag = 0; + for (k=0; k<2; k++) { - plen = (int32_t)strlen(pubkeys[j]); - plen >>= 1; - decode_hex(pubkey,plen,pubkeys[j]); - bitcoin_address(coinaddr,coin->chain->pubtype,pubkey,plen); - n2 = iguana_rwmsgtx(coin,1,0,serialized,maxsize,msgtx,&txid,vpnstr); - hashtype = bitcoin_hashtype(saveinput,scriptlens[vini],scriptspace,scriptlen); - msgtx->vins[vini].script = saveinput; - if ( n2 > 0 ) + asmtype = (k == 0) ? IGUANA_SCRIPT_76A988AC : IGUANA_SCRIPT_76AC; + if ( bitcoin_scriptget(coin,&hashtype,vp,saveinput,scriptlens[vini],asmtype) < 0 ) { - n2 += iguana_rwnum(1,&serialized[n2],sizeof(hashtype),&hashtype); - revsigtxid = bits256_doublesha256(txidstr,serialized,n2); - for (i=0; ivin.prev_hash),vp->vin.prev_vout); + continue; + } + msgtx->vins[vini].script = vp->spendscript; + msgtx->vins[vini].scriptlen = vp->spendlen; + for (j=0; jN; j++) + { + pubkey = vp->signers[j].pubkey; + if ( (plen= bitcoin_pubkeylen(pubkey)) < 0 ) { - sig = sigspace; - siglen = bitcoin_sign(sig,sizeof(sigspace),sigtxid.bytes,sizeof(sigtxid),myprivkey); - printf("plen.%d siglen.%d %s\n",plen,siglen,bits256_str(str,myprivkey)); - msgtx->vins[vini].scriptlen = siglen + plen + 2; - msgtx->vins[vini].script[0] = siglen; - memcpy(msgtx->vins[vini].script+1,sigspace,siglen); - msgtx->vins[vini].script[siglen + 1] = plen; - memcpy(msgtx->vins[vini].script+1+siglen+1,pubkey,plen); - cJSON *j = cJSON_CreateObject(); - char *txstr = iguana_rawtxbytes(coin,malloc(10000),10000,j,msgtx); - printf("SIGNEDTX.(%s) %s\n",txstr,jprint(j,0)); - siglen++; - //printf("retjson.(%s) %p\n",jprint(retjson,0),retjson); + printf("illegal plen.%d [%02x]\n",plen,pubkey[0]); + break; } - if ( bitcoin_verify(sig,siglen-1,sigtxid.bytes,sizeof(sigtxid),0,pubkey,plen) < 0 ) + bitcoin_address(coinaddr,coin->chain->pubtype,pubkey,plen); + n2 = iguana_rwmsgtx(coin,1,0,serialized,maxsize,msgtx,&txid,vpnstr); + msgtx->vins[vini].script = saveinput; + if ( n2 > 0 ) { - init_hexbytes_noT(bigstr,serialized,n2); - printf("(%s) doesnt verify hash2.%s\n",bigstr,bits256_str(str,sigtxid)); - return(-1); - } else printf("SIG.%d VERIFIED\n",vini); - } else return(-1); + n2 += iguana_rwnum(1,&serialized[n2],sizeof(hashtype),&hashtype); + revsigtxid = bits256_doublesha256(txidstr,serialized,n2); + for (i=0; isigners[j].privkey) != 0 ) + { + vp->signers[j].siglen = bitcoin_sign(vp->signers[j].sig,sizeof(vp->signers[j].sig),sigtxid.bytes,sizeof(sigtxid),vp->signers[j].privkey); + sig = vp->signers[j].sig; + siglen = vp->signers[j].siglen; + msgtx->vins[vini].scriptlen = bitcoin_scriptsig(msgtx->vins[vini].script,0,(const struct vin_info *)vp); + printf("SIGNEDTX plen.%d siglen.%d\n",plen,siglen); + } + if ( bitcoin_verify(sig,siglen,sigtxid.bytes,sizeof(sigtxid),0,vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 ) + { + init_hexbytes_noT(bigstr,serialized,n2); + printf("(%s) doesnt verify hash2.%s\n",bigstr,bits256_str(str,sigtxid)); + } + else + { + printf("SIG.%d VERIFIED\n",vini); + *signedtx = iguana_rawtxbytes(coin,0,msgtx); + *signedtxidp = msgtx->txid; + flag = 1; + break; + } + } else printf("bitcoin_verifyvins: vini.%d n2.%d\n",vini,n2); + } + if ( flag > 0 ) + { + retval++; + break; + } + if ( vp->type != IGUANA_SCRIPT_76A988AC && vp->type != IGUANA_SCRIPT_76AC ) + break; } } - return(0); + return(retval); } //printf("privkey.%s\n",bits256_str(str,privkey)); @@ -1052,17 +1102,16 @@ ffffffff\ 76a914097072524438d003d23a2f23edb65aae1bb3e46988ac\ 00000000"; -int32_t bitcoin_verifytx(struct iguana_info *coin,char *rawtxstr) +int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V) { int32_t i,len,maxsize,*scriptlens,numvins,retval = -1; uint8_t *serialized,*serialized2; - struct iguana_msgtx msgtx; bits256 txid,myprivkey; char vpnstr[64]; + struct iguana_msgtx msgtx; bits256 txid; char vpnstr[64]; len = (int32_t)strlen(rawtxstr); maxsize = len + 32768; serialized = calloc(1,maxsize); serialized2 = calloc(1,maxsize); len >>= 1; vpnstr[0] = 0; -decode_hex(myprivkey.bytes,sizeof(myprivkey),"18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725"); decode_hex(serialized,len,rawtxstr); memset(&msgtx,0,sizeof(msgtx)); if ( iguana_rwmsgtx(coin,0,0,serialized,maxsize,&msgtx,&txid,vpnstr) > 0 ) @@ -1071,27 +1120,144 @@ decode_hex(myprivkey.bytes,sizeof(myprivkey),"18E14A7B6A307F426A94F8114701E7C8E7 scriptlens = calloc(numvins,sizeof(*scriptlens)); for (i=0; ichain->hastimestamp != 0 ) + jaddnum(json,"timestamp",timestamp); + jadd(json,"vin",cJSON_CreateArray()); + jadd(json,"vout",cJSON_CreateArray()); + return(json); +} + +cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,double amount) +{ + char *hexstr; cJSON *item,*skey,*vouts = jduplicate(jobj(txobj,"vout")); + item = cJSON_CreateObject(); + jaddnum(item,"value",amount); + skey = cJSON_CreateObject(); + hexstr = malloc(len*2 + 1); + init_hexbytes_noT(hexstr,paymentscript,len); + jaddstr(skey,"hex",hexstr); + free(hexstr); + jadd(item,"scriptPubkey",skey); + jdelete(vouts,"vout"); + jadd(vouts,"vout",item); + return(txobj); +} + +cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence) +{ + cJSON *item,*vins = jduplicate(jobj(txobj,"vin")); + item = cJSON_CreateObject(); + jaddbits256(item,"txid",txid); + jaddnum(item,"vout",vout); + jaddnum(item,"sequence",sequence); + jdelete(vins,"vin"); + jadd(vins,"vin",item); + return(txobj); +} + +char *bitcoin_cltvtx(struct iguana_info *coin,char *changeaddr,char *senderaddr,char *destaddr,int32_t duration,double amount,bits256 txid,int32_t vout,uint64_t inputsatoshis,bits256 privkey) +{ + uint64_t change,satoshis; char *rawtxstr,*signedtx; struct vin_info V; bits256 cltxid,signedtxid; + int32_t cltvlen,len; uint32_t timestamp,locktime; char ps2h_coinaddr[65]; cJSON *txobj; + uint8_t p2sh_rmd160[20],cltvscript[1024],paymentscript[64],rmd160[20],addrtype; + timestamp = (uint32_t)time(NULL); + locktime = timestamp + duration; + cltvlen = bitcoin_cltvscript(coin->chain->p2shtype,ps2h_coinaddr,p2sh_rmd160,cltvscript,0,senderaddr,destaddr,locktime); + txobj = bitcoin_createtx(coin,duration); + len = bitcoin_p2shspend(paymentscript,0,p2sh_rmd160); + satoshis = (amount * SATOSHIDEN); + bitcoin_addoutput(coin,txobj,paymentscript,len,amount); + bitcoin_addinput(coin,txobj,txid,vout,locktime); + if ( inputsatoshis > (satoshis + 10000) ) + { + change = inputsatoshis - (satoshis + 10000); + if ( changeaddr != 0 && changeaddr[0] != 0 ) + { + bitcoin_addr2rmd160(&addrtype,rmd160,changeaddr); + if ( addrtype == coin->chain->pubtype ) + len = bitcoin_standardspend(paymentscript,0,rmd160); + else if ( addrtype == coin->chain->p2shtype ) + len = bitcoin_standardspend(paymentscript,0,rmd160); + else + { + printf("error with mismatched addrtype.%02x vs (%02x %02x)\n",addrtype,coin->chain->pubtype,coin->chain->p2shtype); + return(0); + } + bitcoin_addoutput(coin,txobj,paymentscript,len,change); + } + else + { + printf("error no change address when there is change\n"); + return(0); + } + } + rawtxstr = bitcoin_json2hex(coin,&cltxid,txobj); + char str[65]; printf("CLTV.%s (%s)\n",bits256_str(str,cltxid),rawtxstr); + memset(&V,0,sizeof(V)); + V.signers[0].privkey = privkey; + bitcoin_verifytx(coin,&signedtxid,&signedtx,rawtxstr,&V); + free(rawtxstr); + if ( signedtx != 0 ) + printf("signed CLTV.%s (%s)\n",bits256_str(str,signedtxid),signedtx); + else printf("error generating signedtx\n"); + free_json(txobj); + return(signedtx); +} + cJSON *bitcoin_txtest(struct iguana_info *coin,char *rawtxstr,bits256 txid) { - struct iguana_msgtx msgtx; char str[65],str2[65]; bits256 checktxid,blockhash,myprivkey; + struct iguana_msgtx msgtx; char str[65],str2[65]; bits256 checktxid,blockhash,signedtxid; cJSON *retjson,*txjson; uint8_t *serialized,*serialized2; struct iguana_txid T,*tp; - char vpnstr[64]; int32_t n,i,*scriptlens,height,n2,maxsize,len = (int32_t)strlen(rawtxstr); + struct vin_info *V; char vpnstr[64],*txbytes,*signedtx; int32_t n,txstart,height,n2,maxsize,len; + len = (int32_t)strlen(rawtxstr); rawtxstr = refstr; maxsize = len + 32768; serialized = calloc(1,maxsize); serialized2 = calloc(1,maxsize); len >>= 1; + V = 0; vpnstr[0] = 0; -decode_hex(myprivkey.bytes,sizeof(myprivkey),"18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725"); memset(&msgtx,0,sizeof(msgtx)); + if ( len < maxsize ) { decode_hex(serialized,len,rawtxstr); @@ -1103,16 +1269,16 @@ decode_hex(myprivkey.bytes,sizeof(myprivkey),"18E14A7B6A307F426A94F8114701E7C8E7 free(serialized), free(serialized2); return(cJSON_Parse("{\"error\":\"cant parse txbytes\"}")); } - scriptlens = calloc(msgtx.tx_in,sizeof(*scriptlens)); - for (i=0; inuminputs; i++) - strcpy(T->inputs[i].sigs,"00"); - strcpy(vin->sigs,redeemscript); - vin->sequence = (uint32_t)-1; - T->nlocktime = 0; - //disp_cointx(&T); - emit_cointx(&hash2,data,sizeof(data),T,oldtx_format,SIGHASH_ALL); - //printf("HASH2.(%llx)\n",(long long)hash2.txid); - if ( bp_sign(&key,hash2.bytes,sizeof(hash2),&sig,&siglen) != 0 ) - { - memcpy(sigbuf,sig,siglen); - sigbuf[siglen++] = SIGHASH_ALL; - init_hexbytes_noT(sigs[privkeyind],sigbuf,(int32_t)siglen); - strcpy(vin->sigs,"00"); - for (i=0; isigs + strlen(vin->sigs),"%02x%s",(int32_t)strlen(sigs[i])>>1,sigs[i]); - //printf("(%s).%ld ",sigs[i],strlen(sigs[i])); - } - } - len = (int32_t)(strlen(redeemscript)/2); - if ( len >= 0xfd ) - sprintf(&vin->sigs[strlen(vin->sigs)],"4d%02x%02x",len & 0xff,(len >> 8) & 0xff); - else sprintf(&vin->sigs[strlen(vin->sigs)],"4c%02x",len); - sprintf(&vin->sigs[strlen(vin->sigs)],"%s",redeemscript); - //printf("after A.(%s) othersig.(%s) siglen.%02lx -> (%s)\n",hexstr,othersig != 0 ? othersig : "",siglen,vin->sigs); - //printf("vinsigs.(%s) %ld\n",vin->sigs,strlen(vin->sigs)); - _emit_cointx(hexstr,sizeof(hexstr),T,oldtx_format); - //disp_cointx(&T); - free(T); - return(clonestr(hexstr)); - } - else printf("error signing\n"); - free(T); -}*/ - #define EXCHANGE_NAME "bitcoin" #define UPDATE bitcoin ## _price #define SUPPORTS bitcoin ## _supports @@ -1250,7 +1386,11 @@ char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson) { - return(clonestr("{\"error\":\"bitcoin is not yet\"}")); + cJSON *retjson,*array = cJSON_CreateArray(); + retjson = cJSON_CreateObject(); + instantdex_acceptable(SuperNET_MYINFO(0),array,"","*","*",0); + jadd(retjson,"result",array); + return(jprint(retjson,1)); } char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson) diff --git a/iguana/exchanges/bitcoin.h b/iguana/exchanges/bitcoin.h index 3a9fa468f..3b6655e2d 100755 --- a/iguana/exchanges/bitcoin.h +++ b/iguana/exchanges/bitcoin.h @@ -22,6 +22,7 @@ #define SIGHASH_SINGLE 3 #define SIGHASH_ANYONECANPAY 0x80 +#define SCRIPT_OP_NOP 0x00 #define SCRIPT_OP_TRUE 0x51 #define SCRIPT_OP_2 0x52 #define SCRIPT_OP_3 0x53 diff --git a/iguana/exchanges/nxtae.c b/iguana/exchanges/nxtae.c index 429bce7b4..212945906 100755 --- a/iguana/exchanges/nxtae.c +++ b/iguana/exchanges/nxtae.c @@ -13,13 +13,13 @@ * * ******************************************************************************/ -#define NXT_ASSETID ('N' + ((uint64_t)'X'<<8) + ((uint64_t)'T'<<16)) // 5527630 #define DEFAULT_NXT_DEADLINE 720 #define issue_NXTPOST(cmdstr) bitcoind_RPC(0,"curl",myinfo->NXTAPIURL,0,0,cmdstr) #define NXT_MSTYPE 5 #define NXT_ASSETTYPE 2 #define NXT_GENESISTIME 1385294400 + cJSON *_issue_NXTjson(struct supernet_info *myinfo,char *extra) { char cmd[4096],*jsonstr; cJSON *json = 0; @@ -101,6 +101,48 @@ uint32_t get_blockutime(struct supernet_info *myinfo,uint32_t blocknum) return(timestamp); } +uint32_t get_NXTheight(struct supernet_info *myinfo,uint32_t *firsttimep) +{ + static uint32_t last,lastheight,lastNXTtime; + cJSON *json; uint32_t height = 0; char cmd[256],*jsonstr; + if ( time(NULL) > last+10 ) + { + sprintf(cmd,"requestType=getState"); + if ( (jsonstr= issue_NXTPOST(cmd)) != 0 ) + { + //printf("(%s) -> (%s)\n",cmd,jsonstr); + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( firsttimep != 0 ) + lastNXTtime = *firsttimep = (uint32_t)get_cJSON_int(json,"time"); + height = (int32_t)get_cJSON_int(json,"numberOfBlocks"); + if ( height > 0 ) + height--; + lastheight = height; + free_json(json); + } + free(jsonstr); + } + last = (uint32_t)time(NULL); + } + else + { + height = lastheight; + if ( firsttimep != 0 ) + *firsttimep = lastNXTtime; + } + return(height); +} + +char *issue_approveTransaction(struct supernet_info *myinfo,char *fullhash,char *revealed,bits256 msghash,char *NXTACCTSECRET) +{ + char cmd[4096],secret[8192],str[65]; + escape_code(secret,NXTACCTSECRET); + sprintf(cmd,"requestType=approveTransaction&secretPhrase=%s&transactionFullHash=%s&revealedSecret=%s&revealedSecretIsText=false&messageIsText=false&feeNQT=%d&deadline=%d&message=%s",secret,fullhash,revealed,0,DEFAULT_NXT_DEADLINE,bits256_str(str,msghash)); + printf("submit approve.(%s)\n",cmd); + return(issue_NXTPOST(cmd)); +} + char *MGWassets[][3] = { { "12659653638116877017", "BTC", "8" }, @@ -404,6 +446,101 @@ int32_t NXT_assetpolarity(struct supernet_info *myinfo,char *name) else return(0); } +uint64_t set_NXTtx(struct supernet_info *myinfo,struct NXT_tx *tx,uint64_t assetidbits,int64_t amount,uint64_t other64bits,int32_t feebits) +{ + char assetidstr[64]; int32_t decimals; uint64_t fee = 0; struct NXT_tx U; + memset(&U,0,sizeof(U)); + U.senderbits = myinfo->myaddr.nxt64bits; + U.recipientbits = other64bits; + U.assetidbits = assetidbits; + if ( feebits >= 0 ) + { + fee = (amount >> feebits); + if ( fee == 0 ) + fee = 1; + } + if ( assetidbits != NXT_ASSETID ) + { + expand_nxt64bits(assetidstr,assetidbits); + U.type = get_assettype(myinfo,&decimals,assetidstr); + //U.subtype = ap->subtype; + U.U.quantityQNT = amount - fee; + } else U.U.amountNQT = amount - fee; + U.feeNQT = 0; + U.deadline = DEFAULT_NXT_DEADLINE; + printf("set_NXTtx(%llu -> %llu) %.8f of %llu\n",(long long)U.senderbits,(long long)U.recipientbits,dstr(amount),(long long)assetidbits); + *tx = U; + return(fee); +} + +cJSON *gen_NXT_tx_json(struct supernet_info *myinfo,char *fullhash,struct NXT_tx *utx,char *reftxid,double myshare) +{ + cJSON *json = 0; char secret[8192],cmd[MAX_JSON_FIELD],destNXTaddr[64],assetidstr[64],*retstr; + if ( utx->senderbits == myinfo->myaddr.nxt64bits ) + { + expand_nxt64bits(destNXTaddr,utx->recipientbits); + cmd[0] = 0; + if ( utx->type == 0 && utx->subtype == 0 ) + sprintf(cmd,"requestType=sendMoney&amountNQT=%lld",(long long)(utx->U.amountNQT*myshare)); + else + { + expand_nxt64bits(assetidstr,utx->assetidbits); + if ( utx->type == 2 && utx->subtype == 1 ) + sprintf(cmd,"requestType=transferAsset&asset=%s&quantityQNT=%lld",assetidstr,(long long)(utx->U.quantityQNT*myshare)); + else if ( utx->type == 5 && utx->subtype == 3 ) + sprintf(cmd,"requestType=transferCurrency¤cy=%s&units=%lld",assetidstr,(long long)(utx->U.quantityQNT*myshare)); + else + { + printf("unsupported type.%d subtype.%d\n",utx->type,utx->subtype); + return(0); + } + } + if ( utx->comment[0] != 0 ) + strcat(cmd,"&messageIsText=true&message="),strcat(cmd,utx->comment); + if ( reftxid != 0 && reftxid[0] != 0 && cmd[0] != 0 ) + strcat(cmd,"&referencedTransactionFullHash="),strcat(cmd,reftxid); + if ( cmd[0] != 0 ) + { + escape_code(secret,myinfo->secret); + sprintf(cmd+strlen(cmd),"&deadline=%u&feeNQT=%lld&secretPhrase=%s&recipient=%s&broadcast=false",utx->deadline,(long long)utx->feeNQT,secret,destNXTaddr); + if ( reftxid != 0 && reftxid[0] != 0 ) + sprintf(cmd+strlen(cmd),"&referencedTransactionFullHash=%s",reftxid); + //printf("generated cmd.(%s) reftxid.(%s)\n",cmd,reftxid); + retstr = issue_NXTPOST(cmd); + if ( retstr != 0 ) + { + json = cJSON_Parse(retstr); + if ( (json= cJSON_Parse(retstr)) != 0 ) + { + if ( jstr(json,"fullHash") != 0 ) + strcpy(fullhash,jstr(json,"fullHash")); + // printf("Parsed.(%s)\n",cJSON_Print(json)); + } + free(retstr); + } + } + } else printf("cant gen_NXT_txjson when sender.%llu is not me.%llu\n",(long long)utx->senderbits,(long long)myinfo->myaddr.nxt64bits); + return(json); +} + +int32_t calc_raw_NXTtx(struct supernet_info *myinfo,char *fullhash,char *utxbytes,char *sighash,uint64_t assetidbits,int64_t amount,uint64_t other64bits) +{ + int32_t retval = -1; struct NXT_tx U; cJSON *json; + utxbytes[0] = sighash[0] = 0; + set_NXTtx(myinfo,&U,assetidbits,amount,other64bits,0); + json = gen_NXT_tx_json(myinfo,fullhash,&U,0,1.); + if ( json != 0 ) + { + if ( extract_cJSON_str(utxbytes,1024,json,"transactionBytes") > 0 && extract_cJSON_str(sighash,1024,json,"signatureHash") > 0 ) + { + retval = 0; + printf("generated utx.(%s) sighash.(%s)\n",utxbytes,sighash); + } + free_json(json); + } + return(retval); +} + #define EXCHANGE_NAME "nxtae" #define UPDATE nxtae ## _price #define SUPPORTS nxtae ## _supports @@ -544,7 +681,7 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang return(hbla); } -uint64_t submit_triggered_nxtae(struct supernet_info *myinfo,int32_t dotrade,char **retjsonstrp,int32_t is_MS,char *bidask,uint64_t assetid,uint64_t qty,uint64_t NXTprice,char *triggerhash,char *comment,uint64_t otherNXT,uint32_t triggerheight) +uint64_t submit_triggered_nxtae(struct supernet_info *myinfo,int32_t dotrade,char **retjsonstrp,int32_t is_MS,char *bidask,uint64_t assetid,uint64_t qty,uint64_t NXTprice,char *triggerhash,char *comment,char *otherNXT,uint32_t triggerheight,char *refhash) { int32_t deadline = 1 + 20; uint64_t txid = 0; struct destbuf errstr; char cmd[4096],secret[8192],*jsonstr; cJSON *json; if ( retjsonstrp != 0 ) @@ -564,21 +701,18 @@ uint64_t submit_triggered_nxtae(struct supernet_info *myinfo,int32_t dotrade,cha } if ( otherNXT != 0 ) sprintf(cmd+strlen(cmd),"&recipient=%llu",(long long)otherNXT); + if ( refhash != 0 ) + sprintf(cmd+strlen(cmd),"&referencedTransactionFullHash=%s",refhash); if ( triggerhash != 0 && triggerhash[0] != 0 ) - { - if ( triggerheight == 0 ) - sprintf(cmd+strlen(cmd),"&referencedTransactionFullHash=%s",triggerhash); - else sprintf(cmd+strlen(cmd),"&referencedTransactionFullHash=%s&phased=true&phasingFinishHeight=%u&phasingVotingModel=4&phasingQuorum=1&phasingLinkedFullHash=%s",triggerhash,triggerheight,triggerhash); - } + sprintf(cmd+strlen(cmd),"&phased=true&phasingFinishHeight=%u&phasingVotingModel=4&phasingQuorum=1&phasingLinkedFullHash=%s",triggerheight,triggerhash); if ( comment != 0 && comment[0] != 0 ) sprintf(cmd+strlen(cmd),"&message=%s",comment); if ( dotrade == 0 ) { if ( retjsonstrp != 0 ) { - json = cJSON_CreateObject(); - jaddstr(json,"submit",cmd); - *retjsonstrp = jprint(json,1); + strcat(cmd,"&broadcast=false"); + *retjsonstrp = issue_NXTPOST(cmd); } return(0); } @@ -603,6 +737,30 @@ uint64_t submit_triggered_nxtae(struct supernet_info *myinfo,int32_t dotrade,cha return(txid); } +char *NXT_phasedxfer(struct supernet_info *myinfo,char *othercoin,char *othercoinaddr,char *otherNXT,uint64_t assetid,double volume,char *comment) +{ + uint8_t NXT_rmd160[20],addrtype; int32_t is_MS,triggerheight,dotrade = 0; + char onetimecoinaddr[64],triggerhash[41],*cmd,*signedtx = 0; uint64_t ap_mult; + if ( (triggerheight= get_NXTheight(myinfo,0)) != 0 ) + { + bitcoin_addr2rmd160(&addrtype,NXT_rmd160,onetimecoinaddr); + init_hexbytes_noT(triggerhash,NXT_rmd160,20); + triggerheight += DEFAULT_NXT_DEADLINE; + if ( (ap_mult= get_assetmult(myinfo,&is_MS,assetid)) == 0 ) + return(0); + else + { + if ( assetid == 0 || assetid == NXT_ASSETID ) + cmd = "sendMoney"; + else if ( is_MS == 0 ) + cmd = "transferAsset"; + else cmd = "transferCurrency"; + submit_triggered_nxtae(myinfo,dotrade,&signedtx,is_MS,cmd,assetid,(volume * SATOSHIDEN) / ap_mult,0,triggerhash,comment,otherNXT,triggerheight,0); + return(signedtx); + } + } else return(0); +} + char *fill_nxtae(struct supernet_info *myinfo,int32_t dotrade,uint64_t *txidp,int32_t dir,double price,double volume,uint64_t baseid,uint64_t relid) { uint64_t txid,assetid,avail,qty,priceNQT,ap_mult; int32_t is_MS; char retbuf[512],*errstr,*cmdstr; @@ -617,7 +775,7 @@ char *fill_nxtae(struct supernet_info *myinfo,int32_t dotrade,uint64_t *txidp,in if ( is_MS == 0 ) cmdstr = dir > 0 ? "placeBidOrder" : "placeAskOrder"; else cmdstr = dir > 0 ? "currencyBuy" : "currencySell"; - txid = submit_triggered_nxtae(myinfo,dotrade,&errstr,is_MS,cmdstr,assetid,qty,priceNQT,0,0,0,0); + txid = submit_triggered_nxtae(myinfo,dotrade,&errstr,is_MS,cmdstr,assetid,qty,priceNQT,0,0,0,0,0); if ( errstr != 0 ) sprintf(retbuf,"{\"error\":\"%s\"}",errstr), free(errstr); else sprintf(retbuf,"{\"result\":\"success\",\"txid\":\"%llu\"}",(long long)txid); diff --git a/iguana/iguana777.h b/iguana/iguana777.h index 136110acb..aae8cf675 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -470,10 +470,10 @@ struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],r struct vin_info { struct iguana_msgvin vin; - int32_t M,N,validmask,spendlen,type; + int32_t M,N,validmask,spendlen,type,p2shlen; struct vin_signer signers[16]; char coinaddr[65]; - uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; + uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE]; }; // peers @@ -588,7 +588,7 @@ double dxblend(double *destp,double val,double decay); // json int32_t iguana_processjsonQ(struct iguana_info *coin); // reentrant, can be called during any idletime -char *iguana_JSON(char *jsonstr); +char *iguana_JSON(char *); char *SuperNET_p2p(struct iguana_info *coin,struct iguana_peer *addr,int32_t *delaymillisp,char *ipaddr,uint8_t *data,int32_t datalen,int32_t compressed); char *mbstr(char *str,double); @@ -682,7 +682,7 @@ void iguana_bundleiclear(struct iguana_info *coin,struct iguana_bundle *bp,int32 int32_t hcalc_bitsize(uint64_t x); struct iguana_pkhash *iguana_pkhashfind(struct iguana_info *coin,struct iguana_pkhash *p,uint8_t rmd160[20]); struct iguana_txid *iguana_txidfind(struct iguana_info *coin,int32_t *heightp,struct iguana_txid *tx,bits256 txid); -int32_t iguana_scriptgen(struct iguana_info *coin,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,int32_t txi,struct vin_info *vp); +int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi); int32_t iguana_ramchain_spendtxid(struct iguana_info *coin,bits256 *txidp,struct iguana_txid *T,int32_t numtxids,bits256 *X,int32_t numexternaltxids,struct iguana_spend *s); struct iguana_info *iguana_coinselect(); void iguana_dedicatedloop(struct iguana_info *coin,struct iguana_peer *addr); @@ -728,9 +728,9 @@ int32_t category_peer(struct supernet_info *myinfo,struct iguana_peer *addr,bits int32_t btc_wif2priv(uint8_t *addrtypep,uint8_t privkey[32],char *wifstr); bits256 iguana_chaingenesis(int32_t version,uint32_t timestamp,uint32_t nBits,uint32_t nonce,bits256 merkle_root); int32_t iguana_send_ConnectTo(struct iguana_info *coin,struct iguana_peer *addr); -cJSON *iguana_txjson(struct iguana_info *coin,struct iguana_txid *tx,int32_t height); +cJSON *iguana_txjson(struct iguana_info *coin,struct iguana_txid *tx,int32_t height,struct vin_info *V); char *iguana_txscan(struct iguana_info *coin,cJSON *json,uint8_t *data,int32_t recvlen,bits256 txid); -char *iguana_rawtxbytes(struct iguana_info *coin,uint8_t *serialized,int32_t datalen,cJSON *json,struct iguana_msgtx *msgtx); +char *iguana_rawtxbytes(struct iguana_info *coin,cJSON *json,struct iguana_msgtx *msgtx); int32_t iguana_send_VPNversion(struct iguana_info *coin,struct iguana_peer *addr,uint64_t myservices); void exchanges777_init(struct supernet_info *myinfo,cJSON *exchanges,int32_t sleepflag); int32_t iguana_rwvout(int32_t rwflag,struct OS_memspace *mem,uint8_t *serialized,struct iguana_msgvout *msg); diff --git a/iguana/iguana_instantdex.c b/iguana/iguana_instantdex.c index 1f44e5d7a..24e450687 100755 --- a/iguana/iguana_instantdex.c +++ b/iguana/iguana_instantdex.c @@ -20,19 +20,28 @@ #define INSTANTDEX_HOPS 3 #define INSTANTDEX_DURATION 60 -#define INSTANTDEX_PROPOSE 1 -#define INSTANTDEX_ACCEPT 2 -#define INSTANTDEX_CONFIRM 3 +#define INSTANTDEX_NXTOFFER 1 +#define INSTANTDEX_REQUEST 2 +#define INSTANTDEX_PROPOSE 3 +#define INSTANTDEX_ACCEPT 4 +#define INSTANTDEX_CONFIRM 5 -cJSON *InstantDEX_argjson(char *reference,char *message,bits256 basetxid,bits256 reltxid,int32_t iter,int32_t val,int32_t val2) +struct instantdex_entry { char base[24],rel[24]; double price,volume,pendingvolume; uint32_t expiration,nonce; }; +struct instantdex_accept { struct queueitem DL; uint64_t txid; struct instantdex_entry A; }; + +cJSON *InstantDEX_argjson(char *reference,char *message,char *othercoinaddr,char *otherNXTaddr,int32_t iter,int32_t val,int32_t val2) { cJSON *argjson = cJSON_CreateObject(); if ( reference != 0 ) jaddstr(argjson,"refstr",reference); if ( message != 0 && message[0] != 0 ) jaddstr(argjson,"message",message); - jaddbits256(argjson,"basetxid",basetxid); - jaddbits256(argjson,"reltxid",reltxid); + if ( othercoinaddr != 0 && othercoinaddr[0] != 0 ) + jaddstr(argjson,"othercoinaddr",othercoinaddr); + if ( otherNXTaddr != 0 && otherNXTaddr[0] != 0 ) + jaddstr(argjson,"otherNXTaddr",otherNXTaddr); + //jaddbits256(argjson,"basetxid",basetxid); + //jaddbits256(argjson,"reltxid",reltxid); if ( iter != 3 ) { if ( val == 0 ) @@ -204,11 +213,56 @@ double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *s return(0); } -char *instantdex_request(struct supernet_info *myinfo,char *cmdstr,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *data,int32_t datalen) +cJSON *instantdex_acceptjson(struct instantdex_accept *ap) +{ + cJSON *item = cJSON_CreateObject(); + jadd64bits(item,"orderid",ap->txid); + jaddstr(item,"base",ap->A.base); + jaddstr(item,"rel",ap->A.rel); + jaddnum(item,"price",ap->A.price); + jaddnum(item,"volume",ap->A.volume); + jaddnum(item,"pendingvolume",ap->A.pendingvolume); + jaddnum(item,"expiresin",ap->A.expiration - time(NULL)); + return(item); +} + +double instantdex_acceptable(struct supernet_info *myinfo,cJSON *array,char *refstr,char *base,char *rel,double volume) +{ + struct instantdex_accept PAD,*ap,*retap = 0; double price = 0.; uint32_t now; + now = (uint32_t)time(NULL); + memset(&PAD,0,sizeof(PAD)); + queue_enqueue("acceptableQ",&myinfo->acceptableQ,&PAD.DL,0); + while ( (ap= queue_dequeue(&myinfo->acceptableQ,0)) != 0 && ap != &PAD ) + { + if ( volume > 0. && (strcmp(base,"*") == 0 || strcmp(base,ap->A.base) == 0) && (strcmp(rel,"*") == 0 || strcmp(rel,ap->A.rel) == 0) && volume < (ap->A.volume - ap->A.pendingvolume) ) + { + if ( ap->A.price > price ) + { + price = ap->A.price; + retap = ap; + } + } + if ( now < ap->A.expiration ) + { + if ( array != 0 ) + jaddi(array,instantdex_acceptjson(ap)); + queue_enqueue("acceptableQ",&myinfo->acceptableQ,&ap->DL,0); + } + } + if ( retap != 0 ) + { + retap->A.pendingvolume -= volume; + price = retap->A.price; + } + return(price); +} + +char *instantdex_request(struct supernet_info *myinfo,char *cmdstr,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *data,int32_t datalen) // receiving side { - char *base,*rel,*request,*refstr,*nextcmdstr,*message,*traderip; - double volume,price,aveprice,totalvol; cJSON *newjson; int32_t duration,flags,nextcmd; - int32_t num,depth; struct exchange_quote sortbuf[1000]; bits256 basetxid,reltxid; + struct NXT_tx feeT; char fullhash[256],*othercoinaddr; cJSON *feejson; uint64_t assetbits = 0; + char *base,*rel,*request,*refstr,*nextcmdstr,*message,*traderip,*otherNXTaddr; + double volume,price; cJSON *newjson; int32_t duration,flags,nextcmd; + int32_t num,depth; //struct exchange_quote sortbuf[1000]; bits256 basetxid,reltxid;,aveprice,totalvol if ( argjson != 0 ) { num = 0; @@ -227,40 +281,73 @@ char *instantdex_request(struct supernet_info *myinfo,char *cmdstr,struct instan printf("got my own request\n"); return(clonestr("{\"result\":\"got my own request\"}")); } - if ( strcmp(cmdstr,"request") == 0 ) + // NXToffer: + // sends NXT assetid, volume and desired rel, also reftx + if ( strcmp(cmdstr,"NXToffer") == 0 ) { - aveprice = instantdex_aveprice(myinfo,sortbuf,(int32_t)(sizeof(sortbuf)/sizeof(*sortbuf)),&totalvol,base,rel,volume,argjson); - OS_randombytes(basetxid.bytes,sizeof(basetxid)); - OS_randombytes(reltxid.bytes,sizeof(reltxid)); - char str[65]; printf("GENERATE txid.%s aveprice %.8f vol %f\n",bits256_str(str,basetxid),aveprice,totalvol); - nextcmd = INSTANTDEX_PROPOSE; - nextcmdstr = "proposal"; - message = "hello"; - price = aveprice; - volume = totalvol; + if ( (price= instantdex_acceptable(myinfo,0,refstr,base,rel,volume)) > 0. ) + { + // sends NXT assetid, volume and desired + if ( strcmp(base,"NXT") == 0 || strcmp(base,"nxt") == 0 ) + assetbits = NXT_ASSETID; + else if ( is_decimalstr(base) > 0 ) + assetbits = calc_nxt64bits(base); + if ( assetbits != 0 ) + { + nextcmd = INSTANTDEX_REQUEST; + nextcmdstr = "request"; + } + } + } + else if ( strcmp(cmdstr,"request") == 0 ) + { + // request: + // other node sends (othercoin, othercoinaddr, otherNXT and reftx that expires before phasedtx) + if ( (strcmp(rel,"BTC") == 0 || strcmp(base,"BTC") == 0) && (price= instantdex_acceptable(myinfo,0,refstr,base,rel,volume)) > 0. ) + { + //aveprice = instantdex_aveprice(myinfo,sortbuf,(int32_t)(sizeof(sortbuf)/sizeof(*sortbuf)),&totalvol,base,rel,volume,argjson); + set_NXTtx(myinfo,&feeT,assetbits,SATOSHIDEN*3,calc_nxt64bits(INSTANTDEX_ACCT),-1); + if ( (feejson= gen_NXT_tx_json(myinfo,fullhash,&feeT,0,1.)) != 0 ) + free_json(feejson); + nextcmd = INSTANTDEX_PROPOSE; + nextcmdstr = "proposal"; + othercoinaddr = myinfo->myaddr.BTC; + otherNXTaddr = myinfo->myaddr.NXTADDR; + } } else { - basetxid = jbits256(argjson,"basetxid"); - reltxid = jbits256(argjson,"reltxid"); if ( strcmp(cmdstr,"proposal") == 0 ) { + // proposal: + // NXT node submits phasedtx that refers to it, but it wont confirm nextcmd = INSTANTDEX_ACCEPT; nextcmdstr = "accept"; - message = "world"; + message = ""; + //instantdex_phasetxsubmit(refstr); } else if ( strcmp(cmdstr,"accept") == 0 ) { + // accept: + // other node verifies unconfirmed has phasedtx and broadcasts cltv, also to NXT node, releases trigger nextcmd = INSTANTDEX_CONFIRM; nextcmdstr = "confirm"; - message = "confirmed"; + message = ""; + //instantdex_phasedtxverify(); + //instantdex_cltvbroadcast(); + //instantdex_releasetrigger(); } else if ( strcmp(cmdstr,"confirm") == 0 ) { + // confirm: + // NXT node verifies bitcoin txbytes has proper payment and cashes in with onetimepubkey + // BTC* node approves phased tx with onetimepubkey + //instantdex_cltvverify(); + //instantdex_phasetxapprove(); return(clonestr("{\"error\":\"trade confirmed\"}")); } } - if ( (newjson= InstantDEX_argjson(refstr,message,basetxid,reltxid,nextcmd,duration,flags)) != 0 ) + if ( nextcmd != 0 && (newjson= InstantDEX_argjson(refstr,message,othercoinaddr,otherNXTaddr,nextcmd,duration,flags)) != 0 ) { jaddnum(newjson,"price",price); jaddnum(newjson,"volume",volume); @@ -274,8 +361,10 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms { static struct { char *cmdstr; char *(*func)(struct supernet_info *myinfo,char *cmdstr,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *data,int32_t datalen); uint64_t cmdbits; } cmds[] = { - { "request", instantdex_request }, { "proposal", instantdex_request }, - { "accept", instantdex_request }, { "confirm", instantdex_request }, + { "NXToffer", instantdex_request }, { "request", instantdex_request }, + { "proposal", instantdex_request }, + { "accept", instantdex_request }, + { "confirm", instantdex_request }, }; char *retstr = 0; int32_t i; uint64_t cmdbits; if ( cmds[0].cmdbits == 0 ) @@ -345,7 +434,34 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char #include "../includes/iguana_apidefs.h" -THREE_STRINGS_AND_DOUBLE(InstantDEX,request,reference,base,rel,volume) +// NXTrequest: +// sends NXT assetid, volume and desired +// request: +// other node sends (othercoin, othercoinaddr, otherNXT and reftx that expires well before phasedtx) +// proposal: +// NXT node submits phasedtx that refers to it, but it wont confirm +// approve: +// other node verifies unconfirmed has phasedtx and broadcasts cltv, also to NXT node, releases trigger +// confirm: +// NXT node verifies bitcoin txbytes has proper payment and cashes in with onetimepubkey +// BTC* node approves phased tx with onetimepubkey + +TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,acceptable,base,rel,price,volume) +{ + struct instantdex_accept A; bits256 hash; + memset(&A,0,sizeof(A)); + OS_randombytes((uint8_t *)&A.A.nonce,sizeof(A.A.nonce)); + safecopy(A.A.base,base,sizeof(A.A.base)); + safecopy(A.A.rel,rel,sizeof(A.A.rel)); + A.A.price = price, A.A.volume = volume; + A.A.expiration = (uint32_t)time(NULL) + 3600; + vcalc_sha256(0,hash.bytes,(void *)&A.A,sizeof(A.A)); + A.txid = hash.txid; + queue_enqueue("acceptableQ",&myinfo->acceptableQ,&A.DL,0); + return(clonestr("{\"result\":\"added acceptable\"}")); +} + +THREE_STRINGS_AND_DOUBLE(InstantDEX,NXToffer,reference,base,rel,volume) // initiator { int32_t hops = INSTANTDEX_HOPS; cJSON *argjson; if ( remoteaddr == 0 ) @@ -355,21 +471,35 @@ THREE_STRINGS_AND_DOUBLE(InstantDEX,request,reference,base,rel,volume) jaddstr(argjson,"base",base); jaddstr(argjson,"rel",rel); jaddnum(argjson,"volume",volume); - return(instantdex_sendcmd(myinfo,argjson,"request",myinfo->ipaddr,hops)); + return(instantdex_sendcmd(myinfo,argjson,"NXToffer",myinfo->ipaddr,hops)); } else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); } -TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,proposal,reference,message,basetxid,reltxid,duration,flags) +THREE_STRINGS_AND_DOUBLE(InstantDEX,request,reference,base,rel,volume) // initiator { int32_t hops = INSTANTDEX_HOPS; cJSON *argjson; if ( remoteaddr == 0 ) { - argjson = InstantDEX_argjson(reference,message,basetxid,reltxid,INSTANTDEX_PROPOSE,duration,flags); + argjson = cJSON_CreateObject(); + jaddstr(argjson,"refstr",reference); + jaddstr(argjson,"base",base); + jaddstr(argjson,"rel",rel); + jaddnum(argjson,"volume",volume); + return(instantdex_sendcmd(myinfo,argjson,"request",myinfo->ipaddr,hops)); + } else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); +} + +TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,proposal,reference,message,basetxid,reltxid,duration,flags) // responder +{ + int32_t hops = INSTANTDEX_HOPS; cJSON *argjson; char str[65],str2[65]; + if ( remoteaddr == 0 ) + { + argjson = InstantDEX_argjson(reference,message,bits256_str(str,basetxid),bits256_str(str2,basetxid),INSTANTDEX_PROPOSE,duration,flags); return(instantdex_sendcmd(myinfo,argjson,"proposal",myinfo->ipaddr,hops)); } else return(clonestr("{\"error\":\"InstantDEX API proposal only local usage!\"}")); } -TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,accept,reference,message,basetxid,reltxid,duration,flags) +/*TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,accept,reference,message,basetxid,reltxid,duration,flags) { int32_t hops = INSTANTDEX_HOPS; cJSON *argjson; if ( remoteaddr == 0 ) @@ -387,7 +517,7 @@ TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,confirm,reference,message,basetx argjson = InstantDEX_argjson(reference,message,basetxid,reltxid,INSTANTDEX_CONFIRM,baseheight,relheight); return(instantdex_sendcmd(myinfo,argjson,"confirm",myinfo->ipaddr,hops)); } else return(clonestr("{\"error\":\"InstantDEX API confirm only local usage!\"}")); -} +}*/ #include "../includes/iguana_apiundefs.h" diff --git a/iguana/iguana_json.c b/iguana/iguana_json.c index 73a509f2d..1b0e9bec2 100755 --- a/iguana/iguana_json.c +++ b/iguana/iguana_json.c @@ -89,6 +89,7 @@ cJSON *SuperNET_helpjson() #define IGUANA_HELP_SSH(agent,name,str,str2,hash) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"))) #define IGUANA_HELP_SSHI(agent,name,str,str2,hash,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#val,"int"))) +#define IGUANA_HELP_SSDD(agent,name,str,str2,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#val,"float"),helpitem(#val2,"float"))) #define IGUANA_HELP_SSHII(agent,name,str,str2,hash,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray5(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#val,"int"),helpitem(#val2,"int"))) #define IGUANA_HELP_SSHHII(agent,name,str,str2,hash,hash2,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#hash2,"hash"),helpitem(#val,"int"),helpitem(#val2,"int"))) #define IGUANA_HELP_SI(agent,name,str,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"int"))) @@ -164,7 +165,8 @@ cJSON *SuperNET_helpjson() #define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_HELP_SSSDDD #define THREE_STRINGS_AND_DOUBLE IGUANA_HELP_SSSD #define STRING_AND_DOUBLE IGUANA_HELP_SD - +#define TWO_STRINGS_AND_TWO_DOUBLES IGUANA_HELP_SSDD + #include "../includes/iguana_apideclares.h" #include "../includes/iguana_apiundefs.h" @@ -840,6 +842,7 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agentstr,char *method,c #define IGUANA_DISPATCH_SSS(agent,name,str,str2,str3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3))) #define IGUANA_DISPATCH_SSSS(agent,name,str,str2,str3,str4) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jstr(json,#str4))) #define IGUANA_DISPATCH_SSSD(agent,name,str,str2,str3,amount) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#amount))) +#define IGUANA_DISPATCH_SSDD(agent,name,str,str2,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jdouble(json,#val),jdouble(json,#val2))) #define IGUANA_DISPATCH_SSSDDD(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#val),jdouble(json,#val2),jdouble(json,#val3))) #define IGUANA_DISPATCH_SSSIII(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jint(json,#val),jint(json,#val2),jint(json,#val3))) @@ -920,7 +923,8 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agentstr,char *method,c #define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_DISPATCH_SSSDDD #define THREE_STRINGS_AND_DOUBLE IGUANA_DISPATCH_SSSD #define STRING_AND_DOUBLE IGUANA_DISPATCH_SD - +#define TWO_STRINGS_AND_TWO_DOUBLES IGUANA_DISPATCH_SSDD + #include "../includes/iguana_apideclares.h" //#undef IGUANA_ARGS diff --git a/iguana/iguana_pubkeys.c b/iguana/iguana_pubkeys.c index 9c1d35627..50fe6547a 100755 --- a/iguana/iguana_pubkeys.c +++ b/iguana/iguana_pubkeys.c @@ -345,7 +345,10 @@ cstring *base58_decode_check(uint8_t *addrtype,const char *s_in) } else { - char str[65]; printf("checkhash mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x (%s)\n",s->str[s->len - 4]&0xff,s->str[s->len - 3]&0xff,s->str[s->len - 2]&0xff,s->str[s->len - 1]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28],bits256_str(str,hash)); + int32_t i; + for (i=0; ilen; i++) + printf("%02x ",s->str[i]&0xff); + char str[65]; printf(" s->len.%ld\n>>>>>>>> matched %02x %02x %02x %02x vs %02x %02x %02x %02x (%s) (%s)\n",s->len,s->str[s->len - 4]&0xff,s->str[s->len - 3]&0xff,s->str[s->len - 2]&0xff,s->str[s->len - 1]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28],bits256_str(str,hash),s_in); } } cstr_free(s,true); diff --git a/iguana/iguana_tx.c b/iguana/iguana_tx.c index 8aac12a34..edf4ed131 100755 --- a/iguana/iguana_tx.c +++ b/iguana/iguana_tx.c @@ -58,7 +58,7 @@ int32_t iguana_voutset(struct iguana_info *coin,uint8_t *scriptspace,char *asmst vout->value = u->value; vout->pk_script = scriptspace; memset(&V,0,sizeof(V)); - scriptlen = iguana_scriptgen(coin,coinaddr,scriptspace,asmstr,p->rmd160,u->type,i,&V); + scriptlen = iguana_scriptgen(coin,&V.M,&V.N,coinaddr,scriptspace,asmstr,p->rmd160,u->type,(const struct vin_info *)&V,i); } vout->pk_scriptlen = scriptlen; return(scriptlen); diff --git a/iguana/main.c b/iguana/main.c index 03aed90ae..6cd7575ae 100644 --- a/iguana/main.c +++ b/iguana/main.c @@ -346,7 +346,7 @@ void iguana_main(void *arg) category_init(&MYINFO); if ( (coinargs= SuperNET_keysinit(&MYINFO,arg)) != 0 ) iguana_launch(iguana_coinadd("BTCD"),"iguana_coins",iguana_coins,coinargs,IGUANA_PERMTHREAD); - else if ( 0 ) + else if ( 1 ) { #ifdef __APPLE__ sleep(1); diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index 7dad92aef..bb383aee4 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -44,10 +44,12 @@ STRING_AND_INT(InstantDEX,pollgap,exchange,pollgap); ZERO_ARGS(InstantDEX,allexchanges); STRING_ARG(InstantDEX,allpairs,exchange); +TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,acceptable,base,rel,price,volume); +THREE_STRINGS_AND_DOUBLE(InstantDEX,NXToffer,reference,base,rel,volume); THREE_STRINGS_AND_DOUBLE(InstantDEX,request,reference,base,rel,volume); TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,proposal,reference,message,basetxid,reltxid,duration,flags); -TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,accept,reference,message,basetxid,reltxid,duration,flags); -TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,confirm,reference,message,basetxid,reltxid,baseheight,relheight); +//TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,accept,reference,message,basetxid,reltxid,duration,flags); +//TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,confirm,reference,message,basetxid,reltxid,baseheight,relheight); THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); diff --git a/includes/iguana_apidefs.h b/includes/iguana_apidefs.h index 33082c212..a3ad0daaa 100755 --- a/includes/iguana_apidefs.h +++ b/includes/iguana_apidefs.h @@ -22,6 +22,7 @@ #define IGUANA_CFUNC_SSI(agent,name,str,str2,val) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,int32_t val) #define IGUANA_CFUNC_SSH(agent,name,str,str2,hash) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash) #define IGUANA_CFUNC_SSHI(agent,name,str,str2,hash,val) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash,int32_t val) +#define IGUANA_CFUNC_SSDD(agent,name,str,str2,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,double val,double val2) #define IGUANA_CFUNC_SSHII(agent,name,str,str2,hash,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash,int32_t val,int32_t val2) #define IGUANA_CFUNC_SSHHII(agent,name,str,str2,hash,hash2,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash,bits256 hash2,int32_t val,int32_t val2) #define IGUANA_CFUNC_SSS(agent,name,str,str2,str3) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3) @@ -86,3 +87,4 @@ #define THREE_STRINGS_AND_THREE_INTS IGUANA_CFUNC_SSSIII #define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_CFUNC_SSSDDD #define THREE_STRINGS_AND_DOUBLE IGUANA_CFUNC_SSSD +#define TWO_STRINGS_AND_TWO_DOUBLES IGUANA_CFUNC_SSDD diff --git a/includes/iguana_apiundefs.h b/includes/iguana_apiundefs.h index 54b986e04..514f127b3 100755 --- a/includes/iguana_apiundefs.h +++ b/includes/iguana_apiundefs.h @@ -38,6 +38,7 @@ #undef THREE_STRINGS_AND_DOUBLE #undef STRING_AND_DOUBLE #undef FOUR_STRINGS +#undef TWO_STRINGS_AND_TWO_DOUBLES #undef IGUANA_ARGS #undef IGUANA_CALLARGS