Browse Source

Merge pull request #393 from jl777/spvdex

split out all separate polling tasks into dedicated threads
fixed some funds recapture edge cases
added signature enforcement for all price quotes and utxos, MUST UPDATE or your node wont propagate any price data
etomic
jl777 7 years ago
committed by GitHub
parent
commit
b46b64a858
  1. 5
      iguana/exchanges/LP_include.h
  2. 254
      iguana/exchanges/LP_nativeDEX.c
  3. 1
      iguana/exchanges/LP_network.c
  4. 2
      iguana/exchanges/LP_ordermatch.c
  5. 8
      iguana/exchanges/LP_portfolio.c
  6. 91
      iguana/exchanges/LP_remember.c
  7. 249
      iguana/exchanges/LP_signatures.c
  8. 4
      iguana/exchanges/LP_transaction.c
  9. 2
      iguana/exchanges/LP_utxo.c
  10. 2
      iguana/exchanges/coins

5
iguana/exchanges/LP_include.h

@ -44,7 +44,7 @@
#define LP_PEERGOOD_ERRORDECAY 0.9
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 15
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 50
@ -286,7 +286,7 @@ struct LP_pubkeyinfo
};
int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item);
int32_t LP_pubkey_sigadd(cJSON *item,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp);
int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp);
void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,uint8_t *data,int32_t datalen,int32_t vout);
void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx);
uint32_t basilisk_requestid(struct basilisk_request *rp);
@ -311,7 +311,6 @@ uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
//void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
int32_t LP_coinbus(uint16_t coin_busport);
int32_t LP_nanomsg_recvs(void *ctx);
int32_t LP_reserved_msgs();
uint64_t LP_smartbalance(struct iguana_info *coin);
int32_t LP_getheight(struct iguana_info *coin);
int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg);

254
iguana/exchanges/LP_nativeDEX.c

@ -19,13 +19,13 @@
// marketmaker
//
// process stats.log local file -> map of realtime activity!
// serialize sighash functions
// select oldest utxo first
// handles <-> pubkeys, deal with offline pubkeys, reputations, bonds etc.
//
// verify portfolio, pricearray, interest to KMD withdraw, reliable networking
// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections
#include <stdio.h>
#include "LP_include.h"
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex;
@ -380,6 +380,15 @@ void command_rpcloop(void *myipaddr)
}
}
void utxosQ_loop(void *myipaddr)
{
while ( 1 )
{
if ( LP_utxosQ_process() == 0 )
usleep(10000);
}
}
int32_t LP_utxos_sync(struct LP_peerinfo *peer)
{
int32_t i,j,n=0,m,v,posted=0; bits256 txid; cJSON *array,*item,*item2,*array2,*array3; uint64_t total,total2,metric; struct iguana_info *coin,*ctmp; struct LP_address *ap; char *retstr,*retstr2,*coinaddr;
@ -500,10 +509,78 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer)
return(posted);
}
void LP_coinsloop(void *_coins)
{
struct iguana_info *coin,*ctmp; bits256 zero; int32_t j,nonz; char *coins = _coins;
while ( 1 )
{
nonz = 0;
HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
if ( coins[0] != 0 )
{
if ( strcmp(coins,coin->symbol) != 0 )
continue;
}
else // avoid hardcode special case LP_coinsloop
{
if ( strcmp("BTC",coin->symbol) == 0 || strcmp("KMD",coin->symbol) == 0 )
continue;
}
memset(&zero,0,sizeof(zero));
if ( coin->inactive != 0 )
continue;
if ( coin->electrum != 0 )
continue;
if ( coin->firstrefht == 0 )
continue;
else if ( coin->firstscanht == 0 )
coin->lastscanht = coin->firstscanht = coin->firstrefht;
else if ( coin->firstrefht < coin->firstscanht )
{
printf("detected %s firstrefht.%d < firstscanht.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht);
coin->lastscanht = coin->firstscanht = coin->firstrefht;
}
if ( coin->lastscanht == coin->longestchain+1 )
{
//printf("%s lastscanht.%d is longest.%d + 1\n",coin->symbol,coin->lastscanht,coin->longestchain);
continue;
}
else if ( coin->lastscanht > coin->longestchain+1 )
{
printf("detected chain rewind lastscanht.%d vs longestchain.%d, first.%d ref.%d\n",coin->lastscanht,coin->longestchain,coin->firstscanht,coin->firstrefht);
LP_undospends(coin,coin->longestchain-1);
//LP_mempoolscan(coin->symbol,zero);
coin->lastscanht = coin->longestchain - 1;
if ( coin->firstscanht < coin->lastscanht )
coin->lastscanht = coin->firstscanht;
continue;
}
//if ( (coin->lastscanht % 1000) == 0 )
printf("[%s]: %s ref.%d scan.%d to %d, longest.%d\n",coins,coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
for (j=0; j<100; j++)
{
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
{
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
break;
}
coin->lastscanht++;
if ( coin->lastscanht == coin->longestchain+1 )
break;
}
nonz++;
continue;
}
if ( nonz == 0 )
usleep(1000);
}
}
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport)
{
static uint32_t counter,numpeers;
struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; bits256 zero; int32_t needpings,j,height,nonz = 0;
struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; int32_t needpings,height,nonz = 0;
now = (uint32_t)time(NULL);
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
@ -532,7 +609,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport);
peer->diduquery = 0;
LP_peer_pricesquery(peer);
LP_utxos_sync(peer);
//LP_utxos_sync(peer);
needpings++;
}
peer->lastpeers = now;
@ -548,32 +625,14 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
needpings++;
}
}
if ( needpings != 0 || (counter % 10000) == 5 )
{
nonz++;
//printf("needpings.%d send notify\n",needpings);
LP_notify_pubkeys(ctx,pubsock);
}
if ( (counter % 6000) == 10 )
{
nonz++;
LP_privkey_updates(ctx,pubsock,0);
}
HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
memset(&zero,0,sizeof(zero));
if ( coin->addr_listunspent_requested != 0 )
{
//printf("PUSH addr_listunspent_requested %u\n",coin->addr_listunspent_requested);
LP_smartutxos_push(coin);
coin->addr_listunspent_requested = 0;
}
if ( coin->inactive != 0 )
continue;
if ( coin->electrum != 0 )
continue;
//if ( coin->obooktime == 0 )
// continue;
if ( time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR )
{
nonz++;
@ -582,57 +641,9 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
coin->longestchain = height;
if ( coin->firstrefht != 0 )
printf(">>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d])\n",coin->symbol,height,coin->firstrefht,coin->firstscanht,coin->lastscanht);
} else LP_mempoolscan(coin->symbol,zero);
} //else LP_mempoolscan(coin->symbol,zero);
coin->lastgetinfo = (uint32_t)time(NULL);
}
if ( coin->firstrefht == 0 )
continue;
else if ( coin->firstscanht == 0 )
coin->lastscanht = coin->firstscanht = coin->firstrefht;
else if ( coin->firstrefht < coin->firstscanht )
{
printf("detected %s firstrefht.%d < firstscanht.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht);
coin->lastscanht = coin->firstscanht = coin->firstrefht;
}
if ( coin->lastscanht == coin->longestchain+1 )
continue;
else if ( coin->lastscanht > coin->longestchain+1 )
{
printf("detected chain rewind lastscanht.%d vs longestchain.%d, first.%d ref.%d\n",coin->lastscanht,coin->longestchain,coin->firstscanht,coin->firstrefht);
LP_undospends(coin,coin->longestchain-1);
LP_mempoolscan(coin->symbol,zero);
coin->lastscanht = coin->longestchain - 1;
if ( coin->firstscanht < coin->lastscanht )
coin->lastscanht = coin->firstscanht;
continue;
}
if ( (coin->lastscanht % 1000) == 0 )
printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
for (j=0; j<100; j++)
{
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
{
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
break;
}
coin->lastscanht++;
if ( coin->lastscanht == coin->longestchain+1 )
break;
}
if ( j < 100 )
continue;
nonz++;
//LP_getestimatedrate(coin);
break;
}
if ( (counter % 100000) == 90000 )
{
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
{
//printf("SWAPS.(%s)\n",retstr);
nonz++;
free(retstr);
}
}
counter++;
return(nonz);
@ -700,9 +711,41 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint
}
}
int32_t LP_reserved_msgs()
void LP_pubkeysloop(void *ctx)
{
sleep(10);
while ( 1 )
{
LP_notify_pubkeys(ctx,LP_mypubsock);
sleep(60);
}
}
void LP_privkeysloop(void *ctx)
{
bits256 zero; int32_t flag,n = 0; struct nn_pollfd pfd;
sleep(20);
while ( 1 )
{
LP_privkey_updates(ctx,LP_mypubsock,0);
sleep(60);
}
}
void LP_swapsloop(void *ignore)
{
char *retstr;
sleep(50);
while ( 1 )
{
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
free(retstr);
sleep(600);
}
}
void LP_reserved_msgs(void *ignore)
{
bits256 zero; int32_t flag; struct nn_pollfd pfd;
memset(zero.bytes,0,sizeof(zero));
while ( 1 )
{
@ -725,13 +768,10 @@ int32_t LP_reserved_msgs()
LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[num_Reserved_msgs]);
Reserved_msgs[num_Reserved_msgs] = 0;
portable_mutex_unlock(&LP_reservedmutex);
usleep(3000);
} else break;
} else break;
if ( ++n > 1 )
break;
}
}
usleep(3000);
}
return(n);
}
int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg)
@ -880,32 +920,72 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
LP_initcoins(ctx,pubsock,coinsjson);
G.waiting = 1;
LP_passphrase_init(passphrase,jstr(argjson,"gui"));
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 )
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)myipaddr) != 0 )
{
printf("error launching LP_psockloop for (%s)\n",myipaddr);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_reserved_msgs,(void *)myipaddr) != 0 )
{
printf("error launching LP_reserved_msgs for (%s)\n",myipaddr);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)utxosQ_loop,(void *)myipaddr) != 0 )
{
printf("error launching utxosQ_loop for (%s)\n",myipaddr);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,(void *)&myipaddr) != 0 )
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,(void *)myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
printf("error launching command_rpcloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)queue_loop,(void *)&myipaddr) != 0 )
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)queue_loop,(void *)myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
printf("error launching queue_loop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)prices_loop,(void *)&myipaddr) != 0 )
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)prices_loop,(void *)myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
printf("error launching prices_loop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_coinsloop,(void *)"") != 0 )
{
printf("error launching LP_coinsloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_coinsloop,(void *)"BTC") != 0 )
{
printf("error launching BTC LP_coinsloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_coinsloop,(void *)"KMD") != 0 )
{
printf("error launching KMD LP_coinsloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_pubkeysloop,(void *)myipaddr) != 0 )
{
printf("error launching LP_pubkeysloop for ctx.%p\n",ctx);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,(void *)&myipaddr) != 0 )
{
printf("error launching LP_privkeysloop for ctx.%p\n",ctx);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,(void *)&myipaddr) != 0 )
{
printf("error launching LP_swapsloop for port.%u\n",myport);
exit(-1);
}
//if ( (retstr= basilisk_swapentry(0,0)) != 0 )
//if ( (retstr= basilisk_swapentry(0,0)) != 0 )
// free(retstr);
int32_t nonz;
printf("start mainloop\n");

1
iguana/exchanges/LP_network.c

@ -144,7 +144,6 @@ void queue_loop(void *ignore)
struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0;
while ( 1 )
{
LP_reserved_msgs();
nonz = 0;
//printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0);
n = 0;

2
iguana/exchanges/LP_ordermatch.c

@ -81,7 +81,7 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str
printf(">>>>>>> quote satoshis.(%.8f %.8f) %s %.8f -> %s %.8f\n",dstr(qp->satoshis),dstr(qp->destsatoshis),qp->srccoin,dstr(qp->satoshis),qp->destcoin,dstr(qp->destsatoshis));
if ( butxo != 0 )
{
if (LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 )
if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 )
{
printf("bob not eligible %s\n",jprint(LP_quotejson(qp),1));
return(-2);

8
iguana/exchanges/LP_portfolio.c

@ -596,7 +596,7 @@ int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *a
void prices_loop(void *ignore)
{
char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; uint32_t expiration; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp; void *ctx = bitcoin_ctx();
char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp; void *ctx = bitcoin_ctx();
while ( 1 )
{
if ( (btcpp= LP_priceinfofind("BTC")) == 0 )
@ -634,12 +634,6 @@ void prices_loop(void *ignore)
}
free(retstr);
}
expiration = (uint32_t)time(NULL) + 60;
while ( time(NULL) < expiration )
{
if ( LP_utxosQ_process() == 0 )
usleep(10000);
}
}
}

91
iguana/exchanges/LP_remember.c

@ -260,24 +260,24 @@ bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,in
}
txid = txids[utxoind];
memset(&spendtxid,0,sizeof(spendtxid));
if ( bits256_nonz(txid) != 0 )
if ( bits256_nonz(txid) != 0 )//&& sentflags[utxoind] != 0 )
{
destaddr[0] = 0;
spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,vout);
if ( bits256_nonz(spendtxid) != 0 )
{
sentflags[utxoind] = 1;
printf("utxoind.%d Alice.(%s %s) Bob.(%s %s) vs destaddr.(%s)\n",utxoind,aliceaddr,Adest,bobaddr,dest,destaddr);
//printf("utxoind.%d Alice.(%s %s) Bob.(%s %s) vs destaddr.(%s)\n",utxoind,aliceaddr,Adest,bobaddr,dest,destaddr);
if ( aliceaddr != 0 && (strcmp(destaddr,aliceaddr) == 0 || strcmp(Adest,destaddr) == 0) )
{
printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
//printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
sentflags[alicespent] = 1;
sentflags[bobspent] = 0;
txids[alicespent] = spendtxid;
}
else if ( bobaddr != 0 && (strcmp(destaddr,bobaddr) == 0 || strcmp(dest,destaddr) == 0) )
{
printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
//printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
sentflags[bobspent] = 1;
sentflags[alicespent] = 0;
txids[bobspent] = spendtxid;
@ -298,7 +298,7 @@ bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,in
txids[alicespent] = spendtxid;
}
}
} else printf("no spend of %s/v%d detected\n",bits256_str(str,txid),vout);
} //else printf("no spend of %s/v%d detected\n",bits256_str(str,txid),vout);
} else printf("utxoind.%d null txid\n",utxoind);
return(spendtxid);
}
@ -353,7 +353,7 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag
{
if ( bits256_nonz(txids[BASILISK_BOBDEPOSIT]) == 0 && sentflags[BASILISK_BOBDEPOSIT] == 0 )
return(1);
else if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) == 0 && sentflags[BASILISK_BOBPAYMENT] == 0 )
else if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) == 0 || sentflags[BASILISK_BOBPAYMENT] == 0 )
{
if ( bits256_nonz(depositspent) != 0 )
return(1);
@ -670,7 +670,7 @@ int32_t LP_refht_update(char *symbol,bits256 txid)
int32_t LP_swap_load(struct LP_swap_remember *rswap)
{
int32_t i,needflag,addflag; long fsize; char fname[1024],str[65],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj,*fileobj; bits256 txid,checktxid; uint64_t value;
int32_t i,needflag,addflag; long fsize; char fname[1024],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj,*fileobj; bits256 txid,checktxid; uint64_t value;
rswap->iambob = -1;
sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap->requestid,rswap->quoteid), OS_compatible_path(fname);
if ( (fstr= OS_filestr(&fsize,fname)) != 0 )
@ -767,7 +767,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
}
free_json(sentobj);
}
printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
//printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
}
}
} //else printf("no symbol\n");
@ -804,17 +804,19 @@ void LP_txbytes_update(char *name,char *symbol,char *txbytes,bits256 *txidp,bits
int32_t LP_rswap_checktx(struct LP_swap_remember *rswap,char *symbol,int32_t txi)
{
struct LP_transaction *tx; struct iguana_info *coin; char str[65];
int32_t ht; struct iguana_info *coin; //char str[65];
if ( rswap->sentflags[txi] == 0 && bits256_nonz(rswap->txids[txi]) != 0 )
{
coin = LP_coinfind(symbol);
printf("[%s] %s txbytes.%p %s\n",txnames[txi],txnames[txi],rswap->txbytes[txi],bits256_str(str,rswap->txids[txi]));
if ( coin != 0 && (tx= LP_transactionfind(coin,rswap->txids[txi])) != 0 && tx->height > 0 )
if ( (coin= LP_coinfind(symbol)) != 0 )
{
rswap->sentflags[txi] = 1;
_LP_refht_update(coin,rswap->txids[txi],tx->height);
} else LP_refht_update(symbol,rswap->txids[txi]);
}
if ( (ht= LP_txheight(coin,rswap->txids[txi])) > 0 )
{
rswap->sentflags[txi] = 1;
_LP_refht_update(coin,rswap->txids[txi],ht);
} else LP_refht_update(symbol,rswap->txids[txi]);
//printf("[%s] %s txbytes.%p %s ht.%d\n",txnames[txi],txnames[txi],rswap->txbytes[txi],bits256_str(str,rswap->txids[txi]),ht);
}
} //else printf("sent.%d %s txi.%d\n",rswap->sentflags[txi],bits256_str(str,rswap->txids[txi]),txi);
return(0);
}
@ -845,11 +847,12 @@ int32_t LP_spends_set(struct LP_swap_remember *rswap)
cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid)
{
static void *ctx;
struct LP_swap_remember rswap; int32_t i,j,numspent,len,secretstart,redeemlen; char str[65],*srcAdest,*srcBdest,*destAdest,*destBdest,otheraddr[64]; cJSON *item; bits256 rev,signedtxid,zero; struct iguana_info *bob=0,*alice=0; uint8_t redeemscript[1024],userdata[1024];
struct LP_swap_remember rswap; int32_t i,j,flag,numspent,len,secretstart,redeemlen; char str[65],*srcAdest,*srcBdest,*destAdest,*destBdest,otheraddr[64]; cJSON *item,*txoutobj; bits256 rev,signedtxid,zero,deadtxid; struct iguana_info *bob=0,*alice=0; uint8_t redeemscript[1024],userdata[1024];
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( (rswap.iambob= LP_rswap_init(&rswap,requestid,quoteid)) < 0 )
return(cJSON_Parse("{\"error\":\"couldnt initialize rswap, are all coins active?\"}"));
decode_hex(deadtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
LP_swap_load(&rswap);
memset(zero.bytes,0,sizeof(zero));
otheraddr[0] = 0;
@ -925,7 +928,10 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
{
if ( rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.paymentspent) == 0 )
{
//if ( txbytes[BASILISK_ALICESPEND] == 0 )
if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobpaymentaddr,rswap.txids[BASILISK_BOBPAYMENT],0)) != 0 )
free_json(txoutobj), flag = 0;
else flag = -1, rswap.paymentspent = deadtxid;
if ( flag == 0 )
{
if ( bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 )
{
@ -950,15 +956,18 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( (rswap.txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"alicespend",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_ALICESPEND],0,0,rswap.bobpaymentaddr,1)) != 0 )
printf("alicespend.(%s)\n",rswap.txbytes[BASILISK_ALICESPEND]);
}
LP_txbytes_update("alicespend",rswap.bobcoin,rswap.txbytes[BASILISK_ALICESPEND],&rswap.txids[BASILISK_ALICESPEND],&rswap.paymentspent,&rswap.sentflags[BASILISK_ALICESPEND]);
}
LP_txbytes_update("alicespend",rswap.bobcoin,rswap.txbytes[BASILISK_ALICESPEND],&rswap.txids[BASILISK_ALICESPEND],&rswap.paymentspent,&rswap.sentflags[BASILISK_ALICESPEND]);
}
}
if ( rswap.sentflags[BASILISK_ALICECLAIM] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 )
{
if ( time(NULL) > rswap.expiration )
{
//if ( txbytes[BASILISK_ALICECLAIM] == 0 )
if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobdepositaddr,rswap.txids[BASILISK_BOBDEPOSIT],0)) != 0 )
free_json(txoutobj), flag = 0;
else flag = -1, rswap.depositspent = deadtxid;
if ( flag == 0 )
{
if ( rswap.Dredeemlen != 0 )
redeemlen = rswap.Dredeemlen, memcpy(redeemscript,rswap.Dredeemscript,rswap.Dredeemlen);
@ -974,13 +983,16 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICECLAIM]);
}
}
LP_txbytes_update("aliceclaim",rswap.bobcoin,rswap.txbytes[BASILISK_ALICECLAIM],&rswap.txids[BASILISK_ALICECLAIM],&rswap.depositspent,&rswap.sentflags[BASILISK_ALICECLAIM]);
}
LP_txbytes_update("aliceclaim",rswap.bobcoin,rswap.txbytes[BASILISK_ALICECLAIM],&rswap.txids[BASILISK_ALICECLAIM],&rswap.depositspent,&rswap.sentflags[BASILISK_ALICECLAIM]);
} else printf("now %u before expiration %u\n",(uint32_t)time(NULL),rswap.expiration);
}
if ( rswap.sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(rswap.Apaymentspent) == 0 && rswap.sentflags[BASILISK_ALICECLAIM] == 0 )
{
//if ( txbytes[BASILISK_ALICERECLAIM] == 0 )
if ( (txoutobj= LP_gettxout(rswap.alicecoin,rswap.alicepaymentaddr,rswap.txids[BASILISK_ALICEPAYMENT],0)) != 0 )
free_json(txoutobj), flag = 0;
else flag = -1, rswap.Apaymentspent = deadtxid;
if ( flag == 0 )
{
rswap.privBn = basilisk_swap_privBn_extract(&rswap.txids[BASILISK_BOBREFUND],rswap.bobcoin,rswap.txids[BASILISK_BOBDEPOSIT],rswap.privBn);
if ( bits256_nonz(rswap.txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(rswap.privAm) != 0 && bits256_nonz(rswap.privBn) != 0 )
@ -988,36 +1000,42 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( (rswap.txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",rswap.alicecoin,rswap.Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,rswap.privAm,rswap.privBn,rswap.txids[BASILISK_ALICEPAYMENT],0,rswap.pubkey33,rswap.expiration,&rswap.values[BASILISK_ALICERECLAIM],rswap.alicepaymentaddr)) != 0 )
printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICERECLAIM]);
}
LP_txbytes_update("alicereclaim",rswap.alicecoin,rswap.txbytes[BASILISK_ALICERECLAIM],&rswap.txids[BASILISK_ALICERECLAIM],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_ALICERECLAIM]);
}
LP_txbytes_update("alicereclaim",rswap.alicecoin,rswap.txbytes[BASILISK_ALICERECLAIM],&rswap.txids[BASILISK_ALICERECLAIM],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_ALICERECLAIM]);
}
}
else if ( rswap.iambob == 1 )
{
if ( rswap.sentflags[BASILISK_BOBSPEND] == 0 && bits256_nonz(rswap.Apaymentspent) == 0 )
{
printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm));
//printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm));
if ( bits256_nonz(rswap.txids[BASILISK_ALICESPEND]) != 0 || bits256_nonz(rswap.privAm) != 0 )
{
//if ( txbytes[BASILISK_BOBSPEND] == 0 )
if ( (txoutobj= LP_gettxout(rswap.alicecoin,rswap.alicepaymentaddr,rswap.txids[BASILISK_ALICEPAYMENT],0)) != 0 )
free_json(txoutobj), flag = 0;
else flag = -1, rswap.Apaymentspent = deadtxid;
if ( flag == 0 )
{
if ( bits256_nonz(rswap.privAm) == 0 )
{
rswap.privAm = basilisk_swap_privbob_extract(rswap.bobcoin,rswap.txids[BASILISK_ALICESPEND],0,1);
printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm));
//printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm));
}
if ( bits256_nonz(rswap.privAm) != 0 && bits256_nonz(rswap.privBn) != 0 )
{
if ( (rswap.txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",rswap.alicecoin,rswap.Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,rswap.privAm,rswap.privBn,rswap.txids[BASILISK_ALICEPAYMENT],0,rswap.pubkey33,rswap.expiration,&rswap.values[BASILISK_BOBSPEND],rswap.alicepaymentaddr)) != 0 )
printf("bobspend.(%s)\n",rswap.txbytes[BASILISK_BOBSPEND]);
}
LP_txbytes_update("bobspend",rswap.alicecoin,rswap.txbytes[BASILISK_BOBSPEND],&rswap.txids[BASILISK_BOBSPEND],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_BOBSPEND]);
}
LP_txbytes_update("bobspend",rswap.alicecoin,rswap.txbytes[BASILISK_BOBSPEND],&rswap.txids[BASILISK_BOBSPEND],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_BOBSPEND]);
}
}
if ( rswap.sentflags[BASILISK_BOBRECLAIM] == 0 && rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 && time(NULL) > rswap.expiration && bits256_nonz(rswap.paymentspent) == 0 )
if ( rswap.sentflags[BASILISK_BOBRECLAIM] == 0 && rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 && bits256_nonz(rswap.paymentspent) == 0 )
{
//if ( txbytes[BASILISK_BOBRECLAIM] == 0 )
if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobpaymentaddr,rswap.txids[BASILISK_BOBPAYMENT],0)) != 0 )
free_json(txoutobj), flag = 0;
else flag = -1, rswap.paymentspent = deadtxid;
if ( flag == 0 && time(NULL) > rswap.expiration )
{
// bobreclaim
redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,rswap.plocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,zero,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256);
@ -1032,12 +1050,17 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
printf(" secretAm, myprivs[1].(%s) bobreclaim.(%s)\n",bits256_str(str,rswap.myprivs[1]),rswap.txbytes[BASILISK_BOBRECLAIM]);
}
}
LP_txbytes_update("bobreclaim",rswap.bobcoin,rswap.txbytes[BASILISK_BOBRECLAIM],&rswap.txids[BASILISK_BOBRECLAIM],&rswap.paymentspent,&rswap.sentflags[BASILISK_BOBRECLAIM]);
}
LP_txbytes_update("bobreclaim",rswap.bobcoin,rswap.txbytes[BASILISK_BOBRECLAIM],&rswap.txids[BASILISK_BOBRECLAIM],&rswap.paymentspent,&rswap.sentflags[BASILISK_BOBRECLAIM]);
else if ( flag == 0 )
printf("bobpayment: now.%u < expiration %u\n",(uint32_t)time(NULL),rswap.expiration);
}
if ( rswap.sentflags[BASILISK_BOBREFUND] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 )
{
if ( bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration )
if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobdepositaddr,rswap.txids[BASILISK_BOBDEPOSIT],0)) != 0 )
free_json(txoutobj), flag = 0;
else flag = -1, rswap.depositspent = deadtxid;
if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration) )
{
printf("do the refund! paymentspent.%s now.%u vs expiration.%u\n",bits256_str(str,rswap.paymentspent),(uint32_t)time(NULL),rswap.expiration);
//if ( txbytes[BASILISK_BOBREFUND] == 0 )
@ -1050,7 +1073,9 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,rswap.pubB1),rswap.txbytes[BASILISK_BOBREFUND]);
}
LP_txbytes_update("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],&rswap.txids[BASILISK_BOBREFUND],&rswap.depositspent,&rswap.sentflags[BASILISK_BOBREFUND]);
} else printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),rswap.expiration);
}
else if ( flag == 0 )
printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),rswap.expiration);
}
}
}
@ -1064,7 +1089,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
if ( bits256_nonz(rswap.txids[i]) != 0 && rswap.values[i] == 0 )
rswap.values[i] = basilisk_txvalue(basilisk_isbobcoin(rswap.iambob,i) ? rswap.bobcoin : rswap.alicecoin,rswap.txids[i],0);
if ( rswap.origfinishedflag == 0 )
if ( 0 && rswap.origfinishedflag == 0 )
{
printf("iambob.%d Apaymentspent.(%s) alice.%d bob.%d %s %.8f\n",rswap.iambob,bits256_str(str,rswap.Apaymentspent),rswap.sentflags[BASILISK_ALICERECLAIM],rswap.sentflags[BASILISK_BOBSPEND],rswap.alicecoin,dstr(rswap.values[BASILISK_ALICEPAYMENT]));
printf("paymentspent.(%s) alice.%d bob.%d %s %.8f\n",bits256_str(str,rswap.paymentspent),rswap.sentflags[BASILISK_ALICESPEND],rswap.sentflags[BASILISK_BOBRECLAIM],rswap.bobcoin,dstr(rswap.values[BASILISK_BOBPAYMENT]));

249
iguana/exchanges/LP_signatures.c

@ -181,9 +181,121 @@ char *LP_quotereceived(cJSON *argjson)
} else return(clonestr("{\"error\":\"nullptr\"}"));
}
int32_t LP_bitcoinsig_add(cJSON *item,bits256 priv,uint8_t *pubsecp,bits256 sighash)
{
static void *ctx; int32_t i,j,siglen; uint8_t pub33[33],sig[65]; char sigstr[128];
if ( ctx == 0 )
ctx = bitcoin_ctx();
for (j=0; j<100; j++)
{
if ( (siglen= bitcoin_sign(ctx,"sigadd",sig,sighash,priv,1)) > 0 && siglen == 65 )
{
memset(pub33,0,33);
if ( bitcoin_recoververify(ctx,"test",sig,sighash,pub33,0) == 0 && memcmp(pub33,pubsecp,33) == 0 )
{
init_hexbytes_noT(sigstr,sig,siglen);
jaddstr(item,"sig",sigstr);
return(siglen);
}
if ( 0 )
{
for (i=0; i<33; i++)
printf("%02x",pubsecp[i]);
printf(" pubsecp -> ");
for (i=0; i<33; i++)
printf("%02x",pub33[i]);
printf(" mismatched recovered pubkey.%d of %d\n",j,100);
}
}
}
return(-1);
}
bits256 LP_price_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,char *base,char *rel,uint64_t price64)
{
uint8_t buf[sizeof(pubkey) + 33 + sizeof(uint64_t)*3 + sizeof(timestamp)]; uint64_t basebits,relbits; bits256 sighash;
basebits = stringbits(base);
relbits = stringbits(rel);
memcpy(buf,pubkey.bytes,sizeof(pubkey));
memcpy(&buf[sizeof(pubkey)],pubsecp,33);
memcpy(&buf[sizeof(pubkey)+33],&price64,sizeof(price64));
memcpy(&buf[sizeof(pubkey)+33+sizeof(price64)],&basebits,sizeof(basebits));
memcpy(&buf[sizeof(pubkey)+33+sizeof(price64)+sizeof(basebits)],&relbits,sizeof(relbits));
memcpy(&buf[sizeof(pubkey)+33+sizeof(price64)+sizeof(basebits)+sizeof(relbits)],&timestamp,sizeof(timestamp));
vcalc_sha256(0,sighash.bytes,buf,sizeof(buf));
return(sighash);
}
bits256 LP_pubkey_sighash(uint32_t timestamp,bits256 pubkey,uint8_t *rmd160,uint8_t *pubsecp)
{
uint8_t buf[sizeof(pubkey) + 20 + 33 + sizeof(timestamp)]; bits256 sighash;
memcpy(buf,pubkey.bytes,sizeof(pubkey));
memcpy(&buf[sizeof(pubkey)],rmd160,20);
memcpy(&buf[sizeof(pubkey)+20],pubsecp,33);
memcpy(&buf[sizeof(pubkey)+20+33],&timestamp,sizeof(timestamp));
vcalc_sha256(0,sighash.bytes,buf,sizeof(buf));
return(sighash);
}
bits256 LP_utxos_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,bits256 utxoshash)
{
uint8_t buf[sizeof(pubkey)+sizeof(utxoshash)+33+sizeof(timestamp)]; bits256 sighash;
memcpy(buf,pubkey.bytes,sizeof(pubkey));
memcpy(&buf[sizeof(pubkey)],pubsecp,33);
memcpy(&buf[sizeof(pubkey)+33],&timestamp,sizeof(timestamp));
memcpy(&buf[sizeof(pubkey)+33+sizeof(timestamp)],utxoshash.bytes,sizeof(utxoshash));
vcalc_sha256(0,sighash.bytes,buf,sizeof(buf));
return(sighash);
}
int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,bits256 utxoshash)
{
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( sigstr != 0 && pubsecpstr != 0 && strlen(sigstr) == 65*2 && strlen(pubsecpstr) == 33 *2 )
{
decode_hex(sig,65,sigstr);
decode_hex(pubsecp,33,pubsecpstr);
sighash = LP_utxos_sighash(timestamp,pubsecp,pubkey,utxoshash);
retval = bitcoin_recoververify(ctx,"utxos",sig,sighash,pub33,0);
if ( memcmp(pub33,pubsecp,33) != 0 || retval != 0 )
{
printf("LP_utxos_sigcheck failure, probably from node with older version\n");
retval = -1;
} else retval = 0;
}
return(retval);
}
bits256 LP_utxoshash_calc(cJSON *array)
{
int32_t i,j,n; bits256 utxoshash,txid; cJSON *item;
memset(utxoshash.bytes,0,sizeof(utxoshash));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
for (j=0; j<4; j++)
utxoshash.ulongs[j] ^= txid.ulongs[j];
utxoshash.uints[0] ^= jint(item,"tx_pos");
}
}
return(utxoshash);
}
int32_t LP_utxos_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pubsecp,bits256 pubkey,bits256 utxoshash)
{
bits256 sighash;
sighash = LP_utxos_sighash(timestamp,pubsecp,pubkey,utxoshash);
return(LP_bitcoinsig_add(item,priv,pubsecp,sighash));
}
void LP_postutxos(char *symbol,char *coinaddr)
{
bits256 zero; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
bits256 zero; uint32_t timestamp; bits256 utxoshash; char pubsecpstr[67]; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
if ( (coin= LP_coinfind(symbol)) != 0 && (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
//printf("LP_postutxos pubsock.%d %s %s\n",pubsock,symbol,coin->smartaddr);
@ -196,6 +308,14 @@ void LP_postutxos(char *symbol,char *coinaddr)
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"coinaddr",coinaddr);
jadd(reqjson,"utxos",array);
timestamp = (uint32_t)time(NULL);
jaddnum(reqjson,"timetamp",timestamp);
init_hexbytes_noT(pubsecpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",pubsecpstr);
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
utxoshash = LP_utxoshash_calc(array);
//char str[65]; printf("utxoshash add %s\n",bits256_str(str,utxoshash));
LP_utxos_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_pubsecp,G.LP_mypub25519,utxoshash);
//printf("post (%s) -> %d\n",msg,LP_mypubsock);
LP_reserved_msg(symbol,symbol,zero,jprint(reqjson,1));
}
@ -207,11 +327,20 @@ struct LP_utxos_qitem { struct queueitem DL; cJSON *argjson; };
char *LP_postutxos_recv(cJSON *argjson)
{
struct LP_utxos_qitem *uitem;
uitem = calloc(1,sizeof(*uitem));
uitem->argjson = jduplicate(argjson);
queue_enqueue("utxosQ",&utxosQ,&uitem->DL);
return(clonestr("{\"result\":\"success\"}"));
struct LP_utxos_qitem *uitem; bits256 utxoshash; cJSON *obj;
if ( (obj= jobj(argjson,"utxos")) != 0 )
{
utxoshash = LP_utxoshash_calc(obj);
//char str[65]; printf("got utxoshash %s\n",bits256_str(str,utxoshash));
if ( LP_utxos_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),jbits256(argjson,"pubkey"),utxoshash) == 0 )
{
uitem = calloc(1,sizeof(*uitem));
uitem->argjson = jduplicate(argjson);
queue_enqueue("utxosQ",&utxosQ,&uitem->DL);
return(clonestr("{\"result\":\"success\"}"));
}
}
return(clonestr("{\"error\":\"sig failure\"}"));
}
int32_t LP_utxosQ_process()
@ -237,9 +366,41 @@ int32_t LP_utxosQ_process()
return(0);
}
int32_t LP_price_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,char *base,char *rel,uint64_t price64)
{
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( sigstr != 0 && pubsecpstr != 0 && strlen(sigstr) == 65*2 && strlen(pubsecpstr) == 33 *2 )
{
decode_hex(sig,65,sigstr);
decode_hex(pubsecp,33,pubsecpstr);
sighash = LP_price_sighash(timestamp,pubsecp,pubkey,base,rel,price64);
retval = bitcoin_recoververify(ctx,"price",sig,sighash,pub33,0);
if ( memcmp(pub33,pubsecp,33) != 0 || retval != 0 )
{
printf("LP_price_sigcheck failure\n");
retval = -1;
}
else
{
retval = 0;
//printf("valid price sig %s/%s %.8f\n",base,rel,dstr(price64));
}
}
return(retval);
}
int32_t LP_price_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pubsecp,bits256 pubkey,char *base,char *rel,uint64_t price64)
{
bits256 sighash;
sighash = LP_price_sighash(timestamp,pubsecp,pubkey,base,rel,price64);
return(LP_bitcoinsig_add(item,priv,pubsecp,sighash));
}
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price)
{
struct iguana_info *basecoin,*relcoin; bits256 zero; cJSON *reqjson = cJSON_CreateObject();
struct iguana_info *basecoin,*relcoin; char pubsecpstr[67]; uint32_t timestamp; uint64_t price64; bits256 zero; cJSON *reqjson = cJSON_CreateObject();
// LP_addsig
if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 && relcoin->electrum == 0 )
{
@ -247,8 +408,15 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
jaddstr(reqjson,"base",base);
jaddstr(reqjson,"rel",rel);
price64 = price * SATOSHIDEN + 0.0000000049;
jaddnum(reqjson,"price",price);
jadd64bits(reqjson,"price64",price64);
jaddstr(reqjson,"method","postprice");
timestamp = (uint32_t)time(NULL);
jaddnum(reqjson,"timestamp",timestamp);
init_hexbytes_noT(pubsecpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",pubsecpstr);
LP_price_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_pubsecp,G.LP_mypub25519,base,rel,price64);
LP_reserved_msg(base,rel,zero,jprint(reqjson,1));
return(clonestr("{\"result\":\"success\"}"));
} else return(clonestr("{\"error\":\"electrum node cant post bob asks\"}"));
@ -263,62 +431,30 @@ char *LP_postprice_recv(cJSON *argjson)
pubkey = jbits256(argjson,"pubkey");
if ( bits256_nonz(pubkey) != 0 )
{
LP_pricefeedupdate(pubkey,base,rel,price);
return(clonestr("{\"result\":\"success\"}"));
if ( LP_price_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,base,rel,j64bits(argjson,"price64")) == 0 )
{
LP_pricefeedupdate(pubkey,base,rel,price);
return(clonestr("{\"result\":\"success\"}"));
} else return(clonestr("{\"error\":\"sig failure\"}"));
}
}
return(clonestr("{\"error\":\"missing fields in posted price\"}"));
}
bits256 LP_pubkey_sighash(bits256 pub,uint8_t *rmd160,uint8_t *pubsecp)
{
uint8_t buf[sizeof(pub) + 20 + 33]; bits256 sighash;
memcpy(buf,pub.bytes,sizeof(pub));
memcpy(&buf[sizeof(pub)],rmd160,20);
memcpy(&buf[sizeof(pub)+20],pubsecp,33);
vcalc_sha256(0,sighash.bytes,buf,sizeof(buf));
return(sighash);
}
int32_t _LP_pubkey_sigcheck(uint8_t *sig,int32_t siglen,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp)
int32_t _LP_pubkey_sigcheck(uint8_t *sig,int32_t siglen,uint32_t timestamp,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp)
{
static void *ctx;
uint8_t pub33[33]; bits256 sighash = LP_pubkey_sighash(pub,rmd160,pubsecp);
static void *ctx; uint8_t pub33[33]; bits256 sighash;
if ( ctx == 0 )
ctx = bitcoin_ctx();
return(bitcoin_recoververify(ctx,"sigcheck",sig,sighash,pub33,0));
sighash = LP_pubkey_sighash(timestamp,pub,rmd160,pubsecp);
return(bitcoin_recoververify(ctx,"pubkey",sig,sighash,pub33,0));
}
int32_t LP_pubkey_sigadd(cJSON *item,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp)
int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp)
{
static void *ctx;
uint8_t sig[128],pub33[33]; int32_t i,j,siglen=0; bits256 sighash; char sigstr[256];
sighash = LP_pubkey_sighash(pub,rmd160,pubsecp);
if ( ctx == 0 )
ctx = bitcoin_ctx();
for (j=0; j<100; j++)
{
if ( (siglen= bitcoin_sign(ctx,"sigadd",sig,sighash,priv,1)) > 0 && siglen == 65 )
{
memset(pub33,0,33);
if ( bitcoin_recoververify(ctx,"test",sig,sighash,pub33,0) == 0 && memcmp(pub33,pubsecp,33) == 0 )
{
init_hexbytes_noT(sigstr,sig,siglen);
jaddstr(item,"sig",sigstr);
return(siglen);
}
if ( 0 )
{
for (i=0; i<33; i++)
printf("%02x",pubsecp[i]);
printf(" pubsecp -> ");
for (i=0; i<33; i++)
printf("%02x",pub33[i]);
printf(" mismatched recovered pubkey.%d of %d\n",j,100);
}
}
}
return(0);
bits256 sighash;
sighash = LP_pubkey_sighash(timestamp,pub,rmd160,pubsecp);
return(LP_bitcoinsig_add(item,priv,pubsecp,sighash));
}
int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
@ -342,7 +478,7 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
{
siglen = len >> 1;
decode_hex(sig,siglen,sigstr);
if ( _LP_pubkey_sigcheck(sig,siglen,pubp->pubkey,rmd160,pubsecp) == 0 )
if ( _LP_pubkey_sigcheck(sig,siglen,juint(item,"timestamp"),pubp->pubkey,rmd160,pubsecp) == 0 )
{
for (i=0; i<20; i++)
printf("%02x",pubp->rmd160[i]);
@ -374,15 +510,16 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
void LP_notify_pubkeys(void *ctx,int32_t pubsock)
{
bits256 zero; char secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
// LP_addsig
bits256 zero; uint32_t timestamp; char secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","notify");
jaddstr(reqjson,"rmd160",G.LP_myrmd160str);
jaddbits256(reqjson,"pub",G.LP_mypub25519);
init_hexbytes_noT(secpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",secpstr);
LP_pubkey_sigadd(reqjson,G.LP_privkey,G.LP_mypub25519,G.LP_myrmd160,G.LP_pubsecp);
timestamp = (uint32_t)time(NULL);
jaddnum(reqjson,"timestamp",timestamp);
LP_pubkey_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_mypub25519,G.LP_myrmd160,G.LP_pubsecp);
LP_reserved_msg("","",zero,jprint(reqjson,1));
}

4
iguana/exchanges/LP_transaction.c

@ -1259,7 +1259,9 @@ bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t v
coinaddr[0] = 0;
memset(&spendtxid,0,sizeof(spendtxid));
if ( LP_spendsearch(destaddr,&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 )
printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout);
{
//printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout);
}
else if ( 0 && (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 )
{
if ( (retjson= LP_gettxout(symbol,coinaddr,utxotxid,vout)) == 0 )

2
iguana/exchanges/LP_utxo.c

@ -638,7 +638,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS
tx->outpoints[spentvout].spendvini = i;
tx->outpoints[spentvout].spendheight = height > 0 ? height : 1;
LP_address_utxoadd(coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1);
if ( 0 && strcmp(coin->symbol,"BTC") != 0 )
if ( 0 && strcmp(coin->symbol,"REVS") == 0 )
printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height);
}
} else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d spendheight.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts,tx->outpoints[spentvout].spendheight);

2
iguana/exchanges/coins

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save