From 3ee5c2f19ad60b98412321ba2c16fec09b02cc0e Mon Sep 17 00:00:00 2001 From: jl777 Date: Sun, 28 May 2017 11:58:53 +0300 Subject: [PATCH] Test --- crypto777/OS_portable.h | 2 +- iguana/dpow/dpow_network.c | 51 +- iguana/exchanges/LP_bitcoin.c | 2357 +++++++++++++++++++++------ iguana/exchanges/LP_commands.c | 101 +- iguana/exchanges/LP_include.h | 469 ++++++ iguana/exchanges/LP_nativeDEX.c | 97 +- iguana/exchanges/LP_network.c | 307 ++++ iguana/exchanges/LP_remember.c | 718 ++++----- iguana/exchanges/LP_rpc.c | 505 ++++++ iguana/exchanges/LP_secp.c | 186 +++ iguana/exchanges/LP_statemachine.c | 558 +++++++ iguana/exchanges/LP_swap.c | 2405 +++++++--------------------- iguana/exchanges/LP_transaction.c | 1657 +++++++++++++++++++ iguana/m_mm | 3 +- 14 files changed, 6649 insertions(+), 2767 deletions(-) create mode 100644 iguana/exchanges/LP_include.h create mode 100644 iguana/exchanges/LP_network.c create mode 100644 iguana/exchanges/LP_rpc.c create mode 100644 iguana/exchanges/LP_secp.c create mode 100644 iguana/exchanges/LP_statemachine.c create mode 100644 iguana/exchanges/LP_transaction.c diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index f986b5216..a90889279 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -347,7 +347,7 @@ char *hmac_tiger_str(char *dest,char *key,int32_t key_size,char *message); char *hmac_whirlpool_str(char *dest,char *key,int32_t key_size,char *message); int nn_base64_encode(const uint8_t *in,size_t in_len,char *out,size_t out_len); int nn_base64_decode(const char *in,size_t in_len,uint8_t *out,size_t out_len); - +void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen); void sha256_sha256(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void rmd160ofsha256(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_md5str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); diff --git a/iguana/dpow/dpow_network.c b/iguana/dpow/dpow_network.c index 9eafc39be..2a98ed265 100755 --- a/iguana/dpow/dpow_network.c +++ b/iguana/dpow/dpow_network.c @@ -145,10 +145,10 @@ int32_t signed_nn_send(struct supernet_info *myinfo,void *ctx,bits256 privkey,in int32_t signed_nn_recv(void **freeptrp,struct supernet_info *myinfo,uint8_t notaries[64][33],int32_t n,int32_t sock,void *packetp) { - int32_t i,recvbytes; uint8_t pubkey33[33],pubkey0[33]; bits256 packethash; struct signed_nnpacket *sigpacket=0; + int32_t i=0,recvbytes; uint8_t pubkey33[33],pubkey0[33]; bits256 packethash; struct signed_nnpacket *sigpacket=0; *(void **)packetp = 0; *freeptrp = 0; - for (i=0; i<100; i++) + /*for (i=0; i<100; i++) { struct nn_pollfd pfd; pfd.fd = myinfo->reqsock; @@ -159,11 +159,11 @@ int32_t signed_nn_recv(void **freeptrp,struct supernet_info *myinfo,uint8_t nota } if ( i == 100 ) recvbytes = 0; - else if ( (recvbytes= nn_recv(sock,&sigpacket,NN_MSG,0)) > 0 ) + else*/ if ( (recvbytes= nn_recv(sock,&sigpacket,NN_MSG,0)) > 0 ) { //for (i=0; ipacketlen == recvbytes-sizeof(*sigpacket)); + printf(" <- [%d] RECV.%d crc.%08x cmp.%d\n",i,recvbytes,calc_crc32(0,(void *)sigpacket,recvbytes),sigpacket->packetlen == recvbytes-sizeof(*sigpacket)); } if ( sigpacket != 0 && recvbytes > sizeof(*sigpacket) && sigpacket->packetlen == recvbytes-sizeof(*sigpacket) ) { @@ -199,9 +199,9 @@ int32_t signed_nn_recv(void **freeptrp,struct supernet_info *myinfo,uint8_t nota printf(" pubkey[%d]\n",i); } } - //for (i=0; i<33; i++) - // printf("%02x",pubkey33[i]); - //printf(" invalid pubkey33 n.%d\n",n); + for (i=0; i<33; i++) + printf("%02x",pubkey33[i]); + printf(" invalid pubkey33 n.%d\n",n); } else printf("recoververify error nonce.%u packetlen.%d\n",sigpacket->nonce,sigpacket->packetlen); } else printf("hash mismatch or bad nonce.%u packetlen.%d\n",sigpacket->nonce,sigpacket->packetlen); } else if ( recvbytes > 0 ) @@ -390,7 +390,7 @@ void dex_packet(struct supernet_info *myinfo,struct dex_nanomsghdr *dexp,int32_t char *_dex_reqsend(struct supernet_info *myinfo,char *handler,uint8_t *key,int32_t keylen,uint8_t *data,int32_t datalen) { - struct dex_nanomsghdr *dexp; cJSON *retjson; char ipaddr[64],str[128]; int32_t timeout,i,n,size,recvbytes,sentbytes = 0,reqsock,subsock; uint32_t *retptr,ipbits; void *freeptr; char *retstr = 0; + struct dex_nanomsghdr *dexp; cJSON *retjson; char ipaddr[64],str[128]; int32_t prio,timeout,i,n,size,recvbytes,sentbytes = 0,reqsock,subsock; uint32_t *retptr,ipbits; void *freeptr; char *retstr = 0; portable_mutex_lock(&myinfo->dexmutex); subsock = myinfo->subsock; reqsock = myinfo->reqsock; @@ -400,15 +400,15 @@ char *_dex_reqsend(struct supernet_info *myinfo,char *handler,uint8_t *key,int32 { timeout = 1000; nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - //timeout = 1500; - //nn_setsockopt(reqsock,NN_TCP,NN_RECONNECT_IVL,&timeout,sizeof(timeout)); - timeout = 3000; + timeout = 1000; + nn_setsockopt(reqsock,NN_TCP,NN_RECONNECT_IVL,&timeout,sizeof(timeout)); + timeout = 10000; nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - //prio = 1; - //nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_SNDPRIO,&prio,sizeof(prio)); - //nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_RCVPRIO,&prio,sizeof(prio)); for (i=0; idexseed_ipaddrs)/sizeof(*myinfo->dexseed_ipaddrs); i++) { + prio = (i/2) + 1; + nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_SNDPRIO,&prio,sizeof(prio)); + nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_RCVPRIO,&prio,sizeof(prio)); if ( nn_connect(reqsock,nanomsg_tcpname(0,str,myinfo->dexseed_ipaddrs[i],REP_SOCK)) < 0 ) { nn_close(reqsock); @@ -416,9 +416,6 @@ char *_dex_reqsend(struct supernet_info *myinfo,char *handler,uint8_t *key,int32 break; } } - //prio = 8; - //nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_SNDPRIO,&prio,sizeof(prio)); - //nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_RCVPRIO,&prio,sizeof(prio)); } if ( reqsock >= 0 ) { @@ -435,14 +432,14 @@ char *_dex_reqsend(struct supernet_info *myinfo,char *handler,uint8_t *key,int32 } if ( reqsock >= 0 && subsock >= 0 ) { - timeout = 100; + timeout = 1; nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); printf("CLIENT sockets req.%d sub.%d\n",reqsock,subsock); //timeout = 5000; //nn_setsockopt(reqsock,NN_TCP,NN_RECONNECT_IVL,&timeout,sizeof(timeout)); - timeout = 10000; - nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + //timeout = 10000; + //nn_setsockopt(reqsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); } } } @@ -481,7 +478,7 @@ char *_dex_reqsend(struct supernet_info *myinfo,char *handler,uint8_t *key,int32 if ( nn_poll(&pfd,1,100) > 0 ) { sentbytes = nn_send(myinfo->reqsock,dexp,size,0); - //printf(" sent.%d:%d datalen.%d crc.%08x\n",sentbytes,size,datalen,calc_crc32(0,(void *)dexp,size)); + printf(" [%d] sent.%d:%d datalen.%d crc.%08x\n",i,sentbytes,size,datalen,calc_crc32(0,(void *)dexp,size)); break; } usleep(1000); @@ -490,7 +487,7 @@ char *_dex_reqsend(struct supernet_info *myinfo,char *handler,uint8_t *key,int32 // printf("%02x",((uint8_t *)data)[i]); if ( (recvbytes= signed_nn_recv(&freeptr,myinfo,myinfo->notaries,myinfo->numnotaries,myinfo->reqsock,&retptr)) >= 0 ) { - //printf("req returned.[%d]\n",recvbytes); + printf("req returned.[%d]\n",recvbytes); portable_mutex_lock(&myinfo->dexmutex); ipbits = 0; if ( strcmp(handler,"DEX") == 0 ) @@ -2163,11 +2160,11 @@ int32_t dpow_nanomsg_update(struct supernet_info *myinfo) if ( (flags & 4) == 0 && (size= nn_recv(myinfo->repsock,&dexp,NN_MSG,0)) > 0 ) { num2++; - //printf("REP got %d crc.%08x\n",size,calc_crc32(0,(void *)dexp,size)); + printf("REP got %d crc.%08x\n",size,calc_crc32(0,(void *)dexp,size)); if ( (retstr= dex_response(&broadcastflag,myinfo,dexp)) != 0 ) { signed_nn_send(myinfo,myinfo->ctx,myinfo->persistent_priv,myinfo->repsock,retstr,(int32_t)strlen(retstr)+1); - //printf("send back[%ld]\n",strlen(retstr)+1); + printf("send back[%ld]\n",strlen(retstr)+1); free(retstr); if ( broadcastflag != 0 ) { @@ -2182,11 +2179,11 @@ int32_t dpow_nanomsg_update(struct supernet_info *myinfo) { r = myinfo->dpowipbits[rand() % m]; signed_nn_send(myinfo,myinfo->ctx,myinfo->persistent_priv,myinfo->repsock,&r,sizeof(r)); - //printf("REP.%08x <- rand ip m.%d %x\n",dexp->crc32,m,r); + printf("REP.%08x <- rand ip m.%d %x\n",dexp->crc32,m,r); } else printf("illegal state without dpowipbits?\n"); if ( dex_packetcheck(myinfo,dexp,size) == 0 ) { - signed_nn_send(myinfo,myinfo->ctx,myinfo->persistent_priv,myinfo->dexsock,dexp,size); + //signed_nn_send(myinfo,myinfo->ctx,myinfo->persistent_priv,myinfo->dexsock,dexp,size); //signed_nn_send(myinfo,myinfo->ctx,myinfo->persistent_priv,myinfo->pubsock,dexp,size); //printf("REP.%08x -> dexbus and pub, t.%d lag.%d\n",dexp->crc32,dexp->timestamp,(int32_t)(time(NULL)-dexp->timestamp)); dex_packet(myinfo,dexp,size); @@ -2208,7 +2205,7 @@ int32_t dpow_nanomsg_update(struct supernet_info *myinfo) } else break; } portable_mutex_unlock(&myinfo->dpowmutex); - return(num); + return(num+n+num2); } #else diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index 421d889ca..078bc1d3f 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -18,52 +18,435 @@ // marketmaker // -#define IGUANA_MAXSCRIPTSIZE 10001 - -struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; //PACKEDSTRUCT; - -struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; }; - -struct vin_info -{ - struct iguana_msgvin vin; uint64_t amount; cJSON *extras; bits256 sigtxid; - int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,hashtype,userdatalen,suppress_pubkeys,ignore_cltverr; - uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65]; - uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE],userdata[IGUANA_MAXSCRIPTSIZE]; -}; - -#define SIGHASH_ALL 1 -#define SIGHASH_NONE 2 -#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 -#define SCRIPT_OP_4 0x54 -#define SCRIPT_OP_IF 0x63 -#define SCRIPT_OP_ELSE 0x67 -#define SCRIPT_OP_RETURN 0x6a -#define SCRIPT_OP_DUP 0x76 -#define SCRIPT_OP_ENDIF 0x68 -#define SCRIPT_OP_DROP 0x75 -#define SCRIPT_OP_EQUALVERIFY 0x88 -#define SCRIPT_OP_SHA256 0xa8 -#define SCRIPT_OP_HASH160 0xa9 - -#define SCRIPT_OP_EQUAL 0x87 -#define SCRIPT_OP_CHECKSIG 0xac -#define SCRIPT_OP_CHECKMULTISIG 0xae -#define SCRIPT_OP_CHECKSEQUENCEVERIFY 0xb2 -#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 - -void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) +{ + int32_t i; uint64_t x; + if ( rwflag == 0 ) + { + x = 0; + for (i=len-1; i>=0; i--) + { + x <<= 8; + x |= serialized[i]; + } + switch ( len ) + { + case 1: *(uint8_t *)endianedp = (uint8_t)x; break; + case 2: *(uint16_t *)endianedp = (uint16_t)x; break; + case 4: *(uint32_t *)endianedp = (uint32_t)x; break; + case 8: *(uint64_t *)endianedp = (uint64_t)x; break; + } + } + else + { + x = 0; + switch ( len ) + { + case 1: x = *(uint8_t *)endianedp; break; + case 2: x = *(uint16_t *)endianedp; break; + case 4: x = *(uint32_t *)endianedp; break; + case 8: x = *(uint64_t *)endianedp; break; + } + for (i=0; i>= 8) + serialized[i] = (uint8_t)(x & 0xff); + } + return(len); +} + +int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp) +{ + int32_t i; + if ( rwflag == 0 ) + { + for (i=0; i> 8) & 0xff; + } + return(serialized); +} + +uint8_t *iguana_varint32(int32_t rwflag,uint8_t *serialized,uint16_t *varint16p) +{ + serialized = iguana_varint16(rwflag,serialized,varint16p); + serialized = iguana_varint16(rwflag,serialized,&varint16p[1]); + return(serialized); +} + +uint8_t *iguana_varint64(int32_t rwflag,uint8_t *serialized,uint32_t *varint32p) +{ + serialized = iguana_varint32(rwflag,serialized,(uint16_t *)varint32p); + serialized = iguana_varint32(rwflag,serialized,(uint16_t *)&varint32p[1]); + return(serialized); +} + +int32_t iguana_rwvarint(int32_t rwflag,uint8_t *serialized,uint64_t *varint64p) +{ + uint64_t n; int32_t vlen = 1; + if ( rwflag == 0 ) + { + *varint64p = 0; + if ( (n= *serialized++) >= 0xfd ) + { + if ( n == 0xfd ) + { + n = 0; + iguana_varint16(rwflag,serialized,(uint16_t *)&n); + vlen += 2; + } + else if ( n == 0xfe ) + { + n = 0; + iguana_varint32(rwflag,serialized,(uint16_t *)&n); + vlen += 4; + } + else if ( n == 0xff ) + { + n = 0; + iguana_varint64(rwflag,serialized,(uint32_t *)&n); + vlen += 8; + } + } + *varint64p = n; + } + else + { + n = *varint64p; + if ( n < 0xfd ) + *serialized++ = (uint8_t)n; + else if ( n <= 0xffff ) + { + *serialized++ = 0xfd; + iguana_varint16(rwflag,serialized,(uint16_t *)varint64p); + vlen += 2; + } + else if ( n <= 0xffffffff ) + { + *serialized++ = 0xfe; + iguana_varint32(rwflag,serialized,(uint16_t *)varint64p); + vlen += 4; + } + else + { + *serialized++ = 0xff; + iguana_varint64(rwflag,serialized,(uint32_t *)varint64p); + vlen += 8; + } + } + return(vlen); +} + +int32_t iguana_rwvarint32(int32_t rwflag,uint8_t *serialized,uint32_t *int32p) +{ + int32_t len; uint64_t x = 0; + if ( rwflag != 0 ) + x = *int32p; + len = iguana_rwvarint(rwflag,serialized,&x); + if ( rwflag == 0 ) + *int32p = (int32_t)x; + return(len); +} + +int32_t iguana_rwvarstr(int32_t rwflag,uint8_t *serialized,int32_t maxlen,char *endianedp) +{ + int32_t vlen; uint64_t n; + if ( rwflag == 0 ) + { + vlen = iguana_rwvarint(rwflag,serialized,&n); + memcpy(endianedp,&serialized[vlen],n); + ((uint8_t *)endianedp)[n] = 0; + } + else + { + n = strlen(endianedp); + if ( n > maxlen ) + n = maxlen; + vlen = iguana_rwvarint(rwflag,serialized,&n); + memcpy(&serialized[vlen],endianedp,n); + } + return((int32_t)(n + vlen)); +} + +int32_t iguana_rwmem(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) +{ + if ( rwflag == 0 ) + memcpy(endianedp,serialized,len); + else memcpy(serialized,endianedp,len); + return(len); +} + +const char *get_opname(uint8_t *stackitemsp,uint8_t *flagsp,int32_t *extralenp,enum opcodetype opcode) +{ + *extralenp = 0; + switch ( opcode ) + { + // push value + case OP_0 : return "0"; + case OP_PUSHDATA1 : *extralenp = 1; return "OP_PUSHDATA1"; + case OP_PUSHDATA2 : *extralenp = 2; return "OP_PUSHDATA2"; + case OP_PUSHDATA4 : *flagsp = IGUANA_EXECUTIONILLEGAL; return "OP_PUSHDATA4"; + case OP_1NEGATE : return "-1"; + case OP_RESERVED : *flagsp = IGUANA_EXECUTIONILLEGAL; return "OP_RESERVED"; + case OP_1 : return "1"; + case OP_2 : return "2"; + case OP_3 : return "3"; + case OP_4 : return "4"; + case OP_5 : return "5"; + case OP_6 : return "6"; + case OP_7 : return "7"; + case OP_8 : return "8"; + case OP_9 : return "9"; + case OP_10 : return "10"; + case OP_11 : return "11"; + case OP_12 : return "12"; + case OP_13 : return "13"; + case OP_14 : return "14"; + case OP_15 : return "15"; + case OP_16 : return "16"; + + // control + case OP_NOP : *flagsp = IGUANA_NOPFLAG; return "OP_NOP"; + case OP_VER : *flagsp = IGUANA_EXECUTIONILLEGAL; return "OP_VER"; + case OP_IF : *flagsp = IGUANA_CONTROLFLAG; *stackitemsp = 1; return "OP_IF"; + case OP_NOTIF : *flagsp = IGUANA_CONTROLFLAG; *stackitemsp = 1; return "OP_NOTIF"; + case OP_VERIF : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_VERIF"; + case OP_VERNOTIF : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_VERNOTIF"; + case OP_ELSE : *flagsp = IGUANA_CONTROLFLAG; return "OP_ELSE"; + case OP_ENDIF : *flagsp = IGUANA_CONTROLFLAG; return "OP_ENDIF"; + case OP_VERIFY : *flagsp = IGUANA_POSTVERIFY; return "OP_VERIFY"; + case OP_RETURN : *flagsp = IGUANA_CONTROLFLAG; return "OP_RETURN"; + + // stack ops + case OP_TOALTSTACK : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 1; return "OP_TOALTSTACK"; + case OP_FROMALTSTACK : *flagsp = IGUANA_STACKFLAG; return "OP_FROMALTSTACK"; + case OP_2DROP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 2; return "OP_2DROP"; + case OP_2DUP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 2; return "OP_2DUP"; + case OP_3DUP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 3; return "OP_3DUP"; + case OP_2OVER : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 4; return "OP_2OVER"; + case OP_2ROT : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 6; return "OP_2ROT"; + case OP_2SWAP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 4; return "OP_2SWAP"; + case OP_IFDUP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 1; return "OP_IFDUP"; + case OP_DEPTH : *flagsp = IGUANA_STACKFLAG; return "OP_DEPTH"; + case OP_DROP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 1; return "OP_DROP"; + case OP_DUP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 1; return "OP_DUP"; + case OP_NIP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 2; return "OP_NIP"; + case OP_OVER : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 2; return "OP_OVER"; + case OP_PICK : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 1; return "OP_PICK"; + case OP_ROLL : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 1; return "OP_ROLL"; + case OP_ROT : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 3; return "OP_ROT"; + case OP_SWAP : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 2; return "OP_SWAP"; + case OP_TUCK : *flagsp = IGUANA_STACKFLAG; *stackitemsp = 2; return "OP_TUCK"; + + // splice ops + case OP_CAT : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_CAT"; + case OP_SUBSTR : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_SUBSTR"; + case OP_LEFT : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_LEFT"; + case OP_RIGHT : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_RIGHT"; + case OP_SIZE : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_SIZE"; + + // bit logic + case OP_INVERT : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_INVERT"; + case OP_AND : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_AND"; + case OP_OR : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_OR"; + case OP_XOR : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_XOR"; + case OP_EQUAL : *stackitemsp = 2; return "OP_EQUAL"; + case OP_EQUALVERIFY : *stackitemsp = 2; *flagsp = IGUANA_POSTVERIFY; return "OP_EQUALVERIFY"; + case OP_RESERVED1 : *flagsp = IGUANA_EXECUTIONILLEGAL; return "OP_RESERVED1"; + case OP_RESERVED2 : *flagsp = IGUANA_EXECUTIONILLEGAL; return "OP_RESERVED2"; + + // numeric + case OP_1ADD : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 1; return "OP_1ADD"; + case OP_1SUB : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 1; return "OP_1SUB"; + case OP_2MUL : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_2MUL"; + case OP_2DIV : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_2DIV"; + case OP_NEGATE : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 1; return "OP_NEGATE"; + case OP_ABS : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 1; return "OP_ABS"; + case OP_NOT : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 1; return "OP_NOT"; + case OP_0NOTEQUAL : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 1; return "OP_0NOTEQUAL"; + case OP_ADD : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_ADD"; + case OP_SUB : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_SUB"; + case OP_MUL : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_MUL"; + case OP_DIV : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_DIV"; + case OP_MOD : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_MOD"; + case OP_LSHIFT : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_LSHIFT"; + case OP_RSHIFT : *flagsp = IGUANA_ALWAYSILLEGAL; return "OP_RSHIFT"; + case OP_BOOLAND : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_BOOLAND"; + case OP_BOOLOR : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_BOOLOR"; + case OP_NUMEQUAL : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_NUMEQUAL"; + case OP_NUMEQUALVERIFY: *flagsp = IGUANA_MATHFLAG | IGUANA_POSTVERIFY; *stackitemsp = 2; return "OP_NUMEQUALVERIFY"; + case OP_NUMNOTEQUAL : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_NUMNOTEQUAL"; + case OP_LESSTHAN : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_LESSTHAN"; + case OP_GREATERTHAN : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_GREATERTHAN"; + case OP_LESSTHANOREQUAL: *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_LESSTHANOREQUAL"; + case OP_GREATERTHANOREQUAL: *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_GREATERTHANOREQUAL"; + case OP_MIN : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_MIN"; + case OP_MAX : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 2; return "OP_MAX"; + case OP_WITHIN : *flagsp = IGUANA_MATHFLAG; *stackitemsp = 3; return "OP_WITHIN"; + + // crypto + case OP_RIPEMD160 : *stackitemsp = 1; *flagsp = IGUANA_CRYPTOFLAG; return "OP_RIPEMD160"; + case OP_SHA1 : *stackitemsp = 1; *flagsp = IGUANA_CRYPTOFLAG; return "OP_SHA1"; + case OP_SHA256 : *stackitemsp = 1; *flagsp = IGUANA_CRYPTOFLAG; return "OP_SHA256"; + case OP_HASH160 : *stackitemsp = 1; *flagsp = IGUANA_CRYPTOFLAG; return "OP_HASH160"; + case OP_HASH256 : *stackitemsp = 1; *flagsp = IGUANA_CRYPTOFLAG; return "OP_HASH256"; + case OP_CODESEPARATOR: return "OP_CODESEPARATOR"; + case OP_CHECKSIG : *stackitemsp = 2; *flagsp = IGUANA_CRYPTOFLAG; return "OP_CHECKSIG"; + case OP_CHECKSIGVERIFY: *stackitemsp = 2; *flagsp = IGUANA_CRYPTOFLAG | IGUANA_POSTVERIFY; return "OP_CHECKSIGVERIFY"; + case OP_CHECKMULTISIG: *flagsp = IGUANA_CRYPTOFLAG; return "OP_CHECKMULTISIG"; + case OP_CHECKMULTISIGVERIFY: *flagsp = IGUANA_CRYPTOFLAG | IGUANA_POSTVERIFY; return "OP_CHECKMULTISIGVERIFY"; + case OP_COMBINEPUBKEYS: *flagsp = IGUANA_CRYPTOFLAG; return "OP_COMBINEPUBKEYS"; + case OP_CHECKSCHNORR: *stackitemsp = 3; *flagsp = IGUANA_CRYPTOFLAG; return "OP_CHECKSCHNORR"; + case OP_CHECKSCHNORRVERIFY: *stackitemsp = 3; *flagsp = IGUANA_CRYPTOFLAG | IGUANA_POSTVERIFY; return "OP_CHECKSCHNORRVERIFY"; + case OP_CHECKPRIVATEKEY: *stackitemsp = 2; *flagsp = IGUANA_CRYPTOFLAG; return "OP_CHECKPRIVATEKEY"; + case OP_CHECKPRIVATEKEYVERIFY: *stackitemsp = 2; *flagsp = IGUANA_CRYPTOFLAG | IGUANA_POSTVERIFY; return "OP_CHECKPRIVATEKEYVERIFY"; + + // expanson + case OP_NOP1 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP1"; + case OP_CHECKLOCKTIMEVERIFY: *stackitemsp = 1; return "OP_CHECKLOCKTIMEVERIFY"; + case OP_CHECKSEQUENCEVERIFY: *stackitemsp = 1; return "OP_CHECKSEQUENCEVERIFY"; + case OP_NOP4 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP4"; + case OP_NOP5 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP5"; + case OP_NOP6 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP6"; + case OP_NOP7 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP7"; + case OP_NOP8 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP8"; + case OP_NOP9 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP9"; + case OP_NOP10 : *flagsp = IGUANA_NOPFLAG; return "OP_NOP10"; + + case OP_INVALIDOPCODE: return "OP_INVALIDOPCODE"; + default: return "OP_UNKNOWN"; + } +} + +void iguana_optableinit() +{ + int32_t i,extralen; uint8_t stackitems,flags; char *opname; struct bitcoin_opcode *op; + if ( OPTABLE == 0 ) + { + for (i=0; i<0x100; i++) + OPCODES[i] = "OP_UNKNOWN"; + for (i=0; i<0x100; i++) + { + extralen = stackitems = flags = 0; + opname = (char *)get_opname(&stackitems,&flags,&extralen,i); + if ( strcmp("OP_UNKNOWN",opname) != 0 ) + { + op = calloc(1,sizeof(*op)); + HASH_ADD_KEYPTR(hh,OPTABLE,opname,strlen(opname),op); + //printf("{%-16s %02x} ",opname,i); + op->opcode = i; + op->flags = flags; + op->stackitems = stackitems; + op->extralen = extralen; + OPCODES[i] = (char *)op->hh.key; + OPCODELENS[i] = (int32_t)strlen(OPCODES[i]); + } + } + //printf("bitcoin opcodes\n"); + } +} + +int32_t iguana_expandscript(char *asmstr,int32_t maxlen,uint8_t *script,int32_t scriptlen) +{ + int32_t len,n,j,i = 0; uint8_t opcode; uint32_t val,extraflag; + iguana_optableinit(); + asmstr[0] = len = 0; + while ( i < scriptlen ) + { + val = extraflag = 0; + opcode = script[i++]; + if ( opcode > 0 && opcode < 76 ) + { + for (j=0; j= IGUANA_OP_1 && opcode <= IGUANA_OP_16 ) + { + sprintf(&asmstr[len],"%d",opcode - IGUANA_OP_1 + 1); + len += strlen(&asmstr[len]); + } + else if ( opcode == IGUANA_OP_0 ) + { + strcpy(&asmstr[len],"OP_FALSE"); + len += 8; + } + else if ( opcode == IGUANA_OP_1NEGATE ) + { + asmstr[len++] = '-'; + asmstr[len++] = '1'; + } + else + { + //printf("dest.%p <- %p %02x\n",&asmstr[len],OPCODES[opcode],opcode); + strcpy(&asmstr[len],OPCODES[opcode]); + len += OPCODELENS[opcode]; + } + if ( i < scriptlen ) + asmstr[len++] = ' '; + if ( opcode == IGUANA_OP_PUSHDATA1 ) + { + n = script[i++]; + for (j=0; j reveal.(%s)\n",bits256_str(str,privkey),bits256_str(str2,reveal)); -#else - reveal = pubkey; -#endif - return(reveal); + return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params)); } -int32_t basilisk_swap_bobredeemscript(int32_t depositflag,int32_t *secretstartp,uint8_t *redeemscript,uint32_t locktime,bits256 pubA0,bits256 pubB0,bits256 pubB1,bits256 privAm,bits256 privBn,uint8_t *secretAm,uint8_t *secretAm256,uint8_t *secretBn,uint8_t *secretBn256) +int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) { - int32_t i,n=0; bits256 cltvpub,destpub,privkey; uint8_t pubkeyA[33],pubkeyB[33],secret160[20],secret256[32]; - if ( depositflag != 0 ) + bits256 hash; uint8_t *buf,_buf[25]; int32_t len; + memset(rmd160,0,20); + *addrtypep = 0; + buf = _buf; + if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 ) { - pubkeyA[0] = 0x02, cltvpub = pubA0; - pubkeyB[0] = 0x03, destpub = pubB0; - privkey = privBn; - memcpy(secret160,secretBn,20); - memcpy(secret256,secretBn256,32); + // validate with trailing hash, then remove hash + hash = bits256_doublesha256(0,buf,21); + *addrtypep = *buf; + memcpy(rmd160,buf+1,20); + if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] ) + { + //printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep); + return(20); + } + else + { + int32_t i; + if ( len > 20 ) + { + hash = bits256_doublesha256(0,buf,len); + } + for (i=0; istarted + swap->putduration + swap->callduration; - else *locktimep = swap->started + swap->putduration; - *redeemlenp = n = basilisk_swap_bobredeemscript(depositflag,secretstartp,redeemscript,*locktimep,swap->pubA0,swap->pubB0,swap->pubB1,swap->privAm,swap->privBn,swap->secretAm,swap->secretAm256,swap->secretBn,swap->secretBn256); - if ( n > 0 ) + uint8_t i; bits256 hash; + data[0] = addrtype; + //for (i=0; i "); + hash = bits256_doublesha256(0,data,(int32_t)data_len+1); + //for (i=0; i<32; i++) + // printf("%02x",hash.bytes[i]); + //printf(" checkhash\n"); + for (i=0; i<4; i++) + data[data_len+i+1] = hash.bytes[31-i]; + return(data_len + 5); +} + +int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr) +{ + int32_t len = -1; bits256 hash; uint8_t buf[256]; + memset(buf,0,sizeof(buf)); + if ( (len= bitcoin_base58decode(buf,wifstr)) >= 4 ) { - calc_rmd160_sha256(rmd160,redeemscript,n); - n = bitcoin_p2shspend(script,0,rmd160); - //for (i=0; i wif.(%s) addrtype.%02x -> %02x (%s)\n",bits256_str(str,privkey),wifstr,addrtype,checktype,bits256_str(str2,checkpriv)); + } + } + return((int32_t)strlen(wifstr)); } -int32_t basilisk_priviextract(struct supernet_info *myinfo,struct iguana_info *coin,char *name,bits256 *destp,uint8_t secret160[20],bits256 srctxid,int32_t srcvout) +int32_t bitcoin_priv2wiflong(char *wifstr,bits256 privkey,uint8_t addrtype) { - bits256 txid,privkey; char str[65]; int32_t i,vini,scriptlen; uint8_t rmd160[20],scriptsig[IGUANA_MAXSCRIPTSIZE]; - memset(privkey.bytes,0,sizeof(privkey)); - // use dex_listtransactions! - if ( (vini= iguana_vinifind(myinfo,coin,&txid,srctxid,srcvout)) >= 0 ) + uint8_t data[128]; int32_t len = 32; + memcpy(data+1,privkey.bytes,sizeof(privkey)); + len = base58encode_checkbuf(addrtype,data,len); + if ( bitcoin_base58encode(wifstr,data,len) == 0 ) + return(-1); + if ( 1 ) { - if ( (scriptlen= iguana_scriptsigextract(myinfo,coin,scriptsig,sizeof(scriptsig),txid,vini)) > 32 ) + uint8_t checktype; bits256 checkpriv; char str[65],str2[65]; + if ( bitcoin_wif2priv(&checktype,&checkpriv,wifstr) == sizeof(bits256) ) { - for (i=0; i<32; i++) - privkey.bytes[i] = scriptsig[scriptlen - 33 + i]; - revcalc_rmd160_sha256(rmd160,privkey);//.bytes,sizeof(privkey)); - if ( memcmp(secret160,rmd160,sizeof(rmd160)) == sizeof(rmd160) ) - { - *destp = privkey; - printf("basilisk_priviextract found privi %s (%s)\n",name,bits256_str(str,privkey)); - return(0); - } + if ( checktype != addrtype || bits256_cmp(checkpriv,privkey) != 0 ) + printf("(%s) -> wif.(%s) addrtype.%02x -> %02x (%s)\n",bits256_str(str,privkey),wifstr,addrtype,checktype,bits256_str(str2,checkpriv)); } } - return(-1); + return((int32_t)strlen(wifstr)); } -int32_t basilisk_confirmsobj(cJSON *item) +char *_setVsigner(uint8_t pubtype,struct vin_info *V,int32_t ind,char *pubstr,char *wifstr) { - int32_t height,numconfirms; - height = jint(item,"height"); - numconfirms = jint(item,"numconfirms"); - if ( height > 0 && numconfirms >= 0 ) - return(numconfirms); - printf("basilisk_confirmsobj height.%d numconfirms.%d (%s)\n",height,numconfirms,jprint(item,0)); - return(-1); + uint8_t addrtype; + decode_hex(V->signers[ind].pubkey,(int32_t)strlen(pubstr)/2,pubstr); + bitcoin_wif2priv(&addrtype,&V->signers[ind].privkey,wifstr); + if ( addrtype != pubtype ) + return(clonestr("{\"error\":\"invalid wifA\"}")); + else return(0); } -int32_t basilisk_numconfirms(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) +uint8_t iguana_addrtype(uint8_t pubtype,uint8_t p2shtype,uint8_t script_type) { - cJSON *argjson,*valuearray=0; char *valstr; int32_t i,n,retval = -1; -#ifdef BASILISK_DISABLEWAITTX - return(100); -#endif - argjson = cJSON_CreateObject(); - jaddbits256(argjson,"txid",rawtx->I.actualtxid); - jaddnum(argjson,"vout",0); - jaddstr(argjson,"coin",rawtx->coin->symbol); - if ( (valstr= basilisk_value(myinfo,rawtx->coin,0,0,swap->persistent_pubkey,argjson,0)) != 0 ) - { - char str[65]; printf("basilisk_numconfirms required.%d %s %s valstr.(%s)\n",rawtx->I.numconfirms,rawtx->name,bits256_str(str,rawtx->I.actualtxid),valstr); - //basilisk_numconfirms required.0 alicespend 29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85 valstr.({"result":"success","numconfirms":0,"address":"1JGvZ67oTdM7kCya4J8kj1uErbSRAoq3wH","satoshis":"1413818","value":0.01413818,"height":462440,"txid":"29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85","vout":0,"coin":"BTC"}) - - if ( (valuearray= cJSON_Parse(valstr)) != 0 ) - { - if ( valstr[0] == '[' && is_cJSON_Array(valuearray) != 0 ) - { - n = cJSON_GetArraySize(valuearray); - for (i=0; i= 0 ) - break; - } - } else retval = basilisk_confirmsobj(valuearray); - free_json(valuearray); - } else printf("parse error\n"); - free(valstr); + if ( script_type == IGUANA_SCRIPT_76A988AC || script_type == IGUANA_SCRIPT_AC || script_type == IGUANA_SCRIPT_76AC ) + return(pubtype); + else + { + //printf("P2SH type.%d\n",script_type); + return(p2shtype); } - free_json(argjson); - printf("numconfirms.%d returned\n",retval); - return(retval); } -bits256 basilisk_swap_broadcast(char *name,struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,uint8_t *data,int32_t datalen) +int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,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) { - bits256 txid; char *signedtx,*retstr; int32_t i; - memset(txid.bytes,0,sizeof(txid)); - if ( data != 0 && datalen != 0 ) + uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t plen,i,m,n,flag = 0,scriptlen = 0; + m = n = 0; + if ( asmstr != 0 ) + asmstr[0] = 0; + addrtype = iguana_addrtype(pubtype,p2shtype,type); + if ( type == IGUANA_SCRIPT_76A988AC || type == IGUANA_SCRIPT_AC || type == IGUANA_SCRIPT_76AC || type == IGUANA_SCRIPT_P2SH ) { - char str[65]; -#ifdef BASILISK_DISABLESENDTX - txid = bits256_doublesha256(0,data,datalen); - printf("%s <- dont sendrawtransaction (%s)\n",name,bits256_str(str,txid)); - return(txid); -#endif - signedtx = malloc(datalen*2 + 1); - init_hexbytes_noT(signedtx,data,datalen); - for (i=0; i<3; i++) + init_hexbytes_noT(rmd160str,rmd160,20); + bitcoin_address(coinaddr,addrtype,rmd160,20); + } + switch ( type ) + { + case IGUANA_SCRIPT_NULL: + if ( asmstr != 0 ) + strcpy(asmstr,txi == 0 ? "coinbase " : "PoSbase "); + flag++; + coinaddr[0] = 0; + break; + case IGUANA_SCRIPT_76AC: + case IGUANA_SCRIPT_AC: + if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) < 0 ) + return(0); + init_hexbytes_noT(pubkeystr,(uint8_t *)vp->signers[0].pubkey,plen); + if ( asmstr != 0 ) + { + if ( type == IGUANA_SCRIPT_76AC ) + strcpy(asmstr,"OP_DUP "); + sprintf(asmstr + strlen(asmstr),"%s OP_CHECKSIG // %s",pubkeystr,coinaddr); + } + if ( type == IGUANA_SCRIPT_76AC ) + script[scriptlen++] = 0x76; + scriptlen = bitcoin_pubkeyspend(script,scriptlen,(uint8_t *)vp->signers[0].pubkey); + //printf("[%02x] type.%d scriptlen.%d\n",vp->signers[0].pubkey[0],type,scriptlen); + break; + case IGUANA_SCRIPT_76A988AC: + if ( asmstr != 0 ) + sprintf(asmstr,"OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG // %s",rmd160str,coinaddr); + scriptlen = bitcoin_standardspend(script,0,rmd160); + break; + case IGUANA_SCRIPT_P2SH: + if ( asmstr != 0 ) + sprintf(asmstr,"OP_HASH160 %s OP_EQUAL // %s",rmd160str,coinaddr); + scriptlen = bitcoin_p2shspend(script,0,rmd160); + break; + case IGUANA_SCRIPT_OPRETURN: + if ( asmstr != 0 ) + strcpy(asmstr,"OP_RETURN "); + bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); + flag++; + break; + case IGUANA_SCRIPT_3of3: m = 3, n = 3; break; + case IGUANA_SCRIPT_2of3: m = 2, n = 3; break; + case IGUANA_SCRIPT_1of3: m = 1, n = 3; break; + case IGUANA_SCRIPT_2of2: m = 2, n = 2; break; + case IGUANA_SCRIPT_1of2: m = 1, n = 2; break; + case IGUANA_SCRIPT_1of1: m = 1, n = 1; break; + case IGUANA_SCRIPT_MSIG: m = vp->M, n = vp->N; break; + case IGUANA_SCRIPT_DATA: + if ( asmstr != 0 ) + strcpy(asmstr,"DATA ONLY"); + bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); + flag++; + break; + case IGUANA_SCRIPT_STRANGE: + if ( asmstr != 0 ) + strcpy(asmstr,"STRANGE SCRIPT "); + bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); + flag++; + break; + default: break;//printf("unexpected script type.%d\n",type); break; + } + if ( n > 0 ) + { + scriptlen = bitcoin_MofNspendscript(rmd160,script,0,vp); + bitcoin_address(coinaddr,p2shtype,script,scriptlen); + if ( asmstr != 0 ) { - if ( (retstr= basilisk_sendrawtransaction(myinfo,coin,signedtx)) != 0 ) + sprintf(asmstr,"%d ",m); + for (i=0; isigners[i].pubkey)) > 0 ) { - printf("sendrawtransaction %s error.(%s)\n",name,retstr); - free(retstr); + init_hexbytes_noT(asmstr + strlen(asmstr),(uint8_t *)vp->signers[i].pubkey,plen); + if ( asmstr != 0 ) + strcat(asmstr," "); } - } else printf("sendrawtransaction %s got null return\n",name); + else if ( asmstr != 0 ) + strcat(asmstr,"NOPUBKEY "); + sprintf(asmstr + strlen(asmstr),"%d // M.%d of N.%d [",n,m,n); + for (i=0; isigners[i].coinaddr,ispendlen > 0 ) + init_hexbytes_noT(asmstr + strlen(asmstr),(uint8_t *)vp->spendscript,vp->spendlen); + *Mp = m, *nump = n; + return(scriptlen); } -int32_t _basilisk_rawtx_sign(struct supernet_info *myinfo,int32_t height,uint32_t timestamp,uint32_t locktime,uint32_t sequenceid,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr) -{ - char *rawtxbytes=0,*signedtx=0,hexstr[999],wifstr[128]; cJSON *txobj,*vins,*item,*sobj,*privkeys; int32_t needsig=1,retval = -1; struct vin_info *V; - V = calloc(256,sizeof(*V)); - V[0].signers[0].privkey = privkey; - bitcoin_pubkey33(myinfo->ctx,V[0].signers[0].pubkey,privkey); - privkeys = cJSON_CreateArray(); - bitcoin_priv2wif(wifstr,privkey,rawtx->coin->chain->wiftype); - jaddistr(privkeys,wifstr); - if ( privkey2 != 0 ) - { - V[0].signers[1].privkey = *privkey2; - bitcoin_pubkey33(myinfo->ctx,V[0].signers[1].pubkey,*privkey2); - bitcoin_priv2wif(wifstr,*privkey2,rawtx->coin->chain->wiftype); - jaddistr(privkeys,wifstr); - V[0].N = V[0].M = 2; - //char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2)); - } else V[0].N = V[0].M = 1; - V[0].suppress_pubkeys = dest->I.suppress_pubkeys; - V[0].ignore_cltverr = ignore_cltverr; - if ( dest->I.redeemlen != 0 ) - memcpy(V[0].p2shscript,dest->redeemscript,dest->I.redeemlen), V[0].p2shlen = dest->I.redeemlen; - txobj = bitcoin_txcreate(rawtx->coin->symbol,rawtx->coin->chain->isPoS,locktime,userdata == 0 ? 1 : 1,timestamp);//rawtx->coin->chain->locktime_txversion); - vins = cJSON_CreateArray(); - item = cJSON_CreateObject(); - if ( userdata != 0 && userdatalen > 0 ) - { - memcpy(V[0].userdata,userdata,userdatalen); - V[0].userdatalen = userdatalen; - init_hexbytes_noT(hexstr,userdata,userdatalen); - jaddstr(item,"userdata",hexstr); -#ifdef DISABLE_CHECKSIG - needsig = 0; -#endif +int32_t bitcoin_scriptget(uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype) +{ + int32_t j,n,siglen,plen; uint8_t *p2shscript; + j = n = 0; + *userdatap = 0; + *userdatalenp = *pubkeysizep = *sigsizep = 0; + *hashtypep = SIGHASH_ALL; + while ( (siglen= scriptsig[n]) >= 70 && siglen <= 73 && n+siglen < len && j < 16 ) + { + vp->signers[j].siglen = siglen; + memcpy(vp->signers[j].sig,&scriptsig[n+1],siglen); + if ( j == 0 ) + *hashtypep = vp->signers[j].sig[siglen-1]; + else if ( vp->signers[j].sig[siglen-1] != *hashtypep ) + { + //printf("SIGHASH.%d mismatch %d vs %d\n",j,vp->signers[j].sig[siglen-1],*hashtypep); + break; + } + (*sigsizep) += siglen; + //printf("sigsize %d [%02x]\n",*sigsizep,vp->signers[j].sig[siglen-1]); + n += (siglen + 1); + j++; + if ( spendtype == 0 && j > 1 ) + spendtype = IGUANA_SCRIPT_MSIG; } - //printf("rawtx B\n"); - if ( bits256_nonz(rawtx->I.actualtxid) != 0 ) - jaddbits256(item,"txid",rawtx->I.actualtxid); - else jaddbits256(item,"txid",rawtx->I.signedtxid); - jaddnum(item,"vout",0); - sobj = cJSON_CreateObject(); - init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->I.spendlen); - jaddstr(sobj,"hex",hexstr); - jadd(item,"scriptPubKey",sobj); - jaddnum(item,"suppress",dest->I.suppress_pubkeys); - jaddnum(item,"sequence",sequenceid); - if ( (dest->I.redeemlen= rawtx->I.redeemlen) != 0 ) + vp->numsigs = j; + vp->type = spendtype; + if ( j == 0 ) { - init_hexbytes_noT(hexstr,rawtx->redeemscript,rawtx->I.redeemlen); - memcpy(dest->redeemscript,rawtx->redeemscript,rawtx->I.redeemlen); - jaddstr(item,"redeemScript",hexstr); + //*userdatalenp = len; + vp->spendlen = len; + return(vp->spendlen); } - jaddi(vins,item); - jdelete(txobj,"vin"); - jadd(txobj,"vin",vins); - //printf("basilisk_rawtx_sign locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->I.locktime,dest->I.locktime,rawtx->name,hexstr,dest->name,dest->I.suppress_pubkeys); - txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->I.spendlen,dest->I.amount); - if ( (rawtxbytes= bitcoin_json2hex(myinfo,rawtx->coin,&dest->I.txid,txobj,V)) != 0 ) - { - //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins); - if ( needsig == 0 ) - signedtx = rawtxbytes; - if ( signedtx != 0 || (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&dest->I.signedtxid,&dest->I.completed,vins,rawtxbytes,privkeys,V)) != 0 ) - { - dest->I.datalen = (int32_t)strlen(signedtx) >> 1; - if ( dest->I.datalen <= sizeof(dest->txbytes) ) - decode_hex(dest->txbytes,dest->I.datalen,signedtx); - else printf("DEX tx is too big %d vs %d\n",dest->I.datalen,(int32_t)sizeof(dest->txbytes)); - if ( signedtx != rawtxbytes ) - free(signedtx); - if ( dest->I.completed != 0 ) - retval = 0; - else printf("couldnt complete sign transaction %s\n",rawtx->name); - } else printf("error signing\n"); - free(rawtxbytes); - } else printf("error making rawtx\n"); - free_json(privkeys); - free_json(txobj); - free(V); - return(retval); -} - -int32_t basilisk_rawtx_sign(struct supernet_info *myinfo,int32_t height,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr) -{ - uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; - timestamp = swap->I.started; - if ( dest == &swap->aliceclaim ) - locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0; - else if ( dest == &swap->bobreclaim ) - locktime = swap->bobpayment.I.locktime + 1, sequenceid = 0; - return(_basilisk_rawtx_sign(myinfo,height,timestamp,locktime,sequenceid,dest,rawtx,privkey,privkey2,userdata,userdatalen,ignore_cltverr)); -} - -cJSON *basilisk_privkeyarray(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins) -{ - cJSON *privkeyarray,*item,*sobj; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],account[128],wifstr[64],str[65],typestr[64],*hexstr; uint8_t script[1024]; int32_t i,n,len,vout; bits256 txid,privkey; double bidasks[2]; - privkeyarray = cJSON_CreateArray(); - //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr); - if ( (n= cJSON_GetArraySize(vins)) > 0 ) + j = 0; + while ( ((plen= scriptsig[n]) == 33 || plen == 65) && j < 16 && plen+n <= len ) { - for (i=0; isigners[j].pubkey,&scriptsig[n+1],plen); + calc_rmd160_sha256(vp->signers[j].rmd160,vp->signers[j].pubkey,plen); + if ( j == 0 ) + memcpy(vp->rmd160,vp->signers[j].rmd160,20); + n += (plen + 1); + (*pubkeysizep) += plen; + j++; + } + vp->numpubkeys = j; + *userdatap = &scriptsig[n]; + if ( len > n ) + *userdatalenp = (len - n); + p2shscript = 0; + while ( n < len ) + { + if ( n+2 < len && (scriptsig[n] == 0x4c || scriptsig[n] == 0x4d) ) { - item = jitem(vins,i); - txid = jbits256(item,"txid"); - vout = jint(item,"vout"); - if ( bits256_nonz(txid) != 0 && vout >= 0 ) + 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; + //printf("p2sh opcode.%02x %02x %02x scriptlen.%d\n",scriptsig[n],scriptsig[n+1],scriptsig[n+2],vp->p2shlen); + if ( vp->p2shlen < IGUANA_MAXSCRIPTSIZE && n+vp->p2shlen <= len ) { - iguana_txidcategory(myinfo,coin,account,coinaddr,txid,vout); - if ( coinaddr[0] == 0 && (sobj= jobj(item,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && is_hexstr(hexstr,0) > 0 ) - { - len = (int32_t)strlen(hexstr) >> 1; - if ( len < (sizeof(script) << 1) ) - { - decode_hex(script,len,hexstr); - if ( len == 25 && script[0] == 0x76 && script[1] == 0xa9 && script[2] == 0x14 ) - bitcoin_address(coinaddr,coin->chain->pubtype,script+3,20); - } - } - if ( coinaddr[0] != 0 ) - { - if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 ) - { - bitcoin_priv2wif(wifstr,waddr->privkey,coin->chain->wiftype); - jaddistr(privkeyarray,waddr->wifstr); - } - else if ( smartaddress(myinfo,typestr,bidasks,&privkey,coin->symbol,coinaddr) >= 0 ) - { - bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype); - jaddistr(privkeyarray,wifstr); - } - else printf("cant find (%s) in wallet\n",coinaddr); - } else printf("cant coinaddr from (%s).v%d\n",bits256_str(str,txid),vout); - } else printf("invalid txid/vout %d of %d\n",i,n); + p2shscript = &scriptsig[n]; + memcpy(vp->p2shscript,&scriptsig[n],vp->p2shlen); + n += vp->p2shlen; + vp->type = IGUANA_SCRIPT_P2SH; + } else vp->p2shlen = 0; } } - return(privkeyarray); + if ( *userdatap == p2shscript ) + *userdatap = 0; + /*if ( len == 0 ) + { + // txid.(eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2).v1 + decode_hex(vp->rmd160,20,"010966776006953d5567439e5e39f86a0d273bee");//3564a74f9ddb4372301c49154605573d7d1a88fe"); + vp->type = IGUANA_SCRIPT_76A988AC; + }*/ + vp->spendlen = iguana_scriptgen(pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,vp->spendscript,0,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 basilisk_rawtx_return(struct supernet_info *myinfo,int32_t height,struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V) +int32_t _iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp) { - char *signedtx,*txbytes; cJSON *vins,*privkeyarray; int32_t i,n,retval = -1; - if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 ) + static uint8_t zero_rmd160[20]; + char hexstr[8192]; uint8_t *script,type; int32_t i,n,m,plen; + if ( vp->N == 0 ) + vp->N = 1; + if ( vp->M == 0 ) + vp->M = 1; + type = IGUANA_SCRIPT_STRANGE; + init_hexbytes_noT(hexstr,vp->spendscript,vp->spendlen); + //char str[65]; printf("script.(%s).%d in %s len.%d plen.%d spendlen.%d cmp.%d\n",hexstr,vp->spendlen,bits256_str(str,vp->vin.prev_hash),vp->spendlen,bitcoin_pubkeylen(&vp->spendscript[1]),vp->spendlen,vp->spendscript[vp->spendlen-1] == SCRIPT_OP_CHECKSIG); + if ( vp->spendlen == 0 ) + { + if ( zero_rmd160[0] == 0 ) + { + calc_rmd160_sha256(zero_rmd160,vp->spendscript,vp->spendlen); + //vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen); // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + //calc_rmd160(0,zero_rmd160,sha256,sizeof(sha256)); // b472a266d0bd89c13706a4132ccfb16f7c3b9fcb + init_hexbytes_noT(hexstr,zero_rmd160,20); + } + memcpy(vp->rmd160,zero_rmd160,sizeof(zero_rmd160)); + return(IGUANA_SCRIPT_NULL); + } + else if ( vp->spendscript[0] == SCRIPT_OP_RETURN ) + type = IGUANA_SCRIPT_OPRETURN; + else if ( vp->spendscript[0] == SCRIPT_OP_DUP && vp->spendscript[1] == SCRIPT_OP_HASH160 && vp->spendscript[2] == 20 && vp->spendscript[vp->spendscript[2]+3] == SCRIPT_OP_EQUALVERIFY && vp->spendscript[vp->spendscript[2]+4] == SCRIPT_OP_CHECKSIG ) + { + //printf("IGUANA_SCRIPT_76A988AC plen.%d vs %d vp->spendlen\n",vp->spendscript[2]+4,vp->spendlen); + // 76a9145f69cb73016264270dae9f65c51f60d0e4d6fd4488ac + memcpy(vp->rmd160,&vp->spendscript[3],20); + if ( (plen= vp->spendscript[2]+5) != vp->spendlen ) + { + return(IGUANA_SCRIPT_STRANGE); + /*while ( plen < vp->spendlen ) + if ( vp->spendscript[plen++] != 0x61 ) // nop + return(IGUANA_SCRIPT_STRANGE);*/ + } + return(IGUANA_SCRIPT_76A988AC); + } + // 21035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055eac + else if ( vp->spendscript[0] == SCRIPT_OP_DUP && (plen= bitcoin_pubkeylen(&vp->spendscript[2])) > 0 && vp->spendscript[vp->spendlen-1] == SCRIPT_OP_CHECKSIG && vp->spendscript[0] == plen && vp->spendlen == plen+3 ) + { + memcpy(vp->signers[0].pubkey,&vp->spendscript[2],plen); + calc_rmd160_sha256(vp->rmd160,vp->signers[0].pubkey,plen); + //printf("found IGUANA_SCRIPT_76AC\n"); + return(IGUANA_SCRIPT_76AC); + } + else if ( (plen= bitcoin_pubkeylen(&vp->spendscript[1])) > 0 && vp->spendscript[vp->spendlen-1] == SCRIPT_OP_CHECKSIG && vp->spendscript[0] == plen && vp->spendlen == plen+2 ) { - privkeyarray = basilisk_privkeyarray(myinfo,rawtx->coin,vins); - if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&rawtx->I.signedtxid,&rawtx->I.completed,vins,txbytes,privkeyarray,V)) != 0 ) + memcpy(vp->signers[0].pubkey,&vp->spendscript[1],plen); + calc_rmd160_sha256(vp->rmd160,vp->signers[0].pubkey,plen); + //printf("found IGUANA_SCRIPT_AC\n"); + return(IGUANA_SCRIPT_AC); + } + else if ( vp->spendscript[0] == SCRIPT_OP_HASH160 && vp->spendscript[1] == 0x14 && vp->spendlen == 23 && vp->spendscript[22] == SCRIPT_OP_EQUAL ) + { + memcpy(vp->rmd160,vp->spendscript+2,20); + return(IGUANA_SCRIPT_P2SH); + } + else if ( vp->spendlen > 34 && vp->spendscript[vp->spendlen-1] == SCRIPT_OP_CHECKMULTISIG && (n= vp->spendscript[vp->spendlen-2]) >= 0x51 && n <= 0x60 && (m= vp->spendscript[0]) >= 0x51 && m <= n ) // m of n multisig + { + m -= 0x50, n -= 0x50; + script = vp->spendscript+1; + for (i=0; icoin,vins); - if ( (n= cJSON_GetArraySize(vins)) != 0 ) - { - bits256 txid; int32_t vout; - for (i=0; iI.datalen = (int32_t)strlen(signedtx) >> 1; - //rawtx->txbytes = calloc(1,rawtx->I.datalen); - decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); - //printf("%s SIGNEDTX.(%s)\n",rawtx->name,signedtx); - free(signedtx); - retval = 0; - } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll - free_json(privkeyarray); + memcpy(vp->signers[i].pubkey,script,plen); + calc_rmd160_sha256(vp->signers[i].rmd160,vp->signers[i].pubkey,plen); + bitcoin_address(vp->signers[i].coinaddr,pubtype,vp->signers[i].pubkey,plen); + } + if ( (int32_t)((long)script - (long)vp->spendscript) == vp->spendlen-2 ) + { + vp->N = n; + vp->M = m; + //printf("M.%d N.%d\n",m,n); + } + calc_rmd160_sha256(vp->rmd160,vp->spendscript,vp->spendlen); + if ( n == 3 ) + { + if ( m == 3 ) + return(IGUANA_SCRIPT_3of3); + else if ( m == 2 ) + return(IGUANA_SCRIPT_2of3); + else if ( m == 1 ) + return(IGUANA_SCRIPT_1of3); + } + else if ( n == 2 ) + { + if ( m == 2 ) + return(IGUANA_SCRIPT_2of2); + else if ( m == 1 ) + return(IGUANA_SCRIPT_1of2); + } + else if ( m == 1 && n == 1 ) + return(IGUANA_SCRIPT_1of1); + //printf("strange msig M.%d of N.%d\n",m,n); + return(IGUANA_SCRIPT_MSIG); + } + else if ( vp->spendlen == vp->spendscript[0]+1 ) + { + //printf("just data.%d\n",vp->spendlen); + memcpy(vp->rmd160,zero_rmd160,sizeof(zero_rmd160)); + return(IGUANA_SCRIPT_DATA); + } + if ( type != IGUANA_SCRIPT_OPRETURN && type != IGUANA_SCRIPT_DATA ) + { + if ( vp->spendlen > 0 && vp->spendlen < sizeof(hexstr)/2-1 ) + { + static FILE *fp; + init_hexbytes_noT(hexstr,vp->spendscript,vp->spendlen); + //char str[65]; printf("unparsed script.(%s).%d in %s len.%d\n",hexstr,vp->spendlen,bits256_str(str,vp->vin.prev_hash),vp->spendlen); + if ( 1 && fp == 0 ) + fp = fopen("unparsed.txt","w"); + if ( fp != 0 ) + fprintf(fp,"%s\n",hexstr), fflush(fp); + } else sprintf(hexstr,"pkscript overflowed %ld\n",(long)sizeof(hexstr)); } - return(retval); + calc_rmd160_sha256(vp->rmd160,vp->spendscript,vp->spendlen); + return(type); } -int32_t _basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay) +int32_t iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,char *asmstr,struct vin_info *vp,uint8_t *pk_script,int32_t pk_scriptlen,bits256 debugtxid,int32_t vout,uint32_t sequence) { - char *retstr,*jsonstr,scriptstr[1024],coinaddr[64]; uint32_t basilisktag; int32_t flag,i,n,retval = -1; cJSON *addresses,*valsobj,*retarray=0; struct vin_info *V; - //bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33); - if ( rawtx->coin->changeaddr[0] == 0 ) + int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; + memset(vp,0,sizeof(*vp)); + vp->vin.prev_hash = debugtxid, vp->vin.prev_vout = vout; + vp->spendlen = pk_scriptlen; + vp->vin.sequence = sequence; + memcpy(vp->spendscript,pk_script,pk_scriptlen); + if ( (vp->type= _iguana_calcrmd160(pubtype,p2shtype,vp)) >= 0 ) { - bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->chain->pubtype,pubkey33,33); - printf("set change address.(%s)\n",rawtx->coin->changeaddr); - } - init_hexbytes_noT(scriptstr,script,scriptlen); - basilisktag = (uint32_t)rand(); - valsobj = cJSON_CreateObject(); - jaddstr(valsobj,"coin",rawtx->coin->symbol); - jaddstr(valsobj,"spendscript",scriptstr); - jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); - jadd64bits(valsobj,"satoshis",rawtx->I.amount); - if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 ) - txfee = 50000; - jadd64bits(valsobj,"txfee",txfee); - jaddnum(valsobj,"minconf",minconf); - if ( locktime == 0 ) - locktime = (uint32_t)time(NULL) - 777; - jaddnum(valsobj,"locktime",locktime); - jaddnum(valsobj,"timeout",30000); - jaddnum(valsobj,"timestamp",swapstarted+delay); - addresses = cJSON_CreateArray(); - bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,pubkey33,33); - jaddistr(addresses,coinaddr); - jadd(valsobj,"addresses",addresses); - rawtx->I.locktime = locktime; - printf("%s locktime.%u\n",rawtx->name,locktime); - V = calloc(256,sizeof(*V)); - if ( (retstr= basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V)) != 0 ) - { - printf("%s %s basilisk_bitcoinrawtx.(%s) txfee %.8f\n",rawtx->name,str,retstr,dstr(txfee)); - flag = 0; - if ( (retarray= cJSON_Parse(retstr)) != 0 ) - { - if ( is_cJSON_Array(retarray) != 0 ) + scriptlen = iguana_scriptgen(pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout); + if ( vp->M == 0 && vp->N == 0 ) + { + vp->M = vp->N = 1; + strcpy(vp->signers[0].coinaddr,vp->coinaddr); + memcpy(vp->signers[0].rmd160,vp->rmd160,20); + } + if ( scriptlen != pk_scriptlen || (scriptlen != 0 && memcmp(script,pk_script,scriptlen) != 0) ) + { + if ( vp->type != IGUANA_SCRIPT_OPRETURN && vp->type != IGUANA_SCRIPT_DATA && vp->type != IGUANA_SCRIPT_STRANGE ) { - n = cJSON_GetArraySize(retarray); - for (i=0; icoin->longestchain,rawtx,jitem(retarray,i),lockinputs,V)) == 0 ) - { - rawtx->vins = jduplicate(jobj(jitem(retarray,i),"vins")); - jsonstr = jprint(rawtx->vins,0); - safecopy(rawtx->vinstr,jsonstr,sizeof(rawtx->vinstr)); - free(jsonstr); - break; - } - } + int32_t i; + printf("\n--------------------\n"); + for (i=0; itype,scriptlen,pk_scriptlen); } - else - { - retval = basilisk_rawtx_return(myinfo,rawtx->coin->longestchain,rawtx,retarray,lockinputs,V); - rawtx->vins = jduplicate(jobj(retarray,"vins")); - jsonstr = jprint(rawtx->vins,0); - safecopy(rawtx->vinstr,jsonstr,sizeof(rawtx->vinstr)); - free(jsonstr); + } + } + return(vp->type); +} + +cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars) +{ + int32_t i; cJSON *scriptjson,*array; + scriptjson = cJSON_CreateObject(); + jaddstr(scriptjson,"asm",asmstr); + jaddnum(scriptjson,"numvars",numvars); + if ( numvars > 0 ) + { + array = cJSON_CreateArray(); + for (i=0; i= 0 ) + { + if ( (n= V.N) == 0 ) + n = 1; + for (i=0; i 0 ) + init_hexbytes_noT(pubkeystr,V.signers[i].pubkey,plen); + else pubkeystr[0] = 0; + jaddistr(pubkeys,pubkeystr); + } + } + return(pubkeys); +} + +void iguana_addscript(cJSON *dest,uint8_t *script,int32_t scriptlen,char *fieldname) +{ + char *scriptstr,scriptbuf[8192+256]; int32_t maxlen; cJSON *scriptobj; + if ( scriptlen < 0 || scriptlen > IGUANA_MAXSCRIPTSIZE || scriptlen > sizeof(scriptbuf) ) + return; + scriptstr = scriptbuf, maxlen = sizeof(scriptbuf); + init_hexbytes_noT(scriptstr,script,scriptlen); + //if ( strcmp(fieldname,"userdata") == 0 ) + // printf("SCRIPT_USERDATA.(%s)\n",scriptstr); + if ( strcmp(fieldname,"coinbase") == 0 ) + jaddstr(dest,"coinbase",scriptstr); + else + { + scriptobj = cJSON_CreateObject(); + jaddstr(scriptobj,"hex",scriptstr); + iguana_expandscript(scriptstr,maxlen,script,scriptlen); + if ( scriptstr[0] != 0 ) + jaddstr(scriptobj,"asm",scriptstr); + if ( scriptstr != scriptbuf ) + free(scriptstr); + jadd(dest,fieldname,scriptobj); + } +} + +cJSON *iguana_pubkeysjson(uint8_t *pubkeyptrs[],int32_t numpubkeys) +{ + int32_t i,plen; char pubkeystr[256]; cJSON *pubkeysjson = cJSON_CreateArray(); + for (i=0; i 0 ) + init_hexbytes_noT(pubkeystr,pubkeyptrs[i],plen); + else pubkeystr[0] = 0; + jaddistr(pubkeysjson,pubkeystr); + } + return(pubkeysjson); +} + +cJSON *bitcoin_txinput(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys,uint8_t *sig,int32_t siglen) +{ + cJSON *item,*vins; char p2shscriptstr[IGUANA_MAXSCRIPTSIZE*2+1]; uint8_t *script,len=0; + vins = jduplicate(jobj(txobj,"vin")); + jdelete(txobj,"vin"); + item = cJSON_CreateObject(); + if ( sig != 0 && siglen > 0 ) + iguana_addscript(item,sig,siglen,"scriptSig"); + if ( spendscript != 0 && spendscript > 0 ) + { + iguana_addscript(item,spendscript,spendlen,"scriptPubKey"); + script = spendscript, len = spendlen; + } + else if ( redeemscript != 0 && p2shlen > 0 ) + { + init_hexbytes_noT(p2shscriptstr,redeemscript,p2shlen); + jaddstr(item,"redeemScript",p2shscriptstr); + script = redeemscript, len = p2shlen; + } else script = 0; + if ( script != 0 && numpubkeys == 0 ) + jadd(item,"pubkeys",iguana_scriptpubkeys(pubtype,p2shtype,script,len,txid,vout,sequenceid)); + else if ( pubkeys != 0 && numpubkeys > 0 ) + jadd(item,"pubkeys",iguana_pubkeysjson(pubkeys,numpubkeys)); + jaddbits256(item,"txid",txid); + jaddnum(item,"vout",vout); + jaddnum(item,"sequence",sequenceid); + jaddi(vins,item); + jadd(txobj,"vin",vins); + //printf("addvin -> (%s)\n",jprint(txobj,0)); + return(txobj); +} + +cJSON *bitcoin_txcreate(char *symbol,int32_t isPoS,int64_t locktime,uint32_t txversion,uint32_t timestamp) +{ + cJSON *json = cJSON_CreateObject(); + jaddnum(json,"version",txversion); + if ( locktime == 0 && strcmp(symbol,"KMD") == 0 ) + locktime = (uint32_t)time(NULL); + jaddnum(json,"locktime",locktime); + if ( isPoS != 0 ) + jaddnum(json,"timestamp",timestamp == 0 ? time(NULL) : timestamp); + jadd(json,"vin",cJSON_CreateArray()); + jadd(json,"vout",cJSON_CreateArray()); + return(json); +} + +cJSON *bitcoin_txoutput(cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis) +{ + char *hexstr; cJSON *item,*skey,*vouts = jduplicate(jobj(txobj,"vout")); + jdelete(txobj,"vout"); + item = cJSON_CreateObject(); + jadd64bits(item,"satoshis",satoshis); + skey = cJSON_CreateObject(); + hexstr = malloc(len*2 + 1); + init_hexbytes_noT(hexstr,paymentscript,len); + jaddstr(skey,"hex",hexstr); + //printf("addoutput.(%s %s)\n",hexstr,jprint(skey,0)); + free(hexstr); + jadd(item,"scriptPubkey",skey); + jaddi(vouts,item); + jadd(txobj,"vout",vouts); + return(txobj); +} + +int32_t bitcoin_txaddspend(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,char *destaddress,uint64_t satoshis) +{ + uint8_t outputscript[128],addrtype,rmd160[20]; int32_t scriptlen; + if ( bitcoin_validaddress(pubtype,p2shtype,destaddress) == 0 && satoshis != 0 ) + { + bitcoin_addr2rmd160(&addrtype,rmd160,destaddress); + scriptlen = bitcoin_standardspend(outputscript,0,rmd160); + bitcoin_txoutput(txobj,outputscript,scriptlen,satoshis); + return(0); + } else return(-1); +} + +int32_t iguana_vinparse(int32_t rwflag,uint8_t *serialized,struct iguana_msgvin *msg) +{ + int32_t p2shlen,len = 0; uint32_t tmp; + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->prev_hash),msg->prev_hash.bytes); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->prev_vout),&msg->prev_vout); + //char str[65]; printf("prev_hash.(%s) v%d\n",bits256_str(str,msg->prev_hash),msg->prev_vout); + if ( rwflag == 1 ) + { + tmp = msg->scriptlen + msg->userdatalen + msg->p2shlen; + if ( msg->p2shlen != 0 ) + { + if ( msg->p2shlen < 76 ) + tmp++; + else if ( msg->p2shlen < 0x100 ) + tmp += 2; + else tmp += 3; + } + } + len += iguana_rwvarint32(rwflag,&serialized[len],&tmp); + if ( rwflag == 0 ) + { + /*if ( msg->p2shlen != 0 ) + { + if ( msg->p2shlen < 76 ) + tmp++; + else if ( msg->p2shlen < 0x100 ) + tmp += 2; + else tmp += 3; + }*/ + msg->scriptlen = tmp; + } + if ( msg->scriptlen > IGUANA_MAXSCRIPTSIZE ) + { + printf("iguana_vinparse illegal scriptlen.%d\n",msg->scriptlen); + return(-1); + } + //printf("len.%d scriptlen.%d user.%d p2sh.%d\n",len,msg->scriptlen,msg->userdatalen,msg->p2shlen); + if ( rwflag == 0 ) + { + msg->vinscript = &serialized[len]; + len += msg->scriptlen; + } + else + { + if ( msg->vinscript != 0 && msg->scriptlen > 0 ) + memcpy(&serialized[len],msg->vinscript,msg->scriptlen), len += msg->scriptlen; // pubkeys here + if ( msg->userdatalen > 0 && msg->userdata != 0 ) + { + //printf("userdata.%d scriptlen.%d\n",msg->userdatalen,msg->scriptlen); + memcpy(&serialized[len],msg->userdata,msg->userdatalen); + len += msg->userdatalen; + } + if ( (p2shlen= msg->p2shlen) > 0 && msg->redeemscript != 0 ) + { + if ( p2shlen < 76 ) + serialized[len++] = p2shlen; + else if ( p2shlen <= 0xff ) + { + serialized[len++] = 0x4c; + serialized[len++] = p2shlen; + } + else if ( p2shlen <= 0xffff ) + { + serialized[len++] = 0x4d; + serialized[len++] = (p2shlen & 0xff); + serialized[len++] = ((p2shlen >> 8) & 0xff); + } else return(-1); + memcpy(&serialized[len],msg->redeemscript,p2shlen), len += p2shlen; + if ( (0) ) + { + int32_t j; + for (j=0; jredeemscript[j]); + printf(" p2shlen.%d %x\n",p2shlen,p2shlen); + } + } + } + //printf("sequence starts.%d %08x\n",len,*(int32_t *)&serialized[len]); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence); + if ( (0) ) + { + int32_t i; char str[65]; + for (i=0; isequence,bits256_str(str,msg->prev_hash),msg->prev_vout,msg->vinscript,msg->scriptlen,rwflag); + } + return(len); +} + +int32_t iguana_voutparse(int32_t rwflag,uint8_t *serialized,struct iguana_msgvout *msg) +{ + int32_t len = 0; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->value),&msg->value); + len += iguana_rwvarint32(rwflag,&serialized[len],&msg->pk_scriptlen); + if ( msg->pk_scriptlen > IGUANA_MAXSCRIPTSIZE ) + { + printf("iguana_voutparse illegal scriptlen.%d\n",msg->pk_scriptlen); + return(-1); + } + if ( rwflag == 0 ) + msg->pk_script = &serialized[len]; + else if ( msg->pk_scriptlen > 0 ) + { + memcpy(&serialized[len],msg->pk_script,msg->pk_scriptlen); + if ( (0) ) + { + int32_t i; + for (i=0; ipk_scriptlen; i++) + printf("%02x",msg->pk_script[i]); + printf(" [%p] scriptlen.%d rwflag.%d %.8f\n",msg->pk_script,msg->pk_scriptlen,rwflag,dstr(msg->value)); + } + } // else serialized[len++] = 0; + len += msg->pk_scriptlen; + return(len); +} + +cJSON *iguana_vinjson(struct iguana_msgvin *vin,bits256 sigtxid) +{ + char str[65]; int32_t vout; cJSON *json = cJSON_CreateObject(); + vout = vin->prev_vout; + jaddnum(json,"sequence",vin->sequence); + if ( vout < 0 && bits256_nonz(vin->prev_hash) == 0 ) + iguana_addscript(json,vin->vinscript,vin->scriptlen,"coinbase"); + else + { + jaddstr(json,"txid",bits256_str(str,vin->prev_hash)); + jaddnum(json,"vout",vout); + if ( bits256_nonz(sigtxid) != 0 ) + jaddbits256(json,"sigtxid",sigtxid); + if ( vin->scriptlen > 0 && vin->vinscript != 0 ) // sigs + iguana_addscript(json,vin->vinscript,vin->scriptlen,"scriptSig"); + if ( vin->userdatalen > 0 && vin->userdata != 0 ) + iguana_addscript(json,vin->userdata,vin->userdatalen,"userdata"); + if ( vin->p2shlen > 0 && vin->redeemscript != 0 ) + iguana_addscript(json,vin->redeemscript,vin->p2shlen,"redeemScript"); + if ( vin->spendlen > 0 && vin->spendscript != 0 ) + iguana_addscript(json,vin->spendscript,vin->spendlen,"scriptPubKey"); + } + return(json); +} + +int32_t iguana_parsehexstr(uint8_t **destp,uint16_t *lenp,uint8_t *dest2,int32_t *len2p,uint8_t *serialized,char *hexstr) +{ + int32_t n; + n = (int32_t)strlen(hexstr) >> 1; + //printf("addhex.(%s) %d\n",hexstr,n); + if ( serialized == 0 ) + { + if ( (serialized= *destp) == 0 ) + printf("iguana_parsehexstr null serialized and destp\n"); + } + if ( serialized != 0 ) + { + decode_hex(serialized,n,hexstr); + *destp = serialized; + *lenp = n; + if ( dest2 != 0 && len2p != 0 ) + { + *len2p = n; + memcpy(dest2,serialized,n); + } + } + return(n); +} + +int32_t iguana_scriptnum(uint8_t opcode) +{ + if ( opcode == 0x00 ) + return(0); + else if ( opcode >= 0x51 && opcode < 0x60 ) + return(opcode - 0x50); + else return(-1); +} + +int32_t iguana_parsevinobj(uint8_t *serialized,int32_t maxsize,struct iguana_msgvin *vin,cJSON *vinobj,struct vin_info *V) +{ + //struct iguana_outpoint outpt; struct iguana_waddress *waddr; struct iguana_waccount *wacct; + uint8_t lastbyte; uint32_t tmp=0; int32_t i,n,starti,suppress_pubkeys,siglen,plen,m,endi,rwflag=1,len = 0; char *userdata=0,*pubkeystr,*hexstr = 0,*redeemstr = 0,*spendstr = 0; cJSON *scriptjson = 0,*obj,*pubkeysjson = 0; + //printf("PARSEVIN.(%s) vin.%p\n",jprint(vinobj,0),vin); + if ( V == 0 ) + memset(vin,0,sizeof(*vin)); + vin->prev_vout = -1; + suppress_pubkeys = juint(vinobj,"suppress"); + if ( jobj(vinobj,"sequence") != 0 ) + vin->sequence = juint(vinobj,"sequence"); + else vin->sequence = 0xffffffff; + if ( (hexstr= jstr(vinobj,"coinbase")) == 0 ) + { + vin->prev_hash = jbits256(vinobj,"txid"); + //char str[65]; printf("vin->prev_hash.(%s)\n",bits256_str(str,vin->prev_hash)); + vin->prev_vout = jint(vinobj,"vout"); + if ( (scriptjson= jobj(vinobj,"scriptSig")) != 0 ) + hexstr = jstr(scriptjson,"hex"); + if ( ((spendstr= jstr(vinobj,"scriptPub")) == 0 && (spendstr= jstr(vinobj,"scriptPubKey")) == 0) || is_hexstr(spendstr,(int32_t)strlen(spendstr)) <= 0 ) + { + if ( (obj= jobj(vinobj,"scriptPub")) != 0 || (obj= jobj(vinobj,"scriptPubKey")) != 0 ) + { + spendstr = jstr(obj,"hex"); + if ( spendstr[0] != 0 ) + { + lastbyte = _decode_hex(&spendstr[strlen(spendstr)-2]); + //if ( lastbyte == SCRIPT_OP_CHECKMULTISIG ) + // need_op0 = 1; + if ( V != 0 ) + { + V->spendlen = (int32_t)strlen(spendstr) >> 1; + decode_hex(V->spendscript,V->spendlen,spendstr); + } + } + } + } + if ( (redeemstr= jstr(vinobj,"redeemScript")) == 0 || is_hexstr(redeemstr,(int32_t)strlen(redeemstr)) <= 0 ) + { + if ( (obj= jobj(vinobj,"redeemScript")) != 0 ) + { + redeemstr = jstr(obj,"hex"); + lastbyte = _decode_hex(&redeemstr[strlen(redeemstr)-2]); + //if ( lastbyte == SCRIPT_OP_CHECKMULTISIG ) + // need_op0 = 1; + } + } + if ( (userdata= jstr(vinobj,"userdata")) == 0 || is_hexstr(userdata,(int32_t)strlen(userdata)) <= 0 ) + { + if ( (obj= jobj(vinobj,"userdata")) != 0 ) + userdata = jstr(obj,"hex"); + } + } + //char str[65]; printf("rw.%d prevhash.(%s)\n",rwflag,bits256_str(str,vin->prev_hash)); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(vin->prev_hash),vin->prev_hash.bytes); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(vin->prev_vout),&vin->prev_vout); + if ( V != 0 ) + { + V->suppress_pubkeys = suppress_pubkeys; + if ( vin->vinscript == 0 && V->spendlen == 0 ) + { + /*if ( iguana_RTunspentindfind(coin,&outpt,V->coinaddr,spendscript,&spendlen,&V->amount,&V->height,vin->prev_hash,vin->prev_vout,coin->bundlescount-1,0) == 0 ) + { + V->unspentind = outpt.unspentind; + if ( V->coinaddr[0] != 0 && (waddr= iguana_waddresssearch(&wacct,V->coinaddr)) != 0 ) + { + plen = bitcoin_pubkeylen(waddr->pubkey); + for (z=0; zsigners[0].pubkey[z] = waddr->pubkey[z]; + } + //printf("V %.8f (%s) spendscript.[%d]\n",dstr(V->amount),V->coinaddr,V->spendlen); } - free(retarray); - } else printf("error parsing.(%s)\n",retstr); - free(retstr); - } else printf("error creating %s %s\n",iambob != 0 ? "BOB" : "ALICE",rawtx->name); - free_json(valsobj); - free(V); - return(retval); -} - -int32_t basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay) -{ - int32_t retval,len; uint64_t newtxfee; struct iguana_info *coin; - if ( (coin= rawtx->coin) == 0 || strcmp(coin->symbol,"BTC") != 0 ) - return(_basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,txfee,minconf,delay)); - retval = _basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,0,rawtx,locktime,script,scriptlen,txfee,minconf,delay); - len = rawtx->I.datalen; - if ( coin->estimatedfee == 0 ) - coin->estimatedfee = iguana_getestimatedfee(myinfo,coin); - newtxfee = coin->estimatedfee * len; - if ( newtxfee > txfee ) - { - retval = _basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,newtxfee,minconf,delay); - printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); - } - return(retval); + if ( spendlen != 0 && V->spendlen == 0 ) + { + V->spendlen = spendlen; + memcpy(V->spendscript,spendscript,spendlen); + }*/ + } + } + tmp = IGUANA_MAXSCRIPTSIZE; + starti = len; + len += iguana_rwvarint32(rwflag,&serialized[len],&tmp); + endi = len; + //printf("rwflag.%d len.%d tmp.%d\n",rwflag,len,tmp); + //if ( need_op0 != 0 ) + // serialized[len++] = 0; // hack for bug for bug backward compatibility + if ( hexstr != 0 ) + { + n = (int32_t)strlen(hexstr) >> 1; + //printf("add.(%s) offset.%d\n",hexstr,len); + vin->vinscript = &serialized[len]; + decode_hex(&serialized[len],n,hexstr); + vin->scriptlen = n;// + need_op0; + if ( V != 0 ) + { + i = m = 0; + while ( m < n ) + { + siglen = serialized[len + m++]; + //if ( i == 0 && m == 1 && siglen == 0 ) // multisig backward compatible + // continue; + if ( serialized[len + m + siglen - 1] == SIGHASH_ALL ) + memcpy(V->signers[i++].sig,&serialized[len + m],siglen); + if ( (0) ) + { + int32_t j; + for (j=0; jvinscript != 0 ) + { + /*if ( vin->vinscript == 0 ) + { + vin->vinscript = serialized; + vin->vinscript[0] = 0; + vin->scriptlen = 1; + }*/ + for (i=0; i> 1) > 0 ) + { + if ( V != 0 ) + { + memcpy(V->signers[i].pubkey,&vin->vinscript[vin->scriptlen],plen); + if ( V->spendlen == 35 && V->spendscript[0] == 33 && V->spendscript[34] == 0xac ) + suppress_pubkeys = 1; + } + if ( suppress_pubkeys == 0 ) + { + printf("addpub.(%s)\n",pubkeystr); + vin->vinscript[vin->scriptlen++] = plen; + decode_hex(&vin->vinscript[vin->scriptlen],plen,pubkeystr); + vin->scriptlen += plen; + serialized[len++] = plen; + memcpy(&serialized[len],&vin->vinscript[vin->scriptlen],plen), len += plen; + } + } + } + } + //printf("userdata len.%d: ",len); + if ( userdata != 0 ) + { + n = iguana_parsehexstr(&vin->userdata,&vin->userdatalen,V!=0?V->userdata:0,V!=0?&V->userdatalen:0,&serialized[len],userdata); + //printf("parsed userdata.%d\n",n); + len += n; + } + //printf("redeemlen.%d: ",len); + if ( redeemstr != 0 ) + { + n = (int32_t)strlen(redeemstr) >> 1; + if ( n < 76 ) + serialized[len++] = n; + else if ( n <= 0xff ) + { + serialized[len++] = 0x4c; + serialized[len++] = n; + } + else + { + serialized[len++] = 0x4d; + serialized[len++] = n & 0xff; + serialized[len++] = (n >> 8) & 0xff; + } + n = iguana_parsehexstr(&vin->redeemscript,&vin->p2shlen,V!=0?V->p2shscript:0,V!=0?&V->p2shlen:0,&serialized[len],redeemstr); + len += n; + if ( vin->redeemscript[vin->p2shlen-1] == SCRIPT_OP_CHECKMULTISIG ) + { + V->M = iguana_scriptnum(vin->redeemscript[0]); + V->N = iguana_scriptnum(vin->redeemscript[vin->p2shlen-2]); + } + } + tmp = (len - endi); + if ( tmp < 0xfd ) + { + serialized[starti] = tmp; + for (i=starti+1; i> 8) & 0xff); + } + //printf("len.%d tmp.%d output sequence.[%d] <- %x\n",len,tmp,len,vin->sequence); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(vin->sequence),&vin->sequence); + if ( spendstr != 0 ) + { + if ( V != 0 ) + { + if ( V->spendlen == 0 ) + { + V->spendlen = (int32_t)strlen(spendstr) >> 1; + decode_hex(V->spendscript,V->spendlen,spendstr); + } + if ( vin->spendscript == 0 ) + vin->spendscript = V->spendscript; + } + if ( vin->spendlen == 0 && vin->spendscript != 0 ) + { + vin->spendlen = (int32_t)strlen(spendstr) >> 1; + decode_hex(vin->spendscript,vin->spendlen,spendstr); + } + //printf("serialized.%p len.%d\n",serialized,len); + //n = iguana_parsehexstr(&vin->spendscript,&vin->spendlen,V!=0?V->spendscript:0,V!=0?&V->spendlen:0,&serialized[len],spendstr); + //len += n; + } + return(len); +} + +int32_t iguana_parsevoutobj(uint8_t *serialized,int32_t maxsize,struct iguana_msgvout *vout,cJSON *voutobj) +{ + int32_t n,len = 0,rwflag = 1; cJSON *skey; char *hexstr; + memset(vout,0,sizeof(*vout)); + if ( jobj(voutobj,"satoshis") != 0 ) + vout->value = j64bits(voutobj,"satoshis"); + else vout->value = jdouble(voutobj,"value") * SATOSHIDEN; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(vout->value),&vout->value); + if ( (skey= jobj(voutobj,"scriptPubKey")) != 0 ) + { + if ( (hexstr= jstr(skey,"hex")) != 0 ) + { + n = (int32_t)strlen(hexstr) >> 1; + vout->pk_scriptlen = n; + len += iguana_rwvarint32(rwflag,&serialized[len],&vout->pk_scriptlen); + decode_hex(&serialized[len],n,hexstr); + vout->pk_script = &serialized[len]; + len += n; + } // else serialized[len++] = 0; + } //else serialized[len++] = 0; + return(len); +} + +cJSON *iguana_voutjson(uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *vout,int32_t txi,bits256 txid) +{ + // 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG + char scriptstr[IGUANA_MAXSCRIPTSIZE+1],asmstr[2*IGUANA_MAXSCRIPTSIZE+1]; 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)); + jadd64bits(json,"satoshis",vout->value); + 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(vp,0,sizeof(*vp)); + if ( (asmtype= iguana_calcrmd160(pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) + { + skey = cJSON_CreateObject(); + scriptlen = iguana_scriptgen(pubtype,p2shtype,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi); + if ( asmstr[0] != 0 ) + jaddstr(skey,"asm",asmstr); + addrs = cJSON_CreateArray(); + if ( vp->N == 1 ) + { + if ( asmtype == 2 ) + { + jaddnum(skey,"reqSigs",1); + jaddstr(skey,"type","pubkeyhash"); + } + if ( vp->coinaddr[0] != 0 ) + jaddistr(addrs,vp->coinaddr); + } + else + { + jaddnum(skey,"reqSigs",vp->M); + for (i=0; iN; i++) + { + //btc_convrmd160(coinaddr,coin->chain->pubtype,V.signers[i].pubkey); + jaddistr(addrs,vp->signers[i].coinaddr); + } + } + jadd(skey,"addresses",addrs); + init_hexbytes_noT(scriptstr,vout->pk_script,vout->pk_scriptlen); + if ( scriptstr[0] != 0 ) + jaddstr(skey,"hex",scriptstr); + jadd(json,"scriptPubKey",skey); + } + } + return(json); +} + +void iguana_vinobjset(struct iguana_msgvin *vin,cJSON *item,uint8_t *spendscript,int32_t maxsize) +{ + char *redeemstr,*hexstr=0; cJSON *sobj; + if ( (redeemstr= jstr(item,"redeemScript")) != 0 && is_hexstr(redeemstr,0) > 0 ) + { + vin->p2shlen = (int32_t)strlen(redeemstr) >> 1; + vin->spendlen = vin->p2shlen; + vin->redeemscript = calloc(1,vin->p2shlen); + decode_hex(vin->redeemscript,vin->p2shlen,redeemstr); + hexstr = redeemstr; + //printf("VINOBJSET.(%s)\n",redeemstr); + } + else if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && is_hexstr(hexstr,0) > 0 && (vin->spendlen == 0 || vin->spendscript == 0) ) + { + vin->spendlen = (int32_t)strlen(hexstr) >> 1; + } + if ( hexstr != 0 && vin->spendlen != 0 ) + { + if ( vin->spendlen < maxsize ) + { + if ( vin->spendscript == 0 ) + vin->spendscript = spendscript; + decode_hex(vin->spendscript,vin->spendlen,hexstr); + } + } +} + +int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout) +{ + bits256 array_txid; cJSON *item; int32_t array_vout,i,n = cJSON_GetArraySize(vinarray); + for (i=0; ivins,dest.tx_in * sizeof(*dest.vins)); + memcpy(dest.vouts,msgtx->vouts,dest.tx_out * sizeof(*dest.vouts)); + memset(sigtxid.bytes,0,sizeof(sigtxid)); + if ( hashtype != SIGHASH_ALL ) + { + printf("currently only SIGHASH_ALL supported, not %d\n",hashtype); + return(sigtxid); + } + for (i=0; i 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 && + { +#ifdef BTC2_VERSION + if ( height >= BTC2_HARDFORK_HEIGHT ) + hashtype |= (0x777 << 20); +#endif + len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype); + revsigtxid = bits256_doublesha256(0,serialized,len); + for (i=0; iversion),&msg->version); + if ( json != 0 ) + { + jaddnum(json,"version",msg->version); + vinarray = cJSON_CreateArray(); + voutarray = cJSON_CreateArray(); + if ( rwflag == 0 ) + sigser = calloc(1,maxsize*2); + //printf("json.%p array.%p sigser.%p\n",json,vinarray,sigser); + } + //printf("version.%d\n",msg->version); + if ( isPoS != 0 ) + { + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->timestamp),&msg->timestamp); + //char str[65]; printf("version.%d timestamp.%08x %u %s\n",msg->version,msg->timestamp,msg->timestamp,utc_str(str,msg->timestamp)); + if ( json != 0 ) + jaddnum(json,"timestamp",msg->timestamp); + } + len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_in); + if ( rwflag == 0 ) + { + if ( msg->vins == 0 ) + { + if ( sizeof(struct iguana_msgvin)*msg->tx_in > extralen ) + { + printf("(size.%d * tx_in.%d) > extralen.%d\n",(int32_t)sizeof(struct iguana_msgvin),msg->tx_in,extralen); + return(-1); + } + msg->vins = (struct iguana_msgvin *)extraspace; + extraused += (sizeof(struct iguana_msgvin) * msg->tx_in); + } else printf("unexpected non-null msg->vins.%p\n",msg->vins); + memset(msg->vins,0,sizeof(struct iguana_msgvin) * msg->tx_in); + } + for (i=0; itx_in; i++) + { + //printf("vin.%d starts offset.%d\n",i,len); + if ( vins != 0 && jitem(vins,i) != 0 ) + iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); + if ( (n= iguana_vinparse(rwflag,&serialized[len],&msg->vins[i])) < 0 ) + return(-1); + //printf("serialized vin.[%02x %02x %02x]\n",serialized[len],serialized[len+1],serialized[len+2]); + if ( msg->vins[i].spendscript == spendscript ) + msg->vins[i].spendscript = 0; + //printf("vin.%d n.%d len.%d\n",i,n,len); + len += n; + if ( len > maxsize ) + { + printf("invalid tx_in.%d len.%d vs maxsize.%d\n",msg->tx_in,len,maxsize); + return(-1); + } + } + //for (i=-3; i<7; i++) + // printf("%02x",serialized[len+i]); + //printf(" prev 3 bytes before tx_out rw.%d\n",rwflag); + len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_out); + if ( rwflag == 0 ) + { + if ( msg->vouts == 0 ) + { + if ( (extraused & 0xf) != 0 ) + extraused += 0xf - (extraused & 0xf); + if ( extraused + sizeof(struct iguana_msgvout)*msg->tx_out > extralen ) + { + printf("extraused.%d + tx_out.%d > extralen.%d\n",extraused,msg->tx_out,extralen); + return(-1); + } + msg->vouts = (struct iguana_msgvout *)&extraspace[extraused]; + extraused += (sizeof(struct iguana_msgvout) * msg->tx_out); + } else printf("unexpected non-null msg->vouts %p\n",msg->vouts); + memset(msg->vouts,0,sizeof(struct iguana_msgvout) * msg->tx_out); + } + for (i=0; itx_out; i++) + { + //printf("rwflag.%d vout.%d starts %d\n",rwflag,i,len); + if ( (n= iguana_voutparse(rwflag,&serialized[len],&msg->vouts[i])) < 0 ) + return(-1); + len += n; + if ( len > maxsize ) + { + printf("invalidC tx_out.%d of %d len.%d vs maxsize.%d n.%d\n",i,msg->tx_out,len,maxsize,n); + return(-1); + } + if ( voutarray != 0 ) + jaddi(voutarray,iguana_voutjson(pubtype,p2shtype,&msg->vouts[i],i,*txidp)); + } + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time); + //printf("lock_time.%08x len.%d\n",msg->lock_time,len); + /*if ( strcmp(coin->symbol,"VPN") == 0 ) + { + uint16_t ddosflag = 0; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ddosflag),&ddosflag); + for (i=0; serialized[len]!=0&&lentx_in; i++) + { + memset(sigtxid.bytes,0,sizeof(sigtxid)); + if ( vins != 0 && jitem(vins,i) != 0 ) + { + iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); + sigtxid = bitcoin_sigtxid(pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys); + //printf("after vini.%d vinscript.%p spendscript.%p spendlen.%d (%s)\n",i,msg->vins[i].vinscript,msg->vins[i].spendscript,msg->vins[i].spendlen,jprint(jitem(vins,i),0)); + if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 ) + jaddi(vinarray,iguana_vinjson(&msg->vins[i],sigtxid)); + if ( msg->vins[i].spendscript == spendscript ) + msg->vins[i].spendscript = 0; + } else if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 ) + jaddi(vinarray,iguana_vinjson(&msg->vins[i],sigtxid)); + } + free(sigser); + jadd(json,"vin",vinarray); + msg->tx_in = cJSON_GetArraySize(vinarray); + jaddnum(json,"numvins",msg->tx_in); + } + if ( voutarray != 0 ) + { + jadd(json,"vout",voutarray); + jaddnum(json,"numvouts",msg->tx_out); + } + *txidp = bits256_doublesha256(txidstr,txstart,len); + if ( json != 0 ) + { + jaddnum(json,"locktime",msg->lock_time); + jaddnum(json,"size",len); + jaddbits256(json,"txid",*txidp); + //printf("TX.(%s) %p\n",jprint(json,0),json); + } + msg->allocsize = len; + return(len); +} + +bits256 iguana_parsetxobj(uint8_t isPoS,int32_t *txstartp,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,cJSON *txobj,struct vin_info *V) +{ + int32_t i,n,numvins,numvouts,len = 0,rwflag=1; cJSON *array=0; bits256 txid; char vpnstr[64]; + memset(&txid,0,sizeof(txid)); + memset(msg,0,sizeof(*msg)); + *txstartp = 0; + if ( txobj == 0 ) + return(txid); + vpnstr[0] = 0; + if ( (msg->version= juint(txobj,"version")) == 0 ) + msg->version = 1; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version); + if ( isPoS != 0 ) + { + if ( (msg->timestamp= juint(txobj,"timestamp")) == 0 ) + msg->timestamp = (uint32_t)time(NULL); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->timestamp),&msg->timestamp); + } + if ( (array= jarray(&numvins,txobj,"vin")) != 0 ) + { + msg->tx_in = numvins; + len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_in); + if ( len + sizeof(struct iguana_msgvin)*msg->tx_in > maxsize ) + return(txid); + maxsize -= (sizeof(struct iguana_msgvin) * msg->tx_in); + msg->vins = (struct iguana_msgvin *)&serialized[maxsize]; + memset(msg->vins,0,sizeof(struct iguana_msgvin) * msg->tx_in); + if ( msg->tx_in > 0 && msg->tx_in*sizeof(struct iguana_msgvin) < maxsize ) + { + for (i=0; itx_in; i++) + { + n = iguana_parsevinobj(&serialized[len],maxsize,&msg->vins[i],jitem(array,i),V!=0?&V[i]:0); + //for (j=0; j<8; j++) + // printf("%02x",serialized[len+j]); + //char str[65]; printf(" <- vinobj.%d starts offset.%d %s\n",i,len,bits256_str(str,msg->vins[i].prev_hash)); + len += n; + } + } + } + if ( (array= jarray(&numvouts,txobj,"vout")) != 0 ) + { + msg->tx_out = numvouts; + len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_out); + if ( len + sizeof(struct iguana_msgvout)*msg->tx_out > maxsize ) + return(txid); + maxsize -= (sizeof(struct iguana_msgvout) * msg->tx_out); + msg->vouts = (struct iguana_msgvout *)&serialized[maxsize]; + memset(msg->vouts,0,sizeof(struct iguana_msgvout) * msg->tx_out); + if ( msg->tx_out > 0 && msg->tx_out*sizeof(struct iguana_msgvout) < maxsize ) + { + for (i=0; itx_out; i++) + { + //printf("parsetxobj parsevout.%d starts %d\n",i,len); + len += iguana_parsevoutobj(&serialized[len],maxsize,&msg->vouts[i],jitem(array,i)); + } + } + } + msg->lock_time = jint(txobj,"locktime"); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time); + //msg->txid = jbits256(txobj,"txid"); + *txstartp = 0; + msg->allocsize = len; + msg->txid = txid = bits256_doublesha256(0,serialized,len); + return(txid); +} + +char *iguana_rawtxbytes(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys) +{ + 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(pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys)) > 0 ) + { + txbytes = malloc(n*2+1); + init_hexbytes_noT(txbytes,serialized,n); + } + free(serialized); + return(txbytes); +} + +char *bitcoin_json2hex(uint8_t isPoS,bits256 *txidp,cJSON *txjson,struct vin_info *V) +{ + int32_t txstart; uint8_t *serialized; struct iguana_msgtx msgtx; char *txbytes = 0; + if ( txjson == 0 ) + { + memset(txidp,0,sizeof(*txidp)); + return(0); + } + serialized = malloc(IGUANA_MAXPACKETSIZE*1.5); + *txidp = iguana_parsetxobj(isPoS,&txstart,serialized,IGUANA_MAXPACKETSIZE*1.5,&msgtx,txjson,V); + if ( msgtx.allocsize > 0 ) + { + txbytes = malloc(msgtx.allocsize*2 + 1); + init_hexbytes_noT(txbytes,&serialized[txstart],msgtx.allocsize); + } else printf("bitcoin_txtest: zero msgtx allocsize.(%s)\n",jprint(txjson,0)); + free(serialized); + return(txbytes); +} + +cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys) +{ + int32_t n; char vpnstr[64]; struct iguana_msgtx M; cJSON *txobj; + if ( serialized == 0 ) + return(0); + txobj = cJSON_CreateObject(); + if ( msgtx == 0 ) + msgtx = &M; + memset(msgtx,0,sizeof(M)); + vpnstr[0] = 0; + memset(txidp,0,sizeof(*txidp)); + if ( (n= iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys)) <= 0 ) + { + printf("errortxobj.(%s)\n",jprint(txobj,0)); + free_json(txobj); + txobj = cJSON_CreateObject(); + jaddstr(txobj,"error","couldnt decode transaction"); + } + //printf("msgtx.(%s)\n",jprint(txobj,0)); + if ( n != len ) + { + int32_t i; + for (i=0; i<=len; i++) + printf("%02x",serialized[i]); + printf(" data2json n.%d vs len.%d\n",n,len); + } + return(txobj); +} + +cJSON *bitcoin_hex2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes,uint8_t *extraspace,int32_t extralen,uint8_t *origserialized,cJSON *vins,int32_t suppress_pubkeys) +{ + int32_t len; uint8_t *serialized; cJSON *txobj; + if ( txbytes == 0 ) + return(0); + len = (int32_t)strlen(txbytes) >> 1; + if ( (serialized= origserialized) == 0 ) + serialized = calloc(1,len+4096); + decode_hex(serialized,len,txbytes); + txobj = bitcoin_data2json(pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys); + if ( serialized != origserialized ) + free(serialized); + return(txobj); } diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index d15ea3f47..7db343df6 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -18,18 +18,39 @@ // marketmaker // +struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector) +{ + memset(rp,0,sizeof(*rp)); + rp->srchash = srchash; + rp->desthash = desthash; + rp->srcamount = srcsatoshis; + rp->destamount = destsatoshis; + rp->timestamp = timestamp; + rp->quotetime = quotetime; + rp->DEXselector = DEXselector; + safecopy(rp->src,src,sizeof(rp->src)); + safecopy(rp->dest,dest,sizeof(rp->dest)); + rp->quoteid = basilisk_quoteid(rp); + rp->requestid = basilisk_requestid(rp); + return(rp); +} + void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) { - char *method,*base,*rel,*retstr; cJSON *retjson; double price; bits256 txid; struct LP_utxoinfo *utxo; + char *method,*base,*rel,*retstr,*pairstr; cJSON *retjson; double price; bits256 srchash,desthash,pubkey,privkey,txid,desttxid; struct LP_utxoinfo *utxo; uint32_t timestamp,quotetime; int32_t destvout,DEXselector = 0; uint64_t txfee,satoshis,desttxfee,destsatoshis,value; struct basilisk_request R; if ( (method= jstr(argjson,"method")) != 0 ) { - if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) + txid = jbits256(argjson,"txid"); + if ( (utxo= LP_utxofind(txid,jint(argjson,"vout"))) != 0 && strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port && (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 ) { - txid = jbits256(argjson,"txid"); - if ( (utxo= LP_utxofind(txid)) != 0 && strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port && utxo->swappending == 0 ) + if ( time(NULL) > utxo->swappending ) + utxo->swappending = 0; + if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) { - if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 ) + if ( utxo->swappending == 0 && utxo->pair < 0 ) { + if ( utxo->pair >= 0 ) + nn_close(utxo->pair), utxo->pair = -1; if ( (price= LP_price(base,rel)) != 0. ) { price *= (1. + profitmargin); @@ -39,11 +60,17 @@ void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_ jaddnum(retjson,"timestamp",time(NULL)); jaddnum(retjson,"price",price); jaddbits256(retjson,"txid",txid); - jadd64bits(retjson,"destsatoshis",price * utxo->satoshis); + pubkey = LP_pubkey(LP_privkey(utxo->coinaddr)); + jaddbits256(retjson,"srchash",pubkey); + txfee = LP_txfee(base); + jadd64bits(retjson,"txfee",txfee); + jadd64bits(retjson,"satoshis",utxo->satoshis - txfee); + jadd64bits(retjson,"destsatoshis",price * (utxo->satoshis-txfee)); if ( strcmp(method,"request") == 0 ) { utxo->swappending = (uint32_t)(time(NULL) + 60); utxo->otherpubkey = jbits256(argjson,"pubkey"); + jaddstr(retjson,"result","reserved"); jaddnum(retjson,"pending",utxo->swappending); } retstr = jprint(retjson,1); @@ -51,10 +78,64 @@ void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_ } } } - } - else if ( ) - { - + else if ( strcmp(method,"connect") == 0 ) + { + if ( utxo->pair < 0 ) + { + if ( (price= LP_price(base,rel)) != 0. ) + { + price *= (1. + profitmargin); + txfee = LP_txfee(base); + satoshis = j64bits(argjson,"satoshis"); + desttxfee = LP_txfee(rel); + desttxid = jbits256(argjson,"desttxid"); + destvout = jint(argjson,"destvout"); + timestamp = juint(argjson,"timestamp"); + quotetime = juint(argjson,"quotetime"); + privkey = LP_privkey(utxo->coinaddr); + pubkey = LP_pubkey(privkey); + srchash = jbits256(argjson,"srchash"); + value = j64bits(argjson,"destsatoshis"); + if ( timestamp == utxo->swappending-60 && quotetime >= timestamp && quotetime < utxo->swappending && bits256_cmp(pubkey,srchash) == 0 && (destsatoshis= LP_txvalue(rel,desttxid,destvout)) > price*(utxo->satoshis-txfee)+desttxfee && value <= destsatoshis-desttxfee ) + { + destsatoshis = value; + if ( (utxo->pair= nn_socket(AF_SP,NN_PAIR)) < 0 ) + printf("error creating utxo->pair\n"); + else if ( (pairstr= jstr(argjson,"pair")) != 0 && nn_connect(utxo->pair,pairstr) >= 0 ) + { + desthash = jbits256(argjson,"desthash"); + LP_requestinit(&R,srchash,desthash,base,satoshis,rel,destsatoshis,timestamp,quotetime,DEXselector); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)utxo) != 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","connected"); + jaddnum(retjson,"requestid",R.requestid); + jaddnum(retjson,"quoteid",R.quoteid); + retstr = jprint(retjson,1); + LP_send(pubsock,retstr,1); + utxo->swap = LP_swapinit(1,0,privkey,&R); + } + else + { + printf("error launching swaploop\n"); + free(utxo->swap); + utxo->swap = 0; + nn_close(utxo->pair); + utxo->pair = -1; + } + } + else + { + if ( pairstr != 0 ) + printf("printf error nn_connect to %s\n",pairstr); + else printf("(%s) missing pair\n",jprint(argjson,0)); + nn_close(utxo->pair); + utxo->pair = -1; + } + } else printf("dest %.8f < required %.8f\n",dstr(value),dstr(price*(utxo->satoshis-txfee))); + } else printf("no price for %s/%s\n",base,rel); + } else printf("utxo->pair.%d when connect came in (%s)\n",utxo->pair,jprint(argjson,0)); + } } } } diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h new file mode 100644 index 000000000..965b2a7ae --- /dev/null +++ b/iguana/exchanges/LP_include.h @@ -0,0 +1,469 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_include.h +// marketmaker +// + +#ifndef LP_INCLUDE_H +#define LP_INCLUDE_H + +#define BASILISK_DISABLEWAITTX +#define BASILISK_DISABLESENDTX + +#define BASILISK_DEFAULT_NUMCONFIRMS 5 +#define DEX_SLEEP 3 +#define BASILISK_DEXDURATION 300 +#define BASILISK_MSGDURATION 30 +#define BASILISK_AUCTION_DURATION 5 + +#define BASILISK_MAXFUTUREBLOCK 60 +#define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) + +extern char GLOBAL_DBDIR[]; + +void *bitcoin_ctx(); +int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen); +int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig,bits256 messagehash2,uint8_t *pubkey,size_t plen); +int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag); +bits256 bitcoin_pubkey33(void *ctx,uint8_t *data,bits256 privkey); +bits256 bitcoin_pub256(void *ctx,bits256 *privkeyp,uint8_t odd_even); + +char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen); +int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); + +#define IGUANA_MAXSCRIPTSIZE 10001 +#define IGUANA_SEQUENCEID_FINAL 0xfffffffe + +#define IGUANA_SCRIPT_NULL 0 +#define IGUANA_SCRIPT_76AC 1 +#define IGUANA_SCRIPT_76A988AC 2 +#define IGUANA_SCRIPT_P2SH 3 +#define IGUANA_SCRIPT_OPRETURN 4 +#define IGUANA_SCRIPT_3of3 5 +#define IGUANA_SCRIPT_2of3 6 +#define IGUANA_SCRIPT_1of3 7 +#define IGUANA_SCRIPT_2of2 8 +#define IGUANA_SCRIPT_1of2 9 +#define IGUANA_SCRIPT_MSIG 10 +#define IGUANA_SCRIPT_DATA 11 +#define IGUANA_SCRIPT_AC 12 +#define IGUANA_SCRIPT_1of1 13 +#define IGUANA_SCRIPT_STRANGE 15 + +#define BASILISK_TIMEOUT 3000 +#define BASILISK_MINFANOUT 8 +#define BASILISK_MAXFANOUT 64 +#define BASILISK_DEFAULTDIFF 0x1effffff +#define BASILISK_HDROFFSET ((int32_t)(sizeof(bits256)+sizeof(struct iguana_msghdr)+sizeof(uint32_t))) + +#define INSTANTDEX_DECKSIZE 1000 +#define INSTANTDEX_LOCKTIME (3600*2 + 300*2) +#define INSTANTDEX_INSURANCEDIV 777 +#define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" +#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" +#define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e" +#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" +#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" +#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" + +struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; + +struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; }; + +struct iguana_msgtx +{ + uint32_t version,tx_in,tx_out,lock_time; + struct iguana_msgvin *vins; + struct iguana_msgvout *vouts; + bits256 txid; + int32_t allocsize,timestamp,numinputs,numoutputs; + int64_t inputsum,outputsum,txfee; + uint8_t *serialized; +}; + +struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; }; + +struct vin_info +{ + struct iguana_msgvin vin; uint64_t amount; cJSON *extras; bits256 sigtxid; + int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,hashtype,userdatalen,suppress_pubkeys,ignore_cltverr; + uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65]; + uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE],userdata[IGUANA_MAXSCRIPTSIZE]; +}; + +struct basilisk_swapmessage +{ + bits256 srchash,desthash; + uint32_t crc32,msgbits,quoteid,datalen; + uint8_t *data; +}; + +struct basilisk_swap; + +struct basilisk_rawtxinfo +{ + char destaddr[64],coinstr[16]; + bits256 txid,signedtxid,actualtxid; + uint64_t amount,change,inputsum; + int32_t redeemlen,datalen,completed,vintype,vouttype,numconfirms,spendlen,secretstart,suppress_pubkeys; + uint32_t locktime,crcs[2]; + uint8_t addrtype,pubkey33[33],rmd160[20]; +}; + +struct basilisk_request +{ + uint32_t requestid,timestamp,quoteid,quotetime; // 0 to 15 + uint64_t srcamount,unused; // 16 to 31 + bits256 srchash; // 32 to 63 + bits256 desthash; + char src[8],dest[8]; + uint64_t destamount; + int32_t optionhours,DEXselector; +}; + +struct basilisk_rawtx +{ + char name[32]; + struct iguana_msgtx msgtx; + struct basilisk_rawtxinfo I; + struct iguana_info *coin; + char vinstr[8192],p2shaddr[64]; + cJSON *vins; + bits256 utxotxid; int32_t utxovout; + uint8_t txbytes[16384],spendscript[512],redeemscript[1024],extraspace[4096],pubkey33[33]; +}; + +struct basilisk_swapinfo +{ + struct basilisk_request req; + char bobstr[64],alicestr[64]; + bits256 myhash,otherhash,orderhash; + uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration; + int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad; + uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance; + + bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn; + uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2]; + int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate,pad2; + uint8_t secretAm[20],secretBn[20]; + uint8_t secretAm256[32],secretBn256[32]; + uint8_t userdata_aliceclaim[256],userdata_aliceclaimlen; + uint8_t userdata_alicereclaim[256],userdata_alicereclaimlen; + uint8_t userdata_alicespend[256],userdata_alicespendlen; + uint8_t userdata_bobspend[256],userdata_bobspendlen; + uint8_t userdata_bobreclaim[256],userdata_bobreclaimlen; + uint8_t userdata_bobrefund[256],userdata_bobrefundlen; +}; + +struct iguana_info +{ + uint64_t txfee,estimatedfee; + int32_t longestchain; + uint8_t pubtype,p2shtype,isPoS,wiftype; + char symbol[16],changeaddr[64]; +}; + +struct basilisk_swap +{ + void *ctx; struct iguana_info bobcoin,alicecoin; + void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob); + int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted; + FILE *fp; + bits256 persistent_privkey,persistent_pubkey; + struct basilisk_swapinfo I; + struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; + bits256 privkeys[INSTANTDEX_DECKSIZE]; + struct basilisk_swapmessage *messages; int32_t nummessages; + char Bdeposit[64],Bpayment[64]; + uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; + uint8_t persistent_pubkey33[33],pad[15],verifybuf[65536]; + +}; + +static struct bitcoin_opcode { UT_hash_handle hh; uint8_t opcode,flags,stackitems; int8_t extralen; } *OPTABLE; static char *OPCODES[0x100]; static int32_t OPCODELENS[0x100]; + +#define SIGHASH_ALL 1 +#define SIGHASH_NONE 2 +#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 +#define SCRIPT_OP_4 0x54 +#define SCRIPT_OP_IF 0x63 +#define SCRIPT_OP_ELSE 0x67 +#define SCRIPT_OP_RETURN 0x6a +#define SCRIPT_OP_DUP 0x76 +#define SCRIPT_OP_ENDIF 0x68 +#define SCRIPT_OP_DROP 0x75 +#define SCRIPT_OP_EQUALVERIFY 0x88 +#define SCRIPT_OP_SHA256 0xa8 +#define SCRIPT_OP_HASH160 0xa9 + +#define SCRIPT_OP_EQUAL 0x87 +#define SCRIPT_OP_CHECKSIG 0xac +#define SCRIPT_OP_CHECKMULTISIG 0xae +#define SCRIPT_OP_CHECKSEQUENCEVERIFY 0xb2 +#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 +#define IGUANA_OP_0 0x00 +#define IGUANA_OP_PUSHDATA1 0x4c +#define IGUANA_OP_PUSHDATA2 0x4d +#define IGUANA_OP_PUSHDATA4 0x4e +#define IGUANA_OP_1NEGATE 0x4f +#define IGUANA_OP_1 0x51 +#define IGUANA_OP_16 0x60 +#define IGUANA_OP_NOP 0x61 +#define IGUANA_OP_IF 0x63 +#define IGUANA_OP_NOTIF 0x64 +#define IGUANA_OP_ELSE 0x67 +#define IGUANA_OP_ENDIF 0x68 +#define IGUANA_OP_VERIFY 0x69 +#define IGUANA_OP_RETURN 0x6a + +#define IGUANA_OP_TOALTSTACK 0x6b +#define IGUANA_OP_FROMALTSTACK 0x6c +#define IGUANA_OP_2DROP 0x6d +#define IGUANA_OP_2DUP 0x6e +#define IGUANA_OP_3DUP 0x6f +#define IGUANA_OP_2OVER 0x70 +#define IGUANA_OP_2ROT 0x71 +#define IGUANA_OP_2SWAP 0x72 +#define IGUANA_OP_IFDUP 0x73 +#define IGUANA_OP_DEPTH 0x74 +#define IGUANA_OP_DROP 0x75 +#define IGUANA_OP_DUP 0x76 +#define IGUANA_OP_NIP 0x77 +#define IGUANA_OP_OVER 0x78 +#define IGUANA_OP_PICK 0x79 +#define IGUANA_OP_ROLL 0x7a +#define IGUANA_OP_ROT 0x7b +#define IGUANA_OP_SWAP 0x7c +#define IGUANA_OP_TUCK 0x7d + +#define IGUANA_OP_EQUAL 0x87 +#define IGUANA_OP_EQUALVERIFY 0x88 + +#define IGUANA_OP_1ADD 0x8b +#define IGUANA_OP_1SUB 0x8c +#define IGUANA_OP_NEGATE 0x8f +#define IGUANA_OP_ABS 0x90 +#define IGUANA_OP_NOT 0x91 +#define IGUANA_OP_0NOTEQUAL 0x92 +#define IGUANA_OP_ADD 0x93 +#define IGUANA_OP_SUB 0x94 + +#define IGUANA_OP_BOOLAND 0x9a +#define IGUANA_OP_BOOLOR 0x9b +#define IGUANA_OP_NUMEQUAL 0x9c +#define IGUANA_OP_NUMEQUALVERIFY 0x9d +#define IGUANA_OP_NUMNOTEQUAL 0x9e +#define IGUANA_OP_LESSTHAN 0x9f +#define IGUANA_OP_GREATERTHAN 0xa0 +#define IGUANA_OP_LESSTHANOREQUAL 0xa1 +#define IGUANA_OP_GREATERTHANOREQUAL 0xa2 +#define IGUANA_OP_MIN 0xa3 +#define IGUANA_OP_MAX 0xa4 +#define IGUANA_OP_WITHIN 0xa5 + +#define IGUANA_OP_RIPEMD160 0xa6 +#define IGUANA_OP_SHA1 0xa7 +#define IGUANA_OP_SHA256 0xa8 +#define IGUANA_OP_HASH160 0xa9 +#define IGUANA_OP_HASH256 0xaa +#define IGUANA_OP_CODESEPARATOR 0xab +#define IGUANA_OP_CHECKSIG 0xac +#define IGUANA_OP_CHECKSIGVERIFY 0xad +#define IGUANA_OP_CHECKMULTISIG 0xae +#define IGUANA_OP_CHECKMULTISIGVERIFY 0xaf + +#define IGUANA_OP_NOP1 0xb0 +#define IGUANA_OP_CHECKLOCKTIMEVERIFY 0xb1 +#define IGUANA_OP_CHECKSEQUENCEVERIFY 0xb2 +#define IGUANA_OP_NOP10 0xb9 + +#define IGUANA_OP_COMBINEPUBKEYS 0xc0 +#define IGUANA_OP_CHECKSCHNORR 0xc1 +#define IGUANA_OP_CHECKSCHNORRVERIFY 0xc2 + +// https://github.com/TierNolan/bips/blob/cpkv/bip-cprkv.mediawiki +#define IGUANA_OP_CHECKPRIVATEKEY 0xc3 +#define IGUANA_OP_CHECKPRIVATEKEYVERIFY 0xc4 + +#define IGUANA_NOPFLAG 1 +#define IGUANA_ALWAYSILLEGAL 2 +#define IGUANA_EXECUTIONILLEGAL 4 +#define IGUANA_POSTVERIFY 8 +#define IGUANA_CRYPTOFLAG 16 +#define IGUANA_MATHFLAG 32 +#define IGUANA_CONTROLFLAG 64 +#define IGUANA_STACKFLAG 128 + +enum opcodetype +{ + // push value + OP_0 = 0x00, + OP_FALSE = OP_0, + OP_PUSHDATA1 = 0x4c, + OP_PUSHDATA2 = 0x4d, + OP_PUSHDATA4 = 0x4e, + OP_1NEGATE = 0x4f, + OP_RESERVED = 0x50, + OP_1 = 0x51, + OP_TRUE=OP_1, + OP_2 = 0x52, + OP_3 = 0x53, + OP_4 = 0x54, + OP_5 = 0x55, + OP_6 = 0x56, + OP_7 = 0x57, + OP_8 = 0x58, + OP_9 = 0x59, + OP_10 = 0x5a, + OP_11 = 0x5b, + OP_12 = 0x5c, + OP_13 = 0x5d, + OP_14 = 0x5e, + OP_15 = 0x5f, + OP_16 = 0x60, + + // control + OP_NOP = 0x61, + OP_VER = 0x62, + OP_IF = 0x63, + OP_NOTIF = 0x64, + OP_VERIF = 0x65, + OP_VERNOTIF = 0x66, + OP_ELSE = 0x67, + OP_ENDIF = 0x68, + OP_VERIFY = 0x69, + OP_RETURN = 0x6a, + + // stack ops + OP_TOALTSTACK = 0x6b, + OP_FROMALTSTACK = 0x6c, + OP_2DROP = 0x6d, + OP_2DUP = 0x6e, + OP_3DUP = 0x6f, + OP_2OVER = 0x70, + OP_2ROT = 0x71, + OP_2SWAP = 0x72, + OP_IFDUP = 0x73, + OP_DEPTH = 0x74, + OP_DROP = 0x75, + OP_DUP = 0x76, + OP_NIP = 0x77, + OP_OVER = 0x78, + OP_PICK = 0x79, + OP_ROLL = 0x7a, + OP_ROT = 0x7b, + OP_SWAP = 0x7c, + OP_TUCK = 0x7d, + + // splice ops + OP_CAT = 0x7e, + OP_SUBSTR = 0x7f, + OP_LEFT = 0x80, + OP_RIGHT = 0x81, + OP_SIZE = 0x82, + + // bit logic + OP_INVERT = 0x83, + OP_AND = 0x84, + OP_OR = 0x85, + OP_XOR = 0x86, + OP_EQUAL = 0x87, + OP_EQUALVERIFY = 0x88, + OP_RESERVED1 = 0x89, + OP_RESERVED2 = 0x8a, + + // numeric + OP_1ADD = 0x8b, + OP_1SUB = 0x8c, + OP_2MUL = 0x8d, + OP_2DIV = 0x8e, + OP_NEGATE = 0x8f, + OP_ABS = 0x90, + OP_NOT = 0x91, + OP_0NOTEQUAL = 0x92, + + OP_ADD = 0x93, + OP_SUB = 0x94, + OP_MUL = 0x95, + OP_DIV = 0x96, + OP_MOD = 0x97, + OP_LSHIFT = 0x98, + OP_RSHIFT = 0x99, + + OP_BOOLAND = 0x9a, + OP_BOOLOR = 0x9b, + OP_NUMEQUAL = 0x9c, + OP_NUMEQUALVERIFY = 0x9d, + OP_NUMNOTEQUAL = 0x9e, + OP_LESSTHAN = 0x9f, + OP_GREATERTHAN = 0xa0, + OP_LESSTHANOREQUAL = 0xa1, + OP_GREATERTHANOREQUAL = 0xa2, + OP_MIN = 0xa3, + OP_MAX = 0xa4, + + OP_WITHIN = 0xa5, + + // crypto + OP_RIPEMD160 = 0xa6, + OP_SHA1 = 0xa7, + OP_SHA256 = 0xa8, + OP_HASH160 = 0xa9, + OP_HASH256 = 0xaa, + OP_CODESEPARATOR = 0xab, + OP_CHECKSIG = 0xac, + OP_CHECKSIGVERIFY = 0xad, + OP_CHECKMULTISIG = 0xae, + OP_CHECKMULTISIGVERIFY = 0xaf, + + // expansion + OP_NOP1 = 0xb0, + OP_CHECKLOCKTIMEVERIFY = 0xb1, + OP_CHECKSEQUENCEVERIFY = 0xb2, + OP_NOP4 = 0xb3, + OP_NOP5 = 0xb4, + OP_NOP6 = 0xb5, + OP_NOP7 = 0xb6, + OP_NOP8 = 0xb7, + OP_NOP9 = 0xb8, + OP_NOP10 = 0xb9, + + OP_COMBINEPUBKEYS = 0xc0, + OP_CHECKSCHNORR = 0xc1, + OP_CHECKSCHNORRVERIFY = 0xc2, + OP_CHECKPRIVATEKEY = 0xc3, + OP_CHECKPRIVATEKEYVERIFY = 0xc4, + + // template matching params + //OP_SMALLINTEGER = 0xfa, + //OP_PUBKEYS = 0xfb, + //OP_PUBKEYHASH = 0xfd, + //OP_PUBKEY = 0xfe, + + OP_INVALIDOPCODE = 0xff, +}; +void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx); +uint32_t basilisk_requestid(struct basilisk_request *rp); +uint32_t basilisk_quoteid(struct basilisk_request *rp); + +#endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index f139d12ac..0c2ecb51d 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -14,11 +14,13 @@ * * ******************************************************************************/ // -// LP_unspents.c +// LP_nativeDEX.c // marketmaker // #include +#include "LP_include.h" +#include "LP_network.c" #define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid @@ -43,41 +45,13 @@ struct LP_utxoinfo bits256 txid,deposittxid,otherpubkey; void *swap; uint64_t satoshis,depositsatoshis; - int32_t vout,depositvout; uint32_t lasttime,errors,swappending; + uint8_t key[sizeof(bits256) + sizeof(int32_t)]; + int32_t vout,depositvout,pair; uint32_t lasttime,errors,swappending; double profitmargin; char ipaddr[64],coinaddr[64],spendscript[256],coin[16]; uint16_t port; } *LP_utxoinfos; -char *nanomsg_tcpname(char *str,char *ipaddr,uint16_t port) -{ - sprintf(str,"tcp://%s:%u",ipaddr,port); - return(str); -} - -int32_t LP_send(int32_t sock,char *msg,int32_t freeflag) -{ - int32_t sentbytes,len,i; struct nn_pollfd pfd; - for (i=0; i<100; i++) - { - pfd.fd = sock; - pfd.events = NN_POLLOUT; - if ( nn_poll(&pfd,1,100) > 0 ) - { - len = (int32_t)strlen(msg) + 1; - if ( (sentbytes= nn_send(sock,msg,len,0)) != len ) - printf("LP_send sent %d instead of %d\n",sentbytes,len); - else printf("SENT.(%s)\n",msg); - if ( freeflag != 0 ) - free(msg); - return(sentbytes); - } - usleep(1000); - } - printf("error LP_send\n"); - return(-1); -} - struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) { struct LP_peerinfo *peer=0; uint64_t ip_port; @@ -88,11 +62,13 @@ struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) return(peer); } -struct LP_utxoinfo *LP_utxofind(bits256 txid) +struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout) { - struct LP_utxoinfo *utxo=0; + struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; + memcpy(key,txid.bytes,sizeof(txid)); + memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); portable_mutex_lock(&LP_utxomutex); - HASH_FIND(hh,LP_utxoinfos,&txid,sizeof(txid),utxo); + HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo); portable_mutex_unlock(&LP_utxomutex); return(utxo); } @@ -214,13 +190,13 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char struct LP_utxoinfo *LP_addutxo(struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t satoshis,bits256 deposittxid,int32_t depositvout,int64_t depositsatoshis,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin) { - struct LP_utxoinfo *utxo = 0; + struct LP_utxoinfo *utxo = 0; uint8_t key[sizeof(txid) + sizeof(vout)]; if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(deposittxid) == 0 || vout < 0 || depositvout < 0 || satoshis <= 0 || depositsatoshis <= 0 ) { printf("malformed addutxo %d %d %d %d %d %d %d %d %d %d %d %d\n", coin == 0,coin[0] == 0,spendscript == 0,spendscript[0] == 0,coinaddr == 0,coinaddr[0] == 0,bits256_nonz(txid) == 0,bits256_nonz(deposittxid) == 0,vout < 0,depositvout < 0,satoshis <= 0,depositsatoshis <= 0); return(0); } - if ( (utxo= LP_utxofind(txid)) != 0 ) + if ( (utxo= LP_utxofind(txid,vout)) != 0 ) { if ( bits256_cmp(txid,utxo->txid) != 0 || bits256_cmp(deposittxid,utxo->deposittxid) != 0 || vout != utxo->vout || satoshis != utxo->satoshis || depositvout != utxo->depositvout || depositsatoshis != utxo->depositsatoshis || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port ) { @@ -233,6 +209,7 @@ struct LP_utxoinfo *LP_addutxo(struct LP_peerinfo *mypeer,int32_t mypubsock,char else { utxo = calloc(1,sizeof(*utxo)); + utxo->pair = -1; utxo->profitmargin = profitmargin; strcpy(utxo->ipaddr,ipaddr); utxo->port = port; @@ -245,8 +222,11 @@ struct LP_utxoinfo *LP_addutxo(struct LP_peerinfo *mypeer,int32_t mypubsock,char utxo->deposittxid = deposittxid; utxo->depositvout = depositvout; utxo->depositsatoshis = depositsatoshis; + memcpy(key,txid.bytes,sizeof(txid)); + memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); + memcpy(utxo->key,key,sizeof(key)); portable_mutex_lock(&LP_utxomutex); - HASH_ADD(hh,LP_utxoinfos,txid,sizeof(txid),utxo); + HASH_ADD(hh,LP_utxoinfos,key,sizeof(key),utxo); if ( mypeer != 0 ) { mypeer->numutxos++; @@ -525,9 +505,50 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin return(total); } + +int32_t basilisk_istrustedbob(struct basilisk_swap *swap) +{ + // for BTC and if trusted LP + return(0); +} + +struct iguana_info KMDcoin,BTCcoin,LTCcoin; + +struct iguana_info *LP_coinfind(char *symbol) +{ + struct iguana_info *coin; + if ( strcmp(symbol,"BTC") == 0 ) + return(&BTCcoin); + else if ( strcmp(symbol,"LTC") == 0 ) + return(<Ccoin); + else //if ( strcmp(symbol,"KMD") == 0 ) + { + coin = calloc(1,sizeof(*coin)); + *coin = KMDcoin; + strcpy(coin->symbol,symbol); + return(coin); + } +} + +void tradebot_swap_balancingtrade(struct basilisk_swap *swap,int32_t iambob) +{ + +} + +void tradebot_pendingadd(cJSON *tradejson,char *base,double basevolume,char *rel,double relvolume) +{ + // add to trades +} + +char GLOBAL_DBDIR[] = "."; + +#include "LP_secp.c" +#include "LP_rpc.c" #include "LP_bitcoin.c" -#include "LP_swap.c" +#include "LP_transaction.c" #include "LP_remember.c" +#include "LP_statemachine.c" +#include "LP_swap.c" #include "LP_commands.c" void LPinit(uint16_t myport,uint16_t mypull,uint16_t mypub,double profitmargin) diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c new file mode 100644 index 000000000..c32ded7f4 --- /dev/null +++ b/iguana/exchanges/LP_network.c @@ -0,0 +1,307 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_network.c +// marketmaker +// + +void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp) +{ +/* char keystr[64],databuf[1024],pubkeystr[128],*retstr,*retstr2,*datastr,*pushaddr=0,*subaddr=0; cJSON *retjson,*addrjson; uint8_t data[512]; int32_t datalen,timeout,pushsock = -1,subsock = -1; + if ( swap->connected == 1 ) + return; + if ( swap->pushsock < 0 && swap->subsock < 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) + { + timeout = 1000; + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + timeout = 1; + nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); + swap->pushsock = pushsock; + swap->subsock = subsock; + } + if ( (subsock= swap->subsock) < 0 || (pushsock= swap->pushsock) < 0 ) + { + printf("error getting nn_sockets\n"); + return; + } + sprintf(keystr,"%08x-%08x",swap->I.req.requestid,swap->I.req.quoteid); + if ( swap->connected == 0 && (retstr= _dex_kvsearch("KV",keystr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (datastr= jstr(retjson,"value")) != 0 ) + { + datalen = (int32_t)strlen(datastr) >> 1; + decode_hex((uint8_t *)databuf,datalen,datastr); + if ( (addrjson= cJSON_Parse(databuf)) != 0 ) + { + pushaddr = jstr(addrjson,"push"); + subaddr = jstr(addrjson,"sub"); + if ( pushaddr != 0 && subaddr != 0 ) + { + printf("KV decoded (%s and %s) %d %d\n",pushaddr,subaddr,swap->pushsock,swap->subsock); + if ( nn_connect(swap->pushsock,pushaddr) >= 0 && nn_connect(swap->subsock,subaddr) >= 0 ) + swap->connected = 1; + } + free_json(addrjson); + } + } + free_json(retjson); + } + printf("KVsearch.(%s) -> (%s) connected.%d socks.(%d %d) amlp.%d\n",keystr,retstr,swap->connected,swap->pushsock,swap->subsock,amlp); + free(retstr); + } + printf("connected.%d amlp.%d subsock.%d pushsock.%d\n",swap->connected,amlp,subsock,pushsock); + if ( swap->connected <= 0 && amlp != 0 && subsock >= 0 && pushsock >= 0 ) + { + if ( (retstr= _dex_psock("{}")) != 0 ) + { + printf("psock returns.(%s)\n",retstr); + // {"result":"success","pushaddr":"tcp://5.9.102.210:30002","subaddr":"tcp://5.9.102.210:30003","randipbits":3606291758,"coin":"KMD","tag":"6952562460568228137"} + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + pushaddr = jstr(retjson,"pushaddr"); + subaddr = jstr(retjson,"subaddr"); + if ( pushaddr != 0 && subaddr != 0 ) + { + if ( nn_connect(pushsock,pushaddr) >= 0 ) + { + printf("connected to %d pushaddr.(%s)\n",pushsock,pushaddr); + if ( nn_connect(subsock,subaddr) >= 0 ) + { + swap->connected = 1; + init_hexbytes_noT(pubkeystr,myinfo->persistent_pubkey33,33); + sprintf((char *)data,"{\"push\":\"%s\",\"sub\":\"%s\",\"trade\":[\"%s\", %.8f, \"%s\", %.8f],\"pub\":\"%s\"}",pushaddr,subaddr,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),pubkeystr); + datalen = (int32_t)strlen((char *)data) + 1; + printf("datalen.%d (%s)\n",datalen,(char *)data); + init_hexbytes_noT(databuf,data,datalen); + printf("%s -> %s\n",keystr,databuf); + if ( (retstr2= _dex_kvupdate("KV",keystr,databuf,1)) != 0 ) + { + printf("KVupdate.(%s)\n",retstr2); + free(retstr2); + } + } else printf("nn_connect error to %d subaddr.(%s)\n",subsock,subaddr); + } else printf("nn_connect error to %d pushaddr.(%s)\n",pushsock,pushaddr); + } + else printf("missing addr (%p) (%p) (%s)\n",pushaddr,subaddr,jprint(retjson,0)); + free_json(retjson); + } else printf("Error parsing psock.(%s)\n",retstr); + free(retstr); + } else printf("error issuing _dex_psock\n"); + }*/ +} + +char *nanomsg_tcpname(char *str,char *ipaddr,uint16_t port) +{ + sprintf(str,"tcp://%s:%u",ipaddr,port); + return(str); +} + +int32_t LP_send(int32_t sock,char *msg,int32_t freeflag) +{ + int32_t sentbytes,len,i; struct nn_pollfd pfd; + for (i=0; i<100; i++) + { + pfd.fd = sock; + pfd.events = NN_POLLOUT; + if ( nn_poll(&pfd,1,100) > 0 ) + { + len = (int32_t)strlen(msg) + 1; + if ( (sentbytes= nn_send(sock,msg,len,0)) != len ) + printf("LP_send sent %d instead of %d\n",sentbytes,len); + else printf("SENT.(%s)\n",msg); + if ( freeflag != 0 ) + free(msg); + return(sentbytes); + } + usleep(1000); + } + printf("error LP_send\n"); + return(-1); +} + +uint32_t LP_swapsend(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2]) +{ + uint8_t *buf; int32_t sentbytes,offset=0,i; + buf = malloc(datalen + sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2); + for (i=0; i<32; i++) + buf[offset++] = swap->I.myhash.bytes[i]; + for (i=0; i<32; i++) + buf[offset++] = swap->I.otherhash.bytes[i]; + offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); + offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); + if ( datalen > 0 ) + memcpy(&buf[offset],data,datalen), offset += datalen; + if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) + { + printf("sentbytes.%d vs offset.%d\n",sentbytes,offset); + if ( sentbytes < 0 ) + { + if ( swap->pushsock >= 0 ) + nn_close(swap->pushsock), swap->pushsock = -1; //, + if ( swap->subsock >= 0 ) // + nn_close(swap->subsock), swap->subsock = -1; + swap->connected = swap->I.iambob != 0 ? -1 : 0; + swap->aborted = (uint32_t)time(NULL); + } + } + //else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data); + free(buf); + return(nextbits); +} + +void basilisk_swap_sendabort(struct basilisk_swap *swap) +{ + uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0; + memset(buf,0,sizeof(buf)); + offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); + offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); + if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) + { + if ( sentbytes < 0 ) + { + if ( swap->pushsock >= 0 ) // + nn_close(swap->pushsock), swap->pushsock = -1; + if ( swap->subsock >= 0 ) // + nn_close(swap->subsock), swap->subsock = -1; + swap->connected = 0; + } + } else printf("basilisk_swap_sendabort\n"); +} + +void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp); + +void basilisk_swapgotdata(struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit) +{ + int32_t i; struct basilisk_swapmessage *mp; + for (i=0; inummessages; i++) + if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 ) + return; + //printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data); + swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1)); + mp = &swap->messages[swap->nummessages++]; + mp->crc32 = crc32; + mp->srchash = srchash; + mp->desthash = desthash; + mp->msgbits = msgbits; + mp->quoteid = quoteid; + mp->data = malloc(datalen); + mp->datalen = datalen; + memcpy(mp->data,data,datalen); + if ( reinit == 0 && swap->fp != 0 ) + { + fwrite(mp,1,sizeof(*mp),swap->fp); + fwrite(data,1,datalen,swap->fp); + fflush(swap->fp); + } +} + +int32_t basilisk_swapget(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(void *ptr,uint8_t *data,int32_t datalen)) +{ + uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0; + while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 ) + { + swap->lasttime = (uint32_t)time(NULL); + memset(srchash.bytes,0,sizeof(srchash)); + memset(desthash.bytes,0,sizeof(desthash)); + //printf("gotmsg.[%d] crc.%x\n",size,crc32); + offset = 0; + for (i=0; i<32; i++) + srchash.bytes[i] = ptr[offset++]; + for (i=0; i<32; i++) + desthash.bytes[i] = ptr[offset++]; + offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid); + offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits); + if ( size > offset ) + { + crc32 = calc_crc32(0,&ptr[offset],size-offset); + if ( size > offset ) + { + //printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset); + basilisk_swapgotdata(swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0); + } + } + else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 ) + { + if ( swap->aborted == 0 ) + { + swap->aborted = (uint32_t)time(NULL); + printf("got abort signal from other side\n"); + } + } else printf("basilisk_swapget: got strange packet\n"); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; + } + //char str[65],str2[65]; + for (i=0; inummessages; i++) + { + //printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash)); + if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 ) + { + if ( swap->messages[i].msgbits == msgbits ) + { + if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 ) + { + printf("nothing received for a while from Bob, try new sockets\n"); + if ( swap->pushsock >= 0 ) // + nn_close(swap->pushsock), swap->pushsock = -1; + if ( swap->subsock >= 0 ) // + nn_close(swap->subsock), swap->subsock = -1; + swap->connected = 0; + basilisk_psockinit(swap,swap->I.iambob != 0); + } + mp = &swap->messages[i]; + if ( msgbits != 0x80000000 ) + break; + } + } + } + if ( mp != 0 ) + retval = (*basilisk_verify_func)(swap,mp->data,mp->datalen); + //printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash)); + return(retval); +} + +int32_t basilisk_messagekeyread(uint8_t *key,uint32_t *channelp,uint32_t *msgidp,bits256 *srchashp,bits256 *desthashp) +{ + int32_t keylen = 0; + keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),channelp); + keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),msgidp); + keylen += iguana_rwbignum(0,&key[keylen],sizeof(*srchashp),srchashp->bytes); + keylen += iguana_rwbignum(0,&key[keylen],sizeof(*desthashp),desthashp->bytes); + return(keylen); +} + +int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash) +{ + int32_t keylen = 0; + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&channel); + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&msgid); + keylen += iguana_rwbignum(1,&key[keylen],sizeof(srchash),srchash.bytes); + keylen += iguana_rwbignum(1,&key[keylen],sizeof(desthash),desthash.bytes); + return(keylen); +} + +void LP_channelsend(bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen) +{ + int32_t keylen; uint8_t key[BASILISK_KEYSIZE]; //char *retstr; + keylen = basilisk_messagekey(key,channel,msgid,srchash,desthash); + //if ( (retstr= _dex_reqsend(myinfo,"DEX",key,keylen,data,datalen)) != 0 ) + // free(retstr); +} + diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index 22ec7d53a..547f8ab9c 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -18,439 +18,341 @@ // marketmaker // - -cJSON *basilisk_nullretjson(cJSON *retjson) -{ - char *outstr; - if ( retjson != 0 ) - { - outstr = jprint(retjson,0); - if ( strcmp(outstr,"{}") == 0 ) - { - free_json(retjson); - retjson = 0; - } - free(outstr); - } - return(retjson); -} - -cJSON *basilisk_swapgettxout(struct supernet_info *myinfo,char *symbol,bits256 trigger,int32_t vout) +/*void basilisk_swaps_init(struct supernet_info *myinfo) { - char *retstr; cJSON *retjson=0; struct iguana_info *coin; - if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 ) + char fname[512]; uint32_t iter,swapcompleted,requestid,quoteid,optionduration,statebits; FILE *fp; bits256 privkey;struct basilisk_request R; struct basilisk_swapmessage M; struct basilisk_swap *swap = 0; + sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); + if ( (myinfo->swapsfp= fopen(fname,"rb+")) != 0 ) { - if ( (retstr= dex_gettxout(myinfo,0,0,0,trigger,symbol,vout)) != 0 ) + while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) ) { - //printf("dexgettxout.(%s)\n",retstr); - retjson = cJSON_Parse(retstr); - free(retstr); + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); + printf("%s\n",fname); + if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed + { + memset(&M,0,sizeof(M)); + swapcompleted = 1; + for (iter=0; iter<2; iter++) + { + if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) && + fread(&R,1,sizeof(R),fp) == sizeof(R) && + fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) && + fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) ) + { + while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) ) + { + M.data = 0; + //printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen); + if ( M.datalen < 100000 ) + { + M.data = malloc(M.datalen); + if ( fread(M.data,1,M.datalen,fp) == M.datalen ) + { + if ( calc_crc32(0,M.data,M.datalen) == M.crc32 ) + { + if ( iter == 1 ) + { + if ( swap == 0 ) + { + swap = basilisk_thread_start(privkey,&R,statebits,optionduration,1); + swap->I.choosei = swap->I.otherchoosei = -1; + } + if ( swap != 0 ) + basilisk_swapgotdata(swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1); + } + } else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32); + } else printf("error reading M.datalen %d\n",M.datalen); + free(M.data), M.data = 0; + } + } + } + if ( swapcompleted != 0 ) + break; + rewind(fp); + } + } } - if ( 0 && strcmp("BTC",symbol) == 0 ) - printf("%s gettxout.(%s)\n",symbol,jprint(retjson,0)); - } - else - { - retjson = dpow_gettxout(myinfo,coin,trigger,vout); - //printf("need to verify passthru has this info\n"); - //printf("dpowgettxout.(%s)\n",jprint(retjson,0)); - } - return(basilisk_nullretjson(retjson)); -} + } else myinfo->swapsfp = fopen(fname,"wb+"); +}*/ -cJSON *basilisk_swapgettx(struct supernet_info *myinfo,char *symbol,bits256 txid) +FILE *basilisk_swap_save(struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) { - char *retstr; cJSON *retjson=0; struct iguana_info *coin; - if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 ) - { - if ( (retstr= dex_gettransaction(myinfo,0,0,0,txid,symbol)) != 0 ) - { - retjson = cJSON_Parse(retstr); - free(retstr); - } - //if ( strcmp("BTC",symbol) == 0 ) - // printf("%s gettx.(%s)\n",symbol,jprint(retjson,0)); - } else retjson = dpow_gettransaction(myinfo,coin,txid); - return(basilisk_nullretjson(retjson)); + FILE *fp=0; /*char fname[512]; + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"rb+")) == 0 ) + { + if ( (fp= fopen(fname,"wb+")) != 0 ) + { + fwrite(privkey.bytes,1,sizeof(privkey),fp); + fwrite(rp,1,sizeof(*rp),fp); + fwrite(&statebits,1,sizeof(statebits),fp); + fwrite(&optionduration,1,sizeof(optionduration),fp); + fflush(fp); + } + } + else if ( reinit != 0 ) + { + }*/ + return(fp); } -int32_t basilisk_swap_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj) +int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp) { - int32_t n,m,retval = -1; cJSON *vouts,*item,*addresses,*skey; char *addr; - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n ) + FILE *fp=0; char fname[512]; int32_t retval = -1; + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"rb+")) != 0 ) { - item = jitem(vouts,vout); - if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) - { - item = jitem(addresses,0); - if ( (addr= jstr(item,0)) != 0 ) - { - safecopy(destaddr,addr,64); - retval = 0; - } - //printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr); - } + if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) && + fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) && + fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) && + fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) ) + retval = 0; + fclose(fp); } return(retval); } -int32_t basilisk_swap_getcoinaddr(struct supernet_info *myinfo,char *symbol,char *coinaddr,bits256 txid,int32_t vout) +void basilisk_swap_saveupdate(struct basilisk_swap *swap) { - cJSON *retjson; - coinaddr[0] = 0; - if ( (retjson= basilisk_swapgettx(myinfo,symbol,txid)) != 0 ) + FILE *fp; char fname[512]; + sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"wb")) != 0 ) { - basilisk_swap_txdestaddr(coinaddr,txid,vout,retjson); - free_json(retjson); + fwrite(&swap->I,1,sizeof(swap->I),fp); + /*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp); + fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp); + fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp); + fwrite(&swap->myfee,1,sizeof(swap->myfee),fp); + fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp); + fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp); + fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp); + fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp); + fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp); + fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp); + fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/ + fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp); + fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp); + fwrite(swap->deck,1,sizeof(swap->deck),fp); + fclose(fp); } - return(coinaddr[0] != 0); } -int32_t basilisk_swap_getsigscript(struct supernet_info *myinfo,char *symbol,uint8_t *script,int32_t maxlen,bits256 txid,int32_t vini) +/*int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr) { - cJSON *retjson,*vins,*item,*skey; int32_t n,scriptlen = 0; char *hexstr; - if ( (retjson= basilisk_swapgettx(myinfo,symbol,txid)) != 0 ) + if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) ) { - if ( (vins= jarray(&n,retjson,"vin")) != 0 && vini < n ) + rawtx->coin = 0; + rawtx->vins = 0; + if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 ) { - item = jitem(vins,vini); - if ( (skey= jobj(item,"scriptSig")) != 0 && (hexstr= jstr(skey,"hex")) != 0 && (scriptlen= (int32_t)strlen(hexstr)) < maxlen*2 ) - { - scriptlen >>= 1; - decode_hex(script,scriptlen,hexstr); - //char str[65]; printf("%s/v%d sigscript.(%s)\n",bits256_str(str,txid),vini,hexstr); - } + rawtx->coin = LP_coinfind(rawtx->I.coinstr); + if ( rawtx->vinstr[0] != 0 ) + rawtx->vins = cJSON_Parse(rawtx->vinstr); + printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen); + return(0); } - free_json(retjson); } - return(scriptlen); -} + return(-1); +}*/ -int64_t basilisk_txvalue(struct supernet_info *myinfo,char *symbol,bits256 txid,int32_t vout) +void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen) { - cJSON *txobj,*vouts,*item; int32_t n; int64_t value = 0; - //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid)); - if ( (txobj= basilisk_swapgettx(myinfo,symbol,txid)) != 0 ) + int32_t i; char scriptstr[513]; + if ( scriptlen != 0 ) { - //printf("txobj.(%s)\n",jprint(txobj,0)); - if ( (vouts= jarray(&n,txobj,"vout")) != 0 ) - { - item = jitem(vouts,vout); - if ( (value= jdouble(item,"amount") * SATOSHIDEN) == 0 ) - value = jdouble(item,"value") * SATOSHIDEN; - } - free_json(txobj); + for (i=0; iI.req.requestid,swap->I.req.quoteid,rawtx->name), OS_compatible_path(fname); + coinaddr[0] = secretAmstr[0] = secretAm256str[0] = secretBnstr[0] = secretBn256str[0] = 0; + memset(zeroes,0,sizeof(zeroes)); + if ( rawtx != 0 && (fp= fopen(fname,"wb")) != 0 ) { - if ( (array= cJSON_Parse(retstr)) != 0 ) + fprintf(fp,"{\"name\":\"%s\",\"coin\":\"%s\"",rawtx->name,rawtx->coin->symbol); + if ( rawtx->I.datalen > 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + fprintf(fp,",\"tx\":\""); + for (i=0; iI.datalen; i++) + fprintf(fp,"%02x",rawtx->txbytes[i]); + fprintf(fp,"\",\"txid\":\"%s\"",bits256_str(str,bits256_doublesha256(0,rawtx->txbytes,rawtx->I.datalen))); + if ( rawtx == &swap->bobdeposit || rawtx == &swap->bobpayment ) { - for (i=0; ibobcoin,coinaddr,rawtx->txbytes,rawtx->I.datalen); + if ( coinaddr[0] != 0 ) { - if ( (item= jitem(array,i)) == 0 ) - continue; - txid = jbits256(item,"txid"); - if ( bits256_nonz(txid) == 0 ) - { - if ( (array2= jarray(&m,item,"inputs")) != 0 && m == 1 ) - { - //printf("found inputs with %s\n",bits256_str(str,spendtxid)); - txid = jbits256(jitem(array2,0),"output_hash"); - if ( bits256_cmp(txid,utxotxid) == 0 ) - { - //printf("matched %s\n",bits256_str(str,txid)); - if ( (array2= jarray(&m,item,"outputs")) != 0 && m == 1 && (addr= jstr(jitem(array2,0),"address")) != 0 ) - { - spendtxid = jbits256(item,"hash"); - strcpy(destaddr,addr); - //printf("set spend addr.(%s) <- %s\n",addr,jprint(item,0)); - break; - } - } - } - } - else if ( bits256_cmp(txid,utxotxid) == 0 ) - { - spendtxid = jbits256(item,"spendtxid"); - if ( bits256_nonz(spendtxid) != 0 ) - { - basilisk_swap_getcoinaddr(myinfo,symbol,destaddr,spendtxid,0); - //char str[65]; printf("found spendtxid.(%s) -> %s\n",bits256_str(str,spendtxid),destaddr); - break; - } - } + if ( (tmp= LP_importaddress(swap->bobcoin.symbol,coinaddr)) != 0 ) + free(tmp); + if ( rawtx == &swap->bobdeposit ) + safecopy(swap->Bdeposit,coinaddr,sizeof(swap->Bdeposit)); + else safecopy(swap->Bpayment,coinaddr,sizeof(swap->Bpayment)); } } - free_json(array); } - free(retstr); - } - return(spendtxid); -} - -bits256 basilisk_swap_spendtxid(struct supernet_info *myinfo,char *symbol,char *destaddr,bits256 utxotxid,int32_t vout) -{ - bits256 spendtxid,txid; char *catstr,*addr; cJSON *array,*item,*item2,*txobj,*vins; int32_t i,n,m; char coinaddr[64],str[65]; struct iguana_info *coin = iguana_coinfind(symbol); - // listtransactions or listspents - destaddr[0] = 0; - coinaddr[0] = 0; - memset(&spendtxid,0,sizeof(spendtxid)); - //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); - if ( (coin == 0 || coin->FULLNODE >= 0) && iguana_isnotarychain(symbol) >= 0 ) - { - //[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}] - basilisk_swap_getcoinaddr(myinfo,symbol,coinaddr,utxotxid,vout); - if ( coinaddr[0] != 0 ) - spendtxid = dex_swap_spendtxid(myinfo,symbol,destaddr,coinaddr,utxotxid,vout); + if ( swap->Bdeposit[0] != 0 ) + fprintf(fp,",\"%s\":\"%s\"","Bdeposit",swap->Bdeposit); + if ( swap->Bpayment[0] != 0 ) + fprintf(fp,",\"%s\":\"%s\"","Bpayment",swap->Bpayment); + fprintf(fp,",\"expiration\":%u",swap->I.expiration); + fprintf(fp,",\"iambob\":%d",swap->I.iambob); + fprintf(fp,",\"bobcoin\":\"%s\"",swap->bobcoin.symbol); + fprintf(fp,",\"alicecoin\":\"%s\"",swap->alicecoin.symbol); + fprintf(fp,",\"lock\":%u",locktime); + fprintf(fp,",\"amount\":%.8f",dstr(rawtx->I.amount)); + if ( bits256_nonz(triggertxid) != 0 ) + fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid)); + if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 ) + { + basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn); + if ( (tmp= LP_importaddress(swap->alicecoin.symbol,coinaddr)) != 0 ) + free(tmp); + fprintf(fp,",\"Apayment\":\"%s\"",coinaddr); + } + /*basilisk_dontforget_userdata("Aclaim",fp,swap->I.userdata_aliceclaim,swap->I.userdata_aliceclaimlen); + basilisk_dontforget_userdata("Areclaim",fp,swap->I.userdata_alicereclaim,swap->I.userdata_alicereclaimlen); + basilisk_dontforget_userdata("Aspend",fp,swap->I.userdata_alicespend,swap->I.userdata_alicespendlen); + basilisk_dontforget_userdata("Bspend",fp,swap->I.userdata_bobspend,swap->I.userdata_bobspendlen); + basilisk_dontforget_userdata("Breclaim",fp,swap->I.userdata_bobreclaim,swap->I.userdata_bobreclaimlen); + basilisk_dontforget_userdata("Brefund",fp,swap->I.userdata_bobrefund,swap->I.userdata_bobrefundlen);*/ + fprintf(fp,"}\n"); + fclose(fp); } - else if ( coin != 0 ) + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"wb")) != 0 ) { - if ( (array= dpow_listtransactions(myinfo,coin,destaddr,1000,0)) != 0 ) + fprintf(fp,"{\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u",swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime); + if ( memcmp(zeroes,swap->I.secretAm,20) != 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; iI.secretAm,20); + fprintf(fp,",\"secretAm\":\"%s\"",secretAmstr); } - if ( destaddr[0] != 0 ) + if ( memcmp(zeroes,swap->I.secretAm256,32) != 0 ) { - if ( (array= dpow_listtransactions(myinfo,coin,destaddr,1000,0)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; i jint(item,"vout") ) - { - item2 = jitem(vins,jint(item,"vout")); - if ( bits256_cmp(utxotxid,jbits256(item2,"txid")) == 0 && vout == jint(item2,"vout") ) - { - spendtxid = txid; - break; - } - } - } - } - } - if ( i == n ) - printf("dpowlist: native couldnt find spendtxid for %s\n",bits256_str(str,utxotxid)); - } - free_json(array); - } - if ( bits256_nonz(spendtxid) != 0 ) - return(spendtxid); + init_hexbytes_noT(secretAm256str,swap->I.secretAm256,32); + fprintf(fp,",\"secretAm256\":\"%s\"",secretAm256str); } - if ( iguana_isnotarychain(symbol) >= 0 ) + if ( memcmp(zeroes,swap->I.secretBn,20) != 0 ) { - basilisk_swap_getcoinaddr(myinfo,symbol,coinaddr,utxotxid,vout); - printf("fallback use DEX for native (%s) (%s)\n",coinaddr,bits256_str(str,utxotxid)); - if ( coinaddr[0] != 0 ) - { - spendtxid = dex_swap_spendtxid(myinfo,symbol,destaddr,coinaddr,utxotxid,vout); - printf("spendtxid.(%s)\n",bits256_str(str,spendtxid)); - } + init_hexbytes_noT(secretBnstr,swap->I.secretBn,20); + fprintf(fp,",\"secretBn\":\"%s\"",secretBnstr); } - } - return(spendtxid); -} - -bits256 basilisk_swap_sendrawtransaction(struct supernet_info *myinfo,char *txname,char *symbol,char *txbytes) -{ - char *retstr; bits256 txid; int32_t i,sentflag = 0; - memset(&txid,0,sizeof(txid)); - for (i=0; i<3; i++) - { - if ( (retstr= _dex_sendrawtransaction(myinfo,symbol,txbytes)) != 0 ) + if ( memcmp(zeroes,swap->I.secretBn256,32) != 0 ) { - if ( is_hexstr(retstr,0) == 64 ) - { - decode_hex(txid.bytes,32,retstr); - sentflag = 1; - } - char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid)); - free(retstr); + init_hexbytes_noT(secretBn256str,swap->I.secretBn256,32); + fprintf(fp,",\"secretBn256\":\"%s\"",secretBn256str); } - if ( sentflag != 0 ) - break; + for (i=0; i<2; i++) + if ( bits256_nonz(swap->I.myprivs[i]) != 0 ) + fprintf(fp,",\"myprivs%d\":\"%s\"",i,bits256_str(str,swap->I.myprivs[i])); + if ( bits256_nonz(swap->I.privAm) != 0 ) + fprintf(fp,",\"privAm\":\"%s\"",bits256_str(str,swap->I.privAm)); + if ( bits256_nonz(swap->I.privBn) != 0 ) + fprintf(fp,",\"privBn\":\"%s\"",bits256_str(str,swap->I.privBn)); + if ( bits256_nonz(swap->I.pubA0) != 0 ) + fprintf(fp,",\"pubA0\":\"%s\"",bits256_str(str,swap->I.pubA0)); + if ( bits256_nonz(swap->I.pubB0) != 0 ) + fprintf(fp,",\"pubB0\":\"%s\"",bits256_str(str,swap->I.pubB0)); + if ( bits256_nonz(swap->I.pubB1) != 0 ) + fprintf(fp,",\"pubB1\":\"%s\"",bits256_str(str,swap->I.pubB1)); + if ( bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 ) + fprintf(fp,",\"Bdeposit\":\"%s\"",bits256_str(str,swap->bobdeposit.I.actualtxid)); + if ( bits256_nonz(swap->bobrefund.I.actualtxid) != 0 ) + fprintf(fp,",\"Brefund\":\"%s\"",bits256_str(str,swap->bobrefund.I.actualtxid)); + if ( bits256_nonz(swap->aliceclaim.I.actualtxid) != 0 ) + fprintf(fp,",\"Aclaim\":\"%s\"",bits256_str(str,swap->aliceclaim.I.actualtxid)); + + if ( bits256_nonz(swap->bobpayment.I.actualtxid) != 0 ) + fprintf(fp,",\"Bpayment\":\"%s\"",bits256_str(str,swap->bobpayment.I.actualtxid)); + if ( bits256_nonz(swap->alicespend.I.actualtxid) != 0 ) + fprintf(fp,",\"Aspend\":\"%s\"",bits256_str(str,swap->alicespend.I.actualtxid)); + if ( bits256_nonz(swap->bobreclaim.I.actualtxid) != 0 ) + fprintf(fp,",\"Breclaim\":\"%s\"",bits256_str(str,swap->bobreclaim.I.actualtxid)); + + if ( bits256_nonz(swap->alicepayment.I.actualtxid) != 0 ) + fprintf(fp,",\"Apayment\":\"%s\"",bits256_str(str,swap->alicepayment.I.actualtxid)); + if ( bits256_nonz(swap->bobspend.I.actualtxid) != 0 ) + fprintf(fp,",\"Bspend\":\"%s\"",bits256_str(str,swap->bobspend.I.actualtxid)); + if ( bits256_nonz(swap->alicereclaim.I.actualtxid) != 0 ) + fprintf(fp,",\"Areclaim\":\"%s\"",bits256_str(str,swap->alicereclaim.I.actualtxid)); + + if ( bits256_nonz(swap->otherfee.I.actualtxid) != 0 ) + fprintf(fp,",\"otherfee\":\"%s\"",bits256_str(str,swap->otherfee.I.actualtxid)); + if ( bits256_nonz(swap->myfee.I.actualtxid) != 0 ) + fprintf(fp,",\"myfee\":\"%s\"",bits256_str(str,swap->myfee.I.actualtxid)); + fprintf(fp,",\"dest33\":\""); + for (i=0; i<33; i++) + fprintf(fp,"%02x",swap->persistent_pubkey33[i]); + fprintf(fp,"\"}\n"); + fclose(fp); } - return(txid); } -char *basilisk_swap_bobtxspend(char *name,struct supernet_info *myinfo,char *symbol,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp) +void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) { - char *rawtxbytes=0,*signedtx=0,str[65],hexstr[999],wifstr[128],destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *utxoobj,*txobj,*vins,*item,*sobj,*privkeys; int32_t height,completed,spendlen,ignore_cltverr=1,suppress_pubkeys=1; struct vin_info *V; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; struct iguana_info *coin; bits256 txid,signedtxid; uint64_t destamount; - *destamountp = 0; - if ( finalseqid == 0 ) - locktime = expiration; - //printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen); - if ( redeemlen < 0 || (coin= iguana_coinfind(symbol)) == 0 ) - return(0); - if ( (utxoobj= basilisk_swapgettxout(myinfo,symbol,utxotxid,vout)) == 0 ) + bits256 triggertxid; + memset(triggertxid.bytes,0,sizeof(triggertxid)); + if ( rawtx == 0 ) { - printf("basilisk_swap_bobtxspend.%s utxo already spent or doesnt exist\n",name); - return(0); + basilisk_dontforget(swap,0,0,triggertxid); + return; } - if ( (destamount= jdouble(utxoobj,"amount")*SATOSHIDEN) == 0 && (destamount= jdouble(utxoobj,"value")*SATOSHIDEN) == 0 ) + if ( rawtx == &swap->myfee ) + basilisk_dontforget(swap,&swap->myfee,0,triggertxid); + else if ( rawtx == &swap->otherfee ) + basilisk_dontforget(swap,&swap->otherfee,0,triggertxid); + else if ( rawtx == &swap->bobdeposit ) { - printf("%s %s basilisk_swap_bobtxspend.%s strange utxo.(%s)\n",symbol,bits256_str(str,utxotxid),name,jprint(utxoobj,0)); - free_json(utxoobj); - return(0); - } else free_json(utxoobj); - *destamountp = destamount; - if ( destamount > 10000 ) - destamount -= 10000; - if ( strcmp(symbol,"BTC") == 0 ) + basilisk_dontforget(swap,&swap->bobdeposit,0,triggertxid); + basilisk_dontforget(swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid); + } + else if ( rawtx == &swap->bobrefund ) + basilisk_dontforget(swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid); + else if ( rawtx == &swap->aliceclaim ) { - if ( destamount > 40000 ) - destamount -= 40000; + basilisk_dontforget(swap,&swap->bobrefund,0,triggertxid); + basilisk_dontforget(swap,&swap->aliceclaim,0,swap->bobrefund.I.actualtxid); } - height = coin->longestchain; - timestamp = (uint32_t)time(NULL); - V = calloc(256,sizeof(*V)); - privkeys = cJSON_CreateArray(); - if ( privkey2p != 0 ) + else if ( rawtx == &swap->alicepayment ) { - V[0].signers[1].privkey = *privkey2p; - bitcoin_pubkey33(myinfo->ctx,V[0].signers[1].pubkey,*privkey2p); - bitcoin_priv2wif(wifstr,*privkey2p,coin->chain->wiftype); - jaddistr(privkeys,wifstr); - V[0].N = V[0].M = 2; - } else V[0].N = V[0].M = 1; - V[0].signers[0].privkey = privkey; - bitcoin_pubkey33(myinfo->ctx,V[0].signers[0].pubkey,privkey); - bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype); - jaddistr(privkeys,wifstr); - V[0].suppress_pubkeys = suppress_pubkeys; - V[0].ignore_cltverr = ignore_cltverr; - if ( redeemlen != 0 ) - memcpy(V[0].p2shscript,redeemscript,redeemlen), V[0].p2shlen = redeemlen; - txobj = bitcoin_txcreate(coin->symbol,coin->chain->isPoS,locktime,1,timestamp); - vins = cJSON_CreateArray(); - item = cJSON_CreateObject(); - if ( userdata != 0 && userdatalen > 0 ) + basilisk_dontforget(swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid); + } + else if ( rawtx == &swap->bobspend ) { - memcpy(V[0].userdata,userdata,userdatalen); - V[0].userdatalen = userdatalen; - init_hexbytes_noT(hexstr,userdata,userdatalen); - jaddstr(item,"userdata",hexstr); + basilisk_dontforget(swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid); + basilisk_dontforget(swap,&swap->bobspend,0,swap->alicepayment.I.actualtxid); } - jaddbits256(item,"txid",utxotxid); - jaddnum(item,"vout",vout); - sobj = cJSON_CreateObject(); - bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33); - bitcoin_addr2rmd160(&addrtype,rmd160,destaddr); - /*int32_t i; - for (i=0; i<33; i++) - printf("%02x",pubkey33[i]); - printf(" pubkey33 ->\n"); - for (i=0; i<20; i++) - printf("%02x",rmd160[i]); - printf(" destaddr.(%s)\n",destaddr); - calc_rmd160_sha256(rmd160,pubkey33,33); - for (i=0; i<20; i++) - printf("%02x",rmd160[i]); - printf(" <- vs direct calc\n");*/ - spendlen = bitcoin_standardspend(spendscript,0,rmd160); - init_hexbytes_noT(hexstr,spendscript,spendlen); - jaddstr(sobj,"hex",hexstr); - jadd(item,"scriptPubKey",sobj); - jaddnum(item,"suppress",suppress_pubkeys); - jaddnum(item,"sequence",sequenceid); - if ( redeemlen != 0 ) + else if ( rawtx == &swap->alicereclaim ) { - init_hexbytes_noT(hexstr,redeemscript,redeemlen); - jaddstr(item,"redeemScript",hexstr); + basilisk_dontforget(swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid); + basilisk_dontforget(swap,&swap->alicereclaim,0,swap->bobrefund.I.actualtxid); } - jaddi(vins,item); - jdelete(txobj,"vin"); - jadd(txobj,"vin",vins); - txobj = bitcoin_txoutput(txobj,spendscript,spendlen,destamount); - if ( (rawtxbytes= bitcoin_json2hex(myinfo,coin,&txid,txobj,V)) != 0 ) + else if ( rawtx == &swap->bobpayment ) { - //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0)); - if ( (signedtx= iguana_signrawtx(myinfo,coin,height,&signedtxid,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) - printf("couldnt sign transaction\n"); - else if ( completed == 0 ) - printf("incomplete signing\n"); - else printf("%s -> %s\n",name,bits256_str(str,signedtxid)); - free(rawtxbytes); - } else printf("error making rawtx\n"); - free_json(privkeys); - free_json(txobj); - free(V); - return(signedtx); -} - -char *basilisk_swap_Aspend(char *name,struct supernet_info *myinfo,char *symbol,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp) -{ - char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn; struct iguana_info *coin = iguana_coinfind(symbol); - if ( coin != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) + basilisk_dontforget(swap,&swap->bobpayment,0,triggertxid); + basilisk_dontforget(swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid); + } + else if ( rawtx == &swap->alicespend ) { - pubAm = bitcoin_pubkey33(myinfo->ctx,tmp33,privAm); - pubBn = bitcoin_pubkey33(myinfo->ctx,tmp33,privBn); - //char str[65]; - //printf("pubAm.(%s)\n",bits256_str(str,pubAm)); - //printf("pubBn.(%s)\n",bits256_str(str,pubBn)); - spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,coin->chain->p2shtype,pubAm,pubBn); - //char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen); - /*rev = privAm; - for (i=0; i<32; i++) - privAm.bytes[i] = rev.bytes[31 - i]; - rev = privBn; - for (i=0; i<32; i++) - privBn.bytes[i] = rev.bytes[31 - i];*/ - signedtx = basilisk_swap_bobtxspend(name,myinfo,symbol,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,pubkey33,1,expiration,destamountp); + basilisk_dontforget(swap,&swap->bobpayment,0,triggertxid); + basilisk_dontforget(swap,&swap->alicespend,0,triggertxid); } - return(signedtx); + else if ( rawtx == &swap->bobreclaim ) + basilisk_dontforget(swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid); } -bits256 basilisk_swap_privbob_extract(struct supernet_info *myinfo,char *symbol,bits256 spendtxid,int32_t vini,int32_t revflag) + + +bits256 basilisk_swap_privbob_extract(char *symbol,bits256 spendtxid,int32_t vini,int32_t revflag) { bits256 privkey; int32_t i,scriptlen,siglen; uint8_t script[1024]; // from Bob refund of Bob deposit memset(&privkey,0,sizeof(privkey)); - if ( (scriptlen= basilisk_swap_getsigscript(myinfo,symbol,script,(int32_t)sizeof(script),spendtxid,vini)) > 0 ) + if ( (scriptlen= basilisk_swap_getsigscript(symbol,script,(int32_t)sizeof(script),spendtxid,vini)) > 0 ) { siglen = script[0]; for (i=0; i<32; i++) @@ -464,20 +366,20 @@ bits256 basilisk_swap_privbob_extract(struct supernet_info *myinfo,char *symbol, return(privkey); } -bits256 basilisk_swap_privBn_extract(struct supernet_info *myinfo,bits256 *bobrefundp,char *bobcoin,bits256 bobdeposit,bits256 privBn) +bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 bobdeposit,bits256 privBn) { char destaddr[64]; if ( bits256_nonz(privBn) == 0 ) { if ( bits256_nonz(bobdeposit) != 0 ) - *bobrefundp = basilisk_swap_spendtxid(myinfo,bobcoin,destaddr,bobdeposit,0); + *bobrefundp = LP_swap_spendtxid(bobcoin,destaddr,bobdeposit,0); if ( bits256_nonz(*bobrefundp) != 0 ) - privBn = basilisk_swap_privbob_extract(myinfo,bobcoin,*bobrefundp,0,0); + privBn = basilisk_swap_privbob_extract(bobcoin,*bobrefundp,0,0); } return(privBn); } -bits256 basilisk_swap_spendupdate(struct supernet_info *myinfo,char *symbol,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr) +bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr) { bits256 spendtxid,txid; char destaddr[64]; txid = txids[utxoind]; @@ -489,7 +391,7 @@ bits256 basilisk_swap_spendupdate(struct supernet_info *myinfo,char *symbol,int3 if ( bits256_nonz(txid) != 0 ) { //char str[65]; - spendtxid = basilisk_swap_spendtxid(myinfo,symbol,destaddr,txid,vout); + spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,vout); if ( bits256_nonz(spendtxid) != 0 ) { sentflags[utxoind] = 1; @@ -598,9 +500,12 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag return(0); } -cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) +cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) { - FILE *fp; struct iguana_info *coin; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)]; + static void *ctx; + FILE *fp; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)],signedtxid; struct iguana_info *bob=0,*alice=0; uint64_t txfee = 10000; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); memset(values,0,sizeof(values)); memset(txids,0,sizeof(txids)); memset(secretAm,0,sizeof(secretAm)); @@ -753,7 +658,7 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t safecopy(alicecoin,symbol,sizeof(alicecoin)); if ( finishedflag == 0 ) { - if ( (sentobj= basilisk_swapgettx(myinfo,symbol,txid)) == 0 ) + if ( (sentobj= LP_swapgettx(symbol,txid)) == 0 ) { //printf("%s %s ready to broadcast\n",symbol,bits256_str(str2,txid)); } @@ -788,27 +693,27 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t { if ( iambob == 0 ) { - if ( (coin= iguana_coinfind(alicecoin)) != 0 ) + if ( (alice= LP_coinfind(alicecoin)) != 0 ) { - bitcoin_address(Adestaddr,coin->chain->pubtype,pubkey33,33); + bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33); AAdest = Adestaddr; } - if ( (coin= iguana_coinfind(bobcoin)) != 0 ) + if ( (bob= LP_coinfind(bobcoin)) != 0 ) { - bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33); + bitcoin_address(destaddr,bob->pubtype,pubkey33,33); Adest = destaddr; } } else { - if ( (coin= iguana_coinfind(bobcoin)) != 0 ) + if ( (bob= LP_coinfind(bobcoin)) != 0 ) { - bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33); + bitcoin_address(destaddr,bob->pubtype,pubkey33,33); Bdest = destaddr; } - if ( (coin= iguana_coinfind(alicecoin)) != 0 ) + if ( (alice= LP_coinfind(alicecoin)) != 0 ) { - bitcoin_address(Adestaddr,coin->chain->pubtype,pubkey33,33); + bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33); ABdest = Adestaddr; } } @@ -817,15 +722,15 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT])); if ( txbytes[BASILISK_ALICEPAYMENT] != 0 ) sentflags[BASILISK_ALICEPAYMENT] = 1; - else if ( (sentobj= basilisk_swapgettx(myinfo,alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 ) + else if ( (sentobj= LP_swapgettx(alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 ) { sentflags[BASILISK_ALICEPAYMENT] = 1; free_json(sentobj); } } - paymentspent = basilisk_swap_spendupdate(myinfo,bobcoin,sentflags,txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest); - Apaymentspent = basilisk_swap_spendupdate(myinfo,alicecoin,sentflags,txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest); - depositspent = basilisk_swap_spendupdate(myinfo,bobcoin,sentflags,txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest); + paymentspent = basilisk_swap_spendupdate(bobcoin,sentflags,txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest); + Apaymentspent = basilisk_swap_spendupdate(alicecoin,sentflags,txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest); + depositspent = basilisk_swap_spendupdate(bobcoin,sentflags,txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest); finishedflag = basilisk_swap_isfinished(iambob,txids,sentflags,paymentspent,Apaymentspent,depositspent); if ( iambob == 0 ) { @@ -845,13 +750,13 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256); len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen); printf("alicespend len.%d redeemlen.%d\n",len,redeemlen); - if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend("alicespend",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND])) != 0 ) + if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND])) != 0 ) printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]); } } if ( txbytes[BASILISK_ALICESPEND] != 0 ) { - txids[BASILISK_ALICESPEND] = basilisk_swap_sendrawtransaction(myinfo,"alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]); + txids[BASILISK_ALICESPEND] = basilisk_swap_sendrawtransaction("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]); if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested { sentflags[BASILISK_ALICESPEND] = 1; @@ -870,13 +775,13 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t if ( redeemlen > 0 ) { len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend("aliceclaim",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM])) != 0 ) + if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM])) != 0 ) printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]); } } if ( txbytes[BASILISK_ALICECLAIM] != 0 ) { - txids[BASILISK_ALICECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]); + txids[BASILISK_ALICECLAIM] = basilisk_swap_sendrawtransaction("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]); if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested { sentflags[BASILISK_ALICECLAIM] = 1; @@ -889,16 +794,16 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t { //if ( txbytes[BASILISK_ALICERECLAIM] == 0 ) { - privBn = basilisk_swap_privBn_extract(myinfo,&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn); + privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn); if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) { - if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",myinfo,alicecoin,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM])) != 0 ) + if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM])) != 0 ) printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]); } } if ( txbytes[BASILISK_ALICERECLAIM] != 0 ) { - txids[BASILISK_ALICERECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]); + txids[BASILISK_ALICERECLAIM] = basilisk_swap_sendrawtransaction("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]); if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested { sentflags[BASILISK_ALICERECLAIM] = 1; @@ -918,17 +823,17 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t { if ( bits256_nonz(privAm) == 0 ) { - privAm = basilisk_swap_privbob_extract(myinfo,bobcoin,txids[BASILISK_ALICESPEND],0,1); + privAm = basilisk_swap_privbob_extract(bobcoin,txids[BASILISK_ALICESPEND],0,1); } if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) { - if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",myinfo,alicecoin,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND])) != 0 ) + if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND])) != 0 ) printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]); } } if ( txbytes[BASILISK_BOBSPEND] != 0 ) { - txids[BASILISK_BOBSPEND] = basilisk_swap_sendrawtransaction(myinfo,"bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]); + txids[BASILISK_BOBSPEND] = basilisk_swap_sendrawtransaction("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]); if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested { sentflags[BASILISK_BOBSPEND] = 1; @@ -946,7 +851,7 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t if ( redeemlen > 0 ) { len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend("bobrefund",myinfo,bobcoin,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM])) != 0 ) + if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM])) != 0 ) { int32_t z; for (z=0; z<20; z++) @@ -957,7 +862,7 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t } if ( txbytes[BASILISK_BOBRECLAIM] != 0 ) { - txids[BASILISK_BOBRECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]); + txids[BASILISK_BOBRECLAIM] = basilisk_swap_sendrawtransaction("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]); if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested { sentflags[BASILISK_BOBRECLAIM] = 1; @@ -976,12 +881,12 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn)); redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256); len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend("bobrefund",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND])) != 0 ) + if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND])) != 0 ) printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]); } if ( txbytes[BASILISK_BOBREFUND] != 0 ) { - txids[BASILISK_BOBREFUND] = basilisk_swap_sendrawtransaction(myinfo,"bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]); + txids[BASILISK_BOBREFUND] = basilisk_swap_sendrawtransaction("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]); if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested { sentflags[BASILISK_BOBREFUND] = 1; @@ -1001,7 +906,7 @@ cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t sentflags[BASILISK_BOBDEPOSIT] = 1; for (i=0; inumswaps; i++) + /*for (i=0; inumswaps; i++) if ( (swap= myinfo->swaps[i]) != 0 && swap->I.req.requestid == requestid && swap->I.req.quoteid == quoteid ) { - jaddi(array,basilisk_swapjson(myinfo,swap)); + jaddi(array,basilisk_swapjson(swap)); flag = 1; break; - } + }*/ if ( flag == 0 ) { - if ( (item= basilisk_remember(myinfo,KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) + if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) { jaddi(array,item); if ( 1 && (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 ) @@ -1157,12 +1063,12 @@ char *basilisk_swaplist(struct supernet_info *myinfo) jaddnum(retjson,"avesell",(double)-Btotal/Ktotal); } array = cJSON_CreateArray(); - for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) + /*for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) { if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 ) jaddi(array,linfo_json(&myinfo->linfos[i])); } - jadd(retjson,"quotes",array); + jadd(retjson,"quotes",array);*/ return(jprint(retjson,1)); } diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c new file mode 100644 index 000000000..be1108238 --- /dev/null +++ b/iguana/exchanges/LP_rpc.c @@ -0,0 +1,505 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_rpc.c +// marketmaker +// + +cJSON *basilisk_nullretjson(cJSON *retjson) +{ + char *outstr; + if ( retjson != 0 ) + { + outstr = jprint(retjson,0); + if ( strcmp(outstr,"{}") == 0 ) + { + free_json(retjson); + retjson = 0; + } + free(outstr); + } + return(retjson); +} + +void LP_unspentslock(char *symbol,cJSON *vins) +{ + +} + +void LP_unspents_mark(char *symbol,cJSON *vins) +{ + +} + +uint64_t LP_getestimatedfee(char *symbol) +{ + return(200); +} + +uint64_t LP_txfee(char *symbol) +{ + return(10000); +} + +char *dpow_validateaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *address) +{ + char buf[128],*retstr=0; + if ( coin->FULLNODE < 0 ) + { + sprintf(buf,"\"%s\"",address); + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"validateaddress",buf); + usleep(10000); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + retstr = bitcoinrpc_validateaddress(myinfo,coin,0,0,address); + } + else + { + return(0); + } + return(retstr); +} + +cJSON *dpow_gettxout(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid,int32_t vout) +{ + char buf[128],str[65],*retstr=0; cJSON *json = 0; + sprintf(buf,"\"%s\", %d",bits256_str(str,txid),vout); + if ( coin->FULLNODE < 0 ) + { + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"gettxout",buf); + usleep(10000); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + printf("need to test following call\n"); + retstr = bitcoinrpc_gettxout(myinfo,coin,0,buf,txid,1,0); // untested + } + else + { + return(0); + } + if ( retstr != 0 ) + { + json = cJSON_Parse(retstr); + free(retstr); + } + //printf("dpow_gettxout.(%s)\n",retstr); + return(json); +} + +char *dpow_decoderawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx) +{ + char *retstr,*paramstr; cJSON *array; + if ( coin->FULLNODE < 0 ) + { + array = cJSON_CreateArray(); + jaddistr(array,rawtx); + paramstr = jprint(array,1); + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"decoderawtransaction",paramstr); + //printf("%s decoderawtransaction.(%s) <- (%s)\n",coin->symbol,retstr,paramstr); + free(paramstr); + usleep(10000); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + retstr = bitcoinrpc_decoderawtransaction(myinfo,coin,0,0,rawtx,1); + } + else + { + return(0); + } + return(retstr); +} + +cJSON *dpow_gettransaction(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid) +{ + char buf[128],str[65],*retstr=0; cJSON *json = 0; + if ( coin->FULLNODE < 0 ) + { + sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid)); + if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getrawtransaction",buf)) != 0 ) + { + } + usleep(10000); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + retstr = bitcoinrpc_getrawtransaction(myinfo,coin,0,0,txid,1); + } + else + { + return(0); + } + if ( retstr != 0 ) + { + json = cJSON_Parse(retstr); + free(retstr); + } + return(json); +} + +cJSON *dpow_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr) +{ + char buf[128],*retstr; cJSON *array,*json = 0; + if ( coin->FULLNODE < 0 ) + { + sprintf(buf,"0, 99999999, [\"%s\"]",coinaddr); + if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",buf)) != 0 ) + { + json = cJSON_Parse(retstr); + //printf("%s (%s) listunspent.(%s)\n",coin->symbol,buf,retstr); + free(retstr); + } else printf("%s null retstr from (%s)n",coin->symbol,buf); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + array = cJSON_CreateArray(); + jaddistr(array,coinaddr); + json = iguana_listunspents(myinfo,coin,array,1,coin->longestchain,""); + free_json(array); + } + else + { + return(0); + } + return(json); +} + +cJSON *dpow_listtransactions(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,int32_t count,int32_t skip) +{ + char buf[128],*retstr; cJSON *json = 0; + if ( coin->FULLNODE < 0 ) + { + if ( count == 0 ) + count = 100; + sprintf(buf,"[\"%s\", %d, %d, true]",coinaddr,count,skip); + if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listtransactions",buf)) != 0 ) + { + //printf("LIST.(%s)\n",retstr); + json = cJSON_Parse(retstr); + free(retstr); + return(json); + } else printf("%s null retstr from (%s)n",coin->symbol,buf); + } + return(0); +} + +char *dpow_signrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx,cJSON *vins) +{ + cJSON *array,*privkeys,*item; char *wifstr,*str,*paramstr,*retstr; uint8_t script[256]; int32_t i,n,len,hashtype; struct vin_info V; struct iguana_waddress *waddr; struct iguana_waccount *wacct; + if ( coin->FULLNODE < 0 ) + { + array = cJSON_CreateArray(); + jaddistr(array,rawtx); + jaddi(array,jduplicate(vins)); + paramstr = jprint(array,1); + //printf("signrawtransaction\n"); + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"signrawtransaction",paramstr); + //printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr); + free(paramstr); + usleep(10000); + return(retstr); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + privkeys = cJSON_CreateArray(); + if ( (n= cJSON_GetArraySize(vins)) > 0 ) + { + for (i=0; i 0 && strlen(str) < sizeof(script)*2 ) + { + len = (int32_t)strlen(str) >> 1; + decode_hex(script,len,str); + V.spendlen = len; + memcpy(V.spendscript,script,len); + if ( (hashtype= _iguana_calcrmd160(coin,&V)) >= 0 && V.coinaddr[0] != 0 ) + { + if ( (waddr= iguana_waddresssearch(myinfo,&wacct,V.coinaddr)) != 0 ) + { + if ( bits256_nonz(waddr->privkey) != 0 ) + { + if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->chain->wiftype) > 0 ) + { + wifstr = waddr->wifstr; + } + } + } + } + } + jaddistr(privkeys,wifstr); + } + } + retstr = bitcoinrpc_signrawtransaction(myinfo,coin,0,0,rawtx,vins,privkeys,"ALL"); + printf("call sign.(%s) vins.(%s) privs.(%s) -> (%s)\n",rawtx,jprint(vins,0),jprint(privkeys,0),retstr); + free_json(privkeys); + return(retstr); + } + else + { + return(0); + } +} + +char *dpow_sendrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *signedtx) +{ + bits256 txid; cJSON *json,*array; char *paramstr,*retstr; + if ( coin->FULLNODE < 0 ) + { + array = cJSON_CreateArray(); + jaddistr(array,signedtx); + paramstr = jprint(array,1); + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"sendrawtransaction",paramstr); + printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); + free(paramstr); + return(retstr); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + txid = iguana_sendrawtransaction(myinfo,coin,signedtx); + json = cJSON_CreateObject(); + jaddbits256(json,"result",txid); + return(jprint(json,1)); + } + else + { + return(0); + } +} + +char *LP_importaddress(char *symbol,char *address) +{ + char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; + if ( (retstr= LP_validateaddress(symbol,address)) != 0 ) + { + if ( (validatejson= cJSON_Parse(retstr)) != 0 ) + { + if ( (isvalid= is_cJSON_True(jobj(validatejson,"isvalid")) != 0) != 0 ) + { + if ( is_cJSON_True(jobj(validatejson,"iswatchonly")) != 0 || is_cJSON_True(jobj(validatejson,"ismine")) != 0 ) + doneflag = 1; + } + free_json(validatejson); + } + free(retstr); + retstr = 0; + } + if ( isvalid == 0 ) + return(clonestr("{\"isvalid\":false}")); + update_alladdresses(myinfo,coin,address); + if ( doneflag != 0 ) + return(0); // success + if ( coin->FULLNODE < 0 ) + { + sprintf(buf,"[\"%s\", \"%s\", false]",address,address); + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"importaddress",buf); + printf("%s importaddress.(%s) -> (%s)\n",coin->symbol,address,retstr); + return(retstr); + } + else return(0); +} + +char *LP_importaddress(char *symbol,char *coinaddr) +{ + return(0); +} + +char *LP_sendrawtransaction(char *symbol,char *signedtx) +{ + return(0); +} + +char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtxbytes,cJSON *privkeys,struct vin_info *V) +{ + return(0); +} + +cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) +{ + return(0); +} + +char *dex_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) +{ + return(0); +} + +bits256 LP_privkey(char *coinaddr) +{ + bits256 privkey; + return(privkey); +} + +bits256 LP_pubkey(bits256 privkey) +{ + bits256 pubkey; + pubkey = curve25519(privkey,curve25519_basepoint9()); + return(pubkey); +} + +cJSON *LP_swapgettxout(char *symbol,bits256 trigger,int32_t vout) +{ + cJSON *retjson=0; //char *retstr; struct iguana_info *coin; + /*if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 ) + { + if ( (retstr= dex_gettxout(0,0,0,trigger,symbol,vout)) != 0 ) + { + //printf("dexgettxout.(%s)\n",retstr); + retjson = cJSON_Parse(retstr); + free(retstr); + } + if ( 0 && strcmp("BTC",symbol) == 0 ) + printf("%s gettxout.(%s)\n",symbol,jprint(retjson,0)); + } + else + { + retjson = dpow_gettxout(coin,trigger,vout); + //printf("need to verify passthru has this info\n"); + //printf("dpowgettxout.(%s)\n",jprint(retjson,0)); + }*/ + return(basilisk_nullretjson(retjson)); +} + +uint64_t LP_txvalue(char *symbol,bits256 txid,int32_t vout) +{ + uint64_t value = 0; + return(value); +} + +cJSON *LP_swapgettx(char *symbol,bits256 txid) +{ + cJSON *retjson=0; //char *retstr; struct iguana_info *coin; + /*if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 ) + { + if ( (retstr= dex_gettransaction(0,0,0,txid,symbol)) != 0 ) + { + retjson = cJSON_Parse(retstr); + free(retstr); + } + //if ( strcmp("BTC",symbol) == 0 ) + // printf("%s gettx.(%s)\n",symbol,jprint(retjson,0)); + } else retjson = dpow_gettransaction(coin,txid);*/ + return(basilisk_nullretjson(retjson)); +} + +bits256 basilisk_swap_sendrawtransaction(char *txname,char *symbol,char *txbytes) +{ + char *retstr; bits256 txid; int32_t i,sentflag = 0; + memset(&txid,0,sizeof(txid)); + for (i=0; i<3; i++) + { + if ( (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) + { + if ( is_hexstr(retstr,0) == 64 ) + { + decode_hex(txid.bytes,32,retstr); + sentflag = 1; + } + char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid)); + free(retstr); + } + if ( sentflag != 0 ) + break; + } + return(txid); +} + +bits256 LP_broadcast(char *name,char *symbol,uint8_t *data,int32_t datalen) +{ + bits256 txid; char *signedtx,*retstr; int32_t i; + memset(txid.bytes,0,sizeof(txid)); + if ( data != 0 && datalen != 0 ) + { + char str[65]; +#ifdef BASILISK_DISABLESENDTX + txid = bits256_doublesha256(0,data,datalen); + printf("%s <- dont sendrawtransaction (%s)\n",name,bits256_str(str,txid)); + return(txid); +#endif + signedtx = malloc(datalen*2 + 1); + init_hexbytes_noT(signedtx,data,datalen); + for (i=0; i<3; i++) + { + if ( (retstr= LP_sendrawtransaction(symbol,signedtx)) != 0 ) + { + if ( is_hexstr(retstr,0) == 64 ) + { + decode_hex(txid.bytes,32,retstr); + free(retstr); + printf("sendrawtransaction.%s %s.(%s)\n",name,symbol,bits256_str(str,txid)); + break; + } + else + { + printf("sendrawtransaction.%s %s error.(%s)\n",name,symbol,retstr); + free(retstr); + } + } else printf("sendrawtransaction.%s %s got null return\n",name,symbol); + } + free(signedtx); + } + return(txid); +} + +int32_t basilisk_confirmsobj(cJSON *item) +{ + int32_t height,numconfirms; + height = jint(item,"height"); + numconfirms = jint(item,"numconfirms"); + if ( height > 0 && numconfirms >= 0 ) + return(numconfirms); + printf("basilisk_confirmsobj height.%d numconfirms.%d (%s)\n",height,numconfirms,jprint(item,0)); + return(-1); +} + +int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) +{ +#ifdef BASILISK_DISABLEWAITTX + return(100); +#endif + /*cJSON *argjson,*valuearray=0; char *valstr; int32_t i,n,retval = -1; + argjson = cJSON_CreateObject(); + jaddbits256(argjson,"txid",rawtx->I.actualtxid); + jaddnum(argjson,"vout",0); + jaddstr(argjson,"coin",rawtx->coin->symbol); + if ( (valstr= basilisk_value(rawtx->coin,0,0,swap->persistent_pubkey,argjson,0)) != 0 ) + { + char str[65]; printf("basilisk_numconfirms required.%d %s %s valstr.(%s)\n",rawtx->I.numconfirms,rawtx->name,bits256_str(str,rawtx->I.actualtxid),valstr); + //basilisk_numconfirms required.0 alicespend 29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85 valstr.({"result":"success","numconfirms":0,"address":"1JGvZ67oTdM7kCya4J8kj1uErbSRAoq3wH","satoshis":"1413818","value":0.01413818,"height":462440,"txid":"29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85","vout":0,"coin":"BTC"}) + + if ( (valuearray= cJSON_Parse(valstr)) != 0 ) + { + if ( valstr[0] == '[' && is_cJSON_Array(valuearray) != 0 ) + { + n = cJSON_GetArraySize(valuearray); + for (i=0; i= 0 ) + break; + } + } else retval = basilisk_confirmsobj(valuearray); + free_json(valuearray); + } else printf("parse error\n"); + free(valstr); + } + free_json(argjson); + printf("numconfirms.%d returned\n",retval); + return(retval);*/ +} diff --git a/iguana/exchanges/LP_secp.c b/iguana/exchanges/LP_secp.c new file mode 100644 index 000000000..7d4409911 --- /dev/null +++ b/iguana/exchanges/LP_secp.c @@ -0,0 +1,186 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_secp.c +// marketmaker +// + + +#include +#include +#include +#include +#include "../../includes/curve25519.h" +#include "../secp256k1/include/secp256k1.h" +#include "../secp256k1/include/secp256k1_ecdh.h" +#include "../secp256k1/include/secp256k1_schnorr.h" +#include "../secp256k1/include/secp256k1_rangeproof.h" +#include "../secp256k1/include/secp256k1_recovery.h" + +SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; + +#define bits256_nonz(a) (((a).ulongs[0] | (a).ulongs[1] | (a).ulongs[2] | (a).ulongs[3]) != 0) + +#define SECP_ENSURE_CTX int32_t flag = 0; if ( ctx == 0 ) { ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); secp256k1_pedersen_context_initialize(ctx); secp256k1_rangeproof_context_initialize(ctx); flag++; } else flag = 0; if ( ctx != 0 ) +#define ENDSECP_ENSURE_CTX if ( flag != 0 ) secp256k1_context_destroy(ctx); + +void *bitcoin_ctx() +{ + void *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + secp256k1_pedersen_context_initialize(ctx); + secp256k1_rangeproof_context_initialize(ctx); + return(ctx); +} + +bits256 bitcoin_pubkey33(void *ctx,uint8_t *data,bits256 privkey) +{ + size_t plen; bits256 pubkey; secp256k1_pubkey secppub; + memset(pubkey.bytes,0,sizeof(pubkey)); + SECP_ENSURE_CTX + { + if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 ) + { + //printf("bitcoin_sign illegal privkey\n"); + return(pubkey); + } + if ( secp256k1_ec_pubkey_create(ctx,&secppub,privkey.bytes) != 0 ) + { + plen = 33; + secp256k1_ec_pubkey_serialize(ctx,data,&plen,&secppub,SECP256K1_EC_COMPRESSED); + if ( plen == 33 ) + memcpy(pubkey.bytes,data+1,sizeof(pubkey)); + } + ENDSECP_ENSURE_CTX + } + return(pubkey); +} + +bits256 bitcoin_pub256(void *ctx,bits256 *privkeyp,uint8_t odd_even) +{ + bits256 pub256; uint8_t pubkey[33]; int32_t i; + for (i=0; i<100; i++) + { + *privkeyp = rand256(0); + pub256 = bitcoin_pubkey33(ctx,pubkey,*privkeyp); + if ( pubkey[0] == odd_even+2 ) + return(pub256); + } + printf("bitcoin_pub256 couldnt generate pubkey.%d\n",odd_even+2); + memset(pub256.bytes,0,sizeof(pub256)); + return(pub256); +} + +int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag) +{ + int32_t fCompressed = 1; + secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB; + seed = rand256(0); + extra_entropy = rand256(0); + SECP_ENSURE_CTX + { + if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 ) + { + //printf("bitcoin_sign illegal privkey\n"); + return(-1); + } + if ( secp256k1_context_randomize(ctx,seed.bytes) != 0 ) + { + if ( recoverflag != 0 ) + { + if ( secp256k1_ecdsa_sign_recoverable(ctx,&rSIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 ) + { + recid = -1; + secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx,sig+1,&recid,&rSIG); + if ( secp256k1_ecdsa_recover(ctx,&SECPUB,&rSIG,txhash2.bytes) != 0 ) + { + if ( secp256k1_ec_pubkey_create(ctx,&CHECKPUB,privkey.bytes) != 0 ) + { + if ( memcmp(&SECPUB,&CHECKPUB,sizeof(SECPUB)) == 0 ) + { + sig[0] = 27 + recid + (fCompressed != 0 ? 4 : 0); + retval = 64 + 1; + //size_t i,plen = 33; uint8_t pubkey[33]; + //secp256k1_ec_pubkey_serialize(ctx,pubkey,&plen,&CHECKPUB,SECP256K1_EC_COMPRESSED); + //for (i=0; i<33; i++) + // printf("%02x",pubkey[i]); + //printf(" bitcoin_sign's pubkey\n"); + + } //else printf("secpub mismatch\n"); + } else printf("pubkey create error\n"); + } //else printf("recover error\n"); + } else printf("secp256k1_ecdsa_sign_recoverable error\n"); + } + else + { + if ( secp256k1_ecdsa_sign(ctx,&SIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 ) + { + if ( secp256k1_ecdsa_signature_serialize_der(ctx,sig,&siglen,&SIG) != 0 ) + retval = (int32_t)siglen; + } + } + } + ENDSECP_ENSURE_CTX + } + return(retval); +} + +int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig,bits256 messagehash2,uint8_t *pubkey,size_t plen) +{ + int32_t retval = -1; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; + pubkey[0] = 0; + SECP_ENSURE_CTX + { + if ( plen == 0 ) + { + plen = (sig[0] <= 31) ? 65 : 33; + sig++; + } + secp256k1_ecdsa_recoverable_signature_parse_compact(ctx,&rSIG,sig,0); + secp256k1_ecdsa_recoverable_signature_convert(ctx,&SIG,&rSIG); + if ( secp256k1_ecdsa_recover(ctx,&PUB,&rSIG,messagehash2.bytes) != 0 ) + { + plen = 33; + memset(pubkey,0,33); + secp256k1_ec_pubkey_serialize(ctx,pubkey,&plen,&PUB,SECP256K1_EC_COMPRESSED);//plen == 65 ? SECP256K1_EC_UNCOMPRESSED : SECP256K1_EC_COMPRESSED); + if ( secp256k1_ecdsa_verify(ctx,&SIG,messagehash2.bytes,&PUB) != 0 ) + { + retval = 0; + /*if ( pubkey[0] == 4 ) // experimentally looks like 04 is set + pubkey[0] = 2; + else if ( pubkey[0] != 2 ) + pubkey[0] = 3;*/ + } else printf("secp256k1_ecdsa_verify error\n"); + } else printf("secp256k1_ecdsa_recover error\n"); + ENDSECP_ENSURE_CTX + } + return(retval); +} + +int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen) +{ + int32_t retval = -1; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; + SECP_ENSURE_CTX + { + if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) != 0 ) + { + secp256k1_ecdsa_signature_parse_der(ctx,&SIG,sig,siglen); + if ( secp256k1_ecdsa_verify(ctx,&SIG,txhash2.bytes,&PUB) != 0 ) + retval = 0; + } + ENDSECP_ENSURE_CTX + } + return(retval); +} diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c new file mode 100644 index 000000000..4cb663b99 --- /dev/null +++ b/iguana/exchanges/LP_statemachine.c @@ -0,0 +1,558 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_statemachine.c +// marketmaker +// + +int32_t basilisk_process_swapverify(void *ptr,int32_t (*internal_func)(void *ptr,uint8_t *data,int32_t datalen),uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t expiration,uint32_t duration) +{ + struct basilisk_swap *swap = ptr; + if ( internal_func != 0 ) + return((*internal_func)(swap,data,datalen)); + else return(0); +} + + + +int32_t basilisk_priviextract(struct iguana_info *coin,char *name,bits256 *destp,uint8_t secret160[20],bits256 srctxid,int32_t srcvout) +{ + /*bits256 txid; char str[65]; int32_t i,vini,scriptlen; uint8_t rmd160[20],scriptsig[IGUANA_MAXSCRIPTSIZE]; + memset(privkey.bytes,0,sizeof(privkey)); + // use dex_listtransactions! + if ( (vini= iguana_vinifind(coin,&txid,srctxid,srcvout)) >= 0 ) + { + if ( (scriptlen= iguana_scriptsigextract(coin,scriptsig,sizeof(scriptsig),txid,vini)) > 32 ) + { + for (i=0; i<32; i++) + privkey.bytes[i] = scriptsig[scriptlen - 33 + i]; + revcalc_rmd160_sha256(rmd160,privkey);//.bytes,sizeof(privkey)); + if ( memcmp(secret160,rmd160,sizeof(rmd160)) == sizeof(rmd160) ) + { + *destp = privkey; + printf("basilisk_priviextract found privi %s (%s)\n",name,bits256_str(str,privkey)); + return(0); + } + } + }*/ + return(-1); +} +int32_t basilisk_verify_privi(void *ptr,uint8_t *data,int32_t datalen); + +int32_t basilisk_privBn_extract(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +{ + if ( basilisk_priviextract(&swap->bobcoin,"privBn",&swap->I.privBn,swap->I.secretBn,swap->bobrefund.I.actualtxid,0) == 0 ) + { + printf("extracted privBn from blockchain\n"); + } + else if ( basilisk_swapget(swap,0x40000000,data,maxlen,basilisk_verify_privi) == 0 ) + { + } + if ( bits256_nonz(swap->I.privBn) != 0 && swap->alicereclaim.I.datalen == 0 ) + { + char str[65]; printf("got privBn.%s\n",bits256_str(str,swap->I.privBn)); + return(basilisk_alicepayment_spend(swap,&swap->alicereclaim)); + } + return(-1); +} + +int32_t basilisk_privAm_extract(struct basilisk_swap *swap) +{ + if ( basilisk_priviextract(&swap->bobcoin,"privAm",&swap->I.privAm,swap->I.secretAm,swap->bobpayment.I.actualtxid,0) == 0 ) + { + printf("extracted privAm from blockchain\n"); + } + if ( bits256_nonz(swap->I.privAm) != 0 && swap->bobspend.I.datalen == 0 ) + { + char str[65]; printf("got privAm.%s\n",bits256_str(str,swap->I.privAm)); + return(basilisk_alicepayment_spend(swap,&swap->bobspend)); + } + return(-1); +} + +int32_t basilisk_verify_otherstatebits(void *ptr,uint8_t *data,int32_t datalen) +{ + int32_t retval; struct basilisk_swap *swap = ptr; + if ( datalen == sizeof(swap->I.otherstatebits) ) + { + retval = iguana_rwnum(0,data,sizeof(swap->I.otherstatebits),&swap->I.otherstatebits); + return(retval); + } else return(-1); +} + +int32_t basilisk_verify_statebits(void *ptr,uint8_t *data,int32_t datalen) +{ + int32_t retval = -1; uint32_t statebits; struct basilisk_swap *swap = ptr; + if ( datalen == sizeof(swap->I.statebits) ) + { + retval = iguana_rwnum(0,data,sizeof(swap->I.statebits),&statebits); + if ( statebits != swap->I.statebits ) + { + printf("statebits.%x != %x\n",statebits,swap->I.statebits); + return(-1); + } + } + return(retval); +} + +void basilisk_sendstate(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +{ + int32_t datalen=0; + datalen = iguana_rwnum(1,data,sizeof(swap->I.statebits),&swap->I.statebits); + LP_swapsend(swap,0x80000000,data,datalen,0,0); +} + +int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +{ + int32_t j,datalen,retval = 0; uint32_t savestatebits=0,saveotherbits=0; + if ( swap->I.iambob != 0 ) + swap->I.statebits |= 0x80; + while ( swap->aborted == 0 && ((swap->I.otherstatebits & 0x80) == 0 || (swap->I.statebits & 0x80) == 0) && retval == 0 && time(NULL) < swap->I.expiration ) + { + if ( swap->connected == 0 ) + basilisk_psockinit(swap,swap->I.iambob != 0); + printf("D r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL))); + if ( swap->I.iambob != 0 && (swap->I.statebits & 0x80) == 0 ) // wait for fee + { + if ( basilisk_swapget(swap,0x80,data,maxlen,basilisk_verify_otherfee) == 0 ) + { + // verify and submit otherfee + swap->I.statebits |= 0x80; + basilisk_sendstate(swap,data,maxlen); + } + } + else if ( swap->I.iambob == 0 ) + swap->I.statebits |= 0x80; + basilisk_sendstate(swap,data,maxlen); + basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + if ( (swap->I.otherstatebits & 0x80) != 0 && (swap->I.statebits & 0x80) != 0 ) + break; + if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) + sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); + savestatebits = swap->I.statebits; + saveotherbits = swap->I.otherstatebits; + basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + basilisk_sendstate(swap,data,maxlen); + if ( (swap->I.otherstatebits & 0x80) == 0 ) + LP_swapdata_rawtxsend(swap,0x80,data,maxlen,&swap->myfee,0x40,0); + } + basilisk_swap_saveupdate(swap); + while ( swap->aborted == 0 && retval == 0 && time(NULL) < swap->I.expiration ) // both sides have setup required data and paid txfee + { + basilisk_swap_saveupdate(swap); + if ( swap->connected == 0 ) + basilisk_psockinit(swap,swap->I.iambob != 0); + //if ( (rand() % 30) == 0 ) + printf("E r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL))); + if ( swap->I.iambob != 0 ) + { + //printf("BOB\n"); + if ( (swap->I.statebits & 0x100) == 0 ) + { + printf("send bobdeposit\n"); + swap->I.statebits |= LP_swapdata_rawtxsend(swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0); + } + // [BLOCKING: altfound] make sure altpayment is confirmed and send payment + else if ( (swap->I.statebits & 0x1000) == 0 ) + { + printf("check alicepayment\n"); + if ( basilisk_swapget(swap,0x1000,data,maxlen,basilisk_verify_alicepaid) == 0 ) + { + swap->I.statebits |= 0x1000; + printf("got alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms); + } + } + else if ( (swap->I.statebits & 0x2000) == 0 ) + { + if ( (swap->I.aliceconfirms == 0 && swap->aliceunconf != 0) || LP_numconfirms(swap,&swap->alicepayment) >= swap->I.aliceconfirms ) + { + swap->I.statebits |= 0x2000; + printf("alicepayment confirmed\n"); + } + } + else if ( (swap->I.statebits & 0x4000) == 0 ) + { + basilisk_bobscripts_set(swap,0,1); + printf("send bobpayment\n"); + swap->I.statebits |= LP_swapdata_rawtxsend(swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0); + } + // [BLOCKING: privM] Bob waits for privAm either from Alice or alice blockchain + else if ( (swap->I.statebits & 0xc0000) != 0xc0000 ) + { + if ( basilisk_swapget(swap,0x40000,data,maxlen,basilisk_verify_privi) == 0 || basilisk_privAm_extract(swap) == 0 ) // divulges privAm + { + //printf("got privi spend alicepayment, dont divulge privBn until bobspend propagated\n"); + basilisk_alicepayment_spend(swap,&swap->bobspend); + if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->bobspend,0x40000,1) == 0 ) + printf("Bob error spending alice payment\n"); + else + { + tradebot_swap_balancingtrade(swap,1); + printf("Bob spends alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms); + swap->I.statebits |= 0x40000; + if ( LP_numconfirms(swap,&swap->bobspend) >= swap->I.aliceconfirms ) + { + printf("bobspend confirmed\n"); + swap->I.statebits |= 0x80000; + printf("Bob confirming spend of Alice's payment\n"); + sleep(DEX_SLEEP); + } + retval = 1; + } + } + } + if ( swap->bobpayment.I.locktime != 0 && time(NULL) > swap->bobpayment.I.locktime ) + { + // submit reclaim of payment + printf("bob reclaims bobpayment\n"); + swap->I.statebits |= (0x40000 | 0x80000); + if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->bobreclaim,0,0) == 0 ) + printf("Bob error reclaiming own payment after alice timed out\n"); + else + { + printf("Bob reclaimed own payment\n"); + while ( 0 && (swap->I.statebits & 0x100000) == 0 ) // why wait for own tx? + { + if ( LP_numconfirms(swap,&swap->bobreclaim) >= 1 ) + { + printf("bobreclaim confirmed\n"); + swap->I.statebits |= 0x100000; + printf("Bob confirms reclain of payment\n"); + break; + } + } + retval = 1; + } + } + } + else + { + //printf("ALICE\n"); + // [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment + if ( (swap->I.statebits & 0x200) == 0 ) + { + printf("checkfor deposit\n"); + if ( basilisk_swapget(swap,0x200,data,maxlen,basilisk_verify_bobdeposit) == 0 ) + { + // verify deposit and submit, set confirmed height + printf("got bobdeposit\n"); + swap->I.statebits |= 0x200; + } else printf("no valid deposit\n"); + } + else if ( (swap->I.statebits & 0x400) == 0 ) + { + if ( basilisk_istrustedbob(swap) != 0 || (swap->I.bobconfirms == 0 && swap->depositunconf != 0) || LP_numconfirms(swap,&swap->bobdeposit) >= swap->I.bobconfirms ) + { + printf("bobdeposit confirmed\n"); + swap->I.statebits |= 0x400; + } + } + else if ( (swap->I.statebits & 0x800) == 0 ) + { + printf("send alicepayment\n"); + swap->I.statebits |= LP_swapdata_rawtxsend(swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0); + } + // [BLOCKING: payfound] make sure payment is confrmed and send in spend or see bob's reclaim and claim + else if ( (swap->I.statebits & 0x8000) == 0 ) + { + if ( basilisk_swapget(swap,0x8000,data,maxlen,basilisk_verify_bobpaid) == 0 ) + { + printf("got bobpayment\n"); + tradebot_swap_balancingtrade(swap,0); + // verify payment and submit, set confirmed height + swap->I.statebits |= 0x8000; + } + } + else if ( (swap->I.statebits & 0x10000) == 0 ) + { + if ( basilisk_istrustedbob(swap) != 0 || (swap->I.bobconfirms == 0 && swap->paymentunconf != 0) || LP_numconfirms(swap,&swap->bobpayment) >= swap->I.bobconfirms ) + { + printf("bobpayment confirmed\n"); + swap->I.statebits |= 0x10000; + } + } + else if ( (swap->I.statebits & 0x20000) == 0 ) + { + printf("alicespend bobpayment\n"); + if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->alicespend,0x20000,0) != 0 )//&& (swap->aliceunconf != 0 || basilisk_numconfirms(swap,&swap->alicespend) > 0) ) + { + swap->I.statebits |= 0x20000; + } + } + else if ( (swap->I.statebits & 0x40000) == 0 ) + { + int32_t numconfs; + if ( (numconfs= LP_numconfirms(swap,&swap->alicespend)) >= swap->I.bobconfirms ) + { + for (j=datalen=0; j<32; j++) + data[datalen++] = swap->I.privAm.bytes[j]; + printf("send privAm %x\n",swap->I.statebits); + swap->I.statebits |= LP_swapsend(swap,0x40000,data,datalen,0x20000,swap->I.crcs_mypriv); + printf("Alice confirms spend of Bob's payment\n"); + retval = 1; + } else printf("alicespend numconfs.%d < %d\n",numconfs,swap->I.bobconfirms); + } + if ( swap->bobdeposit.I.locktime != 0 && time(NULL) > swap->bobdeposit.I.locktime ) + { + printf("Alice claims deposit\n"); + if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->aliceclaim,0,0) == 0 ) + printf("Alice couldnt claim deposit\n"); + else + { + printf("Alice claimed deposit\n"); + retval = 1; + } + } + else if ( swap->aborted != 0 || basilisk_privBn_extract(swap,data,maxlen) == 0 ) + { + printf("Alice reclaims her payment\n"); + swap->I.statebits |= 0x40000000; + if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->alicereclaim,0x40000000,0) == 0 ) + printf("Alice error sending alicereclaim\n"); + else + { + printf("Alice reclaimed her payment\n"); + retval = 1; + } + } + } + if ( (rand() % 30) == 0 ) + printf("finished swapstate.%x other.%x\n",swap->I.statebits,swap->I.otherstatebits); + if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) + sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); + savestatebits = swap->I.statebits; + saveotherbits = swap->I.otherstatebits; + basilisk_sendstate(swap,data,maxlen); + basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + } + return(retval); +} + +int32_t swapcompleted(struct basilisk_swap *swap) +{ + if ( swap->I.iambob != 0 ) + return(swap->I.bobspent); + else return(swap->I.alicespent); +} + +cJSON *swapjson(struct basilisk_swap *swap) +{ + cJSON *retjson = cJSON_CreateObject(); + return(retjson); +} + +int32_t basilisk_rwDEXquote(int32_t rwflag,uint8_t *serialized,struct basilisk_request *rp) +{ + int32_t len = 0; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->requestid),&rp->requestid); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->timestamp),&rp->timestamp); // must be 2nd + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->quoteid),&rp->quoteid); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->quotetime),&rp->quotetime); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->optionhours),&rp->optionhours); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->srcamount),&rp->srcamount); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->unused),&rp->unused); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(rp->srchash),rp->srchash.bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(rp->desthash),rp->desthash.bytes); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->destamount),&rp->destamount); + if ( rwflag != 0 ) + { + memcpy(&serialized[len],rp->src,sizeof(rp->src)), len += sizeof(rp->src); + memcpy(&serialized[len],rp->dest,sizeof(rp->dest)), len += sizeof(rp->dest); + } + else + { + memcpy(rp->src,&serialized[len],sizeof(rp->src)), len += sizeof(rp->src); + memcpy(rp->dest,&serialized[len],sizeof(rp->dest)), len += sizeof(rp->dest); + } + //len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->DEXselector),&rp->DEXselector); + //len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->extraspace),&rp->extraspace); + if ( rp->quoteid != 0 && basilisk_quoteid(rp) != rp->quoteid ) + printf(" basilisk_rwDEXquote.%d: quoteid.%u mismatch calc %u rp.%p\n",rwflag,rp->quoteid,basilisk_quoteid(rp),rp); + if ( basilisk_requestid(rp) != rp->requestid ) + printf(" basilisk_rwDEXquote.%d: requestid.%u mismatch calc %u rp.%p\n",rwflag,rp->requestid,basilisk_requestid(rp),rp); + return(len); +} + +struct basilisk_request *basilisk_parsejson(struct basilisk_request *rp,cJSON *reqjson) +{ + uint32_t requestid,quoteid; + memset(rp,0,sizeof(*rp)); + rp->srchash = jbits256(reqjson,"srchash"); + rp->desthash = jbits256(reqjson,"desthash"); + rp->srcamount = j64bits(reqjson,"srcamount"); + //rp->minamount = j64bits(reqjson,"minamount"); + //rp->destamount = j64bits(reqjson,"destamount"); + rp->destamount = j64bits(reqjson,"destsatoshis"); + //printf("parse DESTSATOSHIS.%llu (%s)\n",(long long)rp->destamount,jprint(reqjson,0)); + requestid = juint(reqjson,"requestid"); + quoteid = juint(reqjson,"quoteid"); + //if ( jstr(reqjson,"relay") != 0 ) + // rp->relaybits = (uint32_t)calc_ipbits(jstr(reqjson,"relay")); + rp->timestamp = juint(reqjson,"timestamp"); + rp->quotetime = juint(reqjson,"quotetime"); + safecopy(rp->src,jstr(reqjson,"src"),sizeof(rp->src)); + safecopy(rp->dest,jstr(reqjson,"dest"),sizeof(rp->dest)); + if ( quoteid != 0 ) + { + rp->quoteid = basilisk_quoteid(rp); + if ( quoteid != rp->quoteid ) + printf("basilisk_parsejson quoteid.%u != %u error\n",quoteid,rp->quoteid); + } + rp->requestid = basilisk_requestid(rp); + if ( requestid != rp->requestid ) + { + int32_t i; for (i=0; irequestid); + } + return(rp); +} + +cJSON *basilisk_requestjson(struct basilisk_request *rp) +{ + cJSON *item = cJSON_CreateObject(); + /*if ( rp->relaybits != 0 ) + { + expand_ipbits(ipaddr,rp->relaybits); + jaddstr(item,"relay",ipaddr); + }*/ + jaddbits256(item,"srchash",rp->srchash); + if ( bits256_nonz(rp->desthash) != 0 ) + jaddbits256(item,"desthash",rp->desthash); + jaddstr(item,"src",rp->src); + if ( rp->srcamount != 0 ) + jadd64bits(item,"srcamount",rp->srcamount); + //if ( rp->minamount != 0 ) + // jadd64bits(item,"minamount",rp->minamount); + jaddstr(item,"dest",rp->dest); + if ( rp->destamount != 0 ) + { + //jadd64bits(item,"destamount",rp->destamount); + jadd64bits(item,"destsatoshis",rp->destamount); + //printf("DESTSATOSHIS.%llu\n",(long long)rp->destamount); + } + jaddnum(item,"quotetime",rp->quotetime); + jaddnum(item,"timestamp",rp->timestamp); + jaddnum(item,"requestid",rp->requestid); + jaddnum(item,"quoteid",rp->quoteid); + //jaddnum(item,"DEXselector",rp->DEXselector); + jaddnum(item,"optionhours",rp->optionhours); + //jaddnum(item,"profit",(double)rp->profitmargin / 1000000.); + if ( rp->quoteid != 0 && basilisk_quoteid(rp) != rp->quoteid ) + printf("quoteid mismatch %u vs %u\n",basilisk_quoteid(rp),rp->quoteid); + if ( basilisk_requestid(rp) != rp->requestid ) + printf("requestid mismatch %u vs calc %u\n",rp->requestid,basilisk_requestid(rp)); + { + int32_t i; struct basilisk_request R; + if ( basilisk_parsejson(&R,item) != 0 ) + { + if ( memcmp(&R,rp,sizeof(*rp)-sizeof(uint32_t)) != 0 ) + { + for (i=0; iI.req.requestid); + jaddnum(item,"quoteid",swap->I.req.quoteid); + jaddnum(item,"state",swap->I.statebits); + jaddnum(item,"otherstate",swap->I.otherstatebits); + jadd(item,"request",basilisk_requestjson(&swap->I.req)); + return(item); +} + +#ifdef later + +cJSON *basilisk_privkeyarray(struct iguana_info *coin,cJSON *vins) +{ + cJSON *privkeyarray,*item,*sobj; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],account[128],wifstr[64],str[65],typestr[64],*hexstr; uint8_t script[1024]; int32_t i,n,len,vout; bits256 txid,privkey; double bidasks[2]; + privkeyarray = cJSON_CreateArray(); + //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr); + if ( (n= cJSON_GetArraySize(vins)) > 0 ) + { + for (i=0; i= 0 ) + { + iguana_txidcategory(coin,account,coinaddr,txid,vout); + if ( coinaddr[0] == 0 && (sobj= jobj(item,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && is_hexstr(hexstr,0) > 0 ) + { + len = (int32_t)strlen(hexstr) >> 1; + if ( len < (sizeof(script) << 1) ) + { + decode_hex(script,len,hexstr); + if ( len == 25 && script[0] == 0x76 && script[1] == 0xa9 && script[2] == 0x14 ) + bitcoin_address(coinaddr,coin->chain->pubtype,script+3,20); + } + } + if ( coinaddr[0] != 0 ) + { + if ( (waddr= iguana_waddresssearch(&wacct,coinaddr)) != 0 ) + { + bitcoin_priv2wif(wifstr,waddr->privkey,coin->chain->wiftype); + jaddistr(privkeyarray,waddr->wifstr); + } + else if ( smartaddress(typestr,bidasks,&privkey,coin->symbol,coinaddr) >= 0 ) + { + bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype); + jaddistr(privkeyarray,wifstr); + } + else printf("cant find (%s) in wallet\n",coinaddr); + } else printf("cant coinaddr from (%s).v%d\n",bits256_str(str,txid),vout); + } else printf("invalid txid/vout %d of %d\n",i,n); + } + } + return(privkeyarray); +} + + +#endif + + +/*void basilisk_swap_purge(struct basilisk_swap *swap) + { + int32_t i,n; + // while still in orderbook, wait + //return; + portable_mutex_lock(&myinfo->DEX_swapmutex); + n = myinfo->numswaps; + for (i=0; iswaps[i] == swap ) + { + myinfo->swaps[i] = myinfo->swaps[--myinfo->numswaps]; + myinfo->swaps[myinfo->numswaps] = 0; + basilisk_swap_finished(swap); + break; + } + portable_mutex_unlock(&myinfo->DEX_swapmutex); + }*/ diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 5df4a6b86..2a1d96bef 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -22,17 +22,15 @@ make sure to broadcast deposit before claiming refund, or to just skip it if neither is done */ -#define DEX_SLEEP 10 -#define BASILISK_DEFAULT_NUMCONFIRMS 5 // Todo: monitor blockchains, ie complete extracting scriptsig // mode to autocreate required outputs // more better LP commands // depends on just three external functions: -// - basilisk_sendrawtransaction(myinfo,coin,signedtx); -// - basilisk_value(myinfo,rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0) -// basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V) +// - basilisk_sendrawtransaction(coin,signedtx); +// - basilisk_value(rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0) +// basilisk_bitcoinrawtx(rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V) // included from basilisk.c @@ -120,1209 +118,33 @@ */ -int32_t basilisk_istrustedbob(struct supernet_info *myinfo,struct basilisk_swap *swap) -{ - // for BTC and if trusted LP - return(0); -} - -struct basilisk_rawtx *basilisk_swapdata_rawtx(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx) -{ - if ( rawtx->I.datalen != 0 && rawtx->I.datalen <= maxlen ) - { - memcpy(data,rawtx->txbytes,rawtx->I.datalen); - return(rawtx); - } - return(0); -} - -int32_t basilisk_verify_otherfee(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - struct basilisk_swap *swap = ptr; - // add verification and broadcast - //swap->otherfee.txbytes = calloc(1,datalen); - memcpy(swap->otherfee.txbytes,data,datalen); - swap->otherfee.I.datalen = datalen; - swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen); - basilisk_txlog(myinfo,swap,&swap->otherfee,-1); - return(0); -} - -int32_t basilisk_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) -{ - int32_t datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr; bits256 txid; - datalen = recvbuf[0]; - datalen += (int32_t)recvbuf[1] << 8; - if ( datalen > 65536 ) - return(-1); - rawtx->I.redeemlen = recvbuf[2]; - data = &recvbuf[3]; - if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) - memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); - //printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen); - if ( rawtx->I.datalen == 0 ) - { - //rawtx->txbytes = calloc(1,datalen); - memcpy(rawtx->txbytes,data,datalen); - rawtx->I.datalen = datalen; - } - else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 ) - { - int32_t i; for (i=0; iI.datalen; i++) - printf("%02x",rawtx->txbytes[i]); - printf(" <- rawtx\n"); - printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen); - return(-1); - } - txid = bits256_doublesha256(0,data,datalen); - char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); - if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) - rawtx->I.actualtxid = txid; - if ( (txobj= bitcoin_data2json(rawtx->coin,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) - { - rawtx->I.actualtxid = rawtx->I.signedtxid; - //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,rawtx->signedtxid),jprint(txobj,0)); - rawtx->I.locktime = rawtx->msgtx.lock_time; - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) - { - vout = jitem(vouts,v); - if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) - { - if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) - { - decode_hex(rawtx->spendscript,hexlen,hexstr); - rawtx->I.spendlen = hexlen; - bitcoin_address(rawtx->p2shaddr,rawtx->coin->chain->p2shtype,rawtx->spendscript,hexlen); - if ( swap != 0 ) - basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment - retval = 0; - } - } else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0)); - } - free_json(txobj); - } - return(retval); -} - -void basilisk_swap_coinaddr(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen) -{ - cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0; - if ( (txobj= bitcoin_data2json(coin,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) - { - //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,signedtxid),jprint(txobj,0)); - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) - { - vout = jitem(vouts,0); - //printf("VOUT.(%s)\n",jprint(vout,0)); - if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) - { - item = jitem(addresses,0); - //printf("item.(%s)\n",jprint(item,0)); - if ( (addr= jstr(item,0)) != 0 ) - { - safecopy(coinaddr,addr,64); - //printf("extracted.(%s)\n",coinaddr); - } - } - } - free_json(txobj); - } -} - -int32_t basilisk_swapuserdata(uint8_t *userdata,bits256 privkey,int32_t ifpath,bits256 signpriv,uint8_t *redeemscript,int32_t redeemlen) -{ - int32_t i,len = 0; -#ifdef DISABLE_CHECKSIG - userdata[len++] = sizeof(signpriv); - for (i=0; i if path, 0 -> else path - return(len); -} - -/* Bob deposit: - OP_IF - OP_CLTV OP_DROP OP_CHECKSIG - OP_ELSE - OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG - OP_ENDIF*/ - -void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen) -{ - int32_t i; char scriptstr[513]; - if ( scriptlen != 0 ) - { - for (i=0; iI.req.requestid,swap->I.req.quoteid,rawtx->name), OS_compatible_path(fname); - coinaddr[0] = secretAmstr[0] = secretAm256str[0] = secretBnstr[0] = secretBn256str[0] = 0; - memset(zeroes,0,sizeof(zeroes)); - if ( rawtx != 0 && (fp= fopen(fname,"wb")) != 0 ) - { - fprintf(fp,"{\"name\":\"%s\",\"coin\":\"%s\"",rawtx->name,rawtx->coin->symbol); - if ( rawtx->I.datalen > 0 ) - { - fprintf(fp,",\"tx\":\""); - for (i=0; iI.datalen; i++) - fprintf(fp,"%02x",rawtx->txbytes[i]); - fprintf(fp,"\",\"txid\":\"%s\"",bits256_str(str,bits256_doublesha256(0,rawtx->txbytes,rawtx->I.datalen))); - if ( rawtx == &swap->bobdeposit || rawtx == &swap->bobpayment ) - { - basilisk_swap_coinaddr(myinfo,swap,swap->bobcoin,coinaddr,rawtx->txbytes,rawtx->I.datalen); - if ( coinaddr[0] != 0 ) - { - if ( swap->bobcoin != 0 && swap->bobcoin->FULLNODE < 0 ) - { - if ( (tmp= dpow_importaddress(myinfo,swap->bobcoin,coinaddr)) != 0 ) - free(tmp); - } - if ( rawtx == &swap->bobdeposit ) - safecopy(swap->Bdeposit,coinaddr,sizeof(swap->Bdeposit)); - else safecopy(swap->Bpayment,coinaddr,sizeof(swap->Bpayment)); - } - } - } - if ( swap->Bdeposit[0] != 0 ) - fprintf(fp,",\"%s\":\"%s\"","Bdeposit",swap->Bdeposit); - if ( swap->Bpayment[0] != 0 ) - fprintf(fp,",\"%s\":\"%s\"","Bpayment",swap->Bpayment); - fprintf(fp,",\"expiration\":%u",swap->I.expiration); - fprintf(fp,",\"iambob\":%d",swap->I.iambob); - fprintf(fp,",\"bobcoin\":\"%s\"",swap->bobcoin->symbol); - fprintf(fp,",\"alicecoin\":\"%s\"",swap->alicecoin->symbol); - fprintf(fp,",\"lock\":%u",locktime); - fprintf(fp,",\"amount\":%.8f",dstr(rawtx->I.amount)); - if ( bits256_nonz(triggertxid) != 0 ) - fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid)); - if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 ) - { - basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin->chain->p2shtype,swap->I.pubAm,swap->I.pubBn); - if ( swap->alicecoin != 0 && swap->alicecoin->FULLNODE < 0 ) - { - if ( (tmp= dpow_importaddress(myinfo,swap->alicecoin,coinaddr)) != 0 ) - free(tmp); - } - fprintf(fp,",\"Apayment\":\"%s\"",coinaddr); - } - /*basilisk_dontforget_userdata("Aclaim",fp,swap->I.userdata_aliceclaim,swap->I.userdata_aliceclaimlen); - basilisk_dontforget_userdata("Areclaim",fp,swap->I.userdata_alicereclaim,swap->I.userdata_alicereclaimlen); - basilisk_dontforget_userdata("Aspend",fp,swap->I.userdata_alicespend,swap->I.userdata_alicespendlen); - basilisk_dontforget_userdata("Bspend",fp,swap->I.userdata_bobspend,swap->I.userdata_bobspendlen); - basilisk_dontforget_userdata("Breclaim",fp,swap->I.userdata_bobreclaim,swap->I.userdata_bobreclaimlen); - basilisk_dontforget_userdata("Brefund",fp,swap->I.userdata_bobrefund,swap->I.userdata_bobrefundlen);*/ - fprintf(fp,"}\n"); - fclose(fp); - } - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - fprintf(fp,"{\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u",swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime); - if ( memcmp(zeroes,swap->I.secretAm,20) != 0 ) - { - init_hexbytes_noT(secretAmstr,swap->I.secretAm,20); - fprintf(fp,",\"secretAm\":\"%s\"",secretAmstr); - } - if ( memcmp(zeroes,swap->I.secretAm256,32) != 0 ) - { - init_hexbytes_noT(secretAm256str,swap->I.secretAm256,32); - fprintf(fp,",\"secretAm256\":\"%s\"",secretAm256str); - } - if ( memcmp(zeroes,swap->I.secretBn,20) != 0 ) - { - init_hexbytes_noT(secretBnstr,swap->I.secretBn,20); - fprintf(fp,",\"secretBn\":\"%s\"",secretBnstr); - } - if ( memcmp(zeroes,swap->I.secretBn256,32) != 0 ) - { - init_hexbytes_noT(secretBn256str,swap->I.secretBn256,32); - fprintf(fp,",\"secretBn256\":\"%s\"",secretBn256str); - } - for (i=0; i<2; i++) - if ( bits256_nonz(swap->I.myprivs[i]) != 0 ) - fprintf(fp,",\"myprivs%d\":\"%s\"",i,bits256_str(str,swap->I.myprivs[i])); - if ( bits256_nonz(swap->I.privAm) != 0 ) - fprintf(fp,",\"privAm\":\"%s\"",bits256_str(str,swap->I.privAm)); - if ( bits256_nonz(swap->I.privBn) != 0 ) - fprintf(fp,",\"privBn\":\"%s\"",bits256_str(str,swap->I.privBn)); - if ( bits256_nonz(swap->I.pubA0) != 0 ) - fprintf(fp,",\"pubA0\":\"%s\"",bits256_str(str,swap->I.pubA0)); - if ( bits256_nonz(swap->I.pubB0) != 0 ) - fprintf(fp,",\"pubB0\":\"%s\"",bits256_str(str,swap->I.pubB0)); - if ( bits256_nonz(swap->I.pubB1) != 0 ) - fprintf(fp,",\"pubB1\":\"%s\"",bits256_str(str,swap->I.pubB1)); - if ( bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 ) - fprintf(fp,",\"Bdeposit\":\"%s\"",bits256_str(str,swap->bobdeposit.I.actualtxid)); - if ( bits256_nonz(swap->bobrefund.I.actualtxid) != 0 ) - fprintf(fp,",\"Brefund\":\"%s\"",bits256_str(str,swap->bobrefund.I.actualtxid)); - if ( bits256_nonz(swap->aliceclaim.I.actualtxid) != 0 ) - fprintf(fp,",\"Aclaim\":\"%s\"",bits256_str(str,swap->aliceclaim.I.actualtxid)); - - if ( bits256_nonz(swap->bobpayment.I.actualtxid) != 0 ) - fprintf(fp,",\"Bpayment\":\"%s\"",bits256_str(str,swap->bobpayment.I.actualtxid)); - if ( bits256_nonz(swap->alicespend.I.actualtxid) != 0 ) - fprintf(fp,",\"Aspend\":\"%s\"",bits256_str(str,swap->alicespend.I.actualtxid)); - if ( bits256_nonz(swap->bobreclaim.I.actualtxid) != 0 ) - fprintf(fp,",\"Breclaim\":\"%s\"",bits256_str(str,swap->bobreclaim.I.actualtxid)); - - if ( bits256_nonz(swap->alicepayment.I.actualtxid) != 0 ) - fprintf(fp,",\"Apayment\":\"%s\"",bits256_str(str,swap->alicepayment.I.actualtxid)); - if ( bits256_nonz(swap->bobspend.I.actualtxid) != 0 ) - fprintf(fp,",\"Bspend\":\"%s\"",bits256_str(str,swap->bobspend.I.actualtxid)); - if ( bits256_nonz(swap->alicereclaim.I.actualtxid) != 0 ) - fprintf(fp,",\"Areclaim\":\"%s\"",bits256_str(str,swap->alicereclaim.I.actualtxid)); - - if ( bits256_nonz(swap->otherfee.I.actualtxid) != 0 ) - fprintf(fp,",\"otherfee\":\"%s\"",bits256_str(str,swap->otherfee.I.actualtxid)); - if ( bits256_nonz(swap->myfee.I.actualtxid) != 0 ) - fprintf(fp,",\"myfee\":\"%s\"",bits256_str(str,swap->myfee.I.actualtxid)); - fprintf(fp,",\"dest33\":\""); - for (i=0; i<33; i++) - fprintf(fp,"%02x",swap->persistent_pubkey33[i]); - fprintf(fp,"\"}\n"); - fclose(fp); - } -} - -void basilisk_dontforget_update(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) -{ - bits256 triggertxid; - memset(triggertxid.bytes,0,sizeof(triggertxid)); - if ( rawtx == 0 ) - { - basilisk_dontforget(myinfo,swap,0,0,triggertxid); - return; - } - if ( rawtx == &swap->myfee ) - basilisk_dontforget(myinfo,swap,&swap->myfee,0,triggertxid); - else if ( rawtx == &swap->otherfee ) - basilisk_dontforget(myinfo,swap,&swap->otherfee,0,triggertxid); - else if ( rawtx == &swap->bobdeposit ) - { - basilisk_dontforget(myinfo,swap,&swap->bobdeposit,0,triggertxid); - basilisk_dontforget(myinfo,swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid); - } - else if ( rawtx == &swap->bobrefund ) - basilisk_dontforget(myinfo,swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid); - else if ( rawtx == &swap->aliceclaim ) - { - basilisk_dontforget(myinfo,swap,&swap->bobrefund,0,triggertxid); - basilisk_dontforget(myinfo,swap,&swap->aliceclaim,0,swap->bobrefund.I.actualtxid); - } - else if ( rawtx == &swap->alicepayment ) - { - basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid); - } - else if ( rawtx == &swap->bobspend ) - { - basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid); - basilisk_dontforget(myinfo,swap,&swap->bobspend,0,swap->alicepayment.I.actualtxid); - } - else if ( rawtx == &swap->alicereclaim ) - { - basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid); - basilisk_dontforget(myinfo,swap,&swap->alicereclaim,0,swap->bobrefund.I.actualtxid); - } - else if ( rawtx == &swap->bobpayment ) - { - basilisk_dontforget(myinfo,swap,&swap->bobpayment,0,triggertxid); - basilisk_dontforget(myinfo,swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid); - } - else if ( rawtx == &swap->alicespend ) - { - basilisk_dontforget(myinfo,swap,&swap->bobpayment,0,triggertxid); - basilisk_dontforget(myinfo,swap,&swap->alicespend,0,triggertxid); - } - else if ( rawtx == &swap->bobreclaim ) - basilisk_dontforget(myinfo,swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid); -} - -int32_t basilisk_verify_bobdeposit(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; struct basilisk_swap *swap = ptr; - if ( basilisk_rawtx_spendscript(swap,swap->bobcoin->longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) - { - swap->bobdeposit.I.signedtxid = basilisk_swap_broadcast(swap->bobdeposit.name,myinfo,swap,swap->bobdeposit.coin,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); - if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) - swap->depositunconf = 1; - basilisk_dontforget_update(myinfo,swap,&swap->bobdeposit); - len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - memcpy(swap->I.userdata_aliceclaim,userdata,len); - swap->I.userdata_aliceclaimlen = len; - if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1)) == 0 ) - { - for (i=0; ibobdeposit.I.datalen; i++) - printf("%02x",swap->bobdeposit.txbytes[i]); - printf(" <- bobdeposit\n"); - for (i=0; ialiceclaim.I.datalen; i++) - printf("%02x",swap->aliceclaim.txbytes[i]); - printf(" <- aliceclaim\n"); - basilisk_txlog(myinfo,swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); - return(retval); - } - } - printf("error with bobdeposit\n"); - return(-1); -} - -int32_t basilisk_bobdeposit_refund(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t delay) -{ - uint8_t userdata[512]; int32_t i,retval,len = 0; char str[65]; - len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - memcpy(swap->I.userdata_bobrefund,userdata,len); - swap->I.userdata_bobrefundlen = len; - if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0)) == 0 ) - { - for (i=0; ibobrefund.I.datalen; i++) - printf("%02x",swap->bobrefund.txbytes[i]); - printf(" <- bobrefund.(%s)\n",bits256_str(str,swap->bobrefund.I.txid)); - basilisk_txlog(myinfo,swap,&swap->bobrefund,delay); - return(retval); - } - return(-1); -} - -/*Bob paytx: - OP_IF - OP_CLTV OP_DROP OP_CHECKSIG - OP_ELSE - OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG - OP_ENDIF*/ - -int32_t basilisk_bobpayment_reclaim(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t delay) -{ - uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; - printf("basilisk_bobpayment_reclaim\n"); - len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - memcpy(swap->I.userdata_bobreclaim,userdata,len); - swap->I.userdata_bobreclaimlen = len; - if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1)) == 0 ) - { - for (i=0; ibobreclaim.I.datalen; i++) - printf("%02x",swap->bobreclaim.txbytes[i]); - printf(" <- bobreclaim\n"); - basilisk_txlog(myinfo,swap,&swap->bobreclaim,delay); - return(retval); - } - return(-1); -} - -int32_t basilisk_verify_bobpaid(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - uint8_t userdata[512]; int32_t i,retval,len = 0; bits256 revAm; struct basilisk_swap *swap = ptr; - memset(revAm.bytes,0,sizeof(revAm)); - if ( basilisk_rawtx_spendscript(swap,swap->bobcoin->longestchain,&swap->bobpayment,0,data,datalen,0) == 0 ) - { - swap->bobpayment.I.signedtxid = basilisk_swap_broadcast(swap->bobpayment.name,myinfo,swap,swap->bobpayment.coin,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); - if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) - swap->paymentunconf = 1; - basilisk_dontforget_update(myinfo,swap,&swap->bobpayment); - for (i=0; i<32; i++) - revAm.bytes[i] = swap->I.privAm.bytes[31-i]; - len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - memcpy(swap->I.userdata_alicespend,userdata,len); - swap->I.userdata_alicespendlen = len; - char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); - if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1)) == 0 ) - { - for (i=0; ibobpayment.I.datalen; i++) - printf("%02x",swap->bobpayment.txbytes[i]); - printf(" <- bobpayment\n"); - for (i=0; ialicespend.I.datalen; i++) - printf("%02x",swap->alicespend.txbytes[i]); - printf(" <- alicespend\n\n"); - swap->I.alicespent = 1; - basilisk_txlog(myinfo,swap,&swap->alicespend,-1); - return(retval); - } - } - return(-1); -} - -void basilisk_alicepayment(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn) -{ - alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->chain->p2shtype,pubAm,pubBn); - basilisk_rawtx_gen("alicepayment",myinfo,swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->chain->txfee,1,0); -} - -int32_t basilisk_alicepayment_spend(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *dest) -{ - int32_t i,retval; - printf("alicepayment_spend\n"); - swap->alicepayment.I.spendlen = basilisk_alicescript(swap->alicepayment.redeemscript,&swap->alicepayment.I.redeemlen,swap->alicepayment.spendscript,0,swap->alicepayment.I.destaddr,swap->alicecoin->chain->p2shtype,swap->I.pubAm,swap->I.pubBn); - printf("alicepayment_spend len.%d\n",swap->alicepayment.I.spendlen); - if ( swap->I.iambob == 0 ) - { - memcpy(swap->I.userdata_alicereclaim,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen); - swap->I.userdata_alicereclaimlen = swap->alicepayment.I.spendlen; - } - else - { - memcpy(swap->I.userdata_bobspend,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen); - swap->I.userdata_bobspendlen = swap->alicepayment.I.spendlen; - } - if ( (retval= basilisk_rawtx_sign(myinfo,swap->alicecoin->longestchain,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1)) == 0 ) - { - for (i=0; iI.datalen; i++) - printf("%02x",dest->txbytes[i]); - printf(" <- msigspend\n\n"); - if ( dest == &swap->bobspend ) - swap->I.bobspent = 1; - basilisk_txlog(myinfo,swap,dest,0); // bobspend or alicereclaim - return(retval); - } - return(-1); -} - -int32_t basilisk_verify_alicepaid(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - struct basilisk_swap *swap = ptr; - if ( basilisk_rawtx_spendscript(swap,swap->alicecoin->longestchain,&swap->alicepayment,0,data,datalen,0) == 0 ) - { - swap->alicepayment.I.signedtxid = basilisk_swap_broadcast(swap->alicepayment.name,myinfo,swap,swap->alicepayment.coin,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); - if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) - swap->aliceunconf = 1; - basilisk_dontforget_update(myinfo,swap,&swap->alicepayment); - return(0); - } - else return(-1); -} - -int32_t basilisk_verify_pubpair(int32_t *wrongfirstbytep,struct basilisk_swap *swap,int32_t ind,uint8_t pub0,bits256 pubi,uint64_t txid) -{ - if ( pub0 != (swap->I.iambob ^ 1) + 0x02 ) - { - (*wrongfirstbytep)++; - printf("wrongfirstbyte[%d] %02x\n",ind,pub0); - return(-1); - } - else if ( swap->otherdeck[ind][1] != pubi.txid ) - { - printf("otherdeck[%d] priv ->pub mismatch %llx != %llx\n",ind,(long long)swap->otherdeck[ind][1],(long long)pubi.txid); - return(-1); - } - else if ( swap->otherdeck[ind][0] != txid ) - { - printf("otherdeck[%d] priv mismatch %llx != %llx\n",ind,(long long)swap->otherdeck[ind][0],(long long)txid); - return(-1); - } - return(0); -} - -int32_t basilisk_bobscripts_set(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t depositflag,int32_t genflag) -{ - int32_t i,j; //char str[65]; - if ( genflag != 0 && swap->I.iambob == 0 ) - printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n"); - if ( depositflag == 0 ) - { - swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0); - bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin->chain->p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - //for (i=0; ibobpayment.redeemlen; i++) - // printf("%02x",swap->bobpayment.redeemscript[i]); - //printf(" <- bobpayment.%d\n",i); - if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 ) - { - for (i=0; i<3; i++) - { - //if ( swap->bobpayment.txbytes != 0 && swap->bobpayment.I.spendlen != 0 ) - // break; - basilisk_rawtx_gen("payment",myinfo,swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->chain->txfee,1,0); - if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 ) - { - printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen); - sleep(DEX_SLEEP); - } - else - { - for (j=0; jbobpayment.I.datalen; j++) - printf("%02x",swap->bobpayment.txbytes[j]); - //printf(" <- bobpayment.%d\n",swap->bobpayment.datalen); - //for (j=0; jbobpayment.redeemlen; j++) - // printf("%02x",swap->bobpayment.redeemscript[j]); - //printf(" <- redeem.%d\n",swap->bobpayment.redeemlen); - printf(" <- GENERATED BOB PAYMENT.%d\n",swap->bobpayment.I.datalen); - iguana_unspents_mark(myinfo,swap->bobcoin,swap->bobpayment.vins); - basilisk_bobpayment_reclaim(myinfo,swap,swap->I.callduration); - printf("bobscripts set completed\n"); - return(0); - } - } - } - } - else - { - swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1); - bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin->chain->p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - if ( genflag != 0 && (swap->bobdeposit.I.datalen == 0 || swap->bobrefund.I.datalen == 0) ) - { - for (i=0; i<3; i++) - { - //if ( swap->bobdeposit.txbytes != 0 && swap->bobdeposit.I.spendlen != 0 ) - // break; - basilisk_rawtx_gen("deposit",myinfo,swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,swap->bobdeposit.coin->chain->txfee,1,0); - if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 ) - { - printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen); - sleep(DEX_SLEEP); - } - else - { - for (j=0; jbobdeposit.I.datalen; j++) - printf("%02x",swap->bobdeposit.txbytes[j]); - printf(" <- GENERATED BOB DEPOSIT.%d\n",swap->bobdeposit.I.datalen); - //for (j=0; jbobdeposit.redeemlen; j++) - // printf("%02x",swap->bobdeposit.redeemscript[j]); - //printf(" <- redeem.%d\n",swap->bobdeposit.redeemlen); - //printf("GENERATED BOB DEPOSIT\n"); - iguana_unspents_mark(myinfo,swap->bobcoin,swap->bobdeposit.vins); - basilisk_bobdeposit_refund(myinfo,swap,swap->I.putduration); - printf("bobscripts set completed\n"); - return(0); - } - } - } - //for (i=0; ibobdeposit.redeemlen; i++) - // printf("%02x",swap->bobdeposit.redeemscript[i]); - //printf(" <- bobdeposit.%d\n",i); - } - return(0); -} - -int32_t basilisk_verify_privi(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - int32_t j,wrongfirstbyte,len = 0; bits256 privkey,pubi; char str[65],str2[65]; uint8_t secret160[20],pubkey33[33]; uint64_t txid; struct basilisk_swap *swap = ptr; - memset(privkey.bytes,0,sizeof(privkey)); - if ( datalen == sizeof(bits256) ) - { - for (j=0; j<32; j++) - privkey.bytes[j] = data[len++]; - revcalc_rmd160_sha256(secret160,privkey);//.bytes,sizeof(privkey)); - memcpy(&txid,secret160,sizeof(txid)); - pubi = bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); - if ( basilisk_verify_pubpair(&wrongfirstbyte,swap,swap->I.choosei,pubkey33[0],pubi,txid) == 0 ) - { - if ( swap->I.iambob != 0 ) - { - swap->I.privAm = privkey; - vcalc_sha256(0,swap->I.secretAm256,privkey.bytes,sizeof(privkey)); - printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); - basilisk_bobscripts_set(myinfo,swap,0,1); - } - else - { - swap->I.privBn = privkey; - vcalc_sha256(0,swap->I.secretBn256,privkey.bytes,sizeof(privkey)); - printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256)); - } - basilisk_dontforget_update(myinfo,swap,0); - char str[65]; printf("privi verified.(%s)\n",bits256_str(str,privkey)); - return(0); - } - } - return(-1); -} - -int32_t basilisk_process_swapverify(struct supernet_info *myinfo,void *ptr,int32_t (*internal_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen),uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t expiration,uint32_t duration) -{ - struct basilisk_swap *swap = ptr; - if ( internal_func != 0 ) - return((*internal_func)(myinfo,swap,data,datalen)); - else return(0); -} - -void basilisk_swapgotdata(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit) -{ - int32_t i; struct basilisk_swapmessage *mp; - for (i=0; inummessages; i++) - if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 ) - return; - //printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data); - swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1)); - mp = &swap->messages[swap->nummessages++]; - mp->crc32 = crc32; - mp->srchash = srchash; - mp->desthash = desthash; - mp->msgbits = msgbits; - mp->quoteid = quoteid; - mp->data = malloc(datalen); - mp->datalen = datalen; - memcpy(mp->data,data,datalen); - if ( reinit == 0 && swap->fp != 0 ) - { - fwrite(mp,1,sizeof(*mp),swap->fp); - fwrite(data,1,datalen,swap->fp); - fflush(swap->fp); - } -} - -FILE *basilisk_swap_save(struct supernet_info *myinfo,struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) -{ - FILE *fp=0; /*char fname[512]; - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"rb+")) == 0 ) - { - if ( (fp= fopen(fname,"wb+")) != 0 ) - { - fwrite(privkey.bytes,1,sizeof(privkey),fp); - fwrite(rp,1,sizeof(*rp),fp); - fwrite(&statebits,1,sizeof(statebits),fp); - fwrite(&optionduration,1,sizeof(optionduration),fp); - fflush(fp); - } - } - else if ( reinit != 0 ) - { - }*/ - return(fp); -} - -int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp) -{ - FILE *fp=0; char fname[512]; int32_t retval = -1; - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"rb+")) != 0 ) - { - if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) && - fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) && - fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) && - fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) ) - retval = 0; - fclose(fp); - } - return(retval); -} - -struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit); - -void basilisk_swaps_init(struct supernet_info *myinfo) -{ - char fname[512]; uint32_t iter,swapcompleted,requestid,quoteid,optionduration,statebits; FILE *fp; bits256 privkey;struct basilisk_request R; struct basilisk_swapmessage M; struct basilisk_swap *swap = 0; - sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); - if ( (myinfo->swapsfp= fopen(fname,"rb+")) != 0 ) - { - while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) ) - { - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); - printf("%s\n",fname); - if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed - { - memset(&M,0,sizeof(M)); - swapcompleted = 1; - for (iter=0; iter<2; iter++) - { - if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) && - fread(&R,1,sizeof(R),fp) == sizeof(R) && - fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) && - fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) ) - { - while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) ) - { - M.data = 0; - //printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen); - if ( M.datalen < 100000 ) - { - M.data = malloc(M.datalen); - if ( fread(M.data,1,M.datalen,fp) == M.datalen ) - { - if ( calc_crc32(0,M.data,M.datalen) == M.crc32 ) - { - if ( iter == 1 ) - { - if ( swap == 0 ) - { - swap = basilisk_thread_start(myinfo,privkey,&R,statebits,optionduration,1); - swap->I.choosei = swap->I.otherchoosei = -1; - } - if ( swap != 0 ) - basilisk_swapgotdata(myinfo,swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1); - } - } else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32); - } else printf("error reading M.datalen %d\n",M.datalen); - free(M.data), M.data = 0; - } - } - } - if ( swapcompleted != 0 ) - break; - rewind(fp); - } - } - } - } else myinfo->swapsfp = fopen(fname,"wb+"); -} - -void basilisk_psockinit(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t amlp); - -int32_t basilisk_swapget(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)) -{ - uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0; - while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 ) - { - swap->lasttime = (uint32_t)time(NULL); - memset(srchash.bytes,0,sizeof(srchash)); - memset(desthash.bytes,0,sizeof(desthash)); - //printf("gotmsg.[%d] crc.%x\n",size,crc32); - offset = 0; - for (i=0; i<32; i++) - srchash.bytes[i] = ptr[offset++]; - for (i=0; i<32; i++) - desthash.bytes[i] = ptr[offset++]; - offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid); - offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits); - if ( size > offset ) - { - crc32 = calc_crc32(0,&ptr[offset],size-offset); - if ( size > offset ) - { - //printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset); - basilisk_swapgotdata(myinfo,swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0); - } - } - else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 ) - { - if ( swap->aborted == 0 ) - { - swap->aborted = (uint32_t)time(NULL); - printf("got abort signal from other side\n"); - } - } else printf("basilisk_swapget: got strange packet\n"); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; - } - //char str[65],str2[65]; - for (i=0; inummessages; i++) - { - //printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash)); - if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 ) - { - if ( swap->messages[i].msgbits == msgbits ) - { - if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 ) - { - printf("nothing received for a while from Bob, try new sockets\n"); - if ( swap->pushsock >= 0 ) // - nn_close(swap->pushsock), swap->pushsock = -1; - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = 0; - basilisk_psockinit(myinfo,swap,swap->I.iambob != 0); - } - mp = &swap->messages[i]; - if ( msgbits != 0x80000000 ) - break; - } - } - } - if ( mp != 0 ) - retval = (*basilisk_verify_func)(myinfo,swap,mp->data,mp->datalen); - //printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash)); - return(retval); -} - -uint32_t basilisk_swapsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2]) -{ - uint8_t *buf; int32_t sentbytes,offset=0,i; - buf = malloc(datalen + sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2); - for (i=0; i<32; i++) - buf[offset++] = swap->I.myhash.bytes[i]; - for (i=0; i<32; i++) - buf[offset++] = swap->I.otherhash.bytes[i]; - offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); - offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); - if ( datalen > 0 ) - memcpy(&buf[offset],data,datalen), offset += datalen; - if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) - { - printf("sentbytes.%d vs offset.%d\n",sentbytes,offset); - if ( sentbytes < 0 ) - { - if ( swap->pushsock >= 0 ) - nn_close(swap->pushsock), swap->pushsock = -1; //, - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = swap->I.iambob != 0 ? -1 : 0; - swap->aborted = (uint32_t)time(NULL); - } - } - //else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data); - free(buf); - return(nextbits); -} - -void basilisk_swap_sendabort(struct supernet_info *myinfo,struct basilisk_swap *swap) -{ - uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0; - memset(buf,0,sizeof(buf)); - offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); - offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); - if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) - { - if ( sentbytes < 0 ) - { - if ( swap->pushsock >= 0 ) // - nn_close(swap->pushsock), swap->pushsock = -1; - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = 0; - } - } else printf("basilisk_swap_sendabort\n"); -} - -int32_t basilisk_privBn_extract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) -{ - if ( basilisk_priviextract(myinfo,swap->bobcoin,"privBn",&swap->I.privBn,swap->I.secretBn,swap->bobrefund.I.actualtxid,0) == 0 ) - { - printf("extracted privBn from blockchain\n"); - } - else if ( basilisk_swapget(myinfo,swap,0x40000000,data,maxlen,basilisk_verify_privi) == 0 ) - { - } - if ( bits256_nonz(swap->I.privBn) != 0 && swap->alicereclaim.I.datalen == 0 ) - { - char str[65]; printf("got privBn.%s\n",bits256_str(str,swap->I.privBn)); - return(basilisk_alicepayment_spend(myinfo,swap,&swap->alicereclaim)); - } - return(-1); -} - -int32_t basilisk_privAm_extract(struct supernet_info *myinfo,struct basilisk_swap *swap) -{ - if ( basilisk_priviextract(myinfo,swap->bobcoin,"privAm",&swap->I.privAm,swap->I.secretAm,swap->bobpayment.I.actualtxid,0) == 0 ) - { - printf("extracted privAm from blockchain\n"); - } - if ( bits256_nonz(swap->I.privAm) != 0 && swap->bobspend.I.datalen == 0 ) - { - char str[65]; printf("got privAm.%s\n",bits256_str(str,swap->I.privAm)); - return(basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend)); - } - return(-1); -} - -bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) -{ - bits256 sharedsecret; - sharedsecret = curve25519_shared(privkey,orderhash); - vcalc_sha256cat(newprivp->bytes,orderhash.bytes,sizeof(orderhash),sharedsecret.bytes,sizeof(sharedsecret)); - return(bitcoin_pubkey33(ctx,pubkey,*newprivp)); -} - -int32_t instantdex_pubkeyargs(void *ctx,struct basilisk_swap *swap,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte) -{ - char buf[3]; int32_t i,n,m,len=0; bits256 pubi,reveal; uint64_t txid; uint8_t secret160[20],pubkey[33]; - sprintf(buf,"%c0",'A' - 0x02 + firstbyte); - if ( numpubs > 2 ) - { - if ( swap->I.numpubs+2 >= numpubs ) - return(numpubs); - //fprintf(stderr,">>>>>> start generating %s\n",buf); - } - for (i=n=m=0; iI.mypubs[n]) == 0 ) - { - swap->I.myprivs[n] = privkey; - memcpy(swap->I.mypubs[n].bytes,pubkey+1,sizeof(bits256)); - reveal = basilisk_revealkey(privkey,swap->I.mypubs[n]); - if ( swap->I.iambob != 0 ) - { - if ( n == 0 ) - swap->I.pubB0 = reveal; - else if ( n == 1 ) - swap->I.pubB1 = reveal; - } - else if ( swap->I.iambob == 0 ) - { - if ( n == 0 ) - swap->I.pubA0 = reveal; - else if ( n == 1 ) - swap->I.pubA1 = reveal; - } - } - } - if ( m < INSTANTDEX_DECKSIZE ) - { - swap->privkeys[m] = privkey; - revcalc_rmd160_sha256(secret160,privkey);//.bytes,sizeof(privkey)); - memcpy(&txid,secret160,sizeof(txid)); - len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][0],sizeof(txid),&txid); - len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][1],sizeof(pubi.txid),&pubi.txid); - m++; - if ( m > swap->I.numpubs ) - swap->I.numpubs = m; - } - n++; - } - if ( n > 2 || m > 2 ) - printf("n.%d m.%d len.%d numpubs.%d\n",n,m,len,swap->I.numpubs); - return(n); -} - -void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33,int32_t jumblrflag) -{ - strcpy(rawtx->name,name); - rawtx->coin = coin; - strcpy(rawtx->I.coinstr,coin->symbol); - rawtx->I.numconfirms = numconfirms; - if ( (rawtx->I.amount= satoshis) < 50000 ) - rawtx->I.amount = 50000; - rawtx->I.vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit - rawtx->I.vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit - if ( rawtx->I.vouttype == 0 ) - { - if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 ) - decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160); - else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160); - bitcoin_address(rawtx->I.destaddr,rawtx->coin->chain->pubtype,rawtx->I.rmd160,20); - } - if ( pubkey33 != 0 ) - { - memcpy(rawtx->I.pubkey33,pubkey33,33); - bitcoin_address(rawtx->I.destaddr,rawtx->coin->chain->pubtype,rawtx->I.pubkey33,33); - bitcoin_addr2rmd160(&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr); - } - if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 ) - { - rawtx->I.spendlen = bitcoin_standardspend(rawtx->spendscript,0,rawtx->I.rmd160); - printf("%s spendlen.%d %s <- %.8f\n",name,rawtx->I.spendlen,rawtx->I.destaddr,dstr(rawtx->I.amount)); - } else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr); -} int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct iguana_info **alicecoinp,char *src,char *dest,bits256 srchash,bits256 desthash) { - struct iguana_info *coin = iguana_coinfind(src); - if ( coin == 0 || iguana_coinfind(dest) == 0 ) + struct iguana_info *coin = LP_coinfind(src); + if ( coin == 0 || LP_coinfind(dest) == 0 ) return(0); *bobcoinp = *alicecoinp = 0; - *bobcoinp = iguana_coinfind(dest); - *alicecoinp = iguana_coinfind(src); + *bobcoinp = LP_coinfind(dest); + *alicecoinp = LP_coinfind(src); if ( bits256_cmp(pubkey,srchash) == 0 ) { if ( strcmp(src,(*bobcoinp)->symbol) == 0 ) return(1); else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 ) - return(-1); - else return(0); - } - else if ( bits256_cmp(pubkey,desthash) == 0 ) - { - if ( strcmp(src,(*bobcoinp)->symbol) == 0 ) - return(-1); - else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 ) - return(1); - else return(0); - } - return(0); -} - -void basilisk_swap_saveupdate(struct supernet_info *myinfo,struct basilisk_swap *swap) -{ - FILE *fp; char fname[512]; - sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - fwrite(&swap->I,1,sizeof(swap->I),fp); - /*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp); - fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp); - fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp); - fwrite(&swap->myfee,1,sizeof(swap->myfee),fp); - fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp); - fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp); - fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp); - fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp); - fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp); - fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp); - fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/ - fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp); - fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp); - fwrite(swap->deck,1,sizeof(swap->deck),fp); - fclose(fp); - } -} - -int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr) -{ - if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) ) - { - rawtx->coin = 0; - rawtx->vins = 0; - if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 ) - { - rawtx->coin = iguana_coinfind(rawtx->I.coinstr); - if ( rawtx->vinstr[0] != 0 ) - rawtx->vins = cJSON_Parse(rawtx->vinstr); - printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen); - return(0); - } - } - return(-1); -} - -struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,int32_t reinit) -{ - FILE *fp; char fname[512]; uint8_t *alicepub33=0,*bobpub33=0; int32_t errs=0,jumblrflag,x = -1; - if ( reinit != 0 ) - { - sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); - printf("reinit.(%s)\n",fname); - if ( (fp= fopen(fname,"rb")) != 0 ) - { - if ( fread(&swap->I,1,sizeof(swap->I),fp) != sizeof(swap->I) ) - errs++; - if ( swap->bobcoin == 0 ) - swap->bobcoin = iguana_coinfind(swap->I.req.dest); - if ( swap->alicecoin == 0 ) - swap->alicecoin = iguana_coinfind(swap->I.req.src); - if ( swap->alicecoin != 0 && swap->bobcoin != 0 ) - { - /*basilisk_swap_loadtx(&swap->bobdeposit,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->bobpayment,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->alicepayment,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->myfee,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->otherfee,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->aliceclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->alicespend,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->bobreclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->bobspend,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->bobrefund,fp,swap->bobcoin->symbol,swap->alicecoin->symbol); - basilisk_swap_loadtx(&swap->alicereclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);*/ - } else printf("missing coins (%p %p)\n",swap->bobcoin,swap->alicecoin); - if ( fread(swap->privkeys,1,sizeof(swap->privkeys),fp) != sizeof(swap->privkeys) ) - errs++; - if ( fread(swap->otherdeck,1,sizeof(swap->otherdeck),fp) != sizeof(swap->otherdeck) ) - errs++; - if ( fread(swap->deck,1,sizeof(swap->deck),fp) != sizeof(swap->deck) ) - errs++; - fclose(fp); - } else printf("cant find.(%s)\n",fname); - } - else - { - swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME; - if ( optionduration < 0 ) - swap->I.putduration -= optionduration; - else if ( optionduration > 0 ) - swap->I.callduration += optionduration; - swap->I.bobsatoshis = swap->I.req.destamount; - swap->I.alicesatoshis = swap->I.req.srcamount; - if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 ) - swap->I.bobinsurance = 50000; - if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 ) - swap->I.aliceinsurance = 50000; - strcpy(swap->I.bobstr,swap->I.req.dest); - strcpy(swap->I.alicestr,swap->I.req.src); - swap->I.started = (uint32_t)time(NULL); - swap->I.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration; - OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei)); - if ( swap->I.choosei < 0 ) - swap->I.choosei = -swap->I.choosei; - swap->I.choosei %= INSTANTDEX_DECKSIZE; - swap->I.otherchoosei = -1; - swap->I.myhash = pubkey25519; - if ( statebits != 0 ) - { - swap->I.iambob = 0; - swap->I.otherhash = swap->I.req.desthash; - } - else - { - swap->I.iambob = 1; - swap->I.otherhash = swap->I.req.srchash; - } - if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(myinfo->ctx,swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE ) - { - char str[65]; printf("couldnt generate privkeys %d %s\n",x,bits256_str(str,privkey)); - return(0); - } - } - swap->bobcoin = iguana_coinfind(swap->I.req.dest); - swap->alicecoin = iguana_coinfind(swap->I.req.src); - if ( swap->bobcoin == 0 || swap->alicecoin == 0 ) - { - printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",swap->bobcoin,swap->alicecoin,iguana_coinfind(swap->I.req.src),iguana_coinfind(swap->I.req.dest)); - free(swap); - return(0); - } - if ( strcmp("BTC",swap->bobcoin->symbol) == 0 ) - { - swap->I.bobconfirms = (1*0 + sqrt(dstr(swap->I.bobsatoshis) * .1)); - swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); - } - else if ( strcmp("BTC",swap->alicecoin->symbol) == 0 ) - { - swap->I.aliceconfirms = (1*0 + sqrt(dstr(swap->I.alicesatoshis) * .1)); - swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); - } - else - { - swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; - swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; - } - /*if ( swap->I.bobconfirms == 0 ) - swap->I.bobconfirms = swap->bobcoin->chain->minconfirms; - if ( swap->I.aliceconfirms == 0 ) - swap->I.aliceconfirms = swap->alicecoin->chain->minconfirms;*/ - jumblrflag = (bits256_cmp(pubkey25519,myinfo->jumblr_pubkey) == 0 || bits256_cmp(pubkey25519,myinfo->jumblr_depositkey) == 0); - printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms); - if ( swap->I.iambob != 0 ) - { - basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); - basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); - bobpub33 = pubkey33; - } - else - { - basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); - basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); - alicepub33 = pubkey33; - } - basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3) + swap->bobcoin->txfee,4,0,jumblrflag); - basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,bobpub33,jumblrflag); - swap->bobrefund.I.suppress_pubkeys = 1; - basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,alicepub33,jumblrflag); - swap->aliceclaim.I.suppress_pubkeys = 1; - swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 1; - - basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + swap->bobcoin->txfee,3,0,jumblrflag); - basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag); - swap->alicespend.I.suppress_pubkeys = 1; - basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag); - swap->bobreclaim.I.suppress_pubkeys = 1; - swap->bobreclaim.I.locktime = swap->I.started + swap->I.putduration + 1; - basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,swap->alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis+swap->alicecoin->txfee,2,0,jumblrflag); - basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag); - swap->bobspend.I.suppress_pubkeys = 1; - basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag); - swap->alicereclaim.I.suppress_pubkeys = 1; - printf("IAMBOB.%d\n",swap->I.iambob); - - return(swap); + return(-1); + else return(0); + } + else if ( bits256_cmp(pubkey,desthash) == 0 ) + { + if ( strcmp(src,(*bobcoinp)->symbol) == 0 ) + return(-1); + else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 ) + return(1); + else return(0); + } + return(0); } -// end of alice/bob code void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) { @@ -1332,7 +154,7 @@ void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) // free(rawtx->txbytes), rawtx->txbytes = 0; } -void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *swap) +void basilisk_swap_finished(struct basilisk_swap *swap) { int32_t i; swap->I.finished = (uint32_t)time(NULL); @@ -1355,82 +177,33 @@ void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *s swap->nummessages = 0; } -void basilisk_swap_purge(struct supernet_info *myinfo,struct basilisk_swap *swap) -{ - int32_t i,n; - // while still in orderbook, wait - //return; - portable_mutex_lock(&myinfo->DEX_swapmutex); - n = myinfo->numswaps; - for (i=0; iswaps[i] == swap ) - { - myinfo->swaps[i] = myinfo->swaps[--myinfo->numswaps]; - myinfo->swaps[myinfo->numswaps] = 0; - basilisk_swap_finished(myinfo,swap); - break; - } - portable_mutex_unlock(&myinfo->DEX_swapmutex); -} - -int32_t basilisk_verify_otherstatebits(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - int32_t retval; struct basilisk_swap *swap = ptr; - if ( datalen == sizeof(swap->I.otherstatebits) ) - { - retval = iguana_rwnum(0,data,sizeof(swap->I.otherstatebits),&swap->I.otherstatebits); - return(retval); - } else return(-1); -} - -int32_t basilisk_verify_statebits(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) +uint32_t basilisk_requestid(struct basilisk_request *rp) { - int32_t retval = -1; uint32_t statebits; struct basilisk_swap *swap = ptr; - if ( datalen == sizeof(swap->I.statebits) ) - { - retval = iguana_rwnum(0,data,sizeof(swap->I.statebits),&statebits); - if ( statebits != swap->I.statebits ) - { - printf("statebits.%x != %x\n",statebits,swap->I.statebits); - return(-1); - } - } - return(retval); + struct basilisk_request R; + R = *rp; + R.requestid = R.quoteid = R.quotetime = R.DEXselector = 0; + R.destamount = R.unused = 0; + memset(R.desthash.bytes,0,sizeof(R.desthash.bytes)); + if ( 0 ) + { + int32_t i; + for (i=0; i %s %.8f %s crc.%u\n",R.timestamp,R.requestid,R.quoteid,R.src,dstr(R.srcamount),bits256_str(str,R.srchash),R.dest,dstr(R.destamount),bits256_str(str2,R.desthash),calc_crc32(0,(void *)&R,sizeof(R))); + } + return(calc_crc32(0,(void *)&R,sizeof(R))); } -int32_t basilisk_verify_choosei(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) +uint32_t basilisk_quoteid(struct basilisk_request *rp) { - int32_t otherchoosei=-1,i,len = 0; struct basilisk_swap *swap = ptr; - if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 ) - { - len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei); - if ( otherchoosei >= 0 && otherchoosei < INSTANTDEX_DECKSIZE ) - { - //printf("otherchoosei.%d\n",otherchoosei); - swap->I.otherchoosei = otherchoosei; - if ( swap->I.iambob != 0 ) - { - for (i=0; i<32; i++) - swap->I.pubA0.bytes[i] = data[len++]; - for (i=0; i<32; i++) - swap->I.pubA1.bytes[i] = data[len++]; - char str[65]; printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0)); - } - else - { - for (i=0; i<32; i++) - swap->I.pubB0.bytes[i] = data[len++]; - for (i=0; i<32; i++) - swap->I.pubB1.bytes[i] = data[len++]; - } - return(0); - } - } - printf("illegal otherchoosei.%d datalen.%d vs %d\n",otherchoosei,datalen,(int32_t)(sizeof(otherchoosei)+sizeof(bits256)*2)); - return(-1); + struct basilisk_request R; + R = *rp; + R.requestid = R.quoteid = R.unused = R.DEXselector = 0; + return(calc_crc32(0,(void *)&R,sizeof(R))); } -int32_t basilisk_swapdata_deck(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +int32_t LP_pubkeys_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { int32_t i,datalen = 0; for (i=0; ideck)/sizeof(swap->deck[0][0]); i++) @@ -1438,133 +211,18 @@ int32_t basilisk_swapdata_deck(struct supernet_info *myinfo,struct basilisk_swap return(datalen); } -int32_t basilisk_verify_otherdeck(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - int32_t i,len = 0; struct basilisk_swap *swap = ptr; - for (i=0; iotherdeck)/sizeof(swap->otherdeck[0][0]); i++) - len += iguana_rwnum(0,&data[len],sizeof(swap->otherdeck[i>>1][i&1]),&swap->otherdeck[i>>1][i&1]); - return(0); -} - -int32_t basilisk_verify_privkeys(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen) -{ - int32_t i,j,wrongfirstbyte=0,errs=0,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33]; uint64_t txid; struct basilisk_swap *swap = ptr; - //printf("verify privkeys choosei.%d otherchoosei.%d datalen.%d vs %d\n",swap->choosei,swap->otherchoosei,datalen,(int32_t)sizeof(swap->privkeys)+20+32); - memset(otherpriv.bytes,0,sizeof(otherpriv)); - if ( swap->I.cutverified == 0 && swap->I.otherchoosei >= 0 && datalen == sizeof(swap->privkeys)+20+2*32 ) - { - for (i=errs=0; iprivkeys)/sizeof(*swap->privkeys); i++) - { - for (j=0; j<32; j++) - otherpriv.bytes[j] = data[len++]; - if ( i != swap->I.choosei ) - { - pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv); - revcalc_rmd160_sha256(secret160,otherpriv);//.bytes,sizeof(otherpriv)); - memcpy(&txid,secret160,sizeof(txid)); - errs += basilisk_verify_pubpair(&wrongfirstbyte,swap,i,otherpubkey[0],pubi,txid); - } - } - if ( errs == 0 && wrongfirstbyte == 0 ) - { - swap->I.cutverified = 1, printf("CUT VERIFIED\n"); - if ( swap->I.iambob != 0 ) - { - for (i=0; i<32; i++) - swap->I.pubAm.bytes[i] = data[len++]; - for (i=0; i<20; i++) - swap->I.secretAm[i] = data[len++]; - for (i=0; i<32; i++) - swap->I.secretAm256[i] = data[len++]; - basilisk_bobscripts_set(myinfo,swap,1,1); - } - else - { - for (i=0; i<32; i++) - swap->I.pubBn.bytes[i] = data[len++]; - for (i=0; i<20; i++) - swap->I.secretBn[i] = data[len++]; - for (i=0; i<32; i++) - swap->I.secretBn256[i] = data[len++]; - //basilisk_bobscripts_set(myinfo,swap,0); - } - } else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs); - } - //printf("privkeys errs.%d wrongfirstbyte.%d\n",errs,wrongfirstbyte); - return(errs); -} - -uint32_t basilisk_swapdata_rawtxsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend) -{ - uint8_t sendbuf[32768]; int32_t sendlen; - if ( basilisk_swapdata_rawtx(myinfo,swap,data,maxlen,rawtx) != 0 ) - { - if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) - { - char str[65],str2[65]; - rawtx->I.actualtxid = basilisk_swap_broadcast(rawtx->name,myinfo,swap,rawtx->coin,rawtx->txbytes,rawtx->I.datalen); - if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 ) - { - printf("%s rawtxsend %s vs %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); - rawtx->I.actualtxid = rawtx->I.signedtxid; - } - if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 ) - { - sendlen = 0; - sendbuf[sendlen++] = rawtx->I.datalen & 0xff; - sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff; - sendbuf[sendlen++] = rawtx->I.redeemlen; - memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen; - if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) - { - memcpy(&sendbuf[sendlen],rawtx->redeemscript,rawtx->I.redeemlen); - sendlen += rawtx->I.redeemlen; - } - basilisk_dontforget_update(myinfo,swap,rawtx); - //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen); - if ( suppress_swapsend == 0 ) - return(basilisk_swapsend(myinfo,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs)); - else - { - printf("suppress swapsend %x\n",msgbits); - return(0); - } - } - } - return(nextbits); - } else if ( swap->I.iambob == 0 ) - printf("error from basilisk_swapdata_rawtx.%s %p len.%d\n",rawtx->name,rawtx->txbytes,rawtx->I.datalen); - return(0); -} - -void basilisk_sendpubkeys(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) -{ - int32_t datalen; - datalen = basilisk_swapdata_deck(myinfo,swap,data,maxlen); - printf("send deck.%d\n",datalen); - swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x02,data,datalen,0x01,swap->I.crcs_mypub); -} - -int32_t basilisk_checkdeck(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - if ( (swap->I.statebits & 0x02) == 0 ) + int32_t i,len = 0; + if ( datalen == sizeof(swap->otherdeck) ) { - //printf("check for other deck\n"); - if ( basilisk_swapget(myinfo,swap,0x02,data,maxlen,basilisk_verify_otherdeck) == 0 ) - swap->I.statebits |= 0x02; - else return(-1); - } - return(0); -} - -void basilisk_sendstate(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) -{ - int32_t datalen=0; - datalen = iguana_rwnum(1,data,sizeof(swap->I.statebits),&swap->I.statebits); - basilisk_swapsend(myinfo,swap,0x80000000,data,datalen,0,0); + for (i=0; iotherdeck)/sizeof(swap->otherdeck[0][0]); i++) + len += iguana_rwnum(0,&data[len],sizeof(swap->otherdeck[i>>1][i&1]),&swap->otherdeck[i>>1][i&1]); + return(0); + } else return(-1); } -void basilisk_sendchoosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +int32_t LP_choosei_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { int32_t i,datalen; char str[65]; datalen = iguana_rwnum(1,data,sizeof(swap->I.choosei),&swap->I.choosei); @@ -1584,46 +242,56 @@ void basilisk_sendchoosei(struct supernet_info *myinfo,struct basilisk_swap *swa data[datalen++] = swap->I.pubA1.bytes[i]; printf("SEND pubA0/1 %s\n",bits256_str(str,swap->I.pubA0)); } - swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x08,data,datalen,0x04,swap->I.crcs_mychoosei); + return(datalen); } -void basilisk_waitchoosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - uint8_t pubkey33[33]; char str[65],str2[65]; - //printf("check otherchoosei\n"); - if ( basilisk_swapget(myinfo,swap,0x08,data,maxlen,basilisk_verify_choosei) == 0 ) + int32_t otherchoosei=-1,i,len = 0; uint8_t pubkey33[33]; char str[65],str2[65]; + if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 ) { - if ( swap->I.iambob != 0 ) + len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei); + if ( otherchoosei >= 0 && otherchoosei < INSTANTDEX_DECKSIZE ) { - if ( bits256_nonz(swap->I.privBn) == 0 ) + swap->I.otherchoosei = otherchoosei; + if ( swap->I.iambob != 0 ) { + for (i=0; i<32; i++) + swap->I.pubA0.bytes[i] = data[len++]; + for (i=0; i<32; i++) + swap->I.pubA1.bytes[i] = data[len++]; + printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0)); swap->I.privBn = swap->privkeys[swap->I.otherchoosei]; memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei])); revcalc_rmd160_sha256(swap->I.secretBn,swap->I.privBn);//.bytes,sizeof(swap->privBn)); vcalc_sha256(0,swap->I.secretBn256,swap->I.privBn.bytes,sizeof(swap->I.privBn)); - swap->I.pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->I.privBn); + swap->I.pubBn = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privBn); printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256)); - basilisk_bobscripts_set(myinfo,swap,1,1); + basilisk_bobscripts_set(swap,1,1); } - } - else - { - if ( bits256_nonz(swap->I.privAm) == 0 ) + else { + for (i=0; i<32; i++) + swap->I.pubB0.bytes[i] = data[len++]; + for (i=0; i<32; i++) + swap->I.pubB1.bytes[i] = data[len++]; + printf("GOT pubB0/1 %s\n",bits256_str(str,swap->I.pubB0)); swap->I.privAm = swap->privkeys[swap->I.otherchoosei]; memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei])); revcalc_rmd160_sha256(swap->I.secretAm,swap->I.privAm);//.bytes,sizeof(swap->privAm)); vcalc_sha256(0,swap->I.secretAm256,swap->I.privAm.bytes,sizeof(swap->I.privAm)); - swap->I.pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->I.privAm); - char str[65],str2[65]; printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); - //basilisk_bobscripts_set(myinfo,swap,0); + swap->I.pubAm = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privAm); + printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); + //basilisk_bobscripts_set(swap,0); } + return(0); } - swap->I.statebits |= 0x08; } + printf("illegal otherchoosei.%d datalen.%d vs %d\n",otherchoosei,datalen,(int32_t)(sizeof(otherchoosei)+sizeof(bits256)*2)); + return(-1); } -void basilisk_sendmostprivs(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +int32_t LP_mostprivs_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { int32_t i,j,datalen; datalen = 0; @@ -1650,408 +318,276 @@ void basilisk_sendmostprivs(struct supernet_info *myinfo,struct basilisk_swap *s for (i=0; i<32; i++) data[datalen++] = swap->I.secretAm256[i]; } - //printf("send privkeys.%d\n",datalen); - swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x20,data,datalen,0x10,swap->I.crcs_myprivs); + return(datalen); } -int32_t basilisk_swapiteration(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +int32_t basilisk_verify_pubpair(int32_t *wrongfirstbytep,struct basilisk_swap *swap,int32_t ind,uint8_t pub0,bits256 pubi,uint64_t txid) { - int32_t j,datalen,retval = 0; uint32_t savestatebits=0,saveotherbits=0; - if ( swap->I.iambob != 0 ) - swap->I.statebits |= 0x80; - while ( swap->aborted == 0 && ((swap->I.otherstatebits & 0x80) == 0 || (swap->I.statebits & 0x80) == 0) && retval == 0 && time(NULL) < swap->I.expiration ) + if ( pub0 != (swap->I.iambob ^ 1) + 0x02 ) { - if ( swap->connected == 0 ) - basilisk_psockinit(myinfo,swap,swap->I.iambob != 0); - printf("D r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL))); - if ( swap->I.iambob != 0 && (swap->I.statebits & 0x80) == 0 ) // wait for fee - { - if ( basilisk_swapget(myinfo,swap,0x80,data,maxlen,basilisk_verify_otherfee) == 0 ) - { - // verify and submit otherfee - swap->I.statebits |= 0x80; - basilisk_sendstate(myinfo,swap,data,maxlen); - } - } - else if ( swap->I.iambob == 0 ) - swap->I.statebits |= 0x80; - basilisk_sendstate(myinfo,swap,data,maxlen); - basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); - if ( (swap->I.otherstatebits & 0x80) != 0 && (swap->I.statebits & 0x80) != 0 ) - break; - if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) - sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); - savestatebits = swap->I.statebits; - saveotherbits = swap->I.otherstatebits; - basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); - basilisk_sendstate(myinfo,swap,data,maxlen); - if ( (swap->I.otherstatebits & 0x80) == 0 ) - basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40,0); + (*wrongfirstbytep)++; + printf("wrongfirstbyte[%d] %02x\n",ind,pub0); + return(-1); } - basilisk_swap_saveupdate(myinfo,swap); - while ( swap->aborted == 0 && retval == 0 && time(NULL) < swap->I.expiration ) // both sides have setup required data and paid txfee + else if ( swap->otherdeck[ind][1] != pubi.txid ) { - basilisk_swap_saveupdate(myinfo,swap); - if ( swap->connected == 0 ) - basilisk_psockinit(myinfo,swap,swap->I.iambob != 0); - //if ( (rand() % 30) == 0 ) - printf("E r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL))); - if ( swap->I.iambob != 0 ) + printf("otherdeck[%d] priv ->pub mismatch %llx != %llx\n",ind,(long long)swap->otherdeck[ind][1],(long long)pubi.txid); + return(-1); + } + else if ( swap->otherdeck[ind][0] != txid ) + { + printf("otherdeck[%d] priv mismatch %llx != %llx\n",ind,(long long)swap->otherdeck[ind][0],(long long)txid); + return(-1); + } + return(0); +} + +int32_t basilisk_verify_privi(void *ptr,uint8_t *data,int32_t datalen) +{ + int32_t j,wrongfirstbyte,len = 0; bits256 privkey,pubi; char str[65],str2[65]; uint8_t secret160[20],pubkey33[33]; uint64_t txid; struct basilisk_swap *swap = ptr; + memset(privkey.bytes,0,sizeof(privkey)); + if ( datalen == sizeof(bits256) ) + { + for (j=0; j<32; j++) + privkey.bytes[j] = data[len++]; + revcalc_rmd160_sha256(secret160,privkey);//.bytes,sizeof(privkey)); + memcpy(&txid,secret160,sizeof(txid)); + pubi = bitcoin_pubkey33(swap->ctx,pubkey33,privkey); + if ( basilisk_verify_pubpair(&wrongfirstbyte,swap,swap->I.choosei,pubkey33[0],pubi,txid) == 0 ) { - //printf("BOB\n"); - if ( (swap->I.statebits & 0x100) == 0 ) - { - printf("send bobdeposit\n"); - swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0); - } - // [BLOCKING: altfound] make sure altpayment is confirmed and send payment - else if ( (swap->I.statebits & 0x1000) == 0 ) - { - printf("check alicepayment\n"); - if ( basilisk_swapget(myinfo,swap,0x1000,data,maxlen,basilisk_verify_alicepaid) == 0 ) - { - swap->I.statebits |= 0x1000; - printf("got alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms); - } - } - else if ( (swap->I.statebits & 0x2000) == 0 ) - { - if ( (swap->I.aliceconfirms == 0 && swap->aliceunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->alicepayment) >= swap->I.aliceconfirms ) - { - swap->I.statebits |= 0x2000; - printf("alicepayment confirmed\n"); - } - } - else if ( (swap->I.statebits & 0x4000) == 0 ) - { - basilisk_bobscripts_set(myinfo,swap,0,1); - printf("send bobpayment\n"); - swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0); - } - // [BLOCKING: privM] Bob waits for privAm either from Alice or alice blockchain - else if ( (swap->I.statebits & 0xc0000) != 0xc0000 ) + if ( swap->I.iambob != 0 ) { - if ( basilisk_swapget(myinfo,swap,0x40000,data,maxlen,basilisk_verify_privi) == 0 || basilisk_privAm_extract(myinfo,swap) == 0 ) // divulges privAm - { - //printf("got privi spend alicepayment, dont divulge privBn until bobspend propagated\n"); - basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend); - if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobspend,0x40000,1) == 0 ) - printf("Bob error spending alice payment\n"); - else - { - tradebot_swap_balancingtrade(myinfo,swap,1); - printf("Bob spends alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms); - swap->I.statebits |= 0x40000; - if ( basilisk_numconfirms(myinfo,swap,&swap->bobspend) >= swap->I.aliceconfirms ) - { - printf("bobspend confirmed\n"); - swap->I.statebits |= 0x80000; - printf("Bob confirming spend of Alice's payment\n"); - sleep(DEX_SLEEP); - } - retval = 1; - } - } + swap->I.privAm = privkey; + vcalc_sha256(0,swap->I.secretAm256,privkey.bytes,sizeof(privkey)); + printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); + basilisk_bobscripts_set(swap,0,1); } - if ( swap->bobpayment.I.locktime != 0 && time(NULL) > swap->bobpayment.I.locktime ) + else { - // submit reclaim of payment - printf("bob reclaims bobpayment\n"); - swap->I.statebits |= (0x40000 | 0x80000); - if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobreclaim,0,0) == 0 ) - printf("Bob error reclaiming own payment after alice timed out\n"); - else - { - printf("Bob reclaimed own payment\n"); - while ( 0 && (swap->I.statebits & 0x100000) == 0 ) // why wait for own tx? - { - if ( basilisk_numconfirms(myinfo,swap,&swap->bobreclaim) >= 1 ) - { - printf("bobreclaim confirmed\n"); - swap->I.statebits |= 0x100000; - printf("Bob confirms reclain of payment\n"); - break; - } - } - retval = 1; - } + swap->I.privBn = privkey; + vcalc_sha256(0,swap->I.secretBn256,privkey.bytes,sizeof(privkey)); + printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256)); } + basilisk_dontforget_update(swap,0); + char str[65]; printf("privi verified.(%s)\n",bits256_str(str,privkey)); + return(0); } - else - { - //printf("ALICE\n"); - // [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment - if ( (swap->I.statebits & 0x200) == 0 ) - { - printf("checkfor deposit\n"); - if ( basilisk_swapget(myinfo,swap,0x200,data,maxlen,basilisk_verify_bobdeposit) == 0 ) - { - // verify deposit and submit, set confirmed height - printf("got bobdeposit\n"); - swap->I.statebits |= 0x200; - } else printf("no valid deposit\n"); - } - else if ( (swap->I.statebits & 0x400) == 0 ) - { - if ( basilisk_istrustedbob(myinfo,swap) != 0 || (swap->I.bobconfirms == 0 && swap->depositunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->bobdeposit) >= swap->I.bobconfirms ) - { - printf("bobdeposit confirmed\n"); - swap->I.statebits |= 0x400; - } - } - else if ( (swap->I.statebits & 0x800) == 0 ) - { - printf("send alicepayment\n"); - swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0); - } - // [BLOCKING: payfound] make sure payment is confrmed and send in spend or see bob's reclaim and claim - else if ( (swap->I.statebits & 0x8000) == 0 ) - { - if ( basilisk_swapget(myinfo,swap,0x8000,data,maxlen,basilisk_verify_bobpaid) == 0 ) - { - printf("got bobpayment\n"); - tradebot_swap_balancingtrade(myinfo,swap,0); - // verify payment and submit, set confirmed height - swap->I.statebits |= 0x8000; - } - } - else if ( (swap->I.statebits & 0x10000) == 0 ) - { - if ( basilisk_istrustedbob(myinfo,swap) != 0 || (swap->I.bobconfirms == 0 && swap->paymentunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->bobpayment) >= swap->I.bobconfirms ) - { - printf("bobpayment confirmed\n"); - swap->I.statebits |= 0x10000; - } - } - else if ( (swap->I.statebits & 0x20000) == 0 ) - { - printf("alicespend bobpayment\n"); - if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicespend,0x20000,0) != 0 )//&& (swap->aliceunconf != 0 || basilisk_numconfirms(myinfo,swap,&swap->alicespend) > 0) ) - { - swap->I.statebits |= 0x20000; - } - } - else if ( (swap->I.statebits & 0x40000) == 0 ) + } + return(-1); +} + +int32_t LP_mostprivs_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + int32_t i,j,wrongfirstbyte=0,errs=0,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33]; uint64_t txid; + //printf("verify privkeys choosei.%d otherchoosei.%d datalen.%d vs %d\n",swap->choosei,swap->otherchoosei,datalen,(int32_t)sizeof(swap->privkeys)+20+32); + memset(otherpriv.bytes,0,sizeof(otherpriv)); + if ( swap->I.cutverified == 0 && swap->I.otherchoosei >= 0 && datalen == sizeof(swap->privkeys)+20+2*32 ) + { + for (i=errs=0; iprivkeys)/sizeof(*swap->privkeys); i++) + { + for (j=0; j<32; j++) + otherpriv.bytes[j] = data[len++]; + if ( i != swap->I.choosei ) { - int32_t numconfs; - if ( (numconfs= basilisk_numconfirms(myinfo,swap,&swap->alicespend)) >= swap->I.bobconfirms ) - { - for (j=datalen=0; j<32; j++) - data[datalen++] = swap->I.privAm.bytes[j]; - printf("send privAm %x\n",swap->I.statebits); - swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x40000,data,datalen,0x20000,swap->I.crcs_mypriv); - printf("Alice confirms spend of Bob's payment\n"); - retval = 1; - } else printf("alicespend numconfs.%d < %d\n",numconfs,swap->I.bobconfirms); + pubi = bitcoin_pubkey33(swap->ctx,otherpubkey,otherpriv); + revcalc_rmd160_sha256(secret160,otherpriv);//.bytes,sizeof(otherpriv)); + memcpy(&txid,secret160,sizeof(txid)); + errs += basilisk_verify_pubpair(&wrongfirstbyte,swap,i,otherpubkey[0],pubi,txid); } - if ( swap->bobdeposit.I.locktime != 0 && time(NULL) > swap->bobdeposit.I.locktime ) + } + if ( errs == 0 && wrongfirstbyte == 0 ) + { + swap->I.cutverified = 1, printf("CUT VERIFIED\n"); + if ( swap->I.iambob != 0 ) { - printf("Alice claims deposit\n"); - if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->aliceclaim,0,0) == 0 ) - printf("Alice couldnt claim deposit\n"); - else - { - printf("Alice claimed deposit\n"); - retval = 1; - } + for (i=0; i<32; i++) + swap->I.pubAm.bytes[i] = data[len++]; + for (i=0; i<20; i++) + swap->I.secretAm[i] = data[len++]; + for (i=0; i<32; i++) + swap->I.secretAm256[i] = data[len++]; + basilisk_bobscripts_set(swap,1,1); } - else if ( swap->aborted != 0 || basilisk_privBn_extract(myinfo,swap,data,maxlen) == 0 ) + else { - printf("Alice reclaims her payment\n"); - swap->I.statebits |= 0x40000000; - if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicereclaim,0x40000000,0) == 0 ) - printf("Alice error sending alicereclaim\n"); - else - { - printf("Alice reclaimed her payment\n"); - retval = 1; - } + for (i=0; i<32; i++) + swap->I.pubBn.bytes[i] = data[len++]; + for (i=0; i<20; i++) + swap->I.secretBn[i] = data[len++]; + for (i=0; i<32; i++) + swap->I.secretBn256[i] = data[len++]; + //basilisk_bobscripts_set(swap,0); } - } - if ( (rand() % 30) == 0 ) - printf("finished swapstate.%x other.%x\n",swap->I.statebits,swap->I.otherstatebits); - if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) - sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); - savestatebits = swap->I.statebits; - saveotherbits = swap->I.otherstatebits; - basilisk_sendstate(myinfo,swap,data,maxlen); - basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + } else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs); } - return(retval); -} - -int32_t swapcompleted(struct supernet_info *myinfo,struct basilisk_swap *swap) -{ - if ( swap->I.iambob != 0 ) - return(swap->I.bobspent); - else return(swap->I.alicespent); + //printf("privkeys errs.%d wrongfirstbyte.%d\n",errs,wrongfirstbyte); + return(errs); } -cJSON *swapjson(struct supernet_info *myinfo,struct basilisk_swap *swap) +int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)) { - cJSON *retjson = cJSON_CreateObject(); - return(retjson); + void *data; int32_t datalen,retval = -1; uint32_t expiration = (uint32_t)time(NULL) + timeout; + while ( time(NULL) < expiration ) + { + if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 ) + { + retval = (*verify)(swap,data,datalen); + nn_freemsg(data); + } + } + return(retval); } -void basilisk_psockinit(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t amlp) +int32_t LP_waitsend(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)) { - char keystr[64],databuf[1024],pubkeystr[128],*retstr,*retstr2,*datastr,*pushaddr=0,*subaddr=0; cJSON *retjson,*addrjson; uint8_t data[512]; int32_t datalen,timeout,pushsock = -1,subsock = -1; - if ( swap->connected == 1 ) - return; - if ( swap->pushsock < 0 && swap->subsock < 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) - { - timeout = 1000; - nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); - swap->pushsock = pushsock; - swap->subsock = subsock; - } - if ( (subsock= swap->subsock) < 0 || (pushsock= swap->pushsock) < 0 ) - { - printf("error getting nn_sockets\n"); - return; - } - sprintf(keystr,"%08x-%08x",swap->I.req.requestid,swap->I.req.quoteid); - if ( swap->connected == 0 && (retstr= _dex_kvsearch(myinfo,"KV",keystr)) != 0 ) + int32_t datalen,sendlen,retval = -1; + if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 ) { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) + if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) { - if ( (datastr= jstr(retjson,"value")) != 0 ) + if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) { - datalen = (int32_t)strlen(datastr) >> 1; - decode_hex((uint8_t *)databuf,datalen,datastr); - if ( (addrjson= cJSON_Parse(databuf)) != 0 ) - { - pushaddr = jstr(addrjson,"push"); - subaddr = jstr(addrjson,"sub"); - if ( pushaddr != 0 && subaddr != 0 ) - { - printf("KV decoded (%s and %s) %d %d\n",pushaddr,subaddr,swap->pushsock,swap->subsock); - if ( nn_connect(swap->pushsock,pushaddr) >= 0 && nn_connect(swap->subsock,subaddr) >= 0 ) - swap->connected = 1; - } - free_json(addrjson); - } - } - free_json(retjson); + retval = 0; + } else printf("send %s error\n",statename); } - printf("KVsearch.(%s) -> (%s) connected.%d socks.(%d %d) amlp.%d\n",keystr,retstr,swap->connected,swap->pushsock,swap->subsock,amlp); - free(retstr); - } - printf("connected.%d amlp.%d subsock.%d pushsock.%d\n",swap->connected,amlp,subsock,pushsock); - if ( swap->connected <= 0 && amlp != 0 && subsock >= 0 && pushsock >= 0 ) + } else printf("didnt get pubkeys\n"); + return(retval); +} + +int32_t LP_sendwait(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)) +{ + int32_t datalen,sendlen,retval = -1; + if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) { - if ( (retstr= _dex_psock(myinfo,"{}")) != 0 ) + if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) { - printf("psock returns.(%s)\n",retstr); - // {"result":"success","pushaddr":"tcp://5.9.102.210:30002","subaddr":"tcp://5.9.102.210:30003","randipbits":3606291758,"coin":"KMD","tag":"6952562460568228137"} - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - pushaddr = jstr(retjson,"pushaddr"); - subaddr = jstr(retjson,"subaddr"); - if ( pushaddr != 0 && subaddr != 0 ) - { - if ( nn_connect(pushsock,pushaddr) >= 0 ) - { - printf("connected to %d pushaddr.(%s)\n",pushsock,pushaddr); - if ( nn_connect(subsock,subaddr) >= 0 ) - { - swap->connected = 1; - init_hexbytes_noT(pubkeystr,myinfo->persistent_pubkey33,33); - sprintf((char *)data,"{\"push\":\"%s\",\"sub\":\"%s\",\"trade\":[\"%s\", %.8f, \"%s\", %.8f],\"pub\":\"%s\"}",pushaddr,subaddr,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),pubkeystr); - datalen = (int32_t)strlen((char *)data) + 1; - printf("datalen.%d (%s)\n",datalen,(char *)data); - init_hexbytes_noT(databuf,data,datalen); - printf("%s -> %s\n",keystr,databuf); - if ( (retstr2= _dex_kvupdate(myinfo,"KV",keystr,databuf,1)) != 0 ) - { - printf("KVupdate.(%s)\n",retstr2); - free(retstr2); - } - } else printf("nn_connect error to %d subaddr.(%s)\n",subsock,subaddr); - } else printf("nn_connect error to %d pushaddr.(%s)\n",pushsock,pushaddr); - } - else printf("missing addr (%p) (%p) (%s)\n",pushaddr,subaddr,jprint(retjson,0)); - free_json(retjson); - } else printf("Error parsing psock.(%s)\n",retstr); - free(retstr); - } else printf("error issuing _dex_psock\n"); + if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 ) + retval = 0; + else printf("didnt get %s\n",statename); + } else printf("send pubkeys error\n"); } + return(retval); } -int32_t basilisk_alicetxs(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +void LP_swapsfp_update(struct basilisk_request *rp) { - int32_t i,retval = -1; - printf("alicetxs\n"); - for (i=0; i<3; i++) + static FILE *swapsfp; + if ( swapsfp == 0 ) { - if ( swap->alicepayment.I.datalen == 0 ) - basilisk_alicepayment(myinfo,swap,swap->alicepayment.coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn); - if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 ) - { - printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen); - sleep(20); - } - else - { - retval = 0; - for (i=0; ialicepayment.I.datalen; i++) - printf("%02x",swap->alicepayment.txbytes[i]); - printf(" ALICE PAYMENT created\n"); - iguana_unspents_mark(myinfo,swap->alicecoin,swap->alicepayment.vins); - basilisk_txlog(myinfo,swap,&swap->alicepayment,-1); - break; - } + char fname[512]; + sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); + if ( (swapsfp= fopen(fname,"rb+")) == 0 ) + swapsfp = fopen(fname,"wb+"); + else fseek(swapsfp,0,SEEK_END); + printf("LIST fp.%p\n",swapsfp); } - if ( swap->myfee.I.datalen == 0 ) + if ( swapsfp != 0 ) { - printf("generate fee\n"); - if ( basilisk_rawtx_gen("myfee",myinfo,swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->chain->txfee,1,0) == 0 ) + fwrite(&rp->requestid,1,sizeof(rp->requestid),swapsfp); + fwrite(&rp->quoteid,1,sizeof(rp->quoteid),swapsfp); + fflush(swapsfp); + } +} + +void LP_bobloop(void *_utxo) +{ + uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; + fprintf(stderr,"start swap iambob\n"); + maxlen = 1024*1024 + sizeof(*swap); + data = malloc(maxlen); + expiration = (uint32_t)time(NULL) + 10; + while ( (swap= utxo->swap) == 0 && time(NULL) < expiration ) + sleep(1); + if ( (utxo->swap= swap) != 0 ) + { + if ( LP_waitsend("pubkeys",10,utxo->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + printf("error waitsend pubkeys\n"); + else if ( LP_waitsend("choosei",10,utxo->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) + printf("error waitsend choosei\n"); + else if ( LP_waitsend("mostprivs",10,utxo->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) + printf("error waitsend mostprivs\n"); + else if ( basilisk_bobscripts_set(swap,1,1) < 0 ) + printf("error bobscripts\n"); + else { - swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40,0); - iguana_unspents_mark(myinfo,swap->I.iambob!=0?swap->bobcoin:swap->alicecoin,swap->myfee.vins); - basilisk_txlog(myinfo,swap,&swap->myfee,-1); - for (i=0; imyfee.I.spendlen; i++) - printf("%02x",swap->myfee.txbytes[i]); - printf(" fee %p %x\n",swap->myfee.txbytes,swap->I.statebits); - swap->I.statebits |= 0x40; + LP_swapsfp_update(&swap->I.req); + // wait alicefee + // send bobdeposit + // wait alicepayment + // send bobpayment + // bobspend + // bobrefund + // done } + } else printf("swap timed out\n"); + basilisk_swap_finished(swap); + free(utxo->swap); + utxo->swap = 0; + nn_close(utxo->pair); + utxo->pair = -1; +} + +void LP_aliceloop(void *_utxo) +{ + uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; + fprintf(stderr,"start swap iambob\n"); + maxlen = 1024*1024 + sizeof(*swap); + data = malloc(maxlen); + expiration = (uint32_t)time(NULL) + 10; + while ( (swap= utxo->swap) == 0 && time(NULL) < expiration ) + sleep(1); + if ( (utxo->swap= swap) != 0 ) + { + if ( LP_sendwait("pubkeys",10,utxo->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + printf("error LP_sendwait pubkeys\n"); + else if ( LP_sendwait("choosei",10,utxo->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) + printf("error LP_sendwait choosei\n"); + else if ( LP_sendwait("mostprivs",10,utxo->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) + printf("error LP_sendwait mostprivs\n"); + else if ( basilisk_alicetxs(swap,data,maxlen) != 0 ) + printf("basilisk_alicetxs error\n"); else { - printf("error creating myfee\n"); - return(-2); + LP_swapsfp_update(&swap->I.req); + // send alicefee + // wait bobdeposit + // send alicepayment + // wait bobpayment + // alicespend + // done } - } - if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 && swap->myfee.I.datalen != 0 && swap->myfee.I.spendlen > 0 ) - return(0); - return(-1); + } else printf("swap timed out\n"); + basilisk_swap_finished(swap); + free(utxo->swap); + utxo->swap = 0; + nn_close(utxo->pair); + utxo->pair = -1; } -void basilisk_swaploop(void *_swap) +#ifdef old +void basilisk_swaploop(void *_utxo) { - uint8_t *data; uint32_t expiration,savestatebits=0,saveotherbits=0; uint32_t channel; int32_t iters,retval=0,j,datalen,maxlen; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap; - myinfo = swap->myinfoptr; - fprintf(stderr,"start swap\n"); + uint8_t *data; uint32_t expiration,savestatebits=0,saveotherbits=0; uint32_t channel; int32_t iters,retval=0,j,datalen,maxlen; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; + swap = utxo->swap; + fprintf(stderr,"start swap iambob.%d\n",swap->I.iambob); maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); expiration = (uint32_t)time(NULL) + 300; - myinfo->DEXactive = expiration; + //myinfo->DEXactive = expiration; channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16); while ( swap->aborted == 0 && (swap->I.statebits & (0x08|0x02)) != (0x08|0x02) && time(NULL) < expiration ) { - dex_channelsend(myinfo,swap->I.req.srchash,swap->I.req.desthash,channel,0x4000000,(void *)&swap->I.req.requestid,sizeof(swap->I.req.requestid)); //,60); + LP_channelsend(swap->I.req.srchash,swap->I.req.desthash,channel,0x4000000,(void *)&swap->I.req.requestid,sizeof(swap->I.req.requestid)); //,60); if ( swap->connected == 0 ) - basilisk_psockinit(myinfo,swap,swap->I.iambob != 0); + basilisk_psockinit(swap,swap->I.iambob != 0); if ( swap->connected > 0 ) { printf("A r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits); - basilisk_sendstate(myinfo,swap,data,maxlen); - basilisk_sendpubkeys(myinfo,swap,data,maxlen); // send pubkeys - if ( basilisk_checkdeck(myinfo,swap,data,maxlen) == 0) // check for other deck 0x02 - basilisk_sendchoosei(myinfo,swap,data,maxlen); - basilisk_waitchoosei(myinfo,swap,data,maxlen); // wait for choosei 0x08 + basilisk_sendstate(swap,data,maxlen); + basilisk_sendpubkeys(swap,data,maxlen); // send pubkeys + if ( basilisk_checkdeck(swap,data,maxlen) == 0) // check for other deck 0x02 + basilisk_sendchoosei(swap,data,maxlen); + basilisk_waitchoosei(swap,data,maxlen); // wait for choosei 0x08 if ( (swap->I.statebits & (0x08|0x02)) == (0x08|0x02) ) break; } @@ -2068,12 +604,12 @@ void basilisk_swaploop(void *_swap) while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x20) == 0 ) { if ( swap->connected == 0 ) - basilisk_psockinit(myinfo,swap,swap->I.iambob != 0); + basilisk_psockinit(swap,swap->I.iambob != 0); printf("B r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits); - basilisk_sendstate(myinfo,swap,data,maxlen); - basilisk_sendchoosei(myinfo,swap,data,maxlen); - basilisk_sendmostprivs(myinfo,swap,data,maxlen); - if ( basilisk_swapget(myinfo,swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 ) + basilisk_sendstate(swap,data,maxlen); + basilisk_sendchoosei(swap,data,maxlen); + basilisk_sendmostprivs(swap,data,maxlen); + if ( basilisk_swapget(swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 ) { swap->I.statebits |= 0x20; break; @@ -2085,11 +621,11 @@ void basilisk_swaploop(void *_swap) if ( time(NULL) > expiration ) break; } - myinfo->DEXactive = swap->I.expiration; + //myinfo->DEXactive = swap->I.expiration; if ( time(NULL) >= expiration ) { retval = -1; - myinfo->DEXactive = 0; + //myinfo->DEXactive = 0; } if ( swap->aborted != 0 ) { @@ -2101,16 +637,16 @@ void basilisk_swaploop(void *_swap) while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x40) == 0 && iters++ < 10 ) // send fee { if ( swap->connected == 0 ) - basilisk_psockinit(myinfo,swap,swap->I.iambob != 0); + basilisk_psockinit(swap,swap->I.iambob != 0); //printf("sendstate.%x\n",swap->I.statebits); - basilisk_sendstate(myinfo,swap,data,maxlen); + basilisk_sendstate(swap,data,maxlen); //printf("swapget\n"); - basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); //printf("after swapget\n"); if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 ) { printf("bobscripts set\n"); - if ( basilisk_bobscripts_set(myinfo,swap,1,1) < 0 ) + if ( basilisk_bobscripts_set(swap,1,1) < 0 ) { sleep(DEX_SLEEP); printf("bobscripts set error\n"); @@ -2149,7 +685,7 @@ void basilisk_swaploop(void *_swap) for (i=0; i<32; i++) printf("%02x",swap->pubB1.bytes[i]); printf(" <- pubB1\n");*/ - if ( (retval= basilisk_alicetxs(myinfo,swap,data,maxlen)) != 0 ) + if ( (retval= basilisk_alicetxs(swap,data,maxlen)) != 0 ) { printf("basilisk_alicetxs error\n"); break; @@ -2174,15 +710,15 @@ void basilisk_swaploop(void *_swap) retval = -7; } } - while ( swap->aborted == 0 && retval == 0 && basilisk_swapiteration(myinfo,swap,data,maxlen) == 0 ) + while ( swap->aborted == 0 && retval == 0 && basilisk_swapiteration(swap,data,maxlen) == 0 ) { if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); savestatebits = swap->I.statebits; saveotherbits = swap->I.otherstatebits; - basilisk_sendstate(myinfo,swap,data,maxlen); - basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); - basilisk_swap_saveupdate(myinfo,swap); + basilisk_sendstate(swap,data,maxlen); + basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + basilisk_swap_saveupdate(swap); if ( time(NULL) > swap->I.expiration ) break; } @@ -2191,8 +727,8 @@ void basilisk_swaploop(void *_swap) printf("BOB waiting for confirm state.%x\n",swap->I.statebits); sleep(60); // wait for confirm/propagation of msig printf("BOB reclaims refund\n"); - basilisk_bobdeposit_refund(myinfo,swap,0); - if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobrefund,0x40000000,0) == 0 ) // use secretBn + basilisk_bobdeposit_refund(swap,0); + if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->bobrefund,0x40000000,0) == 0 ) // use secretBn { printf("Bob submit error getting refund of deposit\n"); } @@ -2201,47 +737,279 @@ void basilisk_swaploop(void *_swap) // maybe wait for bobrefund to be confirmed for (j=datalen=0; j<32; j++) data[datalen++] = swap->I.privBn.bytes[j]; - basilisk_swapsend(myinfo,swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv); + LP_swapsend(swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv); } - basilisk_swap_saveupdate(myinfo,swap); + basilisk_swap_saveupdate(swap); } if ( retval != 0 ) - basilisk_swap_sendabort(myinfo,swap); + basilisk_swap_sendabort(swap); printf("end of atomic swap\n"); - if ( swapcompleted(myinfo,swap) > 0 ) // only if swap completed + if ( swapcompleted(swap) > 0 ) // only if swap completed { if ( swap->I.iambob != 0 ) - tradebot_pendingadd(myinfo,swapjson(myinfo,swap),swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount)); - else tradebot_pendingadd(myinfo,swapjson(myinfo,swap),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.src,dstr(swap->I.req.srcamount)); + tradebot_pendingadd(swapjson(swap),swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount)); + else tradebot_pendingadd(swapjson(swap),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.src,dstr(swap->I.req.srcamount)); } printf("%s swap finished statebits %x\n",swap->I.iambob!=0?"BOB":"ALICE",swap->I.statebits); - basilisk_swap_purge(myinfo,swap); + //basilisk_swap_purge(swap); free(data); } +#endif + +bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) +{ + bits256 sharedsecret; + sharedsecret = curve25519_shared(privkey,orderhash); + vcalc_sha256cat(newprivp->bytes,orderhash.bytes,sizeof(orderhash),sharedsecret.bytes,sizeof(sharedsecret)); + return(bitcoin_pubkey33(ctx,pubkey,*newprivp)); +} + +bits256 basilisk_revealkey(bits256 privkey,bits256 pubkey) +{ + bits256 reveal; +#ifdef DISABLE_CHECKSIG + vcalc_sha256(0,reveal.bytes,privkey.bytes,sizeof(privkey)); + //reveal = revcalc_sha256(privkey); + char str[65],str2[65]; printf("priv.(%s) -> reveal.(%s)\n",bits256_str(str,privkey),bits256_str(str2,reveal)); +#else + reveal = pubkey; +#endif + return(reveal); +} + +int32_t instantdex_pubkeyargs(struct basilisk_swap *swap,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte) +{ + char buf[3]; int32_t i,n,m,len=0; bits256 pubi,reveal; uint64_t txid; uint8_t secret160[20],pubkey[33]; + sprintf(buf,"%c0",'A' - 0x02 + firstbyte); + if ( numpubs > 2 ) + { + if ( swap->I.numpubs+2 >= numpubs ) + return(numpubs); + //fprintf(stderr,">>>>>> start generating %s\n",buf); + } + for (i=n=m=0; ictx,&privkey,pubkey,privkey,hash); + //fprintf(stderr,"i.%d n.%d numpubs.%d %02x vs %02x\n",i,n,numpubs,pubkey[0],firstbyte); + if ( pubkey[0] != firstbyte ) + continue; + if ( n < 2 ) + { + if ( bits256_nonz(swap->I.mypubs[n]) == 0 ) + { + swap->I.myprivs[n] = privkey; + memcpy(swap->I.mypubs[n].bytes,pubkey+1,sizeof(bits256)); + reveal = basilisk_revealkey(privkey,swap->I.mypubs[n]); + if ( swap->I.iambob != 0 ) + { + if ( n == 0 ) + swap->I.pubB0 = reveal; + else if ( n == 1 ) + swap->I.pubB1 = reveal; + } + else if ( swap->I.iambob == 0 ) + { + if ( n == 0 ) + swap->I.pubA0 = reveal; + else if ( n == 1 ) + swap->I.pubA1 = reveal; + } + } + } + if ( m < INSTANTDEX_DECKSIZE ) + { + swap->privkeys[m] = privkey; + revcalc_rmd160_sha256(secret160,privkey);//.bytes,sizeof(privkey)); + memcpy(&txid,secret160,sizeof(txid)); + len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][0],sizeof(txid),&txid); + len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][1],sizeof(pubi.txid),&pubi.txid); + m++; + if ( m > swap->I.numpubs ) + swap->I.numpubs = m; + } + n++; + } + if ( n > 2 || m > 2 ) + printf("n.%d m.%d len.%d numpubs.%d\n",n,m,len,swap->I.numpubs); + return(n); +} + +void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33,int32_t jumblrflag) +{ + strcpy(rawtx->name,name); + rawtx->coin = coin; + strcpy(rawtx->I.coinstr,coin->symbol); + rawtx->I.numconfirms = numconfirms; + if ( (rawtx->I.amount= satoshis) < 50000 ) + rawtx->I.amount = 50000; + rawtx->I.vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit + rawtx->I.vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit + if ( rawtx->I.vouttype == 0 ) + { + if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 ) + decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160); + else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160); + bitcoin_address(rawtx->I.destaddr,rawtx->coin->pubtype,rawtx->I.rmd160,20); + } + if ( pubkey33 != 0 ) + { + memcpy(rawtx->I.pubkey33,pubkey33,33); + bitcoin_address(rawtx->I.destaddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33); + bitcoin_addr2rmd160(&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr); + } + if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 ) + { + rawtx->I.spendlen = bitcoin_standardspend(rawtx->spendscript,0,rawtx->I.rmd160); + printf("%s spendlen.%d %s <- %.8f\n",name,rawtx->I.spendlen,rawtx->I.destaddr,dstr(rawtx->I.amount)); + } else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr); +} + +struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits) +{ + //FILE *fp; char fname[512]; + uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *coin; + swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME; + if ( optionduration < 0 ) + swap->I.putduration -= optionduration; + else if ( optionduration > 0 ) + swap->I.callduration += optionduration; + swap->I.bobsatoshis = swap->I.req.destamount; + swap->I.alicesatoshis = swap->I.req.srcamount; + if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 ) + swap->I.bobinsurance = 50000; + if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 ) + swap->I.aliceinsurance = 50000; + strcpy(swap->I.bobstr,swap->I.req.dest); + strcpy(swap->I.alicestr,swap->I.req.src); + swap->I.started = (uint32_t)time(NULL); + swap->I.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration; + OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei)); + if ( swap->I.choosei < 0 ) + swap->I.choosei = -swap->I.choosei; + swap->I.choosei %= INSTANTDEX_DECKSIZE; + swap->I.otherchoosei = -1; + swap->I.myhash = pubkey25519; + if ( statebits != 0 ) + { + swap->I.iambob = 0; + swap->I.otherhash = swap->I.req.desthash; + } + else + { + swap->I.iambob = 1; + swap->I.otherhash = swap->I.req.srchash; + } + if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE ) + { + char str[65]; printf("couldnt generate privkeys %d %s\n",x,bits256_str(str,privkey)); + return(0); + } + if ( (coin= LP_coinfind(swap->I.req.dest)) != 0 ) + swap->bobcoin = *coin; + else + { + printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); + free(swap); + return(0); + } + if ( (coin= LP_coinfind(swap->I.req.src)) != 0 ) + swap->alicecoin = *coin; + else + { + printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); + free(swap); + return(0); + } + if ( strcmp("BTC",swap->bobcoin.symbol) == 0 ) + { + swap->I.bobconfirms = (1*0 + sqrt(dstr(swap->I.bobsatoshis) * .1)); + swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); + } + else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 ) + { + swap->I.aliceconfirms = (1*0 + sqrt(dstr(swap->I.alicesatoshis) * .1)); + swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); + } + else + { + swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; + swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; + } + /*if ( swap->I.bobconfirms == 0 ) + swap->I.bobconfirms = swap->bobcoin->chain->minconfirms; + if ( swap->I.aliceconfirms == 0 ) + swap->I.aliceconfirms = swap->alicecoin->chain->minconfirms;*/ + //jumblrflag = (bits256_cmp(pubkey25519,myinfo->jumblr_pubkey) == 0 || bits256_cmp(pubkey25519,myinfo->jumblr_depositkey) == 0); + printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms); + if ( swap->I.iambob != 0 ) + { + basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); + basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); + bobpub33 = pubkey33; + } + else + { + basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); + basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); + alicepub33 = pubkey33; + } + basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,&swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3) + swap->bobcoin.txfee,4,0,jumblrflag); + basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,&swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,bobpub33,jumblrflag); + swap->bobrefund.I.suppress_pubkeys = 1; + basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,&swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,alicepub33,jumblrflag); + swap->aliceclaim.I.suppress_pubkeys = 1; + swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 1; + + basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,&swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + swap->bobcoin.txfee,3,0,jumblrflag); + basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,&swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag); + swap->alicespend.I.suppress_pubkeys = 1; + basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,&swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag); + swap->bobreclaim.I.suppress_pubkeys = 1; + swap->bobreclaim.I.locktime = swap->I.started + swap->I.putduration + 1; + basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,&swap->alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis+swap->alicecoin.txfee,2,0,jumblrflag); + basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag); + swap->bobspend.I.suppress_pubkeys = 1; + basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag); + swap->alicereclaim.I.suppress_pubkeys = 1; + printf("IAMBOB.%d\n",swap->I.iambob); + return(swap); +} -cJSON *basilisk_swapjson(struct supernet_info *myinfo,struct basilisk_swap *swap) +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp) { - cJSON *item = cJSON_CreateObject(); - jaddnum(item,"requestid",swap->I.req.requestid); - jaddnum(item,"quoteid",swap->I.req.quoteid); - jaddnum(item,"state",swap->I.statebits); - jaddnum(item,"otherstate",swap->I.otherstatebits); - jadd(item,"request",basilisk_requestjson(&swap->I.req)); - return(item); + struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33]; + swap = calloc(1,sizeof(*swap)); + swap->ctx = bitcoin_ctx(); + vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp)); + swap->I.req = *rp; + printf("basilisk_thread_start request.%u iambob.%d (%s/%s)\n",rp->requestid,iambob,rp->src,rp->dest); + bitcoin_pubkey33(swap->ctx,pubkey33,privkey); + pubkey25519 = curve25519(privkey,curve25519_basepoint9()); + swap->persistent_pubkey = pubkey25519; + swap->persistent_privkey = privkey; + memcpy(swap->persistent_pubkey33,pubkey33,33); + if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob) == 0 ) + { + printf("error doing swapinit\n"); + free(swap); + swap = 0; + } + return(swap); } -struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) +#ifdef notanymore +struct basilisk_swap *basilisk_thread_start(bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) { int32_t i,m,n,iter; uint8_t pubkey33[33]; bits256 pubkey25519; uint32_t channel,starttime; cJSON *retarray,*item,*msgobj; struct iguana_info *coin; double pending=0.; struct basilisk_swap *swap = 0; // statebits 1 -> client, 0 -> LP - if ( myinfo->numswaps > 0 ) + /*if ( myinfo->numswaps > 0 ) { - if ( (coin= iguana_coinfind(rp->src)) == 0 || coin->FULLNODE >= 0 ) + if ( (coin= LP_coinfind(rp->src)) == 0 || coin->FULLNODE >= 0 ) { printf("dont have SRC coin.%s or not native and already swap pending\n",rp->src); return(0); } - if ( (coin= iguana_coinfind(rp->dest)) == 0 || coin->FULLNODE >= 0 ) + if ( (coin= LP_coinfind(rp->dest)) == 0 || coin->FULLNODE >= 0 ) { printf("dont have DEST coin.%s or not native and already swap pending\n",rp->dest); return(0); @@ -2254,31 +1022,32 @@ struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 printf("basilisk_thread_start error trying to start requestid.%u which is already started\n",rp->requestid); break; } - if ( i == myinfo->numswaps && i < sizeof(myinfo->swaps)/sizeof(*myinfo->swaps) ) + if ( i == myinfo->numswaps && i < sizeof(myinfo->swaps)/sizeof(*myinfo->swaps) )*/ { swap = calloc(1,sizeof(*swap)); + swap->ctx = bitcoin_ctx(); swap->subsock = swap->pushsock = -1; vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp)); swap->I.req = *rp; - swap->myinfoptr = myinfo; + //swap->myinfoptr = myinfo; printf("basilisk_thread_start request.%u statebits.%d (%s/%s) reinit.%d\n",rp->requestid,statebits,rp->src,rp->dest,reinit); - bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); + bitcoin_pubkey33(swap->ctx,pubkey33,privkey); pubkey25519 = curve25519(privkey,curve25519_basepoint9()); swap->persistent_pubkey = pubkey25519; swap->persistent_privkey = privkey; memcpy(swap->persistent_pubkey33,pubkey33,33); m = n = 0; - if ( bitcoin_swapinit(myinfo,privkey,pubkey33,pubkey25519,swap,optionduration,statebits,reinit) != 0 ) + if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,statebits,reinit) != 0 ) { for (iter=0; iter<16; iter++) { - basilisk_psockinit(myinfo,swap,statebits == 0); + basilisk_psockinit(swap,statebits == 0); sleep(3); if ( swap->connected > 0 ) break; sleep(10); - /*basilisk_sendstate(myinfo,swap,data,sizeof(data)); - basilisk_swapget(myinfo,swap,0x80000000,data,sizeof(data),basilisk_verify_statebits); + /*basilisk_sendstate(swap,data,sizeof(data)); + basilisk_swapget(swap,0x80000000,data,sizeof(data),basilisk_verify_statebits); if ( swap->connected > 0 ) break; printf("loopback didntwork with %d %d\n",swap->pushsock,swap->subsock);*/ @@ -2289,7 +1058,7 @@ struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 { } - myinfo->swaps[myinfo->numswaps++] = swap; + //myinfo->swaps[myinfo->numswaps++] = swap; } else { @@ -2304,9 +1073,9 @@ struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16); datalen = basilisk_rwDEXquote(1,data,rp); msgid = (uint32_t)time(NULL); - printf("other req.%d >>>>>>>>>>> send response (%llx -> %llx) last.%u r.%u quoteid.%u\n",i,(long long)rp->desthash.txid,(long long)rp->srchash.txid,myinfo->lastdexrequestid,rp->requestid,rp->quoteid); - dex_channelsend(myinfo,rp->desthash,rp->srchash,channel,msgid,data,datalen); - if ( (retarray= basilisk_channelget(myinfo,rp->srchash,rp->desthash,channel,0x4000000,30)) != 0 ) + printf("other req.%d >>>>>>>>>>> send response (%llx -> %llx) r.%u quoteid.%u\n",i,(long long)rp->desthash.txid,(long long)rp->srchash.txid,rp->requestid,rp->quoteid); + LP_channelsend(rp->desthash,rp->srchash,channel,msgid,data,datalen); + if ( (retarray= basilisk_channelget(rp->srchash,rp->desthash,channel,0x4000000,30)) != 0 ) { if ( is_cJSON_Array(retarray) != 0 && (n= cJSON_GetArraySize(retarray)) > 0 ) { @@ -2329,39 +1098,39 @@ struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 { //for (i=0; iI.req); i++) // fprintf(stderr,"%02x",((uint8_t *)&swap->I.req)[i]); - fprintf(stderr," M.%d N.%d launch.%d %d %p reinit.%d\n",m,n,myinfo->numswaps,(int32_t)(sizeof(myinfo->swaps)/sizeof(*myinfo->swaps)),&swap->I.req,reinit); - if ( (swap->fp= basilisk_swap_save(myinfo,swap,privkey,rp,statebits,optionduration,reinit)) != 0 ) + if ( (swap->fp= basilisk_swap_save(swap,privkey,rp,statebits,optionduration,reinit)) != 0 ) { } if ( reinit == 0 ) { - if ( myinfo->swapsfp == 0 ) + static FILE *swapsfp; + if ( swapsfp == 0 ) { char fname[512]; sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); - if ( (myinfo->swapsfp= fopen(fname,"rb+")) == 0 ) - myinfo->swapsfp = fopen(fname,"wb+"); - else fseek(myinfo->swapsfp,0,SEEK_END); - printf("LIST fp.%p\n",myinfo->swapsfp); + if ( (swapsfp= fopen(fname,"rb+")) == 0 ) + swapsfp = fopen(fname,"wb+"); + else fseek(swapsfp,0,SEEK_END); + printf("LIST fp.%p\n",swapsfp); } - if ( myinfo->swapsfp != 0 ) + if ( swapsfp != 0 ) { - fwrite(&rp->requestid,1,sizeof(rp->requestid),myinfo->swapsfp); - fwrite(&rp->quoteid,1,sizeof(rp->quoteid),myinfo->swapsfp); - fflush(myinfo->swapsfp); + fwrite(&rp->requestid,1,sizeof(rp->requestid),swapsfp); + fwrite(&rp->quoteid,1,sizeof(rp->quoteid),swapsfp); + fflush(swapsfp); } } if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 ) { } - myinfo->swaps[myinfo->numswaps++] = swap; + //myinfo->swaps[myinfo->numswaps++] = swap; } else { if ( statebits != 0 ) { - if ( (coin= iguana_coinfind(rp->src)) != 0 ) + if ( (coin= LP_coinfind(rp->src)) != 0 ) { } @@ -2371,9 +1140,9 @@ struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 } } } - portable_mutex_unlock(&myinfo->DEX_swapmutex); + //portable_mutex_unlock(&myinfo->DEX_swapmutex); return(swap); } +#endif -/////////////// remember functions diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c new file mode 100644 index 000000000..2512c83f9 --- /dev/null +++ b/iguana/exchanges/LP_transaction.c @@ -0,0 +1,1657 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_transaction.c +// marketmaker +// + + + +#ifdef later +int32_t iguana_msgtx_Vset(uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,struct vin_info *V) +{ + int32_t vini,j,scriptlen,p2shlen,userdatalen,siglen,plen,need_op0=0,len = 0; uint8_t *script,*redeemscript=0,*userdata=0; struct vin_info *vp; + for (vini=0; vinitx_in; vini++) + { + vp = &V[vini]; + if ( (userdatalen= vp->userdatalen) == 0 ) + { + userdatalen = vp->userdatalen = msgtx->vins[vini].userdatalen; + userdata = msgtx->vins[vini].userdata; + } else userdata = vp->userdata; + if ( (p2shlen= vp->p2shlen) == 0 ) + { + p2shlen = vp->p2shlen = msgtx->vins[vini].p2shlen; + redeemscript = msgtx->vins[vini].redeemscript; + } + else + { + redeemscript = vp->p2shscript; + msgtx->vins[vini].redeemscript = redeemscript; + } + if ( msgtx->vins[vini].spendlen > 33 && msgtx->vins[vini].spendscript[msgtx->vins[vini].spendlen - 1] == SCRIPT_OP_CHECKMULTISIG ) + { + need_op0 = 1; + printf("found multisig spendscript\n"); + } + if ( redeemscript != 0 && p2shlen > 33 && redeemscript[p2shlen - 1] == SCRIPT_OP_CHECKMULTISIG ) + { + need_op0 = 1; + //printf("found multisig redeemscript\n"); + } + msgtx->vins[vini].vinscript = script = &serialized[len]; + msgtx->vins[vini].vinscript[0] = 0; + scriptlen = need_op0; + for (j=0; jN; j++) + { + if ( (siglen= vp->signers[j].siglen) > 0 ) + { + script[scriptlen++] = siglen; + memcpy(&script[scriptlen],vp->signers[j].sig,siglen); + scriptlen += siglen; + } + } + msgtx->vins[vini].scriptlen = scriptlen; + if ( vp->suppress_pubkeys == 0 && (vp->N > 1 || bitcoin_pubkeylen(&vp->spendscript[1]) != vp->spendscript[0] || vp->spendscript[vp->spendlen-1] != 0xac) ) + { + for (j=0; jN; j++) + { + if ( (plen= bitcoin_pubkeylen(vp->signers[j].pubkey)) > 0 ) + { + script[scriptlen++] = plen; + memcpy(&script[scriptlen],vp->signers[j].pubkey,plen); + scriptlen += plen; + } + } + msgtx->vins[vini].scriptlen = scriptlen; + } + if ( userdatalen != 0 ) + { + memcpy(&script[scriptlen],userdata,userdatalen); + msgtx->vins[vini].userdata = &script[scriptlen]; + msgtx->vins[vini].userdatalen = userdatalen; + scriptlen += userdatalen; + } + //printf("USERDATALEN.%d scriptlen.%d redeemlen.%d\n",userdatalen,scriptlen,p2shlen); + if ( p2shlen != 0 ) + { + if ( p2shlen < 76 ) + script[scriptlen++] = p2shlen; + else if ( p2shlen <= 0xff ) + { + script[scriptlen++] = 0x4c; + script[scriptlen++] = p2shlen; + } + else if ( p2shlen <= 0xffff ) + { + script[scriptlen++] = 0x4d; + script[scriptlen++] = (p2shlen & 0xff); + script[scriptlen++] = ((p2shlen >> 8) & 0xff); + } else return(-1); + msgtx->vins[vini].p2shlen = p2shlen; + memcpy(&script[scriptlen],redeemscript,p2shlen); + scriptlen += p2shlen; + } + len += scriptlen; + } + if ( (0) ) + { + int32_t i; for (i=0; itx_out; + vpnstr[0] = 0; + *signedtx = 0; + memset(signedtxidp,0,sizeof(*signedtxidp)); + for (vini=0; vinitx_in; vini++) + { + if ( V->p2shscript[0] != 0 && V->p2shlen != 0 ) + { + script = V->p2shscript; + scriptlen = V->p2shlen; + //printf("V->p2shlen.%d\n",V->p2shlen); + } + else + { + script = msgtx->vins[vini].spendscript; + scriptlen = msgtx->vins[vini].spendlen; + } + sigtxid = bitcoin_sigtxid(pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys); + if ( bits256_nonz(sigtxid) != 0 ) + { + vp = &V[vini]; + vp->sigtxid = sigtxid; + for (j=numsigs=0; jN; j++) + { + sig = vp->signers[j].sig; + siglen = vp->signers[j].siglen; + if ( signtx != 0 && bits256_nonz(vp->signers[j].privkey) != 0 ) + { + siglen = bitcoin_sign(swap->ctx,sig,sigtxid,vp->signers[j].privkey,0); + //if ( (plen= bitcoin_pubkeylen(vp->signers[j].pubkey)) <= 0 ) + bitcoin_pubkey33(swap->ctx,vp->signers[j].pubkey,vp->signers[j].privkey); + sig[siglen++] = sighash; + vp->signers[j].siglen = siglen; + /*char str[65]; printf("SIGTXID.(%s) ",bits256_str(str,sigtxid)); + int32_t i; for (i=0; isigners[j].pubkey[i]); + // s2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1; + printf(" SIGNEDTX.[%02x] siglen.%d priv.%s\n",sig[siglen-1],siglen,bits256_str(str,vp->signers[j].privkey));*/ + } + if ( sig == 0 || siglen == 0 ) + { + memset(vp->signers[j].pubkey,0,sizeof(vp->signers[j].pubkey)); + continue; + } + if ( bitcoin_verify(sig,siglen-1,sigtxid,vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 ) + { + int32_t k; for (k=0; ksigners[j].pubkey); k++) + printf("%02x",vp->signers[j].pubkey[k]); + printf(" SIG.%d.%d ERROR siglen.%d\n",vini,j,siglen); + } + else + { + flag++; + numsigs++; + /*int32_t z; + for (z=0; zsigners[j].pubkey[z]); + printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d\n",vini,j,numsigs,vp->M);*/ + } + } + if ( numsigs >= vp->M ) + complete = 1; + } + } + iguana_msgtx_Vset(serialized,maxlen,msgtx,V); + cJSON *txobj = cJSON_CreateObject(); + *signedtx = iguana_rawtxbytes(pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys); + //printf("SIGNEDTX.(%s)\n",jprint(txobj,1)); + *signedtxidp = msgtx->txid; + return(complete); +} + +int32_t iguana_vininfo_create(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msgtx,cJSON *vins,int32_t numinputs,struct vin_info *V) +{ + int32_t i,plen,finalized = 1,len = 0; struct vin_info *vp; //struct iguana_waccount *wacct; struct iguana_waddress *waddr; uint32_t sigsize,pubkeysize,p2shsize,userdatalen; + msgtx->tx_in = numinputs; + maxsize -= (sizeof(struct iguana_msgvin) * msgtx->tx_in); + msgtx->vins = (struct iguana_msgvin *)&serialized[maxsize]; + memset(msgtx->vins,0,sizeof(struct iguana_msgvin) * msgtx->tx_in); + if ( msgtx->tx_in > 0 && msgtx->tx_in*sizeof(struct iguana_msgvin) < maxsize ) + { + for (i=0; itx_in; i++) + { + vp = &V[i]; + //printf("VINS.(%s)\n",jprint(jitem(vins,i),0)); + len += iguana_parsevinobj(&serialized[len],maxsize,&msgtx->vins[i],jitem(vins,i),vp); + if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL ) + finalized = 0; + if ( msgtx->vins[i].spendscript == 0 ) + { + /*if ( iguana_RTunspentindfind(coin,&outpt,vp->coinaddr,vp->spendscript,&vp->spendlen,&vp->amount,&vp->height,msgtx->vins[i].prev_hash,msgtx->vins[i].prev_vout,coin->bundlescount-1,0) == 0 ) + { + vp->unspentind = outpt.unspentind; + msgtx->vins[i].spendscript = vp->spendscript; + msgtx->vins[i].spendlen = vp->spendlen; + vp->hashtype = iguana_vinscriptparse(coin,vp,&sigsize,&pubkeysize,&p2shsize,&userdatalen,vp->spendscript,vp->spendlen); + vp->userdatalen = userdatalen; + printf("V %.8f (%s) spendscript.[%d] userdatalen.%d\n",dstr(vp->amount),vp->coinaddr,vp->spendlen,userdatalen); + }*/ + } + else + { + memcpy(vp->spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); + vp->spendlen = msgtx->vins[i].spendlen; + _iguana_calcrmd160(pubtype,p2shtype,vp); + if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) > 0 ) + bitcoin_address(vp->coinaddr,pubtype,vp->signers[0].pubkey,plen); + } + if ( vp->M == 0 && vp->N == 0 ) + vp->M = vp->N = 1; + /*if ( vp->coinaddr[i] != 0 && (waddr= iguana_waddresssearch(&wacct,vp->coinaddr)) != 0 ) + { + vp->signers[0].privkey = waddr->privkey; + if ( (plen= bitcoin_pubkeylen(waddr->pubkey)) != vp->spendscript[1] || vp->spendscript[vp->spendlen-1] != 0xac ) + { + if ( plen > 0 && plen < sizeof(vp->signers[0].pubkey) ) + memcpy(vp->signers[0].pubkey,waddr->pubkey,plen); + } + }*/ + } + } + return(finalized); +} + +void iguana_ensure_privkey(struct iguana_info *coin,bits256 privkey) +{ + uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char coinaddr[128]; + bitcoin_pubkey33(swap->ctx,pubkey33,privkey); + bitcoin_address(coinaddr,coin->pubtype,pubkey33,33); + //printf("privkey for (%s)\n",coinaddr); + if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) ) + { + if ( waddr == 0 ) + { + memset(&addr,0,sizeof(addr)); + iguana_waddresscalc(coin->pubtype,coin->wiftype,&addr,privkey); + if ( (wacct= iguana_waccountfind("default")) != 0 ) + waddr = iguana_waddressadd(coin,wacct,&addr,0); + } + if ( waddr != 0 ) + { + waddr->privkey = privkey; + if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->wiftype) > 0 ) + { + if ( (0) && waddr->wiftype != coin->wiftype ) + printf("ensurepriv warning: mismatched wiftype %02x != %02x\n",waddr->wiftype,coin->wiftype); + if ( (0) && waddr->addrtype != coin->pubtype ) + printf("ensurepriv warning: mismatched addrtype %02x != %02x\n",waddr->addrtype,coin->pubtype); + } + } + } +} + +int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLockTime,struct vin_info *V,int32_t numvins) +{ + uint8_t script[IGUANA_MAXSCRIPTSIZE],*activescript,savescript[IGUANA_MAXSCRIPTSIZE]; char str[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t vini,scriptlen,activescriptlen,savelen,errs = 0; cJSON *spendscript,*item=0; + for (vini=0; vini 0 ) + { + activescript = V[vini].p2shscript; + activescriptlen = V[vini].p2shlen; + } + else + { + activescript = V[vini].spendscript; + activescriptlen = V[vini].spendlen; + } + memcpy(V[vini].spendscript,activescript,activescriptlen); + V[vini].spendlen = activescriptlen; + spendscript = iguana_spendasm(coin,activescript,activescriptlen); + if ( activescriptlen < 16 ) + continue; + //printf("interpreter.(%s)\n",jprint(spendscript,0)); + if ( (scriptlen= bitcoin_assembler(coin,logarray,script,spendscript,1,nLockTime,&V[vini])) < 0 ) + { + //printf("bitcoin_assembler error scriptlen.%d\n",scriptlen); + errs++; + } + else if ( scriptlen != activescriptlen || memcmp(script,activescript,scriptlen) != 0 ) + { + if ( logarray != 0 ) + { + item = cJSON_CreateObject(); + jaddstr(item,"error","script reconstruction failed"); + } + init_hexbytes_noT(str,activescript,activescriptlen); + //printf("activescript.(%s)\n",str); + if ( logarray != 0 && item != 0 ) + jaddstr(item,"original",str); + init_hexbytes_noT(str,script,scriptlen); + //printf("reconstructed.(%s)\n",str); + if ( logarray != 0 ) + { + jaddstr(item,"reconstructed",str); + jaddi(logarray,item); + } else printf(" scriptlen mismatch.%d vs %d or miscompare\n",scriptlen,activescriptlen); + errs++; + } + memcpy(V[vini].spendscript,savescript,savelen); + V[vini].spendlen = savelen; + } + if ( errs != 0 ) + return(-errs); + if ( logarray != 0 ) + { + item = cJSON_CreateObject(); + jaddstr(item,"result","success"); + jaddi(logarray,item); + } + return(0); +} + +bits256 iguana_str2priv(char *str) +{ + bits256 privkey; int32_t n; uint8_t addrtype; //struct iguana_waccount *wacct=0; struct iguana_waddress *waddr; + memset(&privkey,0,sizeof(privkey)); + if ( str != 0 ) + { + n = (int32_t)strlen(str) >> 1; + if ( n == sizeof(bits256) && is_hexstr(str,sizeof(bits256)) > 0 ) + decode_hex(privkey.bytes,sizeof(privkey),str); + else if ( bitcoin_wif2priv(&addrtype,&privkey,str) != sizeof(bits256) ) + { + //if ( (waddr= iguana_waddresssearch(&wacct,str)) != 0 ) + // privkey = waddr->privkey; + //else memset(privkey.bytes,0,sizeof(privkey)); + } + } + return(privkey); +} + +int32_t iguana_signrawtransaction(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson) +{ + uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0; + maxsize = 1000000; + memset(privkey.bytes,0,sizeof(privkey)); + if ( rawtx != 0 && rawtx[0] != 0 && (len= (int32_t)strlen(rawtx)>>1) < maxsize ) + { + serialized = malloc(maxsize); + serialized2 = malloc(maxsize); + serialized3 = malloc(maxsize); + serialized4 = malloc(maxsize); + extraspace = malloc(extralen); + memset(msgtx,0,sizeof(*msgtx)); + decode_hex(serialized,len,rawtx); + // printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0)); + if ( (txobj= bitcoin_hex2json(pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys)) != 0 ) + { + //printf("back from bitcoin_hex2json (%s)\n",jprint(vins,0)); + } else fprintf(stderr,"no txobj from bitcoin_hex2json\n"); + if ( (numinputs= cJSON_GetArraySize(vins)) > 0 ) + { + //printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in); + memset(msgtx,0,sizeof(*msgtx)); + if ( iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) + { + memset(pubkeys,0,sizeof(pubkeys)); + memset(privkeys,0,sizeof(privkeys)); + if ( (n= cJSON_GetArraySize(privkeysjson)) > 0 ) + { + for (i=0; ictx,pubkeys[i],privkey); + //if ( bits256_nonz(privkey) != 0 ) + // iguana_ensure_privkey(coin,privkey); + } + } + //printf("after privkeys tx_in.%d\n",msgtx->tx_in); + for (i=0; itx_in; i++) + { + if ( msgtx->vins[i].p2shlen != 0 ) + { + char coinaddr[64]; uint32_t userdatalen,sigsize,pubkeysize; uint8_t *userdata; int32_t j,k,hashtype,type,flag; struct vin_info mvin,mainvin; bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + coinaddr[0] = 0; + sigsize = 0; + flag = (msgtx->vins[i].vinscript[0] == 0); + type = bitcoin_scriptget(pubtype,p2shtype,&hashtype,&sigsize,&pubkeysize,&userdata,&userdatalen,&mainvin,msgtx->vins[i].vinscript+flag,msgtx->vins[i].scriptlen-flag,0); + //printf("i.%d flag.%d type.%d scriptlen.%d\n",i,flag,type,msgtx->vins[i].scriptlen); + if ( msgtx->vins[i].redeemscript != 0 ) + { + //for (j=0; jvins[i].p2shlen; j++) + // printf("%02x",msgtx->vins[i].redeemscript[j]); + bitcoin_address(coinaddr,p2shtype,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen); + type = iguana_calcrmd160(pubtype,p2shtype,0,&mvin,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen,zero,0,0); + for (j=0; jsuppress_pubkeys == 0 ) + { + for (z=0; z<33; z++) + V[i].signers[j].pubkey[z] = mvin.signers[j].pubkey[z]; + } + if ( flag != 0 && pubkeysize == 33 && mainvin.signers[0].siglen != 0 ) // jl777: need to generalize + { + if ( memcmp(mvin.signers[j].pubkey,mainvin.signers[0].pubkey,33) == 0 ) + { + for (z=0; zsuppress_pubkeys == 0 ) + { + for (z=0; z<33; z++) + V[i].signers[j].pubkey[z] = pubkeys[k][z]; + } + //printf("%s -> V[%d].signer.[%d] <- privkey.%d\n",mvin.signers[j].coinaddr,i,j,k); + break; + } + } + } + //printf("type.%d p2sh.[%d] -> %s M.%d N.%d\n",type,i,mvin.coinaddr,mvin.M,mvin.N); + } + } + if ( i < V->N ) + V->signers[i].privkey = privkey; + if ( i < numinputs ) + V[i].signers[0].privkey = privkey; + plen = bitcoin_pubkeylen(V->signers[i].pubkey); + if ( V->suppress_pubkeys == 0 && plen <= 0 ) + { + if ( i < numinputs ) + { + for (z=0; zsigners[i].pubkey[z]; + } + } + } + finalized = iguana_vininfo_create(pubtype,p2shtype,isPoS,serialized2,maxsize,msgtx,vins,numinputs,V); + //printf("finalized.%d\n",finalized); + if ( (complete= bitcoin_verifyvins(pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys)) > 0 && signedtx != 0 ) + { + /*int32_t tmp; //char str[65]; + if ( (tmp= iguana_interpreter(coin,0,iguana_lockval(finalized,jint(txobj,"locktime")),V,numinputs)) < 0 ) + { + printf("iguana_interpreter %d error.(%s)\n",tmp,signedtx); + complete = 0; + } */ + } else printf("complete.%d\n",complete); + } else printf("rwmsgtx error\n"); + } else fprintf(stderr,"no inputs in vins.(%s)\n",vins!=0?jprint(vins,0):"null"); + free(extraspace); + free(serialized), free(serialized2), free(serialized3), free(serialized4); + } else return(-1); + if ( txobj != 0 ) + free_json(txobj); + *signedtxp = signedtx; + return(complete); +} +#endif + +/*int32_t basilisk_rawtx_return(struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V) +{ + char *signedtx,*txbytes; cJSON *vins,*privkeyarray; int32_t i,n,retval = -1; + if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 ) + { + privkeyarray = cJSON_CreateArray(); + jaddistr(privkeyarray,wifstr); + if ( (signedtx= LP_signrawtx(rawtx->coin->symbol,&rawtx->I.signedtxid,&rawtx->I.completed,vins,txbytes,privkeyarray,V)) != 0 ) + { + if ( lockinputs != 0 ) + { + //printf("lockinputs\n"); + LP_unspentslock(rawtx->coin->symbol,vins); + if ( (n= cJSON_GetArraySize(vins)) != 0 ) + { + bits256 txid; int32_t vout; + for (i=0; iI.datalen = (int32_t)strlen(signedtx) >> 1; + //rawtx->txbytes = calloc(1,rawtx->I.datalen); + decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); + //printf("%s SIGNEDTX.(%s)\n",rawtx->name,signedtx); + free(signedtx); + retval = 0; + } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll + free_json(privkeyarray); + } + return(retval); +} + +cJSON *LP_createvins(struct basilisk_rawtx *dest,struct vin_info *V,struct basilisk_rawtx *rawtx,uint8_t *userdata,int32_t userdatalen,uint32_t sequenceid) +{ + cJSON *vins,*item,*sobj; char hexstr[8192]; + vins = cJSON_CreateArray(); + item = cJSON_CreateObject(); + if ( userdata != 0 && userdatalen > 0 ) + { + memcpy(V[0].userdata,userdata,userdatalen); + V[0].userdatalen = userdatalen; + init_hexbytes_noT(hexstr,userdata,userdatalen); + jaddstr(item,"userdata",hexstr); +#ifdef DISABLE_CHECKSIG + needsig = 0; +#endif + } + //printf("rawtx B\n"); + if ( bits256_nonz(rawtx->I.actualtxid) != 0 ) + jaddbits256(item,"txid",rawtx->I.actualtxid); + else jaddbits256(item,"txid",rawtx->I.signedtxid); + jaddnum(item,"vout",0); + sobj = cJSON_CreateObject(); + init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->I.spendlen); + jaddstr(sobj,"hex",hexstr); + jadd(item,"scriptPubKey",sobj); + jaddnum(item,"suppress",dest->I.suppress_pubkeys); + jaddnum(item,"sequence",sequenceid); + if ( (dest->I.redeemlen= rawtx->I.redeemlen) != 0 ) + { + init_hexbytes_noT(hexstr,rawtx->redeemscript,rawtx->I.redeemlen); + memcpy(dest->redeemscript,rawtx->redeemscript,rawtx->I.redeemlen); + jaddstr(item,"redeemScript",hexstr); + } + jaddi(vins,item); + return(vins); +} + +int32_t _basilisk_rawtx_gen(char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey) +{ + char scriptstr[1024],wifstr[256],coinaddr[64],*signedtx,*rawtxbytes; uint32_t basilisktag; int32_t retval = -1; cJSON *vins,*privkeys,*addresses,*valsobj; struct vin_info *V; + //bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33); + if ( rawtx->coin->changeaddr[0] == 0 ) + { + bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->pubtype,pubkey33,33); + printf("set change address.(%s)\n",rawtx->coin->changeaddr); + } + init_hexbytes_noT(scriptstr,script,scriptlen); + basilisktag = (uint32_t)rand(); + valsobj = cJSON_CreateObject(); + jaddstr(valsobj,"coin",rawtx->coin->symbol); + jaddstr(valsobj,"spendscript",scriptstr); + jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); + jadd64bits(valsobj,"satoshis",rawtx->I.amount); + if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 ) + txfee = 50000; + jadd64bits(valsobj,"txfee",txfee); + jaddnum(valsobj,"minconf",minconf); + if ( locktime == 0 ) + locktime = (uint32_t)time(NULL) - 777; + jaddnum(valsobj,"locktime",locktime); + jaddnum(valsobj,"timeout",30000); + jaddnum(valsobj,"timestamp",swapstarted+delay); + addresses = cJSON_CreateArray(); + bitcoin_address(coinaddr,rawtx->coin->pubtype,pubkey33,33); + jaddistr(addresses,coinaddr); + jadd(valsobj,"addresses",addresses); + rawtx->I.locktime = locktime; + printf("%s locktime.%u\n",rawtx->name,locktime); + V = calloc(256,sizeof(*V)); + privkeys = cJSON_CreateArray(); + bitcoin_priv2wif(wifstr,privkey,rawtx->coin->wiftype); + jaddistr(privkeys,wifstr); + vins = LP_createvins(rawtx,V,rawtx,0,0,0xffffffff); + rawtx->vins = jduplicate(vins); + jdelete(valsobj,"vin"); + jadd(valsobj,"vin",vins); + if ( (rawtxbytes= bitcoin_json2hex(rawtx->coin->isPoS,&rawtx->I.txid,valsobj,V)) != 0 ) + { + //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins); + if ( (signedtx= LP_signrawtx(rawtx->coin->symbol,&rawtx->I.signedtxid,&rawtx->I.completed,vins,rawtxbytes,privkeys,V)) != 0 ) + { + rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; + if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) + decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); + else printf("DEX tx is too big %d vs %d\n",rawtx->I.datalen,(int32_t)sizeof(rawtx->txbytes)); + if ( signedtx != rawtxbytes ) + free(signedtx); + if ( rawtx->I.completed != 0 ) + retval = 0; + else printf("couldnt complete sign transaction %s\n",rawtx->name); + } else printf("error signing\n"); + free(rawtxbytes); + } else printf("error making rawtx\n"); + free_json(privkeys); + free_json(valsobj); + free(V); + return(retval); +} + + +int32_t _basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,uint32_t timestamp,uint32_t locktime,uint32_t sequenceid,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr) +{ + char *rawtxbytes=0,*signedtx=0,wifstr[128]; cJSON *txobj,*vins,*privkeys; int32_t needsig=1,retval = -1; struct vin_info *V; + V = calloc(256,sizeof(*V)); + V[0].signers[0].privkey = privkey; + bitcoin_pubkey33(swap->ctx,V[0].signers[0].pubkey,privkey); + privkeys = cJSON_CreateArray(); + bitcoin_priv2wif(wifstr,privkey,wiftype); + jaddistr(privkeys,wifstr); + if ( privkey2 != 0 ) + { + V[0].signers[1].privkey = *privkey2; + bitcoin_pubkey33(swap->ctx,V[0].signers[1].pubkey,*privkey2); + bitcoin_priv2wif(wifstr,*privkey2,wiftype); + jaddistr(privkeys,wifstr); + V[0].N = V[0].M = 2; + //char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2)); + } else V[0].N = V[0].M = 1; + V[0].suppress_pubkeys = dest->I.suppress_pubkeys; + V[0].ignore_cltverr = ignore_cltverr; + if ( dest->I.redeemlen != 0 ) + memcpy(V[0].p2shscript,dest->redeemscript,dest->I.redeemlen), V[0].p2shlen = dest->I.redeemlen; + txobj = bitcoin_txcreate(symbol,isPoS,locktime,userdata == 0 ? 1 : 1,timestamp);//rawtx->coin->locktime_txversion); + vins = LP_createvins(dest,V,rawtx,userdata,userdatalen,sequenceid); + jdelete(txobj,"vin"); + jadd(txobj,"vin",vins); + //printf("basilisk_rawtx_sign locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->I.locktime,dest->I.locktime,rawtx->name,hexstr,dest->name,dest->I.suppress_pubkeys); + txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->I.spendlen,dest->I.amount); + if ( (rawtxbytes= bitcoin_json2hex(isPoS,&dest->I.txid,txobj,V)) != 0 ) + { + //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins); + if ( needsig == 0 ) + signedtx = rawtxbytes; + if ( signedtx != 0 || (signedtx= LP_signrawtx(symbol,&dest->I.signedtxid,&dest->I.completed,vins,rawtxbytes,privkeys,V)) != 0 ) + { + dest->I.datalen = (int32_t)strlen(signedtx) >> 1; + if ( dest->I.datalen <= sizeof(dest->txbytes) ) + decode_hex(dest->txbytes,dest->I.datalen,signedtx); + else printf("DEX tx is too big %d vs %d\n",dest->I.datalen,(int32_t)sizeof(dest->txbytes)); + if ( signedtx != rawtxbytes ) + free(signedtx); + if ( dest->I.completed != 0 ) + retval = 0; + else printf("couldnt complete sign transaction %s\n",rawtx->name); + } else printf("error signing\n"); + free(rawtxbytes); + } else printf("error making rawtx\n"); + free_json(privkeys); + free_json(txobj); + free(V); + return(retval); +}*/ + +char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp) +{ + char *rawtxbytes=0,*signedtx=0,str[65],hexstr[999],wifstr[128],destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *utxoobj,*txobj,*vins,*item,*sobj,*privkeys; int32_t completed,spendlen,ignore_cltverr=1,suppress_pubkeys=1; struct vin_info *V; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t destamount; + *destamountp = 0; + memset(signedtxidp,0,sizeof(*signedtxidp)); + if ( finalseqid == 0 ) + locktime = expiration; + //printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen); + if ( redeemlen < 0 ) + return(0); + if ( (utxoobj= LP_swapgettxout(symbol,utxotxid,vout)) == 0 ) + { + printf("basilisk_swap_bobtxspend.%s utxo already spent or doesnt exist\n",name); + return(0); + } + if ( (destamount= jdouble(utxoobj,"amount")*SATOSHIDEN) == 0 && (destamount= jdouble(utxoobj,"value")*SATOSHIDEN) == 0 ) + { + printf("%s %s basilisk_swap_bobtxspend.%s strange utxo.(%s)\n",symbol,bits256_str(str,utxotxid),name,jprint(utxoobj,0)); + free_json(utxoobj); + return(0); + } else free_json(utxoobj); + *destamountp = destamount; + if ( destamount > txfee ) + destamount -= txfee; + timestamp = (uint32_t)time(NULL); + V = calloc(256,sizeof(*V)); + privkeys = cJSON_CreateArray(); + if ( privkey2p != 0 ) + { + V[0].signers[1].privkey = *privkey2p; + bitcoin_pubkey33(ctx,V[0].signers[1].pubkey,*privkey2p); + bitcoin_priv2wif(wifstr,*privkey2p,wiftype); + jaddistr(privkeys,wifstr); + V[0].N = V[0].M = 2; + } else V[0].N = V[0].M = 1; + V[0].signers[0].privkey = privkey; + bitcoin_pubkey33(ctx,V[0].signers[0].pubkey,privkey); + bitcoin_priv2wif(wifstr,privkey,wiftype); + jaddistr(privkeys,wifstr); + V[0].suppress_pubkeys = suppress_pubkeys; + V[0].ignore_cltverr = ignore_cltverr; + if ( redeemlen != 0 ) + memcpy(V[0].p2shscript,redeemscript,redeemlen), V[0].p2shlen = redeemlen; + txobj = bitcoin_txcreate(symbol,isPoS,locktime,1,timestamp); + vins = cJSON_CreateArray(); + item = cJSON_CreateObject(); + if ( userdata != 0 && userdatalen > 0 ) + { + memcpy(V[0].userdata,userdata,userdatalen); + V[0].userdatalen = userdatalen; + init_hexbytes_noT(hexstr,userdata,userdatalen); + jaddstr(item,"userdata",hexstr); + } + jaddbits256(item,"txid",utxotxid); + jaddnum(item,"vout",vout); + sobj = cJSON_CreateObject(); + bitcoin_address(destaddr,pubtype,pubkey33,33); + bitcoin_addr2rmd160(&addrtype,rmd160,destaddr); + /*int32_t i; + for (i=0; i<33; i++) + printf("%02x",pubkey33[i]); + printf(" pubkey33 ->\n"); + for (i=0; i<20; i++) + printf("%02x",rmd160[i]); + printf(" destaddr.(%s)\n",destaddr); + calc_rmd160_sha256(rmd160,pubkey33,33); + for (i=0; i<20; i++) + printf("%02x",rmd160[i]); + printf(" <- vs direct calc\n");*/ + spendlen = bitcoin_standardspend(spendscript,0,rmd160); + init_hexbytes_noT(hexstr,spendscript,spendlen); + jaddstr(sobj,"hex",hexstr); + jadd(item,"scriptPubKey",sobj); + jaddnum(item,"suppress",suppress_pubkeys); + jaddnum(item,"sequence",sequenceid); + if ( redeemlen != 0 ) + { + init_hexbytes_noT(hexstr,redeemscript,redeemlen); + jaddstr(item,"redeemScript",hexstr); + } + jaddi(vins,item); + jdelete(txobj,"vin"); + jadd(txobj,"vin",vins); + txobj = bitcoin_txoutput(txobj,spendscript,spendlen,destamount); + if ( (rawtxbytes= bitcoin_json2hex(isPoS,&txid,txobj,V)) != 0 ) + { + //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0)); + if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) + printf("couldnt sign transaction\n"); + else if ( completed == 0 ) + { + printf("incomplete signing\n"); + if ( signedtx != 0 ) + free(signedtx), signedtx = 0; + } else printf("%s -> %s\n",name,bits256_str(str,*signedtxidp)); + free(rawtxbytes); + } else printf("error making rawtx\n"); + free_json(privkeys); + free_json(txobj); + free(V); + return(signedtx); +} + +int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey) +{ + int32_t retval=-1,len,iter; char *signedtx; struct iguana_info *coin; int64_t newtxfee=0,destamount; + if ( (coin= rawtx->coin) == 0 ) + return(-1); + //return(_basilisk_rawtx_gen(str,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,txfee,minconf,delay,privkey)); + for (iter=0; iter<2; iter++) + { + if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,pubkey33,1,0,&destamount)) != 0 ) + { + rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; + if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) + { + decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); + rawtx->I.completed = 1; + retval = 0; + } + free(signedtx); + if ( strcmp(coin->symbol,"BTC") != 0 ) + return(retval); + len = rawtx->I.datalen; + if ( coin->estimatedfee == 0 ) + coin->estimatedfee = LP_getestimatedfee(coin->symbol); + newtxfee = coin->estimatedfee * len; + printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); + } else break; + } + return(retval); +} + +int32_t basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr) +{ + char *signedtx; int64_t txfee,newtxfee=0,estimatedfee,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,len,retval = -1; + timestamp = swap->I.started; + if ( dest == &swap->aliceclaim ) + locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0; + else if ( dest == &swap->bobreclaim ) + locktime = swap->bobpayment.I.locktime + 1, sequenceid = 0; + txfee = strcmp("BTC",symbol) == 0 ? 0 : 10000; + for (iter=0; iter<2; iter++) + { + if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,0,0,userdata,userdatalen,rawtx->utxotxid,rawtx->utxovout,rawtx->pubkey33,1,0,&destamount)) != 0 ) + { + rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; + if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) + { + decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); + rawtx->I.completed = 1; + retval = 0; + } + free(signedtx); + if ( strcmp(symbol,"BTC") != 0 ) + return(retval); + len = rawtx->I.datalen; + estimatedfee = LP_getestimatedfee(symbol); + newtxfee = estimatedfee * len; + } else break; + } + return(retval); + //return(_basilisk_rawtx_sign(symbol,pubtype,p2shtype,isPoS,wiftype,swap,timestamp,locktime,sequenceid,dest,rawtx,privkey,privkey2,userdata,userdatalen,ignore_cltverr)); +} + +int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t *script,int32_t n,char *msigaddr,uint8_t altps2h,bits256 pubAm,bits256 pubBn) +{ + uint8_t p2sh160[20]; struct vin_info V; + memset(&V,0,sizeof(V)); + memcpy(&V.signers[0].pubkey[1],pubAm.bytes,sizeof(pubAm)), V.signers[0].pubkey[0] = 0x02; + memcpy(&V.signers[1].pubkey[1],pubBn.bytes,sizeof(pubBn)), V.signers[1].pubkey[0] = 0x03; + V.M = V.N = 2; + *redeemlenp = bitcoin_MofNspendscript(p2sh160,redeemscript,n,&V); + bitcoin_address(msigaddr,altps2h,p2sh160,sizeof(p2sh160)); + n = bitcoin_p2shspend(script,0,p2sh160); + //for (i=0; i<*redeemlenp; i++) + // printf("%02x",redeemscript[i]); + //printf(" <- redeemscript alicetx\n"); + return(n); +} + +char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp) +{ + char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn,signedtxid; uint64_t txfee; + if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) + { + pubAm = bitcoin_pubkey33(ctx,tmp33,privAm); + pubBn = bitcoin_pubkey33(ctx,tmp33,privBn); + //char str[65]; + //printf("pubAm.(%s)\n",bits256_str(str,pubAm)); + //printf("pubBn.(%s)\n",bits256_str(str,pubBn)); + spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,p2shtype,pubAm,pubBn); + //char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen); + /*rev = privAm; + for (i=0; i<32; i++) + privAm.bytes[i] = rev.bytes[31 - i]; + rev = privBn; + for (i=0; i<32; i++) + privBn.bytes[i] = rev.bytes[31 - i];*/ + txfee = LP_txfee(symbol); + signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,pubkey33,1,expiration,destamountp); + } + return(signedtx); +} + +int32_t LP_swap_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj) +{ + int32_t n,m,retval = -1; cJSON *vouts,*item,*addresses,*skey; char *addr; + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n ) + { + item = jitem(vouts,vout); + if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) + { + item = jitem(addresses,0); + if ( (addr= jstr(item,0)) != 0 ) + { + safecopy(destaddr,addr,64); + retval = 0; + } + //printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr); + } + } + return(retval); +} + +int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout) +{ + cJSON *retjson; + coinaddr[0] = 0; + if ( (retjson= LP_swapgettx(symbol,txid)) != 0 ) + { + LP_swap_txdestaddr(coinaddr,txid,vout,retjson); + free_json(retjson); + } + return(coinaddr[0] != 0); +} + +int32_t basilisk_swap_getsigscript(char *symbol,uint8_t *script,int32_t maxlen,bits256 txid,int32_t vini) +{ + cJSON *retjson,*vins,*item,*skey; int32_t n,scriptlen = 0; char *hexstr; + if ( (retjson= LP_swapgettx(symbol,txid)) != 0 ) + { + if ( (vins= jarray(&n,retjson,"vin")) != 0 && vini < n ) + { + item = jitem(vins,vini); + if ( (skey= jobj(item,"scriptSig")) != 0 && (hexstr= jstr(skey,"hex")) != 0 && (scriptlen= (int32_t)strlen(hexstr)) < maxlen*2 ) + { + scriptlen >>= 1; + decode_hex(script,scriptlen,hexstr); + //char str[65]; printf("%s/v%d sigscript.(%s)\n",bits256_str(str,txid),vini,hexstr); + } + } + free_json(retjson); + } + return(scriptlen); +} + +int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) +{ + cJSON *txobj,*vouts,*item; int32_t n; int64_t value = 0; + //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid)); + if ( (txobj= LP_swapgettx(symbol,txid)) != 0 ) + { + //printf("txobj.(%s)\n",jprint(txobj,0)); + if ( (vouts= jarray(&n,txobj,"vout")) != 0 ) + { + item = jitem(vouts,vout); + if ( (value= jdouble(item,"amount") * SATOSHIDEN) == 0 ) + value = jdouble(item,"value") * SATOSHIDEN; + } + free_json(txobj); + } + return(value); +} + +bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 utxotxid,int32_t vout) +{ + char *retstr,*addr; cJSON *array,*item,*array2; int32_t i,n,m; bits256 spendtxid,txid; + memset(&spendtxid,0,sizeof(spendtxid)); + if ( (retstr= dex_listtransactions(symbol,coinaddr,100,0)) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i %s\n",bits256_str(str,spendtxid),destaddr); + break; + } + } + } + } + free_json(array); + } + free(retstr); + } + return(spendtxid); +} + +bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout) +{ + bits256 spendtxid,txid; char *catstr,*addr; cJSON *array,*item,*item2,*txobj,*vins; int32_t i,n,m; char coinaddr[64],str[65]; + // listtransactions or listspents + destaddr[0] = 0; + coinaddr[0] = 0; + memset(&spendtxid,0,sizeof(spendtxid)); + //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); + if ( strcmp("BTC",symbol) == 0 ) + { + //[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}] + LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout); + if ( coinaddr[0] != 0 ) + spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout); + } + else + { + if ( (array= LP_listtransactions(symbol,destaddr,1000,0)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 ) + { + for (i=0; i jint(item,"vout") ) + { + item2 = jitem(vins,jint(item,"vout")); + if ( bits256_cmp(utxotxid,jbits256(item2,"txid")) == 0 && vout == jint(item2,"vout") ) + { + spendtxid = txid; + break; + } + } + } + } + } + if ( i == n ) + printf("dpowlist: native couldnt find spendtxid for %s\n",bits256_str(str,utxotxid)); + } + free_json(array); + } + if ( bits256_nonz(spendtxid) != 0 ) + return(spendtxid); + } + /*if ( iguana_isnotarychain(symbol) >= 0 ) + { + LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout); + printf("fallback use DEX for native (%s) (%s)\n",coinaddr,bits256_str(str,utxotxid)); + if ( coinaddr[0] != 0 ) + { + spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout); + printf("spendtxid.(%s)\n",bits256_str(str,spendtxid)); + } + }*/ + } + return(spendtxid); +} + +int32_t basilisk_swap_bobredeemscript(int32_t depositflag,int32_t *secretstartp,uint8_t *redeemscript,uint32_t locktime,bits256 pubA0,bits256 pubB0,bits256 pubB1,bits256 privAm,bits256 privBn,uint8_t *secretAm,uint8_t *secretAm256,uint8_t *secretBn,uint8_t *secretBn256) +{ + int32_t i,n=0; bits256 cltvpub,destpub,privkey; uint8_t pubkeyA[33],pubkeyB[33],secret160[20],secret256[32]; + if ( depositflag != 0 ) + { + pubkeyA[0] = 0x02, cltvpub = pubA0; + pubkeyB[0] = 0x03, destpub = pubB0; + privkey = privBn; + memcpy(secret160,secretBn,20); + memcpy(secret256,secretBn256,32); + } + else + { + pubkeyA[0] = 0x03, cltvpub = pubB1; + pubkeyB[0] = 0x02, destpub = pubA0; + privkey = privAm; + memcpy(secret160,secretAm,20); + memcpy(secret256,secretAm256,32); + } + //for (i=0; i<32; i++) + // printf("%02x",secret256[i]); + //printf(" <- secret256 depositflag.%d nonz.%d\n",depositflag,bits256_nonz(privkey)); + if ( bits256_nonz(cltvpub) == 0 || bits256_nonz(destpub) == 0 ) + return(-1); + for (i=0; i<20; i++) + if ( secret160[i] != 0 ) + break; + if ( i == 20 ) + return(-1); + memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub)); + memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub)); + redeemscript[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(redeemscript,n,locktime); +#ifdef DISABLE_CHECKSIG + n = bitcoin_secret256spend(redeemscript,n,cltvpub); +#else + n = bitcoin_pubkeyspend(redeemscript,n,pubkeyA); +#endif + redeemscript[n++] = SCRIPT_OP_ELSE; + if ( secretstartp != 0 ) + *secretstartp = n + 2; + if ( 1 ) + { + if ( 1 && bits256_nonz(privkey) != 0 ) + { + uint8_t bufA[20],bufB[20]; + revcalc_rmd160_sha256(bufA,privkey); + calc_rmd160_sha256(bufB,privkey.bytes,sizeof(privkey)); + /*if ( memcmp(bufA,secret160,sizeof(bufA)) == 0 ) + printf("MATCHES BUFA\n"); + else if ( memcmp(bufB,secret160,sizeof(bufB)) == 0 ) + printf("MATCHES BUFB\n"); + else printf("secret160 matches neither\n"); + for (i=0; i<20; i++) + printf("%02x",bufA[i]); + printf(" <- revcalc\n"); + for (i=0; i<20; i++) + printf("%02x",bufB[i]); + printf(" <- calc\n");*/ + memcpy(secret160,bufB,20); + } + n = bitcoin_secret160verify(redeemscript,n,secret160); + } + else + { + redeemscript[n++] = 0xa8;//IGUANA_OP_SHA256; + redeemscript[n++] = 0x20; + memcpy(&redeemscript[n],secret256,0x20), n += 0x20; + redeemscript[n++] = 0x88; //SCRIPT_OP_EQUALVERIFY; + } +#ifdef DISABLE_CHECKSIG + n = bitcoin_secret256spend(redeemscript,n,destpub); +#else + n = bitcoin_pubkeyspend(redeemscript,n,pubkeyB); +#endif + redeemscript[n++] = SCRIPT_OP_ENDIF; + return(n); +} + +int32_t basilisk_bobscript(uint8_t *rmd160,uint8_t *redeemscript,int32_t *redeemlenp,uint8_t *script,int32_t n,uint32_t *locktimep,int32_t *secretstartp,struct basilisk_swapinfo *swap,int32_t depositflag) +{ + if ( depositflag != 0 ) + *locktimep = swap->started + swap->putduration + swap->callduration; + else *locktimep = swap->started + swap->putduration; + *redeemlenp = n = basilisk_swap_bobredeemscript(depositflag,secretstartp,redeemscript,*locktimep,swap->pubA0,swap->pubB0,swap->pubB1,swap->privAm,swap->privBn,swap->secretAm,swap->secretAm256,swap->secretBn,swap->secretBn256); + if ( n > 0 ) + { + calc_rmd160_sha256(rmd160,redeemscript,n); + n = bitcoin_p2shspend(script,0,rmd160); + //for (i=0; i if path, 0 -> else path + return(len); +} + +/*Bob paytx: + OP_IF + OP_CLTV OP_DROP OP_CHECKSIG + OP_ELSE + OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG + OP_ENDIF*/ + +int32_t basilisk_bobpayment_reclaim(struct basilisk_swap *swap,int32_t delay) +{ + uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; + printf("basilisk_bobpayment_reclaim\n"); + len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + memcpy(swap->I.userdata_bobreclaim,userdata,len); + swap->I.userdata_bobreclaimlen = len; + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1)) == 0 ) + { + for (i=0; ibobreclaim.I.datalen; i++) + printf("%02x",swap->bobreclaim.txbytes[i]); + printf(" <- bobreclaim\n"); + //basilisk_txlog(swap,&swap->bobreclaim,delay); + return(retval); + } + return(-1); +} + +int32_t basilisk_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) +{ + int32_t datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr; bits256 txid; + datalen = recvbuf[0]; + datalen += (int32_t)recvbuf[1] << 8; + if ( datalen > 65536 ) + return(-1); + rawtx->I.redeemlen = recvbuf[2]; + data = &recvbuf[3]; + if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) + memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); + //printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen); + if ( rawtx->I.datalen == 0 ) + { + //rawtx->txbytes = calloc(1,datalen); + memcpy(rawtx->txbytes,data,datalen); + rawtx->I.datalen = datalen; + } + else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 ) + { + int32_t i; for (i=0; iI.datalen; i++) + printf("%02x",rawtx->txbytes[i]); + printf(" <- rawtx\n"); + printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen); + return(-1); + } + txid = bits256_doublesha256(0,data,datalen); + char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); + if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) + rawtx->I.actualtxid = txid; + if ( (txobj= bitcoin_data2json(rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) + { + rawtx->I.actualtxid = rawtx->I.signedtxid; + //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,rawtx->signedtxid),jprint(txobj,0)); + rawtx->I.locktime = rawtx->msgtx.lock_time; + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) + { + vout = jitem(vouts,v); + if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) + { + if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) + { + decode_hex(rawtx->spendscript,hexlen,hexstr); + rawtx->I.spendlen = hexlen; + bitcoin_address(rawtx->p2shaddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen); + //if ( swap != 0 ) + // basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment + retval = 0; + } + } else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0)); + } + free_json(txobj); + } + return(retval); +} + +int32_t basilisk_verify_bobpaid(void *ptr,uint8_t *data,int32_t datalen) +{ + uint8_t userdata[512]; int32_t i,retval,len = 0; bits256 revAm; struct basilisk_swap *swap = ptr; + memset(revAm.bytes,0,sizeof(revAm)); + if ( basilisk_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobpayment,0,data,datalen,0) == 0 ) + { + swap->bobpayment.I.signedtxid = LP_broadcast(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); + if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) + swap->paymentunconf = 1; + basilisk_dontforget_update(swap,&swap->bobpayment); + for (i=0; i<32; i++) + revAm.bytes[i] = swap->I.privAm.bytes[31-i]; + len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + memcpy(swap->I.userdata_alicespend,userdata,len); + swap->I.userdata_alicespendlen = len; + char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1)) == 0 ) + { + for (i=0; ibobpayment.I.datalen; i++) + printf("%02x",swap->bobpayment.txbytes[i]); + printf(" <- bobpayment\n"); + for (i=0; ialicespend.I.datalen; i++) + printf("%02x",swap->alicespend.txbytes[i]); + printf(" <- alicespend\n\n"); + swap->I.alicespent = 1; + //basilisk_txlog(swap,&swap->alicespend,-1); + return(retval); + } + } + return(-1); +} + +int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay) +{ + uint8_t userdata[512]; int32_t i,retval,len = 0; char str[65]; + len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + memcpy(swap->I.userdata_bobrefund,userdata,len); + swap->I.userdata_bobrefundlen = len; + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0)) == 0 ) + { + for (i=0; ibobrefund.I.datalen; i++) + printf("%02x",swap->bobrefund.txbytes[i]); + printf(" <- bobrefund.(%s)\n",bits256_str(str,swap->bobrefund.I.txid)); + //basilisk_txlog(swap,&swap->bobrefund,delay); + return(retval); + } + return(-1); +} + +int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,int32_t genflag) +{ + int32_t i,j; //char str[65]; + if ( genflag != 0 && swap->I.iambob == 0 ) + printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n"); + if ( depositflag == 0 ) + { + swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0); + bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + //for (i=0; ibobpayment.redeemlen; i++) + // printf("%02x",swap->bobpayment.redeemscript[i]); + //printf(" <- bobpayment.%d\n",i); + if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 ) + { + for (i=0; i<3; i++) + { + //if ( swap->bobpayment.txbytes != 0 && swap->bobpayment.I.spendlen != 0 ) + // break; + basilisk_rawtx_gen(swap->ctx,"payment",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->txfee,1,0,swap->persistent_privkey); + if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 ) + { + printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen); + sleep(DEX_SLEEP); + } + else + { + for (j=0; jbobpayment.I.datalen; j++) + printf("%02x",swap->bobpayment.txbytes[j]); + //printf(" <- bobpayment.%d\n",swap->bobpayment.datalen); + //for (j=0; jbobpayment.redeemlen; j++) + // printf("%02x",swap->bobpayment.redeemscript[j]); + //printf(" <- redeem.%d\n",swap->bobpayment.redeemlen); + printf(" <- GENERATED BOB PAYMENT.%d\n",swap->bobpayment.I.datalen); + LP_unspents_mark(swap->bobcoin.symbol,swap->bobpayment.vins); + basilisk_bobpayment_reclaim(swap,swap->I.callduration); + printf("bobscripts set completed\n"); + return(0); + } + } + } + } + else + { + swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1); + bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + if ( genflag != 0 && (swap->bobdeposit.I.datalen == 0 || swap->bobrefund.I.datalen == 0) ) + { + for (i=0; i<3; i++) + { + //if ( swap->bobdeposit.txbytes != 0 && swap->bobdeposit.I.spendlen != 0 ) + // break; + basilisk_rawtx_gen(swap->ctx,"deposit",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,swap->bobdeposit.coin->txfee,1,0,swap->persistent_privkey); + if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 ) + { + printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen); + sleep(DEX_SLEEP); + } + else + { + for (j=0; jbobdeposit.I.datalen; j++) + printf("%02x",swap->bobdeposit.txbytes[j]); + printf(" <- GENERATED BOB DEPOSIT.%d\n",swap->bobdeposit.I.datalen); + //for (j=0; jbobdeposit.redeemlen; j++) + // printf("%02x",swap->bobdeposit.redeemscript[j]); + //printf(" <- redeem.%d\n",swap->bobdeposit.redeemlen); + //printf("GENERATED BOB DEPOSIT\n"); + LP_unspents_mark(swap->bobcoin.symbol,swap->bobdeposit.vins); + basilisk_bobdeposit_refund(swap,swap->I.putduration); + printf("bobscripts set completed\n"); + return(0); + } + } + } + //for (i=0; ibobdeposit.redeemlen; i++) + // printf("%02x",swap->bobdeposit.redeemscript[i]); + //printf(" <- bobdeposit.%d\n",i); + } + return(0); +} + +/**/ + +struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx) +{ + if ( rawtx->I.datalen != 0 && rawtx->I.datalen <= maxlen ) + { + memcpy(data,rawtx->txbytes,rawtx->I.datalen); + return(rawtx); + } + return(0); +} + +uint32_t LP_swapdata_rawtxsend(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend) +{ + uint8_t sendbuf[32768]; int32_t sendlen; + if ( LP_swapdata_rawtx(swap,data,maxlen,rawtx) != 0 ) + { + if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) + { + char str[65],str2[65]; + rawtx->I.actualtxid = LP_broadcast(rawtx->name,rawtx->coin->symbol,rawtx->txbytes,rawtx->I.datalen); + if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 ) + { + printf("%s rawtxsend %s vs %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); + rawtx->I.actualtxid = rawtx->I.signedtxid; + } + if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 ) + { + sendlen = 0; + sendbuf[sendlen++] = rawtx->I.datalen & 0xff; + sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff; + sendbuf[sendlen++] = rawtx->I.redeemlen; + memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen; + if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) + { + memcpy(&sendbuf[sendlen],rawtx->redeemscript,rawtx->I.redeemlen); + sendlen += rawtx->I.redeemlen; + } + basilisk_dontforget_update(swap,rawtx); + //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen); + if ( suppress_swapsend == 0 ) + return(LP_swapsend(swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs)); + else + { + printf("suppress swapsend %x\n",msgbits); + return(0); + } + } + } + return(nextbits); + } else if ( swap->I.iambob == 0 ) + printf("error from basilisk_swapdata_rawtx.%s %p len.%d\n",rawtx->name,rawtx->txbytes,rawtx->I.datalen); + return(0); +} + +void basilisk_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen) +{ + cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0; + if ( (txobj= bitcoin_data2json(coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) + { + //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,signedtxid),jprint(txobj,0)); + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) + { + vout = jitem(vouts,0); + //printf("VOUT.(%s)\n",jprint(vout,0)); + if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) + { + item = jitem(addresses,0); + //printf("item.(%s)\n",jprint(item,0)); + if ( (addr= jstr(item,0)) != 0 ) + { + safecopy(coinaddr,addr,64); + //printf("extracted.(%s)\n",coinaddr); + } + } + } + free_json(txobj); + } +} + +int32_t basilisk_verify_otherfee(void *ptr,uint8_t *data,int32_t datalen) +{ + struct basilisk_swap *swap = ptr; + // add verification and broadcast + //swap->otherfee.txbytes = calloc(1,datalen); + memcpy(swap->otherfee.txbytes,data,datalen); + swap->otherfee.I.datalen = datalen; + swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen); + //basilisk_txlog(swap,&swap->otherfee,-1); + return(0); +} + +/* Bob deposit: + OP_IF + OP_CLTV OP_DROP OP_CHECKSIG + OP_ELSE + OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG + OP_ENDIF*/ + +int32_t basilisk_verify_bobdeposit(void *ptr,uint8_t *data,int32_t datalen) +{ + uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; struct basilisk_swap *swap = ptr; + if ( basilisk_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) + { + swap->bobdeposit.I.signedtxid = LP_broadcast(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); + if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) + swap->depositunconf = 1; + basilisk_dontforget_update(swap,&swap->bobdeposit); + len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + memcpy(swap->I.userdata_aliceclaim,userdata,len); + swap->I.userdata_aliceclaimlen = len; + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1)) == 0 ) + { + for (i=0; ibobdeposit.I.datalen; i++) + printf("%02x",swap->bobdeposit.txbytes[i]); + printf(" <- bobdeposit\n"); + for (i=0; ialiceclaim.I.datalen; i++) + printf("%02x",swap->aliceclaim.txbytes[i]); + printf(" <- aliceclaim\n"); + //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); + return(retval); + } + } + printf("error with bobdeposit\n"); + return(-1); +} + +void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn) +{ + alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->p2shtype,pubAm,pubBn); + basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->txfee,1,0,swap->persistent_privkey); +} + +int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_rawtx *dest) +{ + int32_t i,retval; + printf("alicepayment_spend\n"); + swap->alicepayment.I.spendlen = basilisk_alicescript(swap->alicepayment.redeemscript,&swap->alicepayment.I.redeemlen,swap->alicepayment.spendscript,0,swap->alicepayment.I.destaddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn); + printf("alicepayment_spend len.%d\n",swap->alicepayment.I.spendlen); + if ( swap->I.iambob == 0 ) + { + memcpy(swap->I.userdata_alicereclaim,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen); + swap->I.userdata_alicereclaimlen = swap->alicepayment.I.spendlen; + } + else + { + memcpy(swap->I.userdata_bobspend,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen); + swap->I.userdata_bobspendlen = swap->alicepayment.I.spendlen; + } + if ( (retval= basilisk_rawtx_sign(swap->alicecoin.symbol,swap->alicecoin.pubtype,swap->alicecoin.p2shtype,swap->alicecoin.isPoS,swap->alicecoin.wiftype,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1)) == 0 ) + { + for (i=0; iI.datalen; i++) + printf("%02x",dest->txbytes[i]); + printf(" <- msigspend\n\n"); + if ( dest == &swap->bobspend ) + swap->I.bobspent = 1; + //basilisk_txlog(swap,dest,0); // bobspend or alicereclaim + return(retval); + } + return(-1); +} + +int32_t basilisk_verify_alicepaid(void *ptr,uint8_t *data,int32_t datalen) +{ + struct basilisk_swap *swap = ptr; + if ( basilisk_rawtx_spendscript(swap,swap->alicecoin.longestchain,&swap->alicepayment,0,data,datalen,0) == 0 ) + { + swap->alicepayment.I.signedtxid = LP_broadcast(swap->alicepayment.name,swap->alicecoin.symbol,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); + if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) + swap->aliceunconf = 1; + basilisk_dontforget_update(swap,&swap->alicepayment); + return(0); + } + else return(-1); +} + +int32_t basilisk_alicetxs(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +{ + int32_t i,retval = -1; + printf("alicetxs\n"); + for (i=0; i<3; i++) + { + if ( swap->alicepayment.I.datalen == 0 ) + basilisk_alicepayment(swap,swap->alicepayment.coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn); + if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 ) + { + printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen); + sleep(20); + } + else + { + retval = 0; + for (i=0; ialicepayment.I.datalen; i++) + printf("%02x",swap->alicepayment.txbytes[i]); + printf(" ALICE PAYMENT created\n"); + LP_unspents_mark(swap->alicecoin.symbol,swap->alicepayment.vins); + //basilisk_txlog(swap,&swap->alicepayment,-1); + break; + } + } + if ( swap->myfee.I.datalen == 0 ) + { + printf("generate fee\n"); + if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->txfee,1,0,swap->persistent_privkey) == 0 ) + { + swap->I.statebits |= LP_swapdata_rawtxsend(swap,0x80,data,maxlen,&swap->myfee,0x40,0); + LP_unspents_mark(swap->I.iambob!=0?swap->bobcoin.symbol:swap->alicecoin.symbol,swap->myfee.vins); + //basilisk_txlog(swap,&swap->myfee,-1); + for (i=0; imyfee.I.spendlen; i++) + printf("%02x",swap->myfee.txbytes[i]); + printf(" fee %p %x\n",swap->myfee.txbytes,swap->I.statebits); + swap->I.statebits |= 0x40; + } + else + { + printf("error creating myfee\n"); + return(-2); + } + } + if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 && swap->myfee.I.datalen != 0 && swap->myfee.I.spendlen > 0 ) + return(0); + return(-1); +} diff --git a/iguana/m_mm b/iguana/m_mm index 9672d7988..2e310704b 100755 --- a/iguana/m_mm +++ b/iguana/m_mm @@ -1 +1,2 @@ -gcc -o marketmaker -I../crypto777 exchanges/mm.c ../crypto777/cJSON.c ../agents/libcrypto777.a -lnanomsg -lcurl -lpthread -lm +cd secp256k1; ./m_unix; cd .. +gcc -o marketmaker -I../crypto777 exchanges/mm.c mini-gmp.c secp256k1.o ../agents/libcrypto777.a -lnanomsg -lcurl -lpthread -lm