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/crypto777/cJSON.c b/crypto777/cJSON.c index 3e5377dcb..e29e0e3f3 100755 --- a/crypto777/cJSON.c +++ b/crypto777/cJSON.c @@ -1075,6 +1075,8 @@ uint64_t calc_nxt64bits(const char *NXTaddr) printf("calc_nxt64bits: warning: 64bit overflow %llx < %llx\n",(long long)nxt64bits,(long long)lastval); lastval = nxt64bits; } + while ( *NXTaddr == '0' && *NXTaddr != 0 ) + NXTaddr++; if ( cmp_nxt64bits(NXTaddr,nxt64bits) != 0 ) printf("error calculating nxt64bits: %s -> %llx -> %s\n",NXTaddr,(long long)nxt64bits,nxt64str(nxt64bits)); if ( polarity < 0 ) diff --git a/crypto777/tools/common.mk b/crypto777/tools/common.mk index 922b289b0..1aa7ab4e6 100644 --- a/crypto777/tools/common.mk +++ b/crypto777/tools/common.mk @@ -1,4 +1,4 @@ -# Copyrigh t (c) 2012 The Chromium Authors. All rights reserved. +# Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -32,9 +32,12 @@ TOP_MAKE := $(word 1,$(MAKEFILE_LIST)) # # Figure out which OS we are running on. # -GETOS := python $(NACL_SDK_ROOT)/tools/getos.py -NACL_CONFIG := python $(NACL_SDK_ROOT)/tools/nacl_config.py -FIXDEPS := python $(NACL_SDK_ROOT)/tools/fix_deps.py -c +#GETOS := python $(NACL_SDK_ROOT)/tools/getos.py +#NACL_CONFIG := python $(NACL_SDK_ROOT)/tools/nacl_config.py +#FIXDEPS := python $(NACL_SDK_ROOT)/tools/fix_deps.py -c +GETOS := python tools/getos.py +NACL_CONFIG := python tools/nacl_config.py +FIXDEPS := python tools/fix_deps.py -c OSNAME := $(shell $(GETOS)) @@ -203,7 +206,7 @@ endif # # Compute path to requested NaCl Toolchain # -TC_PATH := $(abspath $(NACL_SDK_ROOT)/../toolchain) +TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain) # @@ -260,8 +263,6 @@ clean: $(RM) -f $(TARGET).nmf $(RM) -rf $(OUTDIR) $(RM) -rf user-data-dir - mkdir pnacl; mkdir pnacl/Release - cp Release/* nacl_io.stamp pnacl/Release; # @@ -294,7 +295,6 @@ ifeq (,$(2)) else +$(MAKE) -C $(2) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3) endif - cp pnacl/Release/*.pexe pnacl/Release/*.bc pnacl/Release/SuperNET_API.nmf Release all: rebuild_$(1) $(STAMPDIR)/$(1).stamp: rebuild_$(1) @@ -443,8 +443,7 @@ endif # Variables for running examples with Chrome. # RUN_PY := python $(NACL_SDK_ROOT)/tools/run.py -#HTTPD_PY := python $(NACL_SDK_ROOT)/tools/httpd.py -HTTPD_PY := python tools/httpd.py +HTTPD_PY := python $(NACL_SDK_ROOT)/tools/httpd.py # Add this to launch Chrome with additional environment variables defined. # Each element should be specified as KEY=VALUE, with whitespace separating @@ -532,7 +531,7 @@ debug: check_for_chrome all $(PAGE) .PHONY: serve serve: all - echo run tools/httpd.py + $(HTTPD_PY) -C $(CURDIR) endif # uppercase aliases (for backward compatibility) diff --git a/deprecated/obsolete.h b/deprecated/obsolete.h index 5b3239105..e9ecf4aa2 100644 --- a/deprecated/obsolete.h +++ b/deprecated/obsolete.h @@ -13091,5 +13091,232 @@ 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); + }*/ + + /* + if ( strcmp(cmdstr+3,"offer") == 0 ) + { + + } + 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 ( strncmp(cmdstr,"ALT",3) == 0 ) + { + 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 ( strncmp(cmdstr,"NXT",3) == 0 ) + { + 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"; + } + } + } + { + + } + + 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 + { + if ( strcmp(cmdstr,"proposal") == 0 ) + { + // proposal: + // NXT node submits phasedtx that refers to it, but it wont confirm + nextcmd = INSTANTDEX_ACCEPT; + nextcmdstr = "accept"; + 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 = ""; + //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 ( nextcmd != 0 && (newjson= InstantDEX_argjson(refstr,message,othercoinaddr,otherNXTaddr,nextcmd,duration,flags)) != 0 ) + { + jaddnum(newjson,"price",price); + jaddnum(newjson,"volume",volume); + return(instantdex_sendcmd(myinfo,newjson,nextcmdstr,myinfo->ipaddr,INSTANTDEX_HOPS)); + } + } + return(clonestr("{\"error\":\"request needs argjson\"}")); + } + num = 0; + depth = 30; + request = jstr(argjson,"request"); + base = jstr(argjson,"base"); + rel = jstr(argjson,"rel"); + refstr = jstr(argjson,"refstr"); + volume = jdouble(argjson,"volume"); + duration = juint(argjson,"duration"); + flags = juint(argjson,"flags"); + nextcmd = 0; + nextcmdstr = message = ""; + + */ #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.c b/iguana/SuperNET.c index bd9a38a37..959fb74fd 100644 --- a/iguana/SuperNET.c +++ b/iguana/SuperNET.c @@ -91,7 +91,7 @@ int32_t SuperNET_confirmip(struct supernet_info *myinfo,uint32_t ipbits) return(total); } -void SuperNET_myipaddr(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *myipaddr,char *remoteaddr) +void SuperNET_checkipaddr(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *myipaddr,char *remoteaddr) { uint32_t myipbits = (uint32_t)calc_ipbits(myipaddr); if ( addr->myipbits == 0 ) @@ -773,7 +773,7 @@ char *SuperNET_p2p(struct iguana_info *coin,struct iguana_peer *addr,int32_t *de if ( 0 && jstr(json,"method") != 0 && strcmp(jstr(json,"method"),"getpeers") != 0 ) printf("GOT >>>>>>>> SUPERNET P2P.(%s) from.%s %s valid.%d:%d\n",jprint(json,0),coin->symbol,addr->ipaddr,addr->validpub,addr->othervalid); if ( (myipaddr= jstr(json,"yourip")) != 0 ) - SuperNET_myipaddr(SuperNET_MYINFO(0),coin,addr,myipaddr,ipaddr); + SuperNET_checkipaddr(SuperNET_MYINFO(0),coin,addr,myipaddr,ipaddr); jaddstr(json,"fromp2p",coin->symbol); method = jstr(json,"method"); if ( method != 0 && strcmp(method,"stop") == 0 ) @@ -919,14 +919,18 @@ cJSON *SuperNET_rosettajson(bits256 privkey,int32_t showprivs) #include "../includes/iguana_apidefs.h" -HASH_ARG(SuperNET,priv2pub,privkey) +HASH_AND_INT(SuperNET,priv2pub,privkey,addrtype) { - cJSON *retjson; bits256 pubkey; + cJSON *retjson; bits256 pub; uint8_t pubkey[33]; char coinaddr[64]; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); retjson = cJSON_CreateObject(); - crypto_box_priv2pub(pubkey.bytes,privkey.bytes); - jaddbits256(retjson,"result",pubkey); + crypto_box_priv2pub(pub.bytes,privkey.bytes); + jaddbits256(retjson,"curve25519",pub); + pub = bitcoin_pubkey33(pubkey,privkey); + jaddbits256(retjson,"secp256k1",pub); + bitcoin_address(coinaddr,addrtype,pubkey,33); + jaddstr(retjson,"result",coinaddr); return(jprint(retjson,1)); } @@ -1241,6 +1245,24 @@ STRING_ARG(SuperNET,wif2priv,wif) return(jprint(retjson,1)); } +ZERO_ARGS(SuperNET,myipaddr) +{ + cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"result",myinfo->ipaddr); + return(jprint(retjson,1)); +} + +STRING_ARG(SuperNET,setmyipaddr,ipaddr) +{ + cJSON *retjson = cJSON_CreateObject(); + if ( is_ipaddr(ipaddr) != 0 ) + { + strcpy(myinfo->ipaddr,ipaddr); + jaddstr(retjson,"result",myinfo->ipaddr); + } else jaddstr(retjson,"error","illegal ipaddr"); + return(jprint(retjson,1)); +} + STRING_ARG(SuperNET,utime2utc,utime) { uint32_t utc = 0; cJSON *retjson = cJSON_CreateObject(); diff --git a/iguana/SuperNET.h b/iguana/SuperNET.h index 728cc2a50..9493cae20 100644 --- a/iguana/SuperNET.h +++ b/iguana/SuperNET.h @@ -84,7 +84,8 @@ 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; + int32_t numagents,numexchanges; struct exchange_info *tradingexchanges[SUPERNET_MAXEXCHANGES]; char handle[1024]; }; @@ -165,6 +166,8 @@ char *SuperNET_keysinit(struct supernet_info *myinfo,char *jsonstr); double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *sortbuf,int32_t max,double *totalvolp,char *base,char *rel,double volume,cJSON *argjson); 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); +bits256 bitcoin_pubkey33(uint8_t data[33],bits256 privkey); +char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey,int32_t len); #endif diff --git a/iguana/app/startup.js b/iguana/app/startup.js index bf289a88d..fe252ba32 100644 --- a/iguana/app/startup.js +++ b/iguana/app/startup.js @@ -94,7 +94,57 @@ $(function () { else if(e.className && e.className.indexOf('clear-response-coin') != -1){ $(".coin_result").text("JSON response"); } - ///clear-response-coin + else if(e.className && e.className.indexOf('instantdex_set_userid') != -1){ + InstantDEX_setuserid(); + } + else if(e.className && e.className.indexOf('Tradebot_set_method_table') != -1){ + tradebot_set_method_table(e.getAttribute("data-method")); + } + else if(e.className && e.className.indexOf('Tradebot_monitorall') != -1){ + Tradebot_monitorall_api(); + } + else if(e.className && e.className.indexOf('Tradebot_monitor') != -1){ + Tradebot_monitor_api(); + } + else if(e.className && e.className.indexOf('Tradebot_unmonitor_api') != -1){ + Tradebot_unmonitor_api(); + } + else if(e.className && e.className.indexOf('Tradebot_accumulate') != -1){ + Tradebot_accumulate_api(); + } + else if(e.className && e.className.indexOf('Tradebot_divest') != -1){ + Tradebot_divest_api(); + } + + else if(e.className && e.className.indexOf('Tradebot_activebots') != -1){ + Tradebot_activebots_api(); + } + else if(e.className && e.className.indexOf('Tradebot_status') != -1){ + Tradebot_status_api(); + } + + else if(e.className && e.className.indexOf('Tradebot_pause') != -1){ + Tradebot_pause_api(); + } + else if(e.className && e.className.indexOf('Tradebot_stop') != -1){ + Tradebot_stop_api(); + } + else if(e.className && e.className.indexOf('Tradebot_resume') != -1){ + Tradebot_resume_api(); + } + else if(e.className && e.className.indexOf('instantdex_allpairs') != -1){ + InstantDEX_allpairs(); + + } + // }; + + $("div .btn-primary").on("click",function(){ + $("div .btn-primary").each(function(){ + $(this).removeClass('btn-raised'); + }); + $(this).addClass("btn-raised"); + }); + }); \ No newline at end of file diff --git a/iguana/example.js b/iguana/example.js index 3cac5ee50..1556f9cc5 100755 --- a/iguana/example.js +++ b/iguana/example.js @@ -244,6 +244,7 @@ function ArrayBufferToString(buf) { return String.fromCharCode.apply(null, new U function handleMessage(message_event) { var data = message_event.data; if ((typeof(data) === 'string' || data instanceof String)) { + check_if_pexe_7778_working(data); common.logMessage(data); } else if (data instanceof Object) @@ -279,3 +280,47 @@ function handleMessage(message_event) { common.logMessage('Error: Unknow message `' + data + '` received from NaCl module.'); } } + +var APPLICATION={pexe:"not loaded",port7778:"Not binded"}; + + +var check_if_pexe_7778_working=function(string){ + var if_changed=0; +if(string.indexOf("iguana_rpcloop")>-1 && string.indexOf("bind sock")>-1 ){ + + APPLICATION.port7778="successfully binded"; + if_changed=1; +}else if(string.indexOf("finished DidCreate iguana")>-1){ + APPLICATION.pexe="Loaded"; + if_changed=1; +}else if(string.indexOf("ERROR BINDING PORT.7778")>-1){ + //APPLICATION.state="Loading.."; + APPLICATION.port7778="Retrying"; + /*if(APPLICATION.pexe.indexOf("not loaded")>-1 || APPLICATION.pexe.indexOf("crashed")>-1){ + APPLICATION.state="not working"; + }*/ + if_changed=1; +}else if(string.indexOf("NaCl module crashed")>-1){ + APPLICATION.pexe="crashed"; + if_changed=1; +}else if(string.indexOf("try again: Address already in use")>-1){ + APPLICATION.port7778="bind failed"; + if_changed=1; +} +if(if_changed){change_app_status();} +//finished DidCreate iguana +// ERROR BINDING PORT.7778. will exit. wait up to a minute and try again. dont worry, this is normal +// NativeClient: NaCl module crashed +//string.indexOf(substring) > -1 +//bind(127.0.0.1) port.7778 try again: Address already in use sock.4. errno.98 + + +}; + +var change_app_status=function(){ + var html="ParameterStatus"; + //html=html+"Application state:"+APPLICATION.state+""; + html=html+"Pexe state:"+APPLICATION.pexe+""; + html=html+"Port 7778 state:"+APPLICATION.port7778+""; + $("#appstatus").html(html); +}; diff --git a/iguana/exchanges/bitcoin.c b/iguana/exchanges/bitcoin.c index 0ba8a6365..4bbba662c 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); + //printf("coinaddr.(%s) valid checksum\n",coinaddr); return(20); } 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; ichain->pubtype && addrtype != coin->chain->p2shtype ) + return(-1); + else if ( bitcoin_address(coinaddr,addrtype,rmd160,sizeof(rmd160)) != coinaddr ) + return(-1); + return(0); +} + EC_KEY *bitcoin_privkeyset(uint8_t *oddevenp,bits256 *pubkeyp,bits256 privkey) { BIGNUM *bn; BN_CTX *ctx = NULL; uint8_t *ptr,tmp[33]; EC_POINT *pub_key = NULL; const EC_GROUP *group; @@ -221,7 +255,7 @@ EC_KEY *bitcoin_privkeyset(uint8_t *oddevenp,bits256 *pubkeyp,bits256 privkey) return(KEY); } -bits256 bitcoin_pubkey(uint8_t *data,bits256 privkey) +bits256 bitcoin_pubkey33(uint8_t *data,bits256 privkey) { uint8_t oddeven; bits256 pubkey; EC_KEY *KEY; @@ -234,6 +268,39 @@ bits256 bitcoin_pubkey(uint8_t *data,bits256 privkey) return(pubkey); } +/*int32_t bitcoin_priv2wif(char *wifstr,uint8_t privkey[32],uint8_t addrtype) +{ + uint8_t tmp[128]; char hexstr[67]; cstring *btc_addr; + memcpy(tmp,privkey,32); + tmp[32] = 1; + init_hexbytes_noT(hexstr,tmp,32); + if ( (btc_addr= base58_encode_check(addrtype,true,tmp,33)) != 0 ) + { + strcpy(wifstr,btc_addr->str); + cstr_free(btc_addr,true); + } + printf("-> (%s) -> wif.(%s) addrtype.%02x\n",hexstr,wifstr,addrtype); + return(0); +} + +int32_t bitcoin_wif2priv(uint8_t *addrtypep,uint8_t privkey[32],char *wifstr) +{ + cstring *cstr; int32_t len = -1; + if ( (cstr= base58_decode_check(addrtypep,(const char *)wifstr)) != 0 ) + { + init_hexbytes_noT((void *)privkey,(void *)cstr->str,cstr->len); + if ( cstr->str[cstr->len-1] == 0x01 ) + cstr->len--; + memcpy(privkey,cstr->str,cstr->len); + len = (int32_t)cstr->len; + char tmp[138]; + btc_priv2wif(tmp,privkey,*addrtypep); + printf("addrtype.%02x wifstr.(%llx) len.%d\n",*addrtypep,*(long long *)privkey,len); + cstr_free(cstr,true); + } + return(len); +}*/ + int32_t bitcoin_sign(uint8_t *sig,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 privkey) { uint32_t siglen; EC_KEY *KEY; uint8_t oddeven; bits256 pubkey; int32_t retval = -1; @@ -288,7 +355,10 @@ int32_t bitcoin_verify(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen int32_t bitcoin_pubkeyspend(uint8_t *script,int32_t n,uint8_t pubkey[66]) { - script[n++] = pubkey[0]; memcpy(&script[n],pubkey,pubkey[0]+1); n += pubkey[0]+1; + int32_t scriptlen = bitcoin_pubkeylen(pubkey); + script[n++] = scriptlen; + memcpy(&script[n],pubkey,scriptlen); + n += scriptlen; script[n++] = SCRIPT_OP_CHECKSIG; return(n); } @@ -301,6 +371,14 @@ int32_t bitcoin_p2shspend(uint8_t *script,int32_t n,uint8_t rmd160[20]) return(n); } +int32_t bitcoin_revealsecret160(uint8_t *script,int32_t n,uint8_t secret160[20]) +{ + script[n++] = SCRIPT_OP_HASH160; + script[n++] = 0x14; memcpy(&script[n],secret160,0x14); n += 0x14; + script[n++] = SCRIPT_OP_EQUALVERIFY; + return(n); +} + int32_t bitcoin_standardspend(uint8_t *script,int32_t n,uint8_t rmd160[20]) { script[n++] = SCRIPT_OP_DUP; @@ -319,66 +397,112 @@ int32_t bitcoin_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime) return(n); } -int32_t bitcoin_pubkeylen(uint8_t *pubkey) -{ - if ( pubkey[0] == 2 || pubkey[0] == 3 ) - return(33); - else if ( pubkey[0] == 4 ) - return(65); - else return(-1); -} - -int32_t bitcoin_MofN(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,struct vin_info *vp,int32_t M,int32_t N) +int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp) { uint8_t sha256[32]; int32_t i,plen; - script[n++] = 0x50 + M; - for (i=0; iM; + for (i=0; iN; i++) { if ( (plen= bitcoin_pubkeylen(vp->signers[i].pubkey)) < 0 ) return(-1); + script[n++] = plen; 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_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee) +{ + uint8_t addrtype,rmd160[20]; int32_t len; + *changep = 0; + if ( inputsatoshis >= (satoshis + txfee) ) + { + *changep = inputsatoshis - (satoshis + txfee); + if ( changeaddr != 0 && changeaddr[0] != 0 ) + { + bitcoin_addr2rmd160(&addrtype,rmd160,changeaddr); + if ( addrtype == coin->chain->pubtype ) + len = bitcoin_standardspend(changescript,0,rmd160); + else if ( addrtype == coin->chain->p2shtype ) + len = bitcoin_standardspend(changescript,0,rmd160); + else + { + printf("error with mismatched addrtype.%02x vs (%02x %02x)\n",addrtype,coin->chain->pubtype,coin->chain->p2shtype); + return(-1); + } + return(len); + } + else printf("error no change address when there is change\n"); + } + return(-1); +} + +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 *otheraddr,uint8_t secret160[20],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_HASH160 secret160 OP_EQUALVERIFY 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,otheraddr); + script[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(script,n,locktime); + n = bitcoin_standardspend(script,n,rmd160A); + script[n++] = SCRIPT_OP_ELSE; + n = bitcoin_revealsecret160(script,n,secret160); + 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); } -/* - 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_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 ) { @@ -388,7 +512,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: @@ -397,8 +520,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); @@ -430,11 +555,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); @@ -443,8 +568,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) @@ -505,7 +631,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) plen = *script++; if ( bitcoin_pubkeylen(script) != plen ) { - printf("invalid pubkey[%d] len %d\n",bitcoin_pubkeylen(script),script[0]); + printf("multisig.%d of %d: invalid pubkey[%02x] len %d\n",i,n,script[0],bitcoin_pubkeylen(script)); return(-1); } memcpy(vp->signers[i].pubkey,script,plen); @@ -564,19 +690,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]; @@ -585,13 +698,23 @@ 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); + if ( vp->type != IGUANA_SCRIPT_OPRETURN ) + { + int32_t i; + printf("\n--------------------\n"); + for (i=0; itype,scriptlen,pk_scriptlen); + } } } return(vp->type); @@ -626,7 +749,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 ) { @@ -643,46 +766,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); @@ -709,41 +828,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); @@ -815,7 +906,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])); } @@ -892,7 +983,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)); @@ -928,125 +1019,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)); @@ -1064,17 +1196,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 ) @@ -1083,27 +1214,142 @@ decode_hex(myprivkey.bytes,sizeof(myprivkey),"18E14A7B6A307F426A94F8114701E7C8E7 scriptlens = calloc(numvins,sizeof(*scriptlens)); for (i=0; ichain->hastimestamp != 0 ) + jaddnum(json,"timestamp",time(NULL)); + 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,uint64_t satoshis) +{ + char *hexstr; cJSON *item,*skey,*vouts = jduplicate(jobj(txobj,"vout")); + item = cJSON_CreateObject(); + jaddnum(item,"value",dstr(satoshis)); + 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 *senders_otheraddr,char *otheraddr,uint32_t locktime,uint64_t satoshis,bits256 txid,int32_t vout,uint64_t inputsatoshis,bits256 privkey) +{ + uint64_t change; char *rawtxstr,*signedtx; struct vin_info V; bits256 cltxid,signedtxid; + int32_t cltvlen,len; uint32_t timestamp; char ps2h_coinaddr[65]; cJSON *txobj; + uint8_t p2sh_rmd160[20],cltvscript[1024],paymentscript[64],rmd160[20],secret160[20],addrtype; + timestamp = (uint32_t)time(NULL); + bitcoin_addr2rmd160(&addrtype,secret160,senders_otheraddr); + cltvlen = bitcoin_cltvscript(coin->chain->p2shtype,ps2h_coinaddr,p2sh_rmd160,cltvscript,0,senderaddr,otheraddr,secret160,locktime); + txobj = bitcoin_createtx(coin,locktime); + len = bitcoin_p2shspend(paymentscript,0,p2sh_rmd160); + bitcoin_addoutput(coin,txobj,paymentscript,len,satoshis); + 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); @@ -1115,16 +1361,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 @@ -1216,23 +1432,21 @@ decode_hex(myprivkey.bytes,sizeof(myprivkey),"18E14A7B6A307F426A94F8114701E7C8E7 #define FUNCS bitcoin ## _funcs #define BASERELS bitcoin ## _baserels -static char *BASERELS[][2] = { {"btc","nxt"}, {"btc","btcd"}, {"btc","ltc"}, {"btc","vrc"}, {"btc","doge"} }; +static char *BASERELS[][2] = { {"btcd","btc"}, {"nxt","btc"}, {"asset","btc"} }; #include "exchange_supports.h" -double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert) +double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert) { - char url[1024],lrel[16],lbase[16]; - strcpy(lrel,rel), strcpy(lbase,base); - tolowercase(lrel), tolowercase(lbase); - sprintf(url,"http://api.quadrigacx.com/v2/order_book?book=%s_%s",lbase,lrel); - return(exchanges777_standardprices(exchange,commission,base,rel,url,quotes,0,0,maxdepth,0,invert)); -} - -cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path) -{ - if ( retstrp != 0 ) - *retstrp = clonestr("{\"error\":\"bitcoin is not yet\"}"); - return(cJSON_Parse("{}")); + cJSON *retjson,*bids,*asks; double hbla; + bids = cJSON_CreateArray(); + asks = cJSON_CreateArray(); + instantdex_acceptablefind(exchange,bids,asks,0,base,rel); + retjson = cJSON_CreateObject(); + cJSON_AddItemToObject(retjson,"bids",bids); + cJSON_AddItemToObject(retjson,"asks",asks); + hbla = exchanges777_json_orderbook(exchange,commission,base,rel,bidasks,maxdepth,retjson,0,"bids","asks",0,0,invert); + free_json(retjson); + return(hbla); } char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson) @@ -1245,24 +1459,120 @@ cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson) return(cJSON_Parse("{\"error\":\"bitcoin is not yet\"}")); } +int32_t is_valid_BTCother(char *other) +{ + if ( iguana_coinfind(other) != 0 ) + return(1); + else if ( strcmp(other,"NXT") == 0 || strcmp(other,"nxt") == 0 ) + return(1); + else if ( is_decimalstr(other) > 0 ) + return(1); + else return(0); +} + uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson) { - return(0); + struct instantdex_accept *ap; char *str,coinaddr[64]; uint64_t txid = 0; cJSON *json; + struct supernet_info *myinfo; uint8_t pubkey[33]; struct iguana_info *other; int32_t hops = 3; + myinfo = SuperNET_MYINFO(0); + if ( strcmp(base,"BTC") == 0 || strcmp(base,"btc") == 0 ) + { + base = rel; + rel = "BTC"; + dir = -dir; + volume *= price; + price = 1. / price; + } + if ( is_valid_BTCother(base) != 0 && (strcmp(rel,"BTC") == 0 || strcmp(rel,"btc") == 0) ) + { + ap = 0;//instantdex_acceptable(exchange,base,rel,"BTC",dir,price,volume); + if ( dotrade == 0 ) + { + if ( retstrp != 0 ) + { + if ( ap != 0 ) + *retstrp = jprint(instantdex_acceptjson(ap),1); + else *retstrp = clonestr("{\"result\":\"would issue new trade\"}"); + } + } + else + { + if ( ap != 0 ) + { + // issue matching response + } + else if ( dir < 0 ) + { + printf("bitcoin sell is not yet\n"); + return(0); + } + else + { + json = cJSON_CreateObject(); + jaddstr(json,"base",base); + jaddstr(json,"rel","BTC"); + jaddnum(json,"maxprice",price); + jaddnum(json,"volume",volume); + if ( (other= iguana_coinfind(base)) != 0 ) + { + bitcoin_pubkey33(pubkey,myinfo->persistent_priv); + bitcoin_address(coinaddr,other->chain->pubtype,pubkey,sizeof(pubkey)); + jaddstr(argjson,base,coinaddr); + } + jaddstr(json,"BTC",myinfo->myaddr.BTC); + if ( (str= instantdex_sendcmd(myinfo,json,"BTCoffer",myinfo->ipaddr,hops)) != 0 ) + free(str); + free_json(json); + if ( (str= instantdex_queueaccept(exchange,base,"BTC",price,volume,-1,"BTC",INSTANTDEX_OFFERDURATION)) != 0 ) + { + if ( (json= cJSON_Parse(str)) != 0 ) + { + txid = j64bits(json,"orderid"); + free_json(json); + } + free(str); + } + } + } + } + return(txid); } -char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson) +char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { - return(clonestr("{\"error\":\"bitcoin is not yet\"}")); + struct instantdex_accept *ap; cJSON *retjson; + if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 ) + { + retjson = cJSON_CreateObject(); + jadd(retjson,"result",instantdex_acceptjson(ap)); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"couldnt find orderid\"}")); } -char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson) +char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { - return(clonestr("{\"error\":\"bitcoin is not yet\"}")); + struct instantdex_accept *ap; cJSON *retjson; + if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 ) + { + ap->dead = (uint32_t)time(NULL); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","killed orderid, but might have pending"); + jadd(retjson,"order",instantdex_acceptjson(ap)); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"couldnt find orderid\"}")); } char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson) { - return(clonestr("{\"error\":\"bitcoin is not yet\"}")); + cJSON *retjson,*bids,*asks; + bids = cJSON_CreateArray(); + asks = cJSON_CreateArray(); + instantdex_acceptablefind(exchange,bids,asks,0,"*","*"); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jadd(retjson,"bids",bids); + jadd(retjson,"asks",asks); + 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..7d46eb4f7 100755 --- a/iguana/exchanges/bitcoin.h +++ b/iguana/exchanges/bitcoin.h @@ -13,6 +13,9 @@ * * ******************************************************************************/ +#ifndef H_BITCOIN_H +#define H_BITCOIN_H + #include "../../includes/openssl/ec.h" #include "../../includes/openssl/ecdsa.h" #include "../../includes/openssl/obj_mac.h" @@ -22,6 +25,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 @@ -40,3 +44,23 @@ #define OP_CHECKLOCKTIMEVERIFY 0xb1 struct bp_key { EC_KEY *k; }; + +int32_t bitcoin_validaddress(struct iguana_info *coin,char *coinaddr); +int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,char *senderaddr,char *otheraddr,uint8_t secret160[20],uint32_t locktime); +int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr); +char *bitcoin_cltvtx(struct iguana_info *coin,char *changeaddr,char *senderaddr,char *senders_otheraddr,char *otheraddr,uint32_t locktime,uint64_t satoshis,bits256 txid,int32_t vout,uint64_t inputsatoshis,bits256 privkey); +int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp); +cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime); +cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis); +int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee); +cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence); +int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V); +char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson); + +int32_t bitcoin_pubkeyspend(uint8_t *script,int32_t n,uint8_t pubkey[66]); +int32_t bitcoin_p2shspend(uint8_t *script,int32_t n,uint8_t rmd160[20]); +int32_t bitcoin_revealsecret160(uint8_t *script,int32_t n,uint8_t secret160[20]); +int32_t bitcoin_standardspend(uint8_t *script,int32_t n,uint8_t rmd160[20]); + +#endif + diff --git a/iguana/exchanges/nxtae.c b/iguana/exchanges/nxtae.c index 429bce7b4..1753b0ef7 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 ) @@ -563,22 +700,19 @@ uint64_t submit_triggered_nxtae(struct supernet_info *myinfo,int32_t dotrade,cha else sprintf(cmd+strlen(cmd),"&priceNQT=%llu",(long long)NXTprice); } if ( otherNXT != 0 ) - sprintf(cmd+strlen(cmd),"&recipient=%llu",(long long)otherNXT); + sprintf(cmd+strlen(cmd),"&recipient=%s",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/exchanges777.h b/iguana/exchanges777.h index c742bb58b..e4b5fcbc7 100755 --- a/iguana/exchanges777.h +++ b/iguana/exchanges777.h @@ -19,6 +19,7 @@ #include #include +#define INSTANTDEX_OFFERDURATION 3600 #define EXCHANGES777_MINPOLLGAP 3 #define EXCHANGES777_MAXDEPTH 200 @@ -50,7 +51,7 @@ struct exchange_info uint32_t exchangeid,pollgap,lastpoll; uint64_t lastnonce,exchangebits; double commission; void *privatedata; - CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2],tradebotsQ; + CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2],tradebotsQ,acceptableQ; }; struct instantdex_msghdr @@ -60,6 +61,23 @@ struct instantdex_msghdr uint8_t serialized[]; } __attribute__((packed)); +#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 exchange_request { struct queueitem DL; @@ -71,6 +89,22 @@ struct exchange_request struct exchange_quote bidasks[]; }; +struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; }; +struct bitcoin_spend +{ + char changeaddr[64]; + int32_t numinputs; + uint64_t txfee,input_satoshis,satoshis; + struct bitcoin_unspent inputs[]; +}; + +struct instantdex_entry { char base[24],rel[24]; uint64_t price64,basevolume64,offer64; uint32_t expiration,nonce; char myside,acceptdir; }; +struct instantdex_accept { struct queueitem DL; uint64_t pendingvolume64,orderid; uint32_t dead; struct instantdex_entry A; }; + +struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel); +cJSON *instantdex_acceptjson(struct instantdex_accept *ap); +struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits); + void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); char *instantdex_sendcmd(struct supernet_info *myinfo,cJSON *argjson,char *cmdstr,char *ipaddr,int32_t hops); char *exchanges777_Qprices(struct exchange_info *exchange,char *base,char *rel,int32_t maxseconds,int32_t allfields,int32_t depth,cJSON *argjson,int32_t monitor,double commission); @@ -87,5 +121,6 @@ double truefx_price(struct exchange_info *exchange,char *base,char *rel,struct e double fxcm_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); double instaforex_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); +char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *myside,int32_t duration); #endif diff --git a/iguana/help/header.html b/iguana/help/header.html index bf3836284..c53a53fd2 100644 --- a/iguana/help/header.html +++ b/iguana/help/header.html @@ -5,7 +5,7 @@ - SuperNET API> + SuperNET API Page> @@ -15,8 +15,8 @@ @@ -30,7 +30,7 @@ + +
+
+
+
+

+ Tradebot +

+
+
+ + + + + + + + + + + + + + +
+
+ + + + +
+ + + +
+
+
+
+
@@ -402,9 +441,10 @@ data-path="{tc}/{config}">
-

- ** Awaiting specific requirements ** -

+ + + +