/******************************************************************************
* Copyright © 2014 - 2018 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
//
char DEX_baseaddr [ 64 ] , DEX_reladdr [ 64 ] ;
struct mmpending_order
{
double price , volume ;
int32_t dir ;
uint32_t pending , completed , canceled , cancelstarted , reported ;
cJSON * errorjson ;
char exchange [ 16 ] , base [ 65 ] , rel [ 65 ] , orderid [ 64 ] ;
} * Pending_orders ;
int32_t Num_Pending ;
# define IGUANA_URL "http: //127.0.0.1:7778"
/*char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
" CNY " , " RUB " , " MXN " , " BRL " , " INR " , " HKD " , " TRY " , " ZAR " , " PLN " , " NOK " , " SEK " , " DKK " , " CZK " , " HUF " , " ILS " , " KRW " , " MYR " , " PHP " , " RON " , " SGD " , " THB " , " BGN " , " IDR " , " HRK " , // end of currencies
} ; */
double PAXPRICES [ sizeof ( CURRENCIES ) / sizeof ( * CURRENCIES ) ] ;
uint32_t PAXACTIVE ;
char * DEX_swapstatus ( )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" getswaplist \" } " ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " getswaplist " , postdata , 0 ) ) ;
}
char * DEX_amlp ( char * blocktrail )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" tradebot \" , \" method \" : \" amlp \" , \" blocktrail \" : \" %s \" } " , blocktrail ) ;
return ( bitcoind_RPC ( 0 , " tradebot " , url , 0 , " amlp " , postdata , 0 ) ) ;
}
char * DEX_openorders ( char * exchange )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" openorders \" , \" exchange \" : \" %s \" } " , exchange ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " openorders " , postdata , 0 ) ) ;
}
char * DEX_tradehistory ( char * exchange )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" tradehistory \" , \" exchange \" : \" %s \" } " , exchange ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " tradehistory " , postdata , 0 ) ) ;
}
char * DEX_orderstatus ( char * exchange , char * orderid )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" orderstatus \" , \" exchange \" : \" %s \" , \" orderid \" : \" %s \" } " , exchange , orderid ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " orderstatus " , postdata , 0 ) ) ;
}
char * DEX_cancelorder ( char * exchange , char * orderid )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" cancelorder \" , \" exchange \" : \" %s \" , \" orderid \" : \" %s \" } " , exchange , orderid ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " cancelorder " , postdata , 0 ) ) ;
}
char * DEX_balance ( char * exchange , char * base , char * coinaddr )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
if ( strcmp ( exchange , " DEX " ) = = 0 )
{
sprintf ( postdata , " { \" agent \" : \" dex \" , \" method \" : \" getbalance \" , \" address \" : \" %s \" , \" symbol \" : \" %s \" } " , coinaddr , base ) ;
return ( bitcoind_RPC ( 0 , " dex " , url , 0 , " getbalance " , postdata , 0 ) ) ;
}
else
{
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" balance \" , \" exchange \" : \" %s \" , \" base \" : \" %s \" } " , exchange , base ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " balance " , postdata , 0 ) ) ;
}
}
char * DEX_apikeypair ( char * exchange , char * apikey , char * apisecret )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" apikeypair \" , \" exchange \" : \" %s \" , \" apikey \" : \" %s \" , \" apisecret \" : \" %s \" } " , exchange , apikey , apisecret ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " apikeypair " , postdata , 0 ) ) ;
}
char * DEX_setuserid ( char * exchange , char * userid , char * tradepassword )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" setuserid \" , \" exchange \" : \" %s \" , \" userid \" : \" %s \" , \" tradepassword \" : \" %s \" } " , exchange , userid , tradepassword ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " setuserid " , postdata , 0 ) ) ;
}
char * DEX_trade ( char * exchange , char * base , char * rel , int32_t dir , double price , double volume )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" %s \" , \" exchange \" : \" %s \" , \" base \" : \" %s \" , \" rel \" : \" %s \" , \" price \" :%.8f, \" volume \" :%.8f, \" dotrade \" :1} " , dir > 0 ? " buy " : " sell " , exchange , base , rel , price , volume ) ;
//printf("DEX_trade.(%s)\n",postdata);
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , dir > 0 ? " buy " : " sell " , postdata , 0 ) ) ;
}
char * DEX_withdraw ( char * exchange , char * base , char * destaddr , double amount )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" InstantDEX \" , \" method \" : \" withdraw \" , \" exchange \" : \" %s \" , \" destaddr \" : \" %s \" , \" amount \" :%.8f} " , exchange , destaddr , amount ) ;
return ( bitcoind_RPC ( 0 , " InstantDEX " , url , 0 , " withdraw " , postdata , 0 ) ) ;
}
char * iguana_walletpassphrase ( char * passphrase , int32_t timeout )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase? " , IGUANA_URL ) ;
sprintf ( postdata , " [ \" %s \" , %d] " , passphrase , timeout ) ;
return ( bitcoind_RPC ( 0 , " " , url , 0 , " walletpassphrase " , postdata , 0 ) ) ;
}
/*char *iguana_listunspent(char *coin,char *coinaddr)
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/coin=%s&agent=bitcoinrpc&method=listunspent? " , IGUANA_URL , coin ) ;
sprintf ( postdata , " [ \" %s \" ] " , coinaddr ) ;
return ( bitcoind_RPC ( 0 , " " , url , 0 , " listunspent " , postdata ) ) ;
} */
/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers)
{
char url [ 512 ] ;
sprintf ( url , " http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d " , destip , destport , ipaddr , port , numpeers ) ;
printf ( " (%s) \n " , url ) ;
return ( issue_curl ( url ) ) ;
} */
//
// http://127.0.0.1:7779/api/stats/getpeers
char * DEX_listunspent ( char * coin , char * coinaddr )
{
char url [ 512 ] , postdata [ 1024 ] ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" dex \" , \" method \" : \" listunspent \" , \" address \" : \" %s \" , \" symbol \" : \" %s \" , \" timeout \" :60000} " , coinaddr , coin ) ;
return ( bitcoind_RPC ( 0 , " dex " , url , 0 , " listunspent " , postdata , 0 ) ) ;
}
bits256 iguana_wif2privkey ( char * wifstr )
{
char url [ 512 ] , postdata [ 1024 ] , * retstr , * privstr ; bits256 privkey ; cJSON * retjson ;
memset ( privkey . bytes , 0 , sizeof ( privkey ) ) ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" SuperNET \" , \" method \" : \" wif2priv \" , \" wif \" : \" %s \" } " , wifstr ) ;
if ( ( retstr = bitcoind_RPC ( 0 , " SuperNET " , url , 0 , " wif2priv " , postdata , 0 ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( privstr = jstr ( retjson , " privkey " ) ) ! = 0 )
{
if ( strlen ( privstr ) = = 64 )
decode_hex ( privkey . bytes , 32 , privstr ) ;
}
free_json ( retjson ) ;
}
free ( retstr ) ;
}
return ( privkey ) ;
}
double bittrex_balance ( char * base , char * coinaddr )
{
char * retstr ; cJSON * retjson ; double balance = 0. ;
if ( ( retstr = DEX_balance ( " bittrex " , base , coinaddr ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
balance = jdouble ( retjson , " balance " ) ;
free_json ( retjson ) ;
}
free ( retstr ) ;
}
return ( balance ) ;
}
double dex_balance ( char * base , char * coinaddr )
{
char * retstr ; cJSON * retjson ; double balance = 0. ;
if ( ( retstr = DEX_balance ( " DEX " , base , coinaddr ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
balance = jdouble ( retjson , " balance " ) ;
free_json ( retjson ) ;
}
free ( retstr ) ;
}
return ( balance ) ;
}
int32_t komodo_baseid ( char * base )
{
int32_t i ;
for ( i = 0 ; i < sizeof ( CURRENCIES ) / sizeof ( * CURRENCIES ) ; i + + )
if ( strcmp ( base , CURRENCIES [ i ] ) = = 0 )
return ( i ) ;
return ( - 1 ) ;
}
cJSON * yahoo_allcurrencies ( )
{
char * retstr ; cJSON * retjson = 0 ;
if ( ( retstr = issue_curl ( " http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json " ) ) ! = 0 )
{
retjson = cJSON_Parse ( retstr ) ;
free ( retstr ) ;
}
return ( retjson ) ;
}
void _marketmaker_fiatupdate ( int32_t baseid , double price )
{
PAXPRICES [ baseid ] = price * PAXPRICES [ 0 ] ;
printf ( " %.6f %s per USD, %.8f %s per KMD \n " , price , CURRENCIES [ baseid ] , PAXPRICES [ baseid ] , CURRENCIES [ baseid ] ) ;
}
uint32_t marketmaker_fiatupdate ( cJSON * fiatjson )
{
int32_t i , n , baseid ; cJSON * item , * array ; double price ; char * name ; uint64_t mask = 0 ;
fiatjson = jobj ( fiatjson , " list " ) ;
if ( fiatjson ! = 0 & & ( array = jarray ( & n , fiatjson , " resources " ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
/*
" resource " : {
" classname " : " Quote " ,
" fields " : {
" name " : " USD/BRX " ,
" price " : " 3.063200 " ,
" symbol " : " BRX=X " ,
" ts " : " 1487866204 " ,
" type " : " currency " ,
" utctime " : " 2017-02-23T16:10:04+0000 " ,
" volume " : " 0 "
}
*/
item = jitem ( array , i ) ;
if ( ( item = jobj ( item , " resource " ) ) ! = 0 )
item = jobj ( item , " fields " ) ;
if ( item ! = 0 )
{
price = jdouble ( item , " price " ) ;
if ( price > SMALLVAL & & ( name = jstr ( item , " name " ) ) ! = 0 & & strncmp ( name , " USD/ " , 4 ) = = 0 )
{
if ( ( baseid = komodo_baseid ( name + 4 ) ) > = 0 & & baseid < 32 )
{
if ( ( ( 1LL < < baseid ) & mask ) = = 0 )
{
_marketmaker_fiatupdate ( baseid , price ) ;
mask | = ( 1LL < < baseid ) ;
} else if ( fabs ( price * PAXPRICES [ 0 ] - PAXPRICES [ baseid ] ) > SMALLVAL )
printf ( " DUPLICATE PRICE? %s %.8f vs %.8f \n " , name + 4 , price * PAXPRICES [ 0 ] , PAXPRICES [ baseid ] ) ;
}
}
}
}
}
printf ( " pax mask.%x \n " , ( uint32_t ) mask ) ;
return ( ( uint32_t ) mask ) ;
}
void marketmaker_cancel ( struct mmpending_order * ptr )
{
char * retstr ; cJSON * retjson ;
if ( ptr - > pending ! = 0 & & ptr - > cancelstarted = = 0 )
{
ptr - > cancelstarted = ( uint32_t ) time ( NULL ) ;
if ( ( retstr = DEX_cancelorder ( ptr - > exchange , ptr - > orderid ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
printf ( " cancel %s (%s/%s) %.8f vol %.8f dir.%d -> (%s) \n " , ptr - > exchange , ptr - > base , ptr - > rel , ptr - > price , ptr - > volume , ptr - > dir , jprint ( retjson , 0 ) ) ;
free_json ( retjson ) ;
ptr - > pending = 0 ;
ptr - > canceled = ( uint32_t ) time ( NULL ) ;
}
free ( retstr ) ;
}
}
}
void marketmaker_queue ( char * exchange , char * base , char * rel , int32_t dir , double price , double volume , cJSON * retjson )
{
struct mmpending_order * ptr ; char * orderid ;
//DEX_trade.({"success":true,"message":"","result":{"uuid":"d5faa9e4-660d-436f-a257-2c6a40442d8c"},"tag":"11271578410079391025"}
if ( is_cJSON_True ( jobj ( retjson , " success " ) ) ! = 0 & & jobj ( retjson , " result " ) ! = 0 )
retjson = jobj ( retjson , " result " ) ;
printf ( " QUEUE.%s %s/%s dir.%d %.8f %.6f (%s) \n " , exchange , base , rel , dir , price , volume , jprint ( retjson , 0 ) ) ;
Pending_orders = realloc ( Pending_orders , ( 1 + Num_Pending ) * sizeof ( * Pending_orders ) ) ;
ptr = & Pending_orders [ Num_Pending + + ] ;
memset ( ptr , 0 , sizeof ( * ptr ) ) ;
ptr - > price = price ;
ptr - > volume = volume ;
ptr - > dir = dir ;
ptr - > pending = ( uint32_t ) time ( NULL ) ;
strcpy ( ptr - > exchange , exchange ) ;
strcpy ( ptr - > base , base ) ;
strcpy ( ptr - > rel , rel ) ;
if ( ( orderid = jstr ( retjson , " OrderUuid " ) ) ! = 0 | | ( orderid = jstr ( retjson , " uuid " ) ) ! = 0 )
strcpy ( ptr - > orderid , orderid ) ;
else strcpy ( ptr - > orderid , " 0 " ) ;
}
void marketmaker_pendingupdate ( char * exchange , char * base , char * rel )
{
char * retstr ; cJSON * retjson , * obj ; int32_t i ; struct mmpending_order * ptr ;
for ( i = 0 ; i < Num_Pending ; i + + )
{
ptr = & Pending_orders [ i ] ;
if ( strcmp ( exchange , ptr - > exchange ) ! = 0 | | strcmp ( base , ptr - > base ) ! = 0 | | strcmp ( rel , ptr - > rel ) ! = 0 )
continue ;
if ( ptr - > completed = = 0 & & ( retstr = DEX_orderstatus ( exchange , ptr - > orderid ) ) ! = 0 )
{
//printf("%s status.(%s)\n",ptr->orderid,retstr);
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
obj = jobj ( retjson , " result " ) ;
if ( is_cJSON_Array ( obj ) ! = 0 )
obj = jitem ( retjson , 0 ) ;
if ( jdouble ( obj , " QuantityRemaining " ) = = 0. | | is_cJSON_True ( jobj ( obj , " IsOpen " ) ) = = 0 )
{
//{"Uuid":null,"OrderUuid":"e7b0789c-0c4e-413b-a768-3d5734d9cbe5","Exchange":"BTC-KMD","OrderType":"LIMIT_SELL","Quantity":877.77700000,"QuantityRemaining":462.50512234,"Limit":0.00011770,"CommissionPaid":0.00012219,"Price":0.04887750,"PricePerUnit":0.00011769,"Opened":"2017-02-20T13:16:22.29","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null} printf("uuid.(%s) finished.(%s)\n",ptr->orderid,jprint(retjson,0));
ptr - > completed = ( uint32_t ) time ( NULL ) ;
ptr - > pending = 0 ;
}
free_json ( retjson ) ;
}
free ( retstr ) ;
}
}
}
void marketmaker_pendinginit ( char * exchange , char * base , char * rel )
{
char * retstr , * orderid , * pairstr , relbase [ 65 ] ; cJSON * retjson , * array , * item ; int32_t i , j , n , dir ; struct mmpending_order * ptr ;
sprintf ( relbase , " %s-%s " , rel , base ) ;
if ( ( retstr = DEX_openorders ( exchange ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
//printf("%s\n",jprint(retjson,0));
if ( is_cJSON_True ( jobj ( retjson , " success " ) ) ! = 0 & & ( array = jarray ( & n , retjson , " result " ) ) ! = 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
if ( ( pairstr = jstr ( item , " Exchange " ) ) = = 0 )
continue ;
if ( strcmp ( pairstr , relbase ) ! = 0 )
{
printf ( " skip %s when %s \n " , pairstr , relbase ) ;
continue ;
}
//printf("(%s)\n",jprint(item,0));
//{"success":true,"message":"","result":[{"Uuid":null,"OrderUuid":"81ad3e37-65d4-4fee-9c29-03b050f5192b","Exchange":"BTC-KMD","OrderType":"LIMIT_BUY","Quantity":885.19934578,"QuantityRemaining":885.19934578,"Limit":0.00011184,"CommissionPaid":0,"Price":0,"PricePerUnit":null,"Opened":"2017-02-19T19:14:02.94","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null}],"tag":"10056789044100011414"}
if ( ( orderid = jstr ( item , " OrderUuid " ) ) ! = 0 & & is_cJSON_Null ( jobj ( item , " Closed " ) ) ! = 0 & & is_cJSON_False ( jobj ( item , " CancelInitiated " ) ) ! = 0 )
{
for ( j = 0 ; j < Num_Pending ; j + + )
{
ptr = & Pending_orders [ j ] ;
if ( strcmp ( exchange , ptr - > exchange ) ! = 0 | | strcmp ( base , ptr - > base ) ! = 0 | | strcmp ( rel , ptr - > rel ) ! = 0 )
continue ;
if ( strcmp ( ptr - > orderid , orderid ) = = 0 )
{
ptr - > pending = ( uint32_t ) time ( NULL ) ;
ptr - > completed = 0 ;
printf ( " %s pending \n " , orderid ) ;
break ;
}
}
if ( j = = Num_Pending )
{
if ( jstr ( item , " OrderType " ) ! = 0 )
{
if ( strcmp ( jstr ( item , " OrderType " ) , " LIMIT_BUY " ) = = 0 )
dir = 1 ;
else if ( strcmp ( jstr ( item , " OrderType " ) , " LIMIT_SELL " ) = = 0 )
dir = - 1 ;
else dir = 0 ;
if ( dir ! = 0 )
marketmaker_queue ( exchange , base , rel , dir , jdouble ( item , " Limit " ) , jdouble ( item , " QuantityRemaining " ) , item ) ;
else printf ( " no dir (%s) ( % s ) \ n " ,jprint(item,0),jstr(item, " OrderType " )) ;
}
}
}
}
}
free_json ( retjson ) ;
}
free ( retstr ) ;
}
}
double marketmaker_filled ( char * exchange , char * base , char * rel , double * buyvolp , double * sellvolp , double * pendingbidsp , double * pendingasksp )
{
double pricesum = 0. , volsum = 0. ; struct mmpending_order * ptr ; int32_t i ;
* pendingbidsp = * pendingasksp = 0. ;
for ( i = 0 ; i < Num_Pending ; i + + )
{
ptr = & Pending_orders [ i ] ;
if ( strcmp ( exchange , ptr - > exchange ) ! = 0 | | strcmp ( base , ptr - > base ) ! = 0 | | strcmp ( rel , ptr - > rel ) ! = 0 )
continue ;
if ( ptr - > completed ! = 0 )
{
if ( ptr - > reported = = 0 )
{
if ( ptr - > dir > 0 )
( * buyvolp ) + = ptr - > volume ;
else if ( ptr - > dir < 0 )
( * sellvolp ) + = ptr - > volume ;
pricesum + = ptr - > volume * ptr - > price ;
volsum + = ptr - > volume ;
ptr - > reported = ( uint32_t ) time ( NULL ) ;
printf ( " REPORT dir.%d vol %.8f \n " , ptr - > dir , ptr - > volume ) ;
}
}
else if ( ptr - > pending ! = 0 ) // alternative is error or cancelled
{
if ( ptr - > dir > 0 )
( * pendingbidsp ) + = ptr - > volume ;
else if ( ptr - > dir < 0 )
( * pendingasksp ) + = ptr - > volume ;
}
}
if ( volsum ! = 0. )
pricesum / = volsum ;
return ( pricesum ) ;
}
int32_t marketmaker_prune ( char * exchange , char * base , char * rel , int32_t polarity , double bid , double ask , double separation )
{
int32_t i , n = 0 ; struct mmpending_order * ptr ;
for ( i = 0 ; i < Num_Pending ; i + + )
{
ptr = & Pending_orders [ i ] ;
if ( strcmp ( exchange , ptr - > exchange ) ! = 0 | | strcmp ( base , ptr - > base ) ! = 0 | | strcmp ( rel , ptr - > rel ) ! = 0 )
continue ;
if ( ptr - > pending ! = 0 & & ptr - > cancelstarted = = 0 )
{
if ( polarity ! = 0 )
{
if ( ( ( ptr - > dir * polarity > 0 & & ptr - > price < bid - separation ) | | ( ptr - > dir * polarity < 0 & & ptr - > price > ask + separation ) ) )
{
printf ( " polarity.%d dir.%d price.%f bid.%f ask.%f \n " , polarity , ptr - > dir , ptr - > price , bid , ask ) ;
marketmaker_cancel ( ptr ) , n + + ;
}
}
/*else
{ , * prunebid = 0 , * pruneask = 0 ; double lowbid = 0. , highask = 0.
if ( ptr - > dir > 0 & & ( lowbid = = 0. | | ptr - > price < lowbid ) )
{
lowbid = ptr - > price ;
prunebid = ptr ;
}
else if ( ptr - > dir < 0 & & ( highask = = 0. | | ptr - > price > highask ) )
{
highask = ptr - > price ;
pruneask = ptr ;
}
} */
}
}
/*if ( polarity == 0 )
{
if ( prunebid ! = 0 & & fabs ( prunebid - > price - bid ) > separation )
marketmaker_cancel ( prunebid ) , n + + ;
if ( pruneask ! = 0 & & fabs ( pruneask - > price - ask ) > separation )
marketmaker_cancel ( pruneask ) , n + + ;
} */
return ( n ) ;
}
void marketmaker_volumeset ( double * bidincrp , double * askincrp , double incr , double buyvol , double pendingbids , double sellvol , double pendingasks , double maxexposure )
{
* bidincrp = * askincrp = incr ;
//if ( pendingbids >= pendingasks+maxexposure )
// *bidincrp = 0.;
//else if ( pendingasks >= pendingbids+maxexposure )
// *askincrp = 0.;
if ( * bidincrp > 0. & & pendingbids + * bidincrp > maxexposure )
* bidincrp = ( maxexposure - * bidincrp ) ;
if ( * askincrp > 0. & & pendingasks + * askincrp > maxexposure )
* askincrp = ( maxexposure - * askincrp ) ;
if ( * bidincrp < 0. )
* bidincrp = 0. ;
if ( * askincrp < 0. )
* askincrp = 0. ;
}
int32_t marketmaker_spread ( char * exchange , char * base , char * rel , double bid , double bidvol , double ask , double askvol , double separation )
{
int32_t nearflags [ 2 ] , i , n = 0 ; struct mmpending_order * ptr ; cJSON * retjson , * vals ; char * retstr , postdata [ 1024 ] , url [ 128 ] ; double vol , spread_ratio ;
memset ( nearflags , 0 , sizeof ( nearflags ) ) ;
if ( strcmp ( " DEX " , exchange ) ! = 0 )
{
for ( i = 0 ; i < Num_Pending ; i + + )
{
ptr = & Pending_orders [ i ] ;
if ( strcmp ( exchange , ptr - > exchange ) ! = 0 | | strcmp ( base , ptr - > base ) ! = 0 | | strcmp ( rel , ptr - > rel ) ! = 0 )
continue ;
if ( ptr - > pending ! = 0 & & ptr - > cancelstarted = = 0 )
{
if ( bid > SMALLVAL & & bidvol > SMALLVAL & & ptr - > dir > 0 & & fabs ( bid - ptr - > price ) < separation )
{
//printf("bid %.8f near %.8f\n",bid,ptr->price);
nearflags [ 0 ] + + ;
}
if ( ask > SMALLVAL & & askvol > SMALLVAL & & ptr - > dir < 0 & & fabs ( ask - ptr - > price ) < separation )
{
//printf("%.8f near %.8f\n",ask,ptr->price);
nearflags [ 1 ] + + ;
}
}
}
}
//printf("spread.%s (%.8f %.6f) (%.8f %.6f)\n",exchange,bid,bidvol,ask,askvol);
if ( bid > SMALLVAL & & bidvol > SMALLVAL & & nearflags [ 0 ] = = 0 )
{
if ( strcmp ( " DEX " , exchange ) = = 0 & & strcmp ( base , " KMD " ) = = 0 & & strcmp ( rel , " BTC " ) = = 0 )
{
if ( ask > SMALLVAL & & askvol > SMALLVAL )
{
/*li.profit = jdouble(vals,"profit");
li . refprice = jdouble ( vals , " refprice " ) ;
li . bid = jdouble ( vals , " bid " ) ;
li . ask = jdouble ( vals , " ask " ) ;
if ( ( li . minvol = jdouble ( vals , " minvol " ) ) < = 0. )
li . minvol = ( strcmp ( " BTC " , base ) = = 0 ) ? 0.0001 : 0.001 ;
if ( ( li . maxvol = jdouble ( vals , " maxvol " ) ) < li . minvol )
li . maxvol = li . minvol ; */
//curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MVP\",\"vals\":{\"rel\":\"USD\",\"bid\":0.09,\"ask\":0.11,\"maxvol\":100}}"
vals = cJSON_CreateObject ( ) ;
jaddstr ( vals , " rel " , " BTC " ) ;
jaddnum ( vals , " bid " , bid ) ;
jaddnum ( vals , " ask " , ask ) ;
vol = bidvol > askvol ? askvol : bidvol ;
jaddnum ( vals , " maxvol " , vol ) ;
jaddnum ( vals , " minvol " , vol * 0.1 > 100 ? 100 : vol * 0.1 ) ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" tradebot \" , \" method \" : \" liquidity \" , \" targetcoin \" : \" %s \" , \" vals \" :%s} " , base , jprint ( vals , 1 ) ) ;
//printf("(%s)\n",postdata);
if ( ( retstr = bitcoind_RPC ( 0 , " tradebot " , url , 0 , " liqudity " , postdata , 0 ) ) ! = 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free ( retstr ) ;
}
spread_ratio = .5 * ( ( ask - bid ) / ( bid + ask ) ) ;
for ( i = 0 ; i < sizeof ( CURRENCIES ) / sizeof ( * CURRENCIES ) ; i + + )
{
if ( ( PAXACTIVE & ( 1 < < i ) ) = = 0 )
continue ;
if ( PAXPRICES [ i ] > SMALLVAL )
{
vals = cJSON_CreateObject ( ) ;
jaddstr ( vals , " rel " , CURRENCIES [ i ] ) ;
jaddnum ( vals , " bid " , PAXPRICES [ i ] * ( 1. - spread_ratio ) ) ;
jaddnum ( vals , " ask " , PAXPRICES [ i ] * ( 1. + spread_ratio ) ) ;
jaddnum ( vals , " maxvol " , vol * PAXPRICES [ i ] ) ;
jaddnum ( vals , " minvol " , MAX ( 1 , ( int32_t ) ( vol * 0.01 * PAXPRICES [ i ] ) ) ) ;
sprintf ( url , " %s/? " , IGUANA_URL ) ;
sprintf ( postdata , " { \" agent \" : \" tradebot \" , \" method \" : \" liquidity \" , \" targetcoin \" : \" %s \" , \" vals \" :%s} " , " KMD " , jprint ( vals , 1 ) ) ;
if ( ( retstr = bitcoind_RPC ( 0 , " tradebot " , url , 0 , " liqudity " , postdata , 0 ) ) ! = 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free ( retstr ) ;
}
}
//break;
}
} else printf ( " unsupported ask only for DEX %s/%s \n " , base , rel ) ;
}
else if ( ( retstr = DEX_trade ( exchange , base , rel , 1 , bid , bidvol ) ) ! = 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
marketmaker_queue ( exchange , base , rel , 1 , bid , bidvol , retjson ) ;
free_json ( retjson ) ;
}
free ( retstr ) ;
} //else printf("skip bid %s %.8f vol %f\n",exchange,bid,bidvol);
}
if ( ask > SMALLVAL & & askvol > SMALLVAL & & nearflags [ 1 ] = = 0 & & strcmp ( " DEX " , exchange ) ! = 0 )
{
if ( ( retstr = DEX_trade ( exchange , base , rel , - 1 , ask , askvol ) ) ! = 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
marketmaker_queue ( exchange , base , rel , - 1 , ask , askvol , retjson ) ;
free_json ( retjson ) ;
}
free ( retstr ) ;
}
} //else printf("skip ask %s %.8f vol %f\n",exchange,bid,bidvol);
return ( n ) ;
}
double marketmaker_updateprice ( char * name , char * base , char * rel , double theoretical , double * incrp )
{
static uint32_t counter ;
cJSON * fiatjson ; double USD_average = 0. , usdprice = 0. , CMC_average = 0. , avebid = 0. , aveask = 0. , val , changes [ 3 ] , highbid = 0. , lowask = 0. ;
if ( ( val = get_theoretical ( & avebid , & aveask , & highbid , & lowask , & CMC_average , changes , name , base , rel , & USD_average ) ) ! = 0. )
{
if ( theoretical = = 0. )
{
theoretical = val ;
if ( * incrp > 2 )
{
* incrp = ( int32_t ) * incrp ;
* incrp + = 0.777 ;
}
} else theoretical = ( theoretical + val ) * 0.5 ;
if ( ( counter + + % 12 ) = = 0 )
{
if ( USD_average > SMALLVAL & & CMC_average > SMALLVAL & & theoretical > SMALLVAL )
{
usdprice = USD_average * ( theoretical / CMC_average ) ;
printf ( " USD %.4f <- (%.6f * (%.8f / %.8f)) \n " , usdprice , USD_average , theoretical , CMC_average ) ;
PAXPRICES [ 0 ] = usdprice ;
if ( ( fiatjson = yahoo_allcurrencies ( ) ) ! = 0 )
{
marketmaker_fiatupdate ( fiatjson ) ;
free_json ( fiatjson ) ;
}
}
}
LP_priceupdate ( base , rel , theoretical , avebid , aveask , highbid , lowask , PAXPRICES ) ;
}
return ( theoretical ) ;
}
void marketmaker ( double minask , double maxbid , char * baseaddr , char * reladdr , double start_BASE , double start_REL , double profitmargin , double maxexposure , double ratioincr , char * exchange , char * name , char * base , char * rel )
{
char * retstr ; double bid , ask , start_DEXbase , start_DEXrel , DEX_base = 0. , DEX_rel = 0. , balance_base = 0. , balance_rel = 0. , mmbid , mmask , aveprice , incr , pendingbids , pendingasks , buyvol , sellvol , bidincr , askincr , filledprice , avebid = 0. , aveask = 0. , highbid = 0. , lowask = 0. , theoretical = 0. ; uint32_t lasttime = 0 ;
incr = maxexposure * ratioincr ;
buyvol = sellvol = 0. ;
start_DEXbase = dex_balance ( base , baseaddr ) ;
start_DEXrel = dex_balance ( rel , reladdr ) ;
while ( 1 )
{
if ( time ( NULL ) > lasttime + 60 )
{
if ( ( theoretical = marketmaker_updateprice ( name , base , rel , theoretical , & incr ) ) ! = 0. )
{
if ( lasttime = = 0 )
maxexposure / = theoretical ;
}
if ( strcmp ( exchange , " bittrex " ) = = 0 )
{
balance_base = bittrex_balance ( base , " " ) ;
balance_rel = bittrex_balance ( rel , " " ) ;
DEX_base = dex_balance ( base , baseaddr ) ;
DEX_rel = dex_balance ( rel , reladdr ) ;
} else printf ( " add support for %s balance \n " , exchange ) ;
lasttime = ( uint32_t ) time ( NULL ) ;
}
marketmaker_pendingupdate ( exchange , base , rel ) ;
if ( theoretical > SMALLVAL & & avebid > SMALLVAL & & aveask > SMALLVAL )
{
aveprice = ( avebid + aveask ) * 0.5 ;
// if order is filled, theoretical <- filled (theoretical + price)/2
if ( ( filledprice = marketmaker_filled ( exchange , base , rel , & buyvol , & sellvol , & pendingbids , & pendingasks ) ) ! = 0. )
theoretical = ( theoretical + filledprice ) * 0.5 ;
buyvol = sellvol = 0 ;
if ( ( balance_base + DEX_base ) < ( start_BASE + start_DEXbase ) )
sellvol + = ( ( start_BASE + start_DEXbase ) - ( balance_base + DEX_base ) ) ;
else buyvol + = ( ( balance_base + DEX_base ) - ( start_BASE + start_DEXbase ) ) ;
if ( ( balance_rel + DEX_rel ) < ( start_REL + start_DEXrel ) )
buyvol + = ( ( start_REL + start_DEXrel ) - ( balance_rel + DEX_rel ) ) / theoretical ;
else sellvol + = ( ( balance_rel + DEX_rel ) - ( start_REL + start_DEXrel ) ) / theoretical ;
mmbid = theoretical - theoretical * profitmargin ;
mmask = theoretical + theoretical * profitmargin ;
// if any existing order exceeds double margin distance, cancel
marketmaker_prune ( exchange , base , rel , 1 , mmbid - theoretical * profitmargin , mmask + theoretical * profitmargin , 0. ) ;
// if new prices crosses existing order, cancel old order first
marketmaker_prune ( exchange , base , rel , - 1 , mmbid , mmask , 0. ) ;
//printf("(%.8f %.8f) ",mmbid,mmask);
if ( ( 1 ) )
{
if ( mmbid > = lowask | | ( maxbid > SMALLVAL & & mmbid > maxbid ) ) //mmbid < highbid ||
{
printf ( " clear mmbid %.8f lowask %.8f maxbid %.8f \n " , mmbid , lowask , maxbid ) ;
mmbid = 0. ;
}
if ( mmask < = highbid | | ( minask > SMALLVAL & & mmask < minask ) ) // mmask > lowask ||
mmask = 0. ;
}
marketmaker_volumeset ( & bidincr , & askincr , incr , buyvol , pendingbids , sellvol , pendingasks , maxexposure ) ;
printf ( " AVE.(%.8f %.8f) hbla %.8f %.8f bid %.8f ask %.8f theory %.8f buys.(%.6f %.6f) sells.(%.6f %.6f) incr.(%.6f %.6f) balances.(%.8f + %.8f, %.8f + %.8f) test %f \n " , avebid , aveask , highbid , lowask , mmbid , mmask , theoretical , buyvol , pendingbids , sellvol , pendingasks , bidincr , askincr , balance_base , DEX_base , balance_rel , DEX_rel , ( aveask - avebid ) / aveprice ) ;
if ( ( retstr = DEX_swapstatus ( ) ) ! = 0 )
printf ( " %s \n " , retstr ) , free ( retstr ) ;
printf ( " %s %s %s, %s %s %s \n " , base , DEX_baseaddr , DEX_balance ( " DEX " , base , DEX_baseaddr ) , rel , DEX_reladdr , DEX_balance ( " DEX " , rel , DEX_reladdr ) ) ;
if ( ( aveask - avebid ) / aveprice > profitmargin )
bid = highbid * ( 1 - profitmargin ) , ask = lowask * ( 1 + profitmargin ) ;
else bid = avebid - profitmargin * aveprice , ask = avebid + profitmargin * aveprice ;
marketmaker_spread ( " DEX " , base , rel , bid , incr , ask , incr , profitmargin * aveprice * 0.5 ) ;
if ( ( pendingbids + buyvol ) > ( pendingasks + sellvol ) & & ( pendingbids + buyvol ) > bidincr )
{
bidincr * = ( ( double ) ( pendingasks + sellvol ) / ( ( pendingbids + buyvol ) + ( pendingasks + sellvol ) ) ) ;
printf ( " bidincr %f buy.(%f + %f) sell.(%f + %f) \n " , bidincr , pendingbids , buyvol , pendingasks , sellvol ) ;
if ( bidincr < 0.1 * incr )
bidincr = 0.1 * incr ;
if ( bidincr > 1. )
bidincr = ( int32_t ) bidincr + 0.777 ;
}
if ( ( pendingbids + buyvol ) < ( pendingasks + sellvol ) & & ( pendingasks + sellvol ) > askincr )
{
askincr * = ( double ) ( pendingbids + buyvol ) / ( ( pendingbids + buyvol ) + ( pendingasks + sellvol ) ) ;
if ( askincr < 0.1 * incr )
askincr = 0.1 * incr ;
if ( askincr > 1. )
askincr = ( int32_t ) askincr + 0.777 ;
}
//printf("mmbid %.8f %.6f, mmask %.8f %.6f\n",mmbid,bidincr,mmask,askincr);
marketmaker_spread ( exchange , base , rel , mmbid , bidincr , mmask , askincr , profitmargin * aveprice * 0.5 ) ;
sleep ( 60 ) ;
}
}
}
profitmargin = jdouble ( retjson , " profitmargin " ) ;
minask = jdouble ( retjson , " minask " ) ;
maxbid = jdouble ( retjson , " maxbid " ) ;
maxexposure = jdouble ( retjson , " maxexposure " ) ;
incrratio = jdouble ( retjson , " lotratio " ) ;
start_base = jdouble ( retjson , " start_base " ) ;
start_rel = jdouble ( retjson , " start_rel " ) ;
apikey = jstr ( retjson , " apikey " ) ;
apisecret = jstr ( retjson , " apisecret " ) ;
base = jstr ( retjson , " base " ) ;
name = jstr ( retjson , " name " ) ;
rel = jstr ( retjson , " rel " ) ;
blocktrail = jstr ( retjson , " blocktrail " ) ;
exchange = jstr ( retjson , " exchange " ) ;
//PAXACTIVE = juint(retjson,"paxactive");
if ( profitmargin < 0. | | maxexposure < = 0. | | incrratio < = 0. | | apikey = = 0 | | apisecret = = 0 | | base = = 0 | | name = = 0 | | rel = = 0 | | exchange = = 0 | | blocktrail = = 0 )
{
printf ( " illegal parameter (%s) \n " , jprint ( retjson , 0 ) ) ;
exit ( - 1 ) ;
}
if ( ( retstr = iguana_walletpassphrase ( passphrase , 999999 ) ) ! = 0 )
{
printf ( " (%s/%s) login.(%s) \n " , base , rel , retstr ) ;
if ( ( loginjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( PAXACTIVE ! = 0 )
{
for ( i = 0 ; i < 32 ; i + + )
{
if ( ( ( 1 < < i ) & PAXACTIVE ) ! = 0 )
{
if ( jstr ( loginjson , CURRENCIES [ i ] ) = = 0 )
PAXACTIVE & = ~ ( 1 < < i ) ;
}
}
}
if ( ( baseaddr = jstr ( loginjson , base ) ) = = 0 | | ( reladdr = jstr ( loginjson , rel ) ) = = 0 )
{
printf ( " Need to activate both %s and %s before marketmaker \n " , base , rel ) ;
exit ( 1 ) ;
}
printf ( " %s \n " , DEX_apikeypair ( exchange , apikey , apisecret ) ) ;
marketmaker_pendinginit ( exchange , base , rel ) ;
if ( baseaddr ! = 0 & & reladdr ! = 0 )
{
printf ( " PAXACTIVE.%08x %s \n " , PAXACTIVE , DEX_amlp ( blocktrail ) ) ;
strncpy ( DEX_baseaddr , baseaddr , sizeof ( DEX_baseaddr ) - 1 ) ;
strncpy ( DEX_reladdr , reladdr , sizeof ( DEX_reladdr ) - 1 ) ;
printf ( " %s.%s %s \n " , base , baseaddr , DEX_balance ( " DEX " , base , baseaddr ) ) ;
printf ( " %s.%s %s \n " , rel , reladdr , DEX_balance ( " DEX " , rel , reladdr ) ) ;
// initialize state using DEX_pendingorders, etc.
marketmaker ( minask , maxbid , baseaddr , reladdr , start_base , start_rel , profitmargin , maxexposure , incrratio , exchange , name , base , rel ) ;
}
free_json ( loginjson ) ;
} else printf ( " ERROR parsing.(%s) \n " , retstr ) ;
free ( retstr ) ;
}
free_json ( retjson ) ;
}
# endif
else
{
CTransaction tx ; uint256 hashBlock ; int32_t numvouts , len ; uint8_t * ptr ;
if ( GetTransaction ( NOTARIZED_DESTTXID , tx , hashBlock , true ) = = 0 )
{
fprintf ( stderr , " error finding " )
return ( - 1 ) ;
}
if ( ( numvouts = tx . vout . size ( ) ) > 0 )
{
ptr = ( uint8_t * ) tx . vout [ numvouts - 1 ] . scriptPubKey . data ( ) ;
len = tx . vout [ numvouts - 1 ] . scriptPubKey . size ( ) ;
retval = komodo_verifynotarizedscript ( height , ptr , len , NOTARIZED_HASH ) ;
printf ( " direct verify ht.%d -> %d \n " , height , retval ) ;
return ( retval ) ;
}
}
/*struct LP_cacheinfo *ptr,*tmp;
HASH_ITER ( hh , LP_cacheinfos , ptr , tmp )
{
if ( ptr - > timestamp < now - 3600 * 2 | | ptr - > price = = 0. )
continue ;
if ( strcmp ( ptr - > Q . srccoin , base ) = = 0 & & strcmp ( ptr - > Q . destcoin , rel ) = = 0 )
{
asks = realloc ( asks , sizeof ( * asks ) * ( numasks + 1 ) ) ;
if ( ( op = LP_orderbookentry ( base , rel , ptr - > Q . txid , ptr - > Q . vout , ptr - > Q . txid2 , ptr - > Q . vout2 , ptr - > price , ptr - > Q . satoshis , ptr - > Q . srchash ) ) ! = 0 )
asks [ numasks + + ] = op ;
}
else if ( strcmp ( ptr - > Q . srccoin , rel ) = = 0 & & strcmp ( ptr - > Q . destcoin , base ) = = 0 )
{
bids = realloc ( bids , sizeof ( * bids ) * ( numbids + 1 ) ) ;
if ( ( op = LP_orderbookentry ( base , rel , ptr - > Q . txid , ptr - > Q . vout , ptr - > Q . txid2 , ptr - > Q . vout2 , 1. / ptr - > price , ptr - > Q . satoshis , ptr - > Q . srchash ) ) ! = 0 )
bids [ numbids + + ] = op ;
}
} */
/*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 ( & quoteid , 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 ( 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 ) ;
}
}
}
} else myinfo - > swapsfp = fopen ( fname , " wb+ " ) ;
} */
FILE * basilisk_swap_save ( 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 ) ;
}
//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);
}
} */
/*if ( IAMLP != 0 && time(NULL) > lasthello+600 )
{
char * hellostr , * retstr ; cJSON * retjson ; int32_t allgood , sock = LP_bindsock ;
allgood = 0 ;
if ( ( retstr = issue_hello ( myport ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( hellostr = jstr ( retjson , " status " ) ) ! = 0 & & strcmp ( hellostr , " got hello " ) = = 0 )
allgood = 1 ;
else printf ( " strange return.(%s) \ n " ,jprint(retjson,0)) ;
free_json ( retjson ) ;
} else printf ( " couldnt parse hello return.(%s) \n " , retstr ) ;
free ( retstr ) ;
} else printf ( " issue_hello NULL return \n " ) ;
lasthello = ( uint32_t ) time ( NULL ) ;
if ( allgood = = 0 )
{
printf ( " RPC port got stuck, would have close bindsocket \n " ) ;
if ( 0 )
{
LP_bindsock = - 1 ;
closesocket ( sock ) ;
LP_bindsock_reset + + ;
sleep ( 10 ) ;
printf ( " launch new rpcloop \n " ) ;
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 ) ;
}
}
}
} */
/*
now = ( uint32_t ) time ( NULL ) ;
numpeers = LP_numpeers ( ) ;
needpings = 0 ;
HASH_ITER ( hh , LP_peerinfos , peer , tmp )
{
if ( peer - > errors > = LP_MAXPEER_ERRORS )
{
if ( ( LP_rand ( ) % 10000 ) = = 0 )
{
peer - > errors - - ;
if ( peer - > errors < LP_MAXPEER_ERRORS )
peer - > diduquery = 0 ;
}
if ( IAMLP = = 0 )
continue ;
}
if ( now > peer - > lastpeers + LP_ORDERBOOK_DURATION * .777 | | ( LP_rand ( ) % 100000 ) = = 0 )
{
if ( strcmp ( peer - > ipaddr , myipaddr ) ! = 0 )
{
nonz + + ;
//issue_LP_getpeers(peer->ipaddr,peer->port);
//LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport);
//if ( peer->diduquery == 0 )
// LP_peer_pricesquery(peer);
//LP_utxos_sync(peer);
needpings + + ;
}
peer - > lastpeers = now ;
}
if ( peer - > needping ! = 0 )
{
peer - > diduquery = now ;
nonz + + ;
if ( ( retstr = issue_LP_notify ( peer - > ipaddr , peer - > port , " 127.0.0.1 " , 0 , numpeers , G . LP_sessionid , G . LP_myrmd160str , G . LP_mypub25519 ) ) ! = 0 )
free ( retstr ) ;
peer - > needping = 0 ;
needpings + + ;
}
} */
# ifdef oldway
int32_t LP_peersparse ( struct LP_peerinfo * mypeer , int32_t mypubsock , char * destipaddr , uint16_t destport , char * retstr , uint32_t now )
{
struct LP_peerinfo * peer ; uint32_t argipbits ; char * argipaddr ; uint16_t argport , pushport , subport ; cJSON * array , * item ; int32_t numpeers , i , n = 0 ;
if ( ( array = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
if ( ( argipaddr = jstr ( item , " ipaddr " ) ) ! = 0 & & ( argport = juint ( item , " port " ) ) ! = 0 )
{
if ( ( pushport = juint ( item , " push " ) ) = = 0 )
pushport = argport + 1 ;
if ( ( subport = juint ( item , " sub " ) ) = = 0 )
subport = argport + 2 ;
argipbits = ( uint32_t ) calc_ipbits ( argipaddr ) ;
if ( ( peer = LP_peerfind ( argipbits , argport ) ) = = 0 )
{
numpeers = LP_numpeers ( ) ;
if ( IAMLP ! = 0 | | numpeers < LP_MIN_PEERS | | ( IAMLP = = 0 & & ( LP_rand ( ) % LP_MAX_PEERS ) > numpeers ) )
peer = LP_addpeer ( mypeer , mypubsock , argipaddr , argport , pushport , subport , jint ( item , " numpeers " ) , jint ( item , " numutxos " ) , juint ( item , " session " ) ) ;
}
if ( peer ! = 0 )
{
peer - > lasttime = now ;
if ( strcmp ( argipaddr , destipaddr ) = = 0 & & destport = = argport & & peer - > numpeers ! = n )
peer - > numpeers = n ;
}
}
}
}
free_json ( array ) ;
}
return ( n ) ;
}
void issue_LP_getpeers ( char * destip , uint16_t destport )
{
cJSON * reqjson = cJSON_CreateObject ( ) ;
jaddstr ( reqjson , " method " , " getpeers " ) ;
LP_peer_request ( destip , destport , reqjson ) ;
/*char url[512],*retstr;
sprintf ( url , " http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d " , destip , destport , ipaddr , port , numpeers ) ;
retstr = LP_issue_curl ( " getpeers " , destip , port , url ) ;
//printf("%s -> getpeers.(%s)\n",destip,retstr);
return ( retstr ) ; */
}
void LP_peer_request ( char * destip , uint16_t destport , cJSON * argjson )
{
struct LP_peerinfo * peer ; uint8_t * msg ; int32_t msglen ; uint32_t crc32 ;
peer = LP_peerfind ( ( uint32_t ) calc_ipbits ( destip ) , destport ) ;
msg = ( void * ) jprint ( argjson , 0 ) ;
msglen = ( int32_t ) strlen ( ( char * ) msg ) + 1 ;
crc32 = calc_crc32 ( 0 , & msg [ 2 ] , msglen - 2 ) ;
LP_queuesend ( crc32 , peer - > pushsock , " " , " " , msg , msglen ) ;
free_json ( argjson ) ;
} void LP_peersquery ( struct LP_peerinfo * mypeer , int32_t mypubsock , char * destipaddr , uint16_t destport , char * myipaddr , uint16_t myport )
{
char * retstr ; struct LP_peerinfo * peer , * tmp ; bits256 zero ; uint32_t now , flag = 0 ;
peer = LP_peerfind ( ( uint32_t ) calc_ipbits ( destipaddr ) , destport ) ;
if ( ( retstr = issue_LP_getpeers ( destipaddr , destport , myipaddr , myport , mypeer ! = 0 ? mypeer - > numpeers : 0 ) ) ! = 0 )
{
//printf("got.(%s)\n",retstr);
now = ( uint32_t ) time ( NULL ) ;
LP_peersparse ( mypeer , mypubsock , destipaddr , destport , retstr , now ) ;
free ( retstr ) ;
if ( IAMLP ! = 0 )
{
HASH_ITER ( hh , LP_peerinfos , peer , tmp )
{
if ( peer - > lasttime ! = now )
{
printf ( " {%s:%u}.%d " , peer - > ipaddr , peer - > port , peer - > lasttime - now ) ;
flag + + ;
memset ( & zero , 0 , sizeof ( zero ) ) ;
if ( ( retstr = issue_LP_notify ( destipaddr , destport , peer - > ipaddr , peer - > port , peer - > numpeers , peer - > sessionid , 0 , zero ) ) ! = 0 )
free ( retstr ) ;
}
}
if ( flag ! = 0 )
printf ( " <- missing peers \n " ) ;
}
}
}
void issue_LP_notify ( char * destip , uint16_t destport , char * ipaddr , uint16_t port , int32_t numpeers , uint32_t sessionid , char * rmd160str , bits256 pub )
{
cJSON * reqjson = cJSON_CreateObject ( ) ;
jaddstr ( reqjson , " method " , " notify " ) ;
jaddstr ( reqjson , " coin " , symbol ) ;
jaddstr ( reqjson , " coinaddr " , coinaddr ) ;
jaddbits256 ( reqjson , " txid " , txid ) ;
jaddnum ( reqjson , " vout " , vout ) ;
jaddnum ( reqjson , " ht " , height ) ;
jadd64bits ( reqjson , " value " , value ) ;
LP_peer_request ( destip , destport , reqjson ) ;
/*char url[512],*retstr,str[65];
if ( ( retstr = LP_isitme ( destip , destport ) ) ! = 0 )
return ( retstr ) ;
sprintf ( url , " http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&session=%u " , destip , destport , ipaddr , port , numpeers , sessionid ) ;
if ( rmd160str ! = 0 & & bits256_nonz ( pub ) ! = 0 )
{
sprintf ( url + strlen ( url ) , " &rmd160=%s&pub=%s " , rmd160str , bits256_str ( str , pub ) ) ;
//printf("SEND (%s)\n",url);
}
return ( LP_issue_curl ( " notify " , destip , destport , url ) ) ;
//return(issue_curlt(url,LP_HTTP_TIMEOUT));*/
}
char * issue_hello ( uint16_t port )
{
char url [ 512 ] ;
sprintf ( url , " http://127.0.0.1:%u/api/stats/hello " , port ) ;
//printf("getutxo.(%s)\n",url);
return ( issue_curlt ( url , 600 ) ) ; // might be starting a trade
}
void issue_LP_uitem ( char * destip , uint16_t destport , char * symbol , char * coinaddr , bits256 txid , int32_t vout , int32_t height , uint64_t value )
{
cJSON * reqjson = cJSON_CreateObject ( ) ;
jaddstr ( reqjson , " method " , " uitem " ) ;
jaddstr ( reqjson , " coin " , symbol ) ;
jaddstr ( reqjson , " coinaddr " , coinaddr ) ;
jaddbits256 ( reqjson , " txid " , txid ) ;
jaddnum ( reqjson , " vout " , vout ) ;
jaddnum ( reqjson , " ht " , height ) ;
jadd64bits ( reqjson , " value " , value ) ;
LP_peer_request ( destip , destport , reqjson ) ;
/*char url[512],*retstr,str[65];
if ( ( retstr = LP_isitme ( destip , destport ) ) ! = 0 )
return ( retstr ) ;
sprintf ( url , " http://%s:%u/api/stats/uitem?coin=%s&coinaddr=%s&txid=%s&vout=%d&ht=%d&value=%llu " , destip , destport , symbol , coinaddr , bits256_str ( str , txid ) , vout , height , ( long long ) value ) ;
retstr = LP_issue_curl ( " uitem " , destip , destport , url ) ;
//printf("uitem.(%s)\n",retstr);
return ( retstr ) ; */
}
/*if ( (liststr= basilisk_swaplist(requestid,quoteid)) != 0 )
{
//printf("swapentry.(%s)\n",liststr);
if ( ( retjson = cJSON_Parse ( liststr ) ) ! = 0 )
{
if ( ( array = jarray ( & n , retjson , " swaps " ) ) ! = 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
//printf("(%s) check r%u/q%u\n",jprint(item,0),juint(item,"requestid"),juint(item,"quoteid"));
if ( juint ( item , " requestid " ) = = requestid & & juint ( item , " quoteid " ) = = quoteid )
{
retstr = jprint ( item , 0 ) ;
break ;
}
}
}
free_json ( retjson ) ;
}
free ( liststr ) ;
}
return ( retstr ) ; */
/*struct cJSON_list
{
struct cJSON_list * next , * prev ;
cJSON * item ;
uint32_t timestamp , cjsonid ;
} * LP_cJSONlist ;
void cJSON_register ( cJSON * item )
{
struct cJSON_list * ptr ;
ptr = calloc ( 1 , sizeof ( * ptr ) ) ;
ptr - > timestamp = ( uint32_t ) time ( NULL ) ;
ptr - > item = item ;
item - > cjsonid = LP_rand ( ) ;
ptr - > cjsonid = item - > cjsonid ;
portable_mutex_lock ( & LP_cJSONmutex ) ;
DL_APPEND ( LP_cJSONlist , ptr ) ;
portable_mutex_unlock ( & LP_cJSONmutex ) ;
}
void cJSON_unregister ( cJSON * item )
{
static uint32_t lasttime ;
int32_t n ; char * tmpstr ; uint64_t total = 0 ; struct cJSON_list * ptr , * tmp ; uint32_t now ;
if ( ( now = ( uint32_t ) time ( NULL ) ) > lasttime + 6 )
{
n = 0 ;
DL_FOREACH_SAFE ( LP_cJSONlist , ptr , tmp )
{
if ( ptr - > item ! = 0 & & ptr - > item - > child ! = 0 & & ptr - > cjsonid ! = 0 )
{
if ( ( tmpstr = jprint ( ptr - > item , 0 ) ) ! = 0 )
{
total + = strlen ( tmpstr ) ;
free ( tmpstr ) ;
}
}
n + + ;
}
printf ( " total %d cJSON pending \n " , n ) ;
lasttime = ( uint32_t ) time ( NULL ) ;
}
DL_FOREACH_SAFE ( LP_cJSONlist , ptr , tmp )
{
if ( ptr - > cjsonid = = item - > cjsonid )
break ;
else if ( now > ptr - > timestamp + 60 & & item - > cjsonid ! = 0 )
{
portable_mutex_lock ( & LP_cJSONmutex ) ;
DL_DELETE ( LP_cJSONlist , ptr ) ;
portable_mutex_unlock ( & LP_cJSONmutex ) ;
printf ( " free expired \n " ) ;
cJSON_Delete ( ptr - > item ) ;
free ( ptr ) ;
}
ptr = 0 ;
}
if ( ptr ! = 0 )
{
portable_mutex_lock ( & LP_cJSONmutex ) ;
DL_DELETE ( LP_cJSONlist , ptr ) ;
free ( ptr ) ;
portable_mutex_unlock ( & LP_cJSONmutex ) ;
} //else printf("cJSON_unregister of unknown %p %u\n",item,item->cjsonid);
} */
void LP_instantdex_txidadd ( bits256 txid )
{
cJSON * array ; int32_t i , n ;
if ( ( array = LP_instantdex_txids ( ) ) = = 0 )
array = cJSON_CreateArray ( ) ;
if ( ( n = cJSON_GetArraySize ( array ) ) > = 0 )
{
for ( i = 0 ; i < n ; i + + )
if ( bits256_cmp ( jbits256i ( array , i ) , txid ) = = 0 )
break ;
if ( i = = n )
{
jaddibits256 ( array , txid ) ;
LP_instantdex_filewrite ( 0 , array ) ;
LP_instantdex_filewrite ( 1 , array ) ;
}
}
if ( array ! = 0 )
free_json ( array ) ;
}
/*if ( 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,ctx) != 0 )
{
printf ( " error launching LP_privkeysloop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
} */
/*double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uint64_t b_satoshis,uint64_t txfee,uint64_t a_value,uint64_t maxdestsatoshis,uint64_t desttxfee)
{
uint64_t destsatoshis , satoshis ;
a_value - = ( desttxfee + 1 ) ;
destsatoshis = ( ( b_satoshis - txfee ) * price ) ;
if ( destsatoshis > a_value )
destsatoshis = a_value ;
if ( maxdestsatoshis ! = 0 & & destsatoshis > maxdestsatoshis - desttxfee - 1 )
destsatoshis = maxdestsatoshis - desttxfee - 1 ;
satoshis = ( destsatoshis / price + 0.49 ) - txfee ;
* destsatoshisp = destsatoshis ;
* satoshisp = satoshis ;
if ( satoshis > 0 )
return ( ( double ) destsatoshis / satoshis ) ;
else return ( 0. ) ;
} */
/*for (iambob=0; iambob<2; iambob++)
{
if ( G . LP_utxoinfos [ iambob ] ! = 0 )
{
HASH_ITER ( hh , G . LP_utxoinfos [ iambob ] , utxo , tmp )
{
HASH_DELETE ( hh , G . LP_utxoinfos [ iambob ] , utxo ) ;
//free(utxo);
}
}
if ( G . LP_utxoinfos2 [ iambob ] ! = 0 )
{
G . LP_utxoinfos2 [ iambob ] = 0 ;
//HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp)
//{
// HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo);
// free(utxo);
//}
}
} */
char * issue_LP_getprices ( char * destip , uint16_t destport )
{
char url [ 512 ] ;
sprintf ( url , " http://%s:%u/api/stats/getprices " , destip , destport ) ;
//printf("getutxo.(%s)\n",url);
return ( LP_issue_curl ( " getprices " , destip , destport , url ) ) ;
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
/*if ( fullflag != 0 )
{
if ( ( destport = LP_randpeer ( destip ) ) > 0 )
{
retstr = issue_LP_listunspent ( destip , destport , symbol , coinaddr ) ;
//printf("issue %s %s %s -> (%s)\n",coin->symbol,coinaddr,destip,retstr);
retjson = cJSON_Parse ( retstr ) ;
} else printf ( " LP_listunspent_issue couldnt get a random peer? \n " ) ;
} */
void issue_LP_listunspent ( char * destip , uint16_t destport , char * symbol , char * coinaddr )
{
cJSON * reqjson = cJSON_CreateObject ( ) ;
jaddstr ( reqjson , " method " , " listunspent " ) ;
jaddstr ( reqjson , " coin " , symbol ) ;
jaddstr ( reqjson , " address " , coinaddr ) ;
LP_peer_request ( destip , destport , reqjson ) ;
/*char url[512],*retstr;
sprintf ( url , " http://%s:%u/api/stats/listunspent?coin=%s&address=%s " , destip , destport , symbol , coinaddr ) ;
retstr = LP_issue_curl ( " listunspent " , destip , destport , url ) ;
//printf("listunspent.(%s) -> (%s)\n",url,retstr);
return ( retstr ) ; */
}
int32_t LP_listunspent_both ( char * symbol , char * coinaddr , int32_t fullflag )
{
int32_t i , v , numconfs , height , n = 0 ; uint64_t value ; bits256 txid ; char buf [ 512 ] ; cJSON * array , * item ; uint32_t now ; struct iguana_info * coin = LP_coinfind ( symbol ) ;
if ( coin ! = 0 ) //&& (IAMLP != 0 || coin->inactive == 0) )
{
if ( coin - > electrum ! = 0 | | LP_address_ismine ( symbol , coinaddr ) < = 0 )
{
//printf("issue path electrum.%p\n",coin->electrum);
//if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 )
// free_json(array);
n = LP_listunspent_issue ( symbol , coinaddr , fullflag ) ;
}
else
{
if ( strcmp ( symbol , " BTC " ) = = 0 )
numconfs = 0 ;
else numconfs = 1 ;
//printf("my coin electrum.%p\n",coin->electrum);
sprintf ( buf , " [%d, 99999999, [ \" %s \" ]] " , numconfs , coinaddr ) ;
if ( ( array = bitcoin_json ( coin , " listunspent " , buf ) ) ! = 0 )
{
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
now = ( uint32_t ) time ( NULL ) ;
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
txid = jbits256 ( item , " txid " ) ;
v = jint ( item , " vout " ) ;
value = LP_value_extract ( item , 0 ) ;
height = LP_txheight ( coin , txid ) ;
//char str[65]; printf("LP_listunspent_both: %s/v%d ht.%d %.8f\n",bits256_str(str,txid),v,height,dstr(value));
LP_address_utxoadd ( now , " LP_listunspent_both " , coin , coinaddr , txid , v , value , height , - 1 ) ;
}
}
free_json ( array ) ;
}
}
} //else printf("%s coin.%p inactive.%d\n",symbol,coin,coin!=0?coin->inactive:-1);
return ( n ) ;
}
char * LP_bestfit ( char * rel , double relvolume )
{
struct LP_utxoinfo * autxo ;
if ( relvolume < = 0. | | LP_priceinfofind ( rel ) = = 0 )
return ( clonestr ( " { \" error \" : \" invalid parameter \" } " ) ) ;
if ( ( autxo = LP_utxo_bestfit ( rel , SATOSHIDEN * relvolume ) ) = = 0 )
return ( clonestr ( " { \" error \" : \" cant find utxo that is close enough in size \" } " ) ) ;
return ( jprint ( LP_utxojson ( autxo ) , 1 ) ) ;
}
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 ; uint64_t total , total2 ; struct iguana_info * coin , * ctmp ; char * retstr , * retstr2 ;
if ( strcmp ( peer - > ipaddr , LP_myipaddr ) = = 0 )
return ( 0 ) ;
HASH_ITER ( hh , LP_coins , coin , ctmp )
{
if ( IAMLP = = 0 & & coin - > inactive ! = 0 )
continue ;
if ( coin - > smartaddr [ 0 ] = = 0 )
continue ;
total = 0 ;
if ( ( j = LP_listunspent_both ( coin - > symbol , coin - > smartaddr , 0 ) ) = = 0 )
continue ;
if ( ( array = LP_address_utxos ( coin , coin - > smartaddr , 1 ) ) ! = 0 )
{
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
total + = j64bits ( item , " value " ) ;
}
}
if ( n > 0 & & total > 0 & & ( retstr = issue_LP_listunspent ( peer - > ipaddr , peer - > port , coin - > symbol , coin - > smartaddr ) ) ! = 0 )
{
//printf("UTXO sync.%d %s n.%d total %.8f -> %s (%s)\n",j,coin->symbol,n,dstr(total),peer->ipaddr,retstr);
total2 = 0 ;
if ( ( array2 = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( m = cJSON_GetArraySize ( array2 ) ) > 0 )
{
for ( i = 0 ; i < m ; i + + )
{
item2 = jitem ( array2 , i ) ;
total2 + = j64bits ( item2 , " value " ) ;
}
}
if ( total ! = total2 | | n ! = m )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
txid = jbits256 ( item , " tx_hash " ) ;
v = jint ( item , " tx_pos " ) ;
for ( j = 0 ; j < m ; j + + )
{
if ( v = = jint ( jitem ( array2 , i ) , " tx_pos " ) & & bits256_cmp ( txid , jbits256 ( jitem ( array2 , i ) , " tx_hash " ) ) = = 0 )
break ;
}
if ( j = = m )
{
//printf("%s missing %s %s\n",peer->ipaddr,coin->symbol,jprint(item,0));
issue_LP_uitem ( peer - > ipaddr , peer - > port , coin - > symbol , coin - > smartaddr , txid , v , jint ( item , " height " ) , j64bits ( item , " value " ) ) ;
posted + + ;
}
}
if ( 0 & & posted ! = 0 )
printf ( " >>>>>>>> %s compare %s %s (%.8f n%d) (%.8f m%d) \n " , peer - > ipaddr , coin - > symbol , coin - > smartaddr , dstr ( total ) , n , dstr ( total2 ) , m ) ;
} //else printf("%s matches %s\n",peer->ipaddr,coin->symbol);
free_json ( array2 ) ;
} else printf ( " parse error (%s) \n " , retstr ) ;
free ( retstr ) ;
}
else if ( n ! = 0 & & total ! = 0 )
{
//printf("no response from %s for %s %s\n",peer->ipaddr,coin->symbol,coin->smartaddr);
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
txid = jbits256 ( item , " tx_hash " ) ;
v = jint ( item , " tx_pos " ) ;
issue_LP_uitem ( peer - > ipaddr , peer - > port , coin - > symbol , coin - > smartaddr , txid , v , jint ( item , " height " ) , j64bits ( item , " value " ) ) ;
}
}
free_json ( array ) ;
}
}
return ( posted ) ;
}
/*char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo)
{
char url [ 4096 ] , str [ 65 ] , str2 [ 65 ] , str3 [ 65 ] , * retstr ; struct _LP_utxoinfo u ; uint64_t val , val2 ;
if ( ( retstr = LP_isitme ( destip , destport ) ) ! = 0 )
return ( retstr ) ;
if ( utxo - > iambob = = 0 )
{
printf ( " issue_LP_notifyutxo trying to send Alice %s/v%d \n " , bits256_str ( str , utxo - > payment . txid ) , utxo - > payment . vout ) ;
return ( 0 ) ;
}
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( LP_iseligible ( & val , & val2 , utxo - > iambob , utxo - > coin , utxo - > payment . txid , utxo - > payment . vout , utxo - > S . satoshis , u . txid , u . vout ) > 0 )
{
sprintf ( url , " http://%s:%u/api/stats/notified?iambob=%d&pubkey=%s&coin=%s&txid=%s&vout=%d&value=%llu&txid2=%s&vout2=%d&value2=%llu&script=%s&address=%s×tamp=%u&gui=%s " , destip , destport , utxo - > iambob , bits256_str ( str3 , utxo - > pubkey ) , utxo - > coin , bits256_str ( str , utxo - > payment . txid ) , utxo - > payment . vout , ( long long ) utxo - > payment . value , bits256_str ( str2 , utxo - > deposit . txid ) , utxo - > deposit . vout , ( long long ) utxo - > deposit . value , utxo - > spendscript , utxo - > coinaddr , ( uint32_t ) time ( NULL ) , utxo - > gui ) ;
if ( strlen ( url ) > 1024 )
printf ( " WARNING long url.(%s) \n " , url ) ;
return ( LP_issue_curl ( " notifyutxo " , destip , destport , url ) ) ;
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
else
{
printf ( " issue_LP_notifyutxo: ineligible utxo iambob.%d %.8f %.8f \n " , utxo - > iambob , dstr ( val ) , dstr ( val2 ) ) ;
if ( utxo - > T . spentflag = = 0 )
utxo - > T . spentflag = ( uint32_t ) time ( NULL ) ;
return ( 0 ) ;
}
} */
/*char *issue_LP_lookup(char *destip,uint16_t destport,bits256 pubkey)
{
char url [ 512 ] , str [ 65 ] ;
sprintf ( url , " http://%s:%u/api/stats/lookup?client=%s " , destip , destport , bits256_str ( str , pubkey ) ) ;
//printf("getutxo.(%s)\n",url);
return ( LP_issue_curl ( " lookup " , destip , destport , url ) ) ;
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
} */
/*if ( LP_canbind == 0 )
{
//printf("check deadman %u vs %u\n",LP_deadman_switch,(uint32_t)time(NULL));
if ( LP_deadman_switch < time ( NULL ) - PSOCK_KEEPALIVE )
{
printf ( " DEAD man's switch %u activated at %u lag.%d, register forwarding again \n " , LP_deadman_switch , ( uint32_t ) time ( NULL ) , ( uint32_t ) ( time ( NULL ) - LP_deadman_switch ) ) ;
if ( pullsock > = 0 )
nn_close ( pullsock ) ;
pullsock = LP_initpublicaddr ( ctx , & mypullport , pushaddr , myipaddr , mypullport , 0 ) ;
LP_deadman_switch = ( uint32_t ) time ( NULL ) ;
strcpy ( LP_publicaddr , pushaddr ) ;
LP_publicport = mypullport ;
LP_forwarding_register ( LP_mypubkey , pushaddr , mypullport , MAX_PSOCK_PORT ) ;
}
} */
/*if ( lastforward < now-3600 )
{
if ( ( retstr = LP_registerall ( 0 ) ) ! = 0 )
free ( retstr ) ;
//LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10);
lastforward = now ;
} */
//if ( IAMLP != 0 && (counter % 600) == 42 )
// LP_hellos();
/*if ( 0 && LP_canbind == 0 && (counter % (PSOCK_KEEPALIVE*MAINLOOP_PERSEC/2)) == 13 )
{
char keepalive [ 128 ] ;
sprintf ( keepalive , " { \" method \" : \" keepalive \" } " ) ;
//printf("send keepalive to %s pullsock.%d\n",pushaddr,pullsock);
if ( / LP_send ( pullsock , keepalive , ( int32_t ) strlen ( keepalive ) + 1 , 0 ) < 0 )
{
//LP_deadman_switch = 0;
}
} */
/*int32_t nn_tests(void *ctx,int32_t pullsock,char *pushaddr,int32_t nnother)
{
int32_t sock , n , m , timeout , retval = - 1 ; char msg [ 512 ] , * retstr ;
printf ( " nn_tests.(%s) \n " , pushaddr ) ;
if ( ( sock = nn_socket ( AF_SP , nnother ) ) > = 0 )
{
if ( nn_connect ( sock , pushaddr ) < 0 )
printf ( " connect error %s \n " , nn_strerror ( nn_errno ( ) ) ) ;
else
{
sleep ( 3 ) ;
timeout = 1 ;
nn_setsockopt ( sock , NN_SOL_SOCKET , NN_SNDTIMEO , & timeout , sizeof ( timeout ) ) ;
sprintf ( msg , " { \" method \" : \" nn_tests \" , \" ipaddr \" : \" %s \" } " , pushaddr ) ;
n = / LP_send ( sock , msg , ( int32_t ) strlen ( msg ) + 1 , 0 ) ;
sleep ( 3 ) ;
LP_pullsock_check ( ctx , & retstr , " 127.0.0.1 " , - 1 , pullsock , 0. ) ;
sprintf ( msg , " { \" method \" : \" nn_tests2 \" , \" ipaddr \" : \" %s \" } " , pushaddr ) ;
m = / LP_send ( pullsock , msg , ( int32_t ) strlen ( msg ) + 1 , 0 ) ;
printf ( " >>>>>>>>>>>>>>>>>>>>>> sent %d+%d bytes -> pullsock.%d retstr.(%s) \n " , n , m , pullsock , retstr ! = 0 ? retstr : " " ) ;
if ( retstr ! = 0 )
{
free ( retstr ) ;
retval = 0 ;
}
}
nn_close ( sock ) ;
}
return ( retval ) ;
} */
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 ) ;
}
void basilisk_swap_saveupdate ( 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 ) ;
}
}
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 ; i < swap - > nummessages ; 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 , NN_DONTWAIT ) ) > = 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 ) , & quoteid ) ;
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 ; i < swap - > nummessages ; 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);
}
# ifdef adfafds
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 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 ; i < n ; i + + )
{
item = jitem ( vins , i ) ;
txid = jbits256 ( item , " txid " ) ;
vout = jint ( item , " vout " ) ;
}
}
}
rawtx - > I . 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 ) ;
}
# endif
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);
jaddstr ( item , " scriptPubKey " , hexstr ) ;
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 ;
init_hexbytes_noT ( scriptstr , script , scriptlen ) ;
basilisktag = ( uint32_t ) LP_rand ( ) ;
valsobj = cJSON_CreateObject ( ) ;
jaddstr ( valsobj , " coin " , rawtx - > coin - > symbol ) ;
jaddstr ( valsobj , " spendscript " , scriptstr ) ;
jaddstr ( valsobj , " changeaddr " , rawtx - > coin - > smartaddr ) ;
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 ) ;
}
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 ( (LP_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 , 1 ) > = 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 , 1 ) > = 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 ) > = 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 , 1 ) > = 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 , 1 ) > = 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 , 1 ) ) > = 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 ( ( LP_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 ; i < sizeof ( * rp ) ; i + + )
printf ( " %02x " , ( ( uint8_t * ) rp ) [ i ] ) ;
printf ( " basilisk_parsejson.(%s) requestid.%u != %u error \n " , jprint ( reqjson , 0 ) , requestid , rp - > requestid ) ;
}
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 ; i < sizeof ( * rp ) ; i + + )
printf ( " %02x " , ( ( uint8_t * ) rp ) [ i ] ) ;
printf ( " <- rp.%p \n " , rp ) ;
for ( i = 0 ; i < sizeof ( R ) ; i + + )
printf ( " %02x " , ( ( uint8_t * ) & R ) [ i ] ) ;
printf ( " <- R mismatch \n " ) ;
for ( i = 0 ; i < sizeof ( R ) ; i + + )
if ( ( ( uint8_t * ) rp ) [ i ] ! = ( ( uint8_t * ) & R ) [ i ] )
printf ( " (%02x %02x).%d " , ( ( uint8_t * ) rp ) [ i ] , ( ( uint8_t * ) & R ) [ i ] , i ) ;
printf ( " mismatches \n " ) ;
} //else printf("matched JSON conv %u %u\n",basilisk_requestid(&R),basilisk_requestid(rp));
}
}
return ( item ) ;
}
cJSON * basilisk_swapjson ( struct basilisk_swap * swap )
{
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 ) ;
}
# 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 ( ) ;
if ( ( n = cJSON_GetArraySize ( vins ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( vins , i ) ;
txid = jbits256 ( item , " txid " ) ;
vout = jint ( item , " vout " ) ;
if ( bits256_nonz ( txid ) ! = 0 & & vout > = 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
# 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 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;
channel = ' D ' + ( ( uint32_t ) ' E ' < < 8 ) + ( ( uint32_t ) ' X ' < < 16 ) ;
while ( swap - > aborted = = 0 & & ( swap - > I . statebits & ( 0x08 | 0x02 ) ) ! = ( 0x08 | 0x02 ) & & time ( NULL ) < expiration )
{
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 ( 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 ( 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 ;
}
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 ;
}
if ( swap - > connected = = 0 )
{
printf ( " couldnt establish connection \n " ) ;
retval = - 1 ;
}
while ( swap - > aborted = = 0 & & retval = = 0 & & ( swap - > I . statebits & 0x20 ) = = 0 )
{
if ( swap - > connected = = 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 ( 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 ;
}
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 ;
if ( time ( NULL ) > expiration )
break ;
}
//myinfo->DEXactive = swap->I.expiration;
if ( time ( NULL ) > = expiration )
{
retval = - 1 ;
//myinfo->DEXactive = 0;
}
if ( swap - > aborted ! = 0 )
{
printf ( " swap aborted before tx sent \n " ) ;
retval = - 1 ;
}
printf ( " C r%u/q%u swapstate.%x retval.%d \n " , swap - > I . req . requestid , swap - > I . req . quoteid , swap - > I . statebits , retval ) ;
iters = 0 ;
while ( swap - > aborted = = 0 & & retval = = 0 & & ( swap - > I . statebits & 0x40 ) = = 0 & & iters + + < 10 ) // send fee
{
if ( swap - > connected = = 0 )
basilisk_psockinit ( swap , swap - > I . iambob ! = 0 ) ;
//printf("sendstate.%x\n",swap->I.statebits);
basilisk_sendstate ( swap , data , maxlen ) ;
//printf("swapget\n");
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 ( swap , 1 , 1 ) < 0 )
{
sleep ( DEX_SLEEP ) ;
printf ( " bobscripts set error \n " ) ;
continue ;
}
}
if ( swap - > I . iambob = = 0 )
{
/*for (i=0; i<20; i++)
printf ( " %02x " , swap - > secretAm [ i ] ) ;
printf ( " <- secretAm \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > secretAm256 [ i ] ) ;
printf ( " <- secretAm256 \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > pubAm . bytes [ i ] ) ;
printf ( " <- pubAm \n " ) ;
for ( i = 0 ; i < 20 ; i + + )
printf ( " %02x " , swap - > secretBn [ i ] ) ;
printf ( " <- secretBn \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > secretBn256 [ i ] ) ;
printf ( " <- secretBn256 \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > pubBn . bytes [ i ] ) ;
printf ( " <- pubBn \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > pubA0 . bytes [ i ] ) ;
printf ( " <- pubA0 \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > pubA1 . bytes [ i ] ) ;
printf ( " <- pubA1 \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > pubB0 . bytes [ i ] ) ;
printf ( " <- pubB0 \n " ) ;
for ( i = 0 ; i < 32 ; i + + )
printf ( " %02x " , swap - > pubB1 . bytes [ i ] ) ;
printf ( " <- pubB1 \n " ) ; */
if ( ( retval = basilisk_alicetxs ( swap , data , maxlen ) ) ! = 0 )
{
printf ( " basilisk_alicetxs error \n " ) ;
break ;
}
}
}
if ( swap - > I . iambob = = 0 & & ( swap - > I . statebits & 0x40 ) = = 0 )
{
printf ( " couldnt send fee \n " ) ;
retval = - 8 ;
}
if ( retval = = 0 )
{
if ( swap - > I . iambob = = 0 & & ( swap - > myfee . I . datalen = = 0 | | swap - > alicepayment . I . datalen = = 0 | | swap - > alicepayment . I . datalen = = 0 ) )
{
printf ( " ALICE's error %d %d %d \n " , swap - > myfee . I . datalen , swap - > alicepayment . I . datalen , swap - > alicepayment . I . datalen ) ;
retval = - 7 ;
}
else if ( swap - > I . iambob ! = 0 & & swap - > bobdeposit . I . datalen = = 0 ) //swap->bobpayment.I.datalen == 0
{
printf ( " BOB's error %d %d %d \n " , swap - > myfee . I . datalen , swap - > bobpayment . I . datalen , swap - > bobdeposit . I . datalen ) ;
retval = - 7 ;
}
}
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 ( swap , data , maxlen ) ;
basilisk_swapget ( swap , 0x80000000 , data , maxlen , basilisk_verify_otherstatebits ) ;
basilisk_swap_saveupdate ( swap ) ;
if ( time ( NULL ) > swap - > I . expiration )
break ;
}
if ( swap - > I . iambob ! = 0 & & swap - > bobdeposit . I . datalen ! = 0 & & bits256_nonz ( swap - > bobdeposit . I . actualtxid ) ! = 0 )
{
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 ( 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 " ) ;
}
else
{
// maybe wait for bobrefund to be confirmed
for ( j = datalen = 0 ; j < 32 ; j + + )
data [ datalen + + ] = swap - > I . privBn . bytes [ j ] ;
LP_swapsend ( swap , 0x40000000 , data , datalen , 0x40000000 , swap - > I . crcs_mypriv ) ;
}
basilisk_swap_saveupdate ( swap ) ;
}
if ( retval ! = 0 )
basilisk_swap_sendabort ( swap ) ;
printf ( " end of atomic swap \n " ) ;
if ( swapcompleted ( swap ) > 0 ) // only if swap completed
{
if ( swap - > I . iambob ! = 0 )
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 ( swap ) ;
free ( data ) ;
}
# endif
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 = LP_coinfind ( src ) ;
if ( coin = = 0 | | LP_coinfind ( dest ) = = 0 )
return ( 0 ) ;
* bobcoinp = * alicecoinp = 0 ;
* 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 ) ;
}
struct LP_utxoinfo * LP_utxopairfind ( int32_t iambob , bits256 txid , int32_t vout , bits256 txid2 , int32_t vout2 )
{
struct LP_utxoinfo * utxo = 0 ; struct _LP_utxoinfo u ;
if ( ( utxo = LP_utxofind ( iambob , txid , vout ) ) ! = 0 )
{
u = ( iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( vout2 = = u . vout & & bits256_cmp ( u . txid , txid2 ) = = 0 )
return ( utxo ) ;
}
return ( 0 ) ;
}
void LP_utxosetkey ( uint8_t * key , bits256 txid , int32_t vout )
{
memcpy ( key , txid . bytes , sizeof ( txid ) ) ;
memcpy ( & key [ sizeof ( txid ) ] , & vout , sizeof ( vout ) ) ;
}
struct LP_utxoinfo * _LP_utxofind ( int32_t iambob , bits256 txid , int32_t vout )
{
struct LP_utxoinfo * utxo = 0 ; uint8_t key [ sizeof ( txid ) + sizeof ( vout ) ] ;
LP_utxosetkey ( key , txid , vout ) ;
HASH_FIND ( hh , G . LP_utxoinfos [ iambob ! = 0 ] , key , sizeof ( key ) , utxo ) ;
return ( utxo ) ;
}
void _LP_utxo_delete ( int32_t iambob , struct LP_utxoinfo * utxo )
{
HASH_DELETE ( hh , G . LP_utxoinfos [ iambob ] , utxo ) ;
}
void _LP_utxo2_delete ( int32_t iambob , struct LP_utxoinfo * utxo )
{
HASH_DELETE ( hh , G . LP_utxoinfos2 [ iambob ] , utxo ) ;
}
struct LP_utxoinfo * _LP_utxo2find ( int32_t iambob , bits256 txid2 , int32_t vout2 )
{
struct LP_utxoinfo * utxo = 0 ; uint8_t key2 [ sizeof ( txid2 ) + sizeof ( vout2 ) ] ;
LP_utxosetkey ( key2 , txid2 , vout2 ) ;
HASH_FIND ( hh2 , G . LP_utxoinfos2 [ iambob ] , key2 , sizeof ( key2 ) , utxo ) ;
return ( utxo ) ;
}
struct LP_utxoinfo * LP_utxofind ( int32_t iambob , bits256 txid , int32_t vout )
{
struct LP_utxoinfo * utxo = 0 ;
/*if ( iambob != 0 )
{
printf ( " LP_utxofind deprecated iambob \n " ) ;
return ( 0 ) ;
} */
portable_mutex_lock ( & LP_utxomutex ) ;
utxo = _LP_utxofind ( iambob , txid , vout ) ;
portable_mutex_unlock ( & LP_utxomutex ) ;
return ( utxo ) ;
}
struct LP_utxoinfo * LP_utxo2find ( int32_t iambob , bits256 txid2 , int32_t vout2 )
{
struct LP_utxoinfo * utxo = 0 ;
/*if ( iambob != 0 )
{
printf ( " LP_utxo2find deprecated iambob \n " ) ;
return ( 0 ) ;
} */
portable_mutex_lock ( & LP_utxomutex ) ;
utxo = _LP_utxo2find ( iambob , txid2 , vout2 ) ;
portable_mutex_unlock ( & LP_utxomutex ) ;
return ( utxo ) ;
}
/*void LP_privkeysloop(void *ctx)
{
strcpy ( LP_privkeysloop_stats . name , " LP_privkeysloop " ) ;
LP_privkeysloop_stats . threshold = ( LP_ORDERBOOK_DURATION * .8 * 1000 ) + 10000 ;
sleep ( 20 ) ;
while ( 1 )
{
LP_millistats_update ( & LP_privkeysloop_stats ) ;
//printf("LP_privkeysloop %u\n",LP_counter);
LP_privkey_updates ( ctx , LP_mypubsock , 0 ) ;
sleep ( LP_ORDERBOOK_DURATION * .777 ) ;
}
} */
/*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 ; i < n ; i + + )
if ( myinfo - > swaps [ 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 ) ;
} */
/*if ( bits256_nonz(Q.srchash) == 0 || bits256_cmp(Q.srchash,G.LP_mypub25519) == 0 || strcmp(butxo->coinaddr,coin->smartaddr) != 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 )
{
qprice = ( double ) Q . destsatoshis / Q . satoshis ;
strcpy ( Q . gui , G . gui ) ;
strcpy ( Q . coinaddr , coin - > smartaddr ) ;
strcpy ( butxo - > coinaddr , coin - > smartaddr ) ;
Q . srchash = G . LP_mypub25519 ;
memset ( & Q . txid , 0 , sizeof ( Q . txid ) ) ;
memset ( & Q . txid2 , 0 , sizeof ( Q . txid2 ) ) ;
Q . vout = Q . vout2 = - 1 ;
recalc = 1 ;
}
else if ( ( qprice = LP_quote_validate ( autxo , butxo , & Q , 1 ) ) < SMALLVAL )
recalc = 1 ;
else if ( price < qprice )
{
char tmp [ 64 ] ;
if ( bits256_nonz ( Q . txid ) ! = 0 )
LP_utxos_remove ( Q . txid , Q . vout ) ;
else recalc = 1 ;
if ( bits256_nonz ( Q . txid2 ) ! = 0 )
LP_utxos_remove ( Q . txid2 , Q . vout2 ) ;
else recalc = 1 ;
//printf("price %.8f qprice %.8f\n",price,qprice);
if ( recalc = = 0 )
{
value = LP_txvalue ( tmp , Q . srccoin , Q . txid , Q . vout ) ;
value2 = LP_txvalue ( tmp , Q . srccoin , Q . txid2 , Q . vout2 ) ;
//printf("call LP_utxoadd.(%s) %.8f %.8f\n",Q.coinaddr,dstr(value),dstr(value2));
if ( ( butxo = LP_utxoadd ( 1 , coin - > symbol , Q . txid , Q . vout , value , Q . txid2 , Q . vout2 , value2 , Q . coinaddr , Q . srchash , G . gui , 0 , Q . satoshis ) ) = = 0 )
recalc = 1 ;
else if ( bits256_cmp ( Q . txid , butxo - > payment . txid ) ! = 0 | | Q . vout ! = butxo - > payment . vout | | bits256_cmp ( Q . txid2 , butxo - > deposit . txid ) ! = 0 | | Q . vout2 ! = butxo - > deposit . vout )
recalc = 1 ;
}
} else return ( retval ) ; */
int32_t LP_isavailable ( struct LP_utxoinfo * utxo )
{
struct _LP_utxoinfo u ;
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( LP_allocated ( utxo - > payment . txid , utxo - > payment . vout ) = = 0 & & LP_allocated ( u . txid , u . vout ) = = 0 )
return ( 1 ) ;
else return ( 0 ) ;
}
/*int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double origprice)
{
double price , bid , ask ; uint32_t now ; cJSON * retjson ; struct LP_quoteinfo Q ; char * retstr ;
if ( ( now = ( uint32_t ) time ( NULL ) ) > utxo - > T . swappending & & utxo - > S . swap = = 0 )
utxo - > T . swappending = 0 ;
if ( now > utxo - > T . published + 60 & & LP_isavailable ( utxo ) & & ( price = LP_myprice ( & bid , & ask , utxo - > coin , rel ) ) ! = 0. )
{
if ( origprice < price )
price = origprice ;
if ( LP_quoteinfoinit ( & Q , utxo , rel , price ) < 0 )
return ( - 1 ) ;
Q . timestamp = ( uint32_t ) time ( NULL ) ;
retjson = LP_quotejson ( & Q ) ;
jaddstr ( retjson , " method " , " quote " ) ;
retstr = jprint ( retjson , 1 ) ;
//printf("PING.(%s)\n",retstr);
if ( pubsock > = 0 )
LP_send ( pubsock , retstr , 1 ) ;
else
{
// verify it is in list
// push if it isnt
}
utxo - > T . published = now ;
return ( 0 ) ;
}
return ( - 1 ) ;
} */
/*if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 )
{
value = LP_txvalue ( Q . coinaddr , Q . srccoin , Q . txid , Q . vout ) ;
value2 = LP_txvalue ( Q . coinaddr , Q . srccoin , Q . txid2 , Q . vout2 ) ;
if ( value = = 0 | | value2 = = 0 )
{
printf ( " zero value %.8f or value2 %.8f \n " , dstr ( value ) , dstr ( value2 ) ) ;
return ( clonestr ( " { \" error \" : \" spent txid or txid2 for bob? \" } " ) ) ;
}
if ( ( butxo = LP_utxoadd ( 1 , Q . srccoin , Q . txid , Q . vout , value , Q . txid2 , Q . vout2 , value2 , Q . coinaddr , Q . srchash , LP_gui , 0 ) ) = = 0 )
{
printf ( " cant find or create butxo \n " ) ;
return ( clonestr ( " { \" error \" : \" cant find or create butxo \" } " ) ) ;
}
if ( value < Q . satoshis )
{
printf ( " butxo value %.8f less satoshis %.8f \n " , dstr ( value ) , dstr ( Q . satoshis ) ) ;
return ( clonestr ( " { \" error \" : \" butxo value less than satoshis \" } " ) ) ;
}
} */
/*if ( addflag != 0 && LP_utxofind(1,Q.txid,Q.vout) == 0 )
{
LP_utxoadd ( 1 , - 1 , Q . srccoin , Q . txid , Q . vout , Q . value , Q . txid2 , Q . vout2 , Q . value2 , " " , Q . srcaddr , Q . srchash , 0. ) ;
LP_utxoadd ( 0 , - 1 , Q . destcoin , Q . desttxid , Q . destvout , Q . destvalue , Q . feetxid , Q . feevout , Q . feevalu , " " , Q . destaddr , Q . desthash , 0. ) ;
} */
/*struct LP_utxoinfo *utxo,*tmp;
HASH_ITER ( hh , LP_utxoinfos [ 1 ] , utxo , tmp )
{
if ( LP_ismine ( utxo ) > 0 & & strcmp ( utxo - > coin , base ) = = 0 )
LP_priceping ( LP_mypubsock , utxo , rel , price * LP_profitratio ) ;
} */
int32_t LP_ismine ( struct LP_utxoinfo * utxo )
{
if ( utxo ! = 0 & & bits256_cmp ( utxo - > pubkey , G . LP_mypub25519 ) = = 0 )
return ( 1 ) ;
else return ( 0 ) ;
}
queue_t utxosQ ;
struct LP_utxos_qitem { struct queueitem DL ; cJSON * argjson ; } ;
char * LP_postutxos_recv ( cJSON * argjson )
{
struct LP_utxos_qitem * uitem ; struct iguana_info * coin ; char * coinaddr , * symbol ; bits256 utxoshash , pubkey ; cJSON * obj ; struct LP_pubkey_info * pubp ;
printf ( " LP_postutxos_recv deprecated \n " ) ;
pubkey = jbits256 ( argjson , " pubkey " ) ;
pubp = LP_pubkeyfind ( pubkey ) ;
if ( pubp ! = 0 & & pubp - > numerrors > LP_MAXPUBKEY_ERRORS )
return ( clonestr ( " { \" error \" : \" blacklisted \" } " ) ) ;
if ( ( coinaddr = jstr ( argjson , " coinaddr " ) ) ! = 0 & & ( symbol = jstr ( argjson , " coin " ) ) ! = 0 & & ( coin = LP_coinfind ( symbol ) ) ! = 0 )
{
if ( strcmp ( coinaddr , coin - > smartaddr ) = = 0 )
{
//printf("ignore my utxo from external source %s %s\n",symbol,coinaddr);
return ( clonestr ( " { \" result \" : \" success \" } " ) ) ;
}
}
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 " ) , pubkey , utxoshash ) = = 0 )
{
uitem = calloc ( 1 , sizeof ( * uitem ) ) ;
uitem - > argjson = jduplicate ( argjson ) ;
queue_enqueue ( " utxosQ " , & utxosQ , & uitem - > DL ) ;
return ( clonestr ( " { \" result \" : \" success \" } " ) ) ;
} //else printf("valid utxos sig %s\n",bits256_str(str,pubp->pubkey));
}
return ( clonestr ( " { \" error \" : \" sig failure \" } " ) ) ;
}
/*MERK d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a ht.518777 -> {"pos":1,"merkle":["526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8", "f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd"],"block_height":518777} root.(0000000000000000000000000000000000000000000000000000000000000000)
MERK c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 ht .518777 - > { " pos " : 2 , " merkle " : [ " fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501 " , " 8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7 " ] , " block_height " : 518777 } root . ( 0000000000000000000000000000000000000000000000000000000000000000 ) */
/*526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8
d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a
c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543
fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501 */
/*0: 526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8
1 : d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a
2 : c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543
3 : fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501
4 : 8 c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7
5 : f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd
6 : a87ee259560f20b20182760c0e7cc7896d44381f0ad58a2e755a2b6b895b01ec */
/*
0 1 2 3
4 5
6
1 - > [ 0 , 5 ]
2 - > [ 3 , 4 ]
if odd - > right , else left
then / = 2
*/
/*void testmerk()
{
bits256 tree [ 256 ] , roothash , txid ; int32_t i ; char str [ 65 ] ;
memset ( tree , 0 , sizeof ( tree ) ) ;
decode_hex ( tree [ 0 ] . bytes , 32 , " 526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8 " ) ;
decode_hex ( tree [ 1 ] . bytes , 32 , " d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a " ) ;
decode_hex ( tree [ 2 ] . bytes , 32 , " c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 " ) ;
decode_hex ( tree [ 3 ] . bytes , 32 , " fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501 " ) ;
roothash = iguana_merkle ( tree , 4 ) ;
for ( i = 0 ; i < 256 ; i + + )
{
if ( bits256_nonz ( tree [ i ] ) = = 0 )
break ;
printf ( " %d: %s \n " , i , bits256_str ( str , tree [ i ] ) ) ;
}
memset ( tree , 0 , sizeof ( tree ) ) ;
decode_hex ( tree [ 0 ] . bytes , 32 , " 526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8 " ) ;
decode_hex ( tree [ 1 ] . bytes , 32 , " f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd " ) ;
decode_hex ( txid . bytes , 32 , " d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a " ) ;
roothash = validate_merkle ( 1 , txid , tree , 2 ) ;
printf ( " validate 1: %s \n " , bits256_str ( str , roothash ) ) ;
memset ( tree , 0 , sizeof ( tree ) ) ;
decode_hex ( tree [ 0 ] . bytes , 32 , " fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501 " ) ;
decode_hex ( tree [ 1 ] . bytes , 32 , " 8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7 " ) ;
decode_hex ( txid . bytes , 32 , " c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 " ) ;
roothash = validate_merkle ( 2 , txid , tree , 2 ) ;
printf ( " validate 2: %s \n " , bits256_str ( str , roothash ) ) ;
} */
/*else if ( (retstr= LP_orderbook(coin->symbol,"KMD",-1)) != 0 )
{
if ( ( orderbook = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( asks = jarray ( & numasks , orderbook , " asks " ) ) ! = 0 & & numasks > 0 )
{
item = jitem ( asks , 0 ) ;
price = ask = jdouble ( item , " price " ) ;
//printf("%s/%s ask %.8f\n",coin->symbol,"KMD",ask);
}
if ( ( bids = jarray ( & numbids , orderbook , " bids " ) ) ! = 0 & & numbids > 0 )
{
item = jitem ( asks , 0 ) ;
bid = jdouble ( item , " price " ) ;
if ( price = = 0. )
price = bid ;
else price = ( bid + ask ) * 0.5 ;
//printf("%s/%s bid %.8f ask %.8f price %.8f\n",coin->symbol,"KMD",bid,ask,price);
}
KMDvalue = price * balance ;
free_json ( orderbook ) ;
}
free ( retstr ) ;
} */
int32_t LP_utxosQ_process ( )
{
struct LP_utxos_qitem * uitem ; int32_t n ; char * symbol , * coinaddr ; struct LP_address * ap ; struct iguana_info * coin ; cJSON * array ;
if ( ( uitem = queue_dequeue ( & utxosQ ) ) ! = 0 )
{
//printf("LP_utxosQ_process.(%s)\n",jprint(uitem->argjson,0));
if ( ( coinaddr = jstr ( uitem - > argjson , " coinaddr " ) ) ! = 0 & & ( symbol = jstr ( uitem - > argjson , " coin " ) ) ! = 0 & & ( coin = LP_coinfind ( symbol ) ) ! = 0 ) // addsig
{
if ( coin - > electrum = = 0 | | ( ap = LP_addressfind ( coin , coinaddr ) ) ! = 0 )
{
if ( ( array = jarray ( & n , uitem - > argjson , " utxos " ) ) ! = 0 )
LP_unspents_array ( coin , coinaddr , array ) ;
}
else if ( ( array = electrum_address_listunspent ( symbol , coin - > electrum , & array , coinaddr , 1 ) ) ! = 0 )
free_json ( array ) ;
}
free_json ( uitem - > argjson ) ;
free ( uitem ) ;
return ( 1 ) ;
}
return ( 0 ) ;
}
else if ( strcmp ( method , " postutxos " ) = = 0 )
return ( LP_postutxos_recv ( argjson ) ) ;
void utxosQ_loop ( void * myipaddr )
{
strcpy ( utxosQ_loop_stats . name , " utxosQ_loop " ) ;
utxosQ_loop_stats . threshold = 5000. ;
while ( 1 )
{
LP_millistats_update ( & utxosQ_loop_stats ) ;
if ( LP_utxosQ_process ( ) = = 0 )
usleep ( 50000 ) ;
}
}
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 ) ;
}
/*
bestprice = 0. ;
if ( ( array = LP_tradecandidates ( base ) ) ! = 0 )
{
printf ( " candidates.(%s) \n n.%d \n " , jprint ( array , 0 ) , cJSON_GetArraySize ( array ) ) ;
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
memset ( prices , 0 , sizeof ( prices ) ) ;
memset ( Q , 0 , sizeof ( Q ) ) ;
for ( i = 0 ; i < n & & i < sizeof ( prices ) / sizeof ( * prices ) ; i + + )
{
item = jitem ( array , i ) ;
LP_quoteparse ( & Q [ i ] , item ) ;
if ( ( price = jdouble ( item , " price " ) ) = = 0. )
{
price = LP_query ( " price " , & Q [ i ] , base , myutxo - > coin , zero ) ;
Q [ i ] . destsatoshis = price * Q [ i ] . satoshis ;
}
if ( ( prices [ i ] = price ) > SMALLVAL & & ( bestprice = = 0. | | price < bestprice ) )
bestprice = price ;
char str [ 65 ] ; printf ( " i.%d of %d: (%s) -> txid.%s price %.8f best %.8f dest %.8f \n " , i , n , jprint ( item , 0 ) , bits256_str ( str , Q [ i ] . txid ) , price , bestprice , dstr ( Q [ i ] . destsatoshis ) ) ;
}
if ( bestprice > SMALLVAL )
{
bestmetric = 0. ;
besti = - 1 ;
for ( i = 0 ; i < n & & i < sizeof ( prices ) / sizeof ( * prices ) ; i + + )
{
if ( ( price = prices [ i ] ) > SMALLVAL & & myutxo - > S . satoshis > = Q [ i ] . destsatoshis + Q [ i ] . desttxfee )
{
metric = price / bestprice ;
printf ( " %f %f %f %f " , price , metric , dstr ( Q [ i ] . destsatoshis ) , metric * metric * metric ) ;
if ( metric < 1.1 )
{
metric = dstr ( Q [ i ] . destsatoshis ) * metric * metric * metric ;
printf ( " %f \n " , metric ) ;
if ( bestmetric = = 0. | | metric < bestmetric )
{
besti = i ;
bestmetric = metric ;
}
}
} else printf ( " (%f %f) " , dstr ( myutxo - > S . satoshis ) , dstr ( Q [ i ] . destsatoshis ) ) ;
}
printf ( " metrics, best %f \n " , bestmetric ) ;
*/
int32_t LP_utxosquery ( struct LP_peerinfo * mypeer , int32_t mypubsock , char * destipaddr , uint16_t destport , char * coin , int32_t lastn , char * myipaddr , uint16_t myport , int32_t maxentries )
{
char * retstr ; struct LP_peerinfo * peer ; uint32_t now ; int32_t retval = - 1 ;
printf ( " deprecated LP_utxosquery \n " ) ;
return ( - 1 ) ;
peer = LP_peerfind ( ( uint32_t ) calc_ipbits ( destipaddr ) , destport ) ;
if ( coin = = 0 )
coin = " " ;
//printf("utxo query.(%s)\n",destipaddr);
if ( IAMLP ! = 0 )
retstr = issue_LP_getutxos ( destipaddr , destport , coin , lastn , myipaddr , myport , mypeer ! = 0 ? mypeer - > numpeers : 0 , maxentries ) ;
else retstr = issue_LP_clientgetutxos ( destipaddr , destport , coin , maxentries ) ;
if ( retstr ! = 0 )
{
now = ( uint32_t ) time ( NULL ) ;
retval = LP_utxosparse ( destipaddr , destport , retstr , now ) ;
//printf("got.(%s)\n",retstr);
free ( retstr ) ;
}
return ( retval ) ;
}
char * issue_LP_numutxos ( char * destip , uint16_t destport , char * ipaddr , uint16_t port , int32_t numpeers , int32_t numutxos )
{
char url [ 512 ] , * retstr ;
printf ( " deprecated issue_LP_numutxos \n " ) ;
return ( 0 ) ;
sprintf ( url , " http://%s:%u/api/stats/numutxos?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d " , destip , destport , ipaddr , port , numpeers , numutxos ) ;
retstr = LP_issue_curl ( " numutxos " , destip , port , url ) ;
//printf("%s -> getpeers.(%s)\n",destip,retstr);
return ( retstr ) ;
}
char * issue_LP_getutxos ( char * destip , uint16_t destport , char * coin , int32_t lastn , char * ipaddr , uint16_t port , int32_t numpeers , int32_t numutxos )
{
char url [ 512 ] ;
printf ( " deprecated issue_LP_getutxos \n " ) ;
return ( 0 ) ;
sprintf ( url , " http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&numpeers=%d&numutxos=%d " , destip , destport , coin , lastn , ipaddr , port , numpeers , numutxos ) ;
return ( LP_issue_curl ( " getutxos " , destip , destport , url ) ) ;
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char * issue_LP_clientgetutxos ( char * destip , uint16_t destport , char * coin , int32_t lastn )
{
char url [ 512 ] ; //,*retstr;
printf ( " deprecated issue_LP_clientgetutxos \n " ) ;
return ( 0 ) ;
sprintf ( url , " http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0 " , destip , destport , coin , lastn ) ;
return ( LP_issue_curl ( " clientgetutxos " , destip , destport , url ) ) ;
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
//printf("%s clientgetutxos.(%s)\n",url,retstr);
//return(retstr);
}
void LP_address_monitor ( struct LP_pubkeyinfo * pubp )
{
struct iguana_info * coin , * tmp ; char coinaddr [ 64 ] ; cJSON * retjson ; struct LP_address * ap ;
return ;
HASH_ITER ( hh , LP_coins , coin , tmp )
{
bitcoin_address ( coinaddr , coin - > taddr , coin - > pubtype , pubp - > rmd160 , sizeof ( pubp - > rmd160 ) ) ;
portable_mutex_lock ( & coin - > addrmutex ) ;
if ( ( ap = _LP_address ( coin , coinaddr ) ) ! = 0 )
{
ap - > monitor = ( uint32_t ) time ( NULL ) ;
}
portable_mutex_unlock ( & coin - > addrmutex ) ;
if ( coin - > electrum ! = 0 )
{
if ( ( retjson = electrum_address_subscribe ( coin - > symbol , coin - > electrum , & retjson , coinaddr ) ) ! = 0 )
{
printf ( " %s MONITOR.(%s) -> %s \n " , coin - > symbol , coinaddr , jprint ( retjson , 0 ) ) ;
free_json ( retjson ) ;
}
}
}
}
/*else if ( strcmp(method,"ordermatch") == 0 )
{
if ( price > SMALLVAL )
return ( LP_ordermatch ( base , j64bits ( argjson , " txfee " ) , price , jdouble ( argjson , " relvolume " ) , rel , jbits256 ( argjson , " txid " ) , jint ( argjson , " vout " ) , jbits256 ( argjson , " feetxid " ) , jint ( argjson , " feevout " ) , j64bits ( argjson , " desttxfee " ) , jint ( argjson , " duration " ) ) ) ;
else return ( clonestr ( " { \" error \" : \" no price set \" } " ) ) ;
}
else if ( strcmp ( method , " trade " ) = = 0 )
{
struct LP_quoteinfo Q ;
if ( price > SMALLVAL | | jobj ( argjson , " quote " ) ! = 0 )
{
LP_quoteparse ( & Q , jobj ( argjson , " quote " ) ) ;
return ( LP_trade ( ctx , myipaddr , pubsock , & Q , price , jint ( argjson , " timeout " ) , jint ( argjson , " duration " ) ) ) ;
} else return ( clonestr ( " { \" error \" : \" no price set or no quote object \" } " ) ) ;
}
else if ( strcmp ( method , " autotrade " ) = = 0 )
{
if ( price > SMALLVAL )
{
return ( LP_autotrade ( ctx , myipaddr , pubsock , base , rel , price , jdouble ( argjson , " relvolume " ) , jint ( argjson , " timeout " ) , jint ( argjson , " duration " ) ) ) ;
} else return ( clonestr ( " { \" error \" : \" no price set \" } " ) ) ;
} */
if ( flag ! = 0 )
{
// need to find the requestid/quoteid for aliceid
if ( ( retstr = basilisk_swapentries ( bot - > base , bot - > rel , 0 ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( n = cJSON_GetArraySize ( retjson ) ) ! = 0 )
{
for ( flag = j = 0 ; j < n ; j + + )
{
item = jitem ( retjson , j ) ;
aliceid = j64bits ( item , " aliceid " ) ;
for ( i = 0 ; i < bot - > numtrades ; i + + )
{
if ( ( tp = bot - > trades [ i ] ) ! = 0 & & tp - > finished = = 0 & & tp - > requestid = = 0 & & tp - > quoteid = = 0 )
{
if ( tp - > aliceid = = aliceid )
{
tp - > requestid = juint ( item , " requestid " ) ;
tp - > quoteid = juint ( item , " quoteid " ) ;
printf ( " found aliceid.%llx to set requestid.%u quoteid.%u \n " , ( long long ) aliceid , tp - > requestid , tp - > quoteid ) ;
flag = 1 ;
break ;
}
}
}
}
}
free_json ( retjson ) ;
}
free ( retstr ) ;
}
}
// check for finished pending swap
for ( i = 0 ; i < bot - > numtrades ; i + + )
{
if ( ( tp = bot - > trades [ i ] ) ! = 0 & & tp - > finished = = 0 & & tp - > requestid ! = 0 & & tp - > quoteid ! = 0 )
{
if ( ( retstr = basilisk_swapentry ( tp - > requestid , tp - > quoteid ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( status = jstr ( retjson , " status " ) ) ! = 0 & & strcmp ( status , " finished " ) = = 0 )
{
bot - > pendbasesum - = tp - > basevol , bot - > basesum + = tp - > basevol ;
bot - > pendrelsum - = tp - > relvol , bot - > relsum + = tp - > relvol ;
bot - > numpending - - , bot - > completed + + ;
printf ( " detected completion aliceid.%llx r.%u q.%u \n " , ( long long ) tp - > aliceid , tp - > requestid , tp - > quoteid ) ;
tp - > finished = ( uint32_t ) time ( NULL ) ;
}
free_json ( retjson ) ;
}
free ( retstr ) ;
}
}
}
}
int32_t LP_utxopurge ( int32_t allutxos )
{
char str [ 65 ] ; struct LP_utxoinfo * utxo , * tmp ; int32_t iambob , n = 0 ;
printf ( " LP_utxopurge mypub.(%s) \n " , bits256_str ( str , LP_mypub25519 ) ) ;
portable_mutex_lock ( & LP_utxomutex ) ;
for ( iambob = 0 ; iambob < = 1 ; iambob + + )
{
HASH_ITER ( hh , LP_utxoinfos [ iambob ] , utxo , tmp )
{
if ( LP_isavailable ( utxo ) > 0 )
{
if ( allutxos ! = 0 | | LP_ismine ( utxo ) > 0 )
{
printf ( " iambob.%d delete.(%s) \n " , iambob , bits256_str ( str , utxo - > payment . txid ) ) ;
HASH_DELETE ( hh , LP_utxoinfos [ iambob ] , utxo ) ;
//free(utxo); let the LP_utxoinfos2 free the utxo, should be 1:1
} else n + + ;
} else n + + ;
}
HASH_ITER ( hh , LP_utxoinfos2 [ iambob ] , utxo , tmp )
{
if ( LP_isavailable ( utxo ) > 0 )
{
if ( allutxos ! = 0 | | LP_ismine ( utxo ) > 0 )
{
printf ( " iambob.%d delete2.(%s) \n " , iambob , bits256_str ( str , utxo - > payment . txid ) ) ;
HASH_DELETE ( hh2 , LP_utxoinfos2 [ iambob ] , utxo ) ;
free ( utxo ) ;
} else n + + ;
} else n + + ;
}
}
portable_mutex_unlock ( & LP_utxomutex ) ;
return ( n ) ;
}
/*struct LP_utxoinfo *_LP_butxo_find(struct LP_utxoinfo *butxo)
{
int32_t i ; struct LP_utxoinfo * utxo = 0 ; uint32_t now = ( uint32_t ) time ( NULL ) ;
//portable_mutex_lock(&LP_butxomutex);
for ( i = 0 ; i < sizeof ( BUTXOS ) / sizeof ( * BUTXOS ) ; i + + )
{
utxo = & BUTXOS [ i ] ;
if ( butxo - > payment . vout = = utxo - > payment . vout & & butxo - > deposit . vout = = utxo - > deposit . vout & & bits256_nonz ( butxo - > payment . txid ) ! = 0 & & bits256_nonz ( butxo - > deposit . txid ) ! = 0 & & bits256_cmp ( butxo - > payment . txid , utxo - > payment . txid ) = = 0 & & bits256_cmp ( butxo - > deposit . txid , utxo - > deposit . txid ) = = 0 )
break ;
if ( utxo - > S . swap = = 0 & & now > utxo - > T . swappending )
memset ( utxo , 0 , sizeof ( * utxo ) ) ;
utxo = 0 ;
}
//portable_mutex_unlock(&LP_butxomutex);
return ( utxo ) ;
}
struct LP_utxoinfo * LP_butxo_add ( struct LP_utxoinfo * butxo )
{
static struct LP_utxoinfo zeroes ;
int32_t i ; struct LP_utxoinfo * utxo = 0 ;
portable_mutex_lock ( & LP_butxomutex ) ;
if ( ( utxo = _LP_butxo_find ( butxo ) ) = = 0 )
{
for ( i = 0 ; i < sizeof ( BUTXOS ) / sizeof ( * BUTXOS ) ; i + + )
{
utxo = & BUTXOS [ i ] ;
if ( memcmp ( & zeroes , utxo , sizeof ( * utxo ) ) = = 0 )
{
* utxo = * butxo ;
break ;
}
utxo = 0 ;
}
}
portable_mutex_unlock ( & LP_butxomutex ) ;
return ( utxo ) ;
}
void LP_butxo_swapfields_copy ( struct LP_utxoinfo * destutxo , struct LP_utxoinfo * srcutxo )
{
destutxo - > S = srcutxo - > S ;
destutxo - > T = srcutxo - > T ;
}
void LP_butxo_swapfields ( struct LP_utxoinfo * butxo )
{
struct LP_utxoinfo * getutxo = 0 ;
portable_mutex_lock ( & LP_butxomutex ) ;
if ( ( getutxo = _LP_butxo_find ( butxo ) ) ! = 0 )
LP_butxo_swapfields_copy ( butxo , getutxo ) ;
portable_mutex_unlock ( & LP_butxomutex ) ;
}
void LP_butxo_swapfields_set ( struct LP_utxoinfo * butxo )
{
struct LP_utxoinfo * setutxo ;
if ( ( setutxo = LP_butxo_add ( butxo ) ) ! = 0 )
{
LP_butxo_swapfields_copy ( setutxo , butxo ) ;
}
} */
/*struct LP_utxoinfo BUTXOS[100];
int32_t LP_butxo_findeither ( bits256 txid , int32_t vout )
{
struct LP_utxoinfo * utxo ; int32_t i , retval = 0 ;
portable_mutex_lock ( & LP_butxomutex ) ;
for ( i = 0 ; i < sizeof ( BUTXOS ) / sizeof ( * BUTXOS ) ; i + + )
{
utxo = & BUTXOS [ i ] ;
if ( ( vout = = utxo - > payment . vout & & bits256_cmp ( txid , utxo - > payment . txid ) ) = = 0 | | ( vout = = utxo - > deposit . vout & & bits256_cmp ( txid , utxo - > deposit . txid ) = = 0 ) )
{
retval = 1 ;
break ;
}
}
portable_mutex_unlock ( & LP_butxomutex ) ;
return ( retval ) ;
} */
struct LP_utxoinfo * LP_utxoaddjson ( int32_t iambob , int32_t pubsock , cJSON * argjson )
{
struct LP_utxoinfo * utxo ;
if ( jobj ( argjson , " iambob " ) = = 0 | | iambob ! = jint ( argjson , " iambob " ) )
{
printf ( " LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s) \n " , iambob , jint ( argjson , " iambob " ) , jobj ( argjson , " iambob " ) , jprint ( argjson , 0 ) ) ;
return ( 0 ) ;
}
portable_mutex_lock ( & LP_UTXOmutex ) ;
utxo = LP_utxoadd ( iambob , pubsock , jstr ( argjson , " coin " ) , jbits256 ( argjson , " txid " ) , jint ( argjson , " vout " ) , j64bits ( argjson , " value " ) , jbits256 ( argjson , " txid2 " ) , jint ( argjson , " vout2 " ) , j64bits ( argjson , " value2 " ) , jstr ( argjson , " script " ) , jstr ( argjson , " address " ) , jbits256 ( argjson , " pubkey " ) , jstr ( argjson , " gui " ) , juint ( argjson , " session " ) ) ;
if ( LP_ismine ( utxo ) > 0 & & utxo - > T . lasttime = = 0 )
{
utxo - > T . lasttime = ( uint32_t ) time ( NULL ) ;
printf ( " set lasttime! \n " ) ;
}
portable_mutex_unlock ( & LP_UTXOmutex ) ;
return ( utxo ) ;
}
int32_t LP_utxosparse ( char * destipaddr , uint16_t destport , char * retstr , uint32_t now )
{
struct LP_peerinfo * peer ; uint32_t argipbits ; char * argipaddr ; uint16_t argport , pushport , subport ; cJSON * array , * item ; int32_t i , n = 0 ; bits256 txid ; struct LP_utxoinfo * utxo ;
//printf("parse.(%s)\n",retstr);
if ( ( array = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
if ( ( argipaddr = jstr ( item , " ipaddr " ) ) ! = 0 & & ( argport = juint ( item , " port " ) ) ! = 0 )
{
if ( ( pushport = juint ( item , " push " ) ) = = 0 )
pushport = argport + 1 ;
if ( ( subport = juint ( item , " sub " ) ) = = 0 )
subport = argport + 2 ;
argipbits = ( uint32_t ) calc_ipbits ( argipaddr ) ;
if ( ( peer = LP_peerfind ( argipbits , argport ) ) = = 0 )
peer = LP_addpeer ( 0 , - 1 , argipaddr , argport , pushport , subport , jint ( item , " numpeers " ) , jint ( item , " numutxos " ) , juint ( item , " session " ) ) ;
}
if ( jobj ( item , " txid " ) ! = 0 )
{
txid = jbits256 ( item , " txid " ) ;
//printf("parse.(%s)\n",jprint(item,0));
if ( ( utxo = LP_utxoaddjson ( 1 , - 1 , item ) ) ! = 0 )
utxo - > T . lasttime = now ;
}
}
if ( ( destpeer = LP_peerfind ( ( uint32_t ) calc_ipbits ( destipaddr ) , destport ) ) ! = 0 )
{
destpeer - > numutxos = n ;
}
}
free_json ( array ) ;
}
return ( n ) ;
}
void LP_spentnotify ( struct LP_utxoinfo * utxo , int32_t selector )
{
//cJSON *argjson; struct _LP_utxoinfo u; char *msg;
if ( utxo = = 0 )
return ;
utxo - > T . spentflag = ( uint32_t ) time ( NULL ) ;
/*if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 )
LP_mypeer - > numutxos - - ;
if ( LP_mypubsock > = 0 )
{
argjson = cJSON_CreateObject ( ) ;
jaddstr ( argjson , " method " , " checktxid " ) ;
jaddbits256 ( argjson , " txid " , utxo - > payment . txid ) ;
jaddnum ( argjson , " vout " , utxo - > payment . vout ) ;
if ( selector ! = 0 )
{
if ( bits256_nonz ( utxo - > deposit . txid ) ! = 0 )
u = utxo - > deposit ;
else u = utxo - > fee ;
jaddbits256 ( argjson , " checktxid " , u . txid ) ;
jaddnum ( argjson , " checkvout " , u . vout ) ;
}
msg = jprint ( argjson , 1 ) ;
/ LP_send ( LP_mypubsock , msg , ( int32_t ) strlen ( msg ) + 1 , 1 ) ;
} */
}
char * LP_utxos ( int32_t iambob , struct LP_peerinfo * mypeer , char * symbol , int32_t lastn )
{
int32_t i , n , m ; uint64_t val , val2 ; struct _LP_utxoinfo u ; struct LP_utxoinfo * utxo , * tmp ; cJSON * utxosjson = cJSON_CreateArray ( ) ;
printf ( " deprecated! LP_utxos \n " ) ;
//n = mypeer != 0 ? mypeer->numutxos : 0;
if ( lastn < = 0 )
lastn = LP_PROPAGATION_SLACK * 2 ;
HASH_ITER ( hh , LP_utxoinfos [ iambob ] , utxo , tmp )
{
//char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid));
if ( ( symbol = = 0 | | symbol [ 0 ] = = 0 | | strcmp ( symbol , utxo - > coin ) = = 0 ) & & utxo - > T . spentflag = = 0 )
{
u = ( iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( LP_iseligible ( & val , & val2 , utxo - > iambob , utxo - > coin , utxo - > payment . txid , utxo - > payment . vout , utxo - > S . satoshis , u . txid , u . vout ) = = 0 )
{
char str [ 65 ] ; printf ( " iambob.%d not eligible (%.8f %.8f) %s %s/v%d \n " , iambob , dstr ( val ) , dstr ( val2 ) , utxo - > coin , bits256_str ( str , utxo - > payment . txid ) , utxo - > payment . vout ) ;
continue ;
} else jaddi ( utxosjson , LP_utxojson ( utxo ) ) ;
}
}
if ( ( n = cJSON_GetArraySize ( utxosjson ) ) > lastn )
{
m = n - lastn ;
for ( i = 0 ; i < m ; i + + )
cJSON_DeleteItemFromArray ( utxosjson , 0 ) ;
}
return ( jprint ( utxosjson , 1 ) ) ;
}
int32_t LP_isunspent ( struct LP_utxoinfo * utxo )
{
struct LP_address_utxo * up ; struct _LP_utxoinfo u ; struct iguana_info * coin ;
if ( ( coin = LP_coinfind ( utxo - > coin ) ) = = 0 )
return ( 0 ) ;
if ( ( up = LP_address_utxofind ( coin , utxo - > coinaddr , utxo - > payment . txid , utxo - > payment . vout ) ) ! = 0 & & up - > spendheight > 0 )
{
utxo - > T . spentflag = up - > spendheight ;
return ( 0 ) ;
}
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( ( up = LP_address_utxofind ( coin , utxo - > coinaddr , u . txid , u . vout ) ) ! = 0 & & up - > spendheight > 0 )
{
utxo - > T . spentflag = up - > spendheight ;
return ( 0 ) ;
}
if ( utxo ! = 0 & & utxo - > T . spentflag = = 0 & & LP_isavailable ( utxo ) > 0 )
return ( 1 ) ;
else return ( 0 ) ;
}
void LP_utxo_clientpublish ( struct LP_utxoinfo * utxo )
{
bits256 zero ; char * msg ;
if ( 0 & & LP_isunspent ( utxo ) > 0 )
{
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
msg = jprint ( LP_utxojson ( utxo ) , 1 ) ;
LP_broadcast_message ( LP_mypubsock , utxo - > coin , " " , zero , msg ) ;
}
}
/*char *LP_spentcheck(cJSON *argjson)
{
bits256 txid , checktxid ; int32_t vout , checkvout ; struct LP_utxoinfo * utxo ; int32_t iambob , retval = 0 ;
txid = jbits256 ( argjson , " txid " ) ;
vout = jint ( argjson , " vout " ) ;
for ( iambob = 0 ; iambob < = 1 ; iambob + + )
{
if ( ( utxo = LP_utxofind ( iambob , txid , vout ) ) ! = 0 & & utxo - > T . spentflag = = 0 )
{
if ( jobj ( argjson , " check " ) = = 0 )
checktxid = txid , checkvout = vout ;
else
{
checktxid = jbits256 ( argjson , " checktxid " ) ;
checkvout = jint ( argjson , " checkvout " ) ;
}
if ( LP_txvalue ( 0 , utxo - > coin , checktxid , checkvout ) = = 0 )
{
//if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 )
// LP_mypeer->numutxos--;
utxo - > T . spentflag = ( uint32_t ) time ( NULL ) ;
retval + + ;
printf ( " indeed txid was spent \n " ) ;
}
}
}
if ( retval > 0 )
return ( clonestr ( " { \" result \" : \" marked as spent \" } " ) ) ;
return ( clonestr ( " { \" error \" : \" cant find txid to check spent status \" } " ) ) ;
} */
/*char *LP_pricestr(char *base,char *rel,double origprice)
{
cJSON * retjson ; double price = 0. ;
if ( base ! = 0 & & base [ 0 ] ! = 0 & & rel ! = 0 & & rel [ 0 ] ! = 0 )
{
price = LP_price ( base , rel ) ;
if ( origprice > SMALLVAL & & origprice < price )
price = origprice ;
}
if ( LP_pricevalid ( price ) > 0 )
{
retjson = cJSON_CreateObject ( ) ;
jaddstr ( retjson , " result " , " success " ) ;
jaddstr ( retjson , " method " , " postprice " ) ;
jaddbits256 ( retjson , " pubkey " , G . LP_mypub25519 ) ;
jaddstr ( retjson , " base " , base ) ;
jaddstr ( retjson , " rel " , rel ) ;
jaddnum ( retjson , " price " , price ) ;
jadd ( retjson , " theoretical " , LP_priceinfomatrix ( 0 ) ) ;
jadd ( retjson , " quotes " , LP_priceinfomatrix ( 1 ) ) ;
return ( jprint ( retjson , 1 ) ) ;
} else return ( clonestr ( " { \" error \" : \" cant find baserel pair \" } " ) ) ;
} */
void LP_utxo_spentcheck ( int32_t pubsock , struct LP_utxoinfo * utxo )
{
struct _LP_utxoinfo u ; struct iguana_info * coin ; char str [ 65 ] ; uint32_t now = ( uint32_t ) time ( NULL ) ;
if ( IAMLP ! = 0 & & ( coin = LP_coinfind ( utxo - > coin ) ) ! = 0 & & coin - > inactive ! = 0 )
return ;
//printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck);
if ( utxo - > T . spentflag = = 0 & & now > utxo - > T . lastspentcheck + 60 )
{
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
utxo - > T . lastspentcheck = now ;
if ( LP_txvalue ( 0 , utxo - > coin , utxo - > payment . txid , utxo - > payment . vout ) = = 0 )
{
printf ( " txid.%s %s/v%d %.8f has been spent \n " , utxo - > coin , bits256_str ( str , utxo - > payment . txid ) , utxo - > payment . vout , dstr ( utxo - > payment . value ) ) ;
LP_spentnotify ( utxo , 0 ) ;
}
else if ( LP_txvalue ( 0 , utxo - > coin , u . txid , u . vout ) = = 0 )
{
printf ( " txid2.%s %s/v%d %.8f has been spent \n " , utxo - > coin , bits256_str ( str , u . txid ) , u . vout , dstr ( u . value ) ) ;
LP_spentnotify ( utxo , 1 ) ;
}
}
}
int32_t LP_peer_utxosquery ( struct LP_peerinfo * mypeer , uint16_t myport , int32_t pubsock , struct LP_peerinfo * peer , uint32_t now , int32_t interval , int32_t maxentries )
{
int32_t lastn , n = - 1 ;
if ( peer - > lastutxos < now - interval )
{
//lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK;
//if ( lastn < LP_PROPAGATION_SLACK * 2 )
lastn = LP_PROPAGATION_SLACK * 2 ;
if ( mypeer = = 0 | | strcmp ( peer - > ipaddr , mypeer - > ipaddr ) ! = 0 )
{
peer - > lastutxos = now ;
//printf("query utxos from %s\n",peer->ipaddr);
n = LP_utxosquery ( mypeer , pubsock , peer - > ipaddr , peer - > port , " " , lastn , mypeer ! = 0 ? mypeer - > ipaddr : " 127.0.0.1 " , myport , maxentries ) ;
}
} //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
return ( n ) ;
}
bestitem = LP_quotejson ( qp ) ;
if ( LP_pricevalid ( price ) > 0 )
{
if ( price < = maxprice )
{
LP_query ( ctx , myipaddr , mypubsock , " connect " , qp ) ;
//price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout);
LP_requestinit ( & qp - > R , qp - > srchash , qp - > desthash , qp - > srccoin , qp - > satoshis - 2 * qp - > txfee , qp - > destcoin , qp - > destsatoshis - 2 * qp - > desttxfee , qp - > timestamp , qp - > quotetime , DEXselector ) ;
while ( time ( NULL ) < expiration )
{
if ( aliceutxo - > S . swap ! = 0 )
break ;
sleep ( 3 ) ;
}
jaddnum ( bestitem , " quotedprice " , price ) ;
jaddnum ( bestitem , " maxprice " , maxprice ) ;
if ( ( swap = aliceutxo - > S . swap ) = = 0 )
{
if ( ( pubp = LP_pubkeyadd ( qp - > srchash ) ) ! = 0 )
pubp - > numerrors + + ;
jaddstr ( bestitem , " status " , " couldnt establish connection " ) ;
}
else
{
jaddstr ( bestitem , " status " , " connected " ) ;
jaddnum ( bestitem , " requestid " , swap - > I . req . requestid ) ;
jaddnum ( bestitem , " quoteid " , swap - > I . req . quoteid ) ;
printf ( " Alice r.%u qp->%u \n " , swap - > I . req . requestid , swap - > I . req . quoteid ) ;
}
}
else
{
jaddnum ( bestitem , " quotedprice " , price ) ;
jaddnum ( bestitem , " maxprice " , maxprice ) ;
jaddstr ( bestitem , " status " , " too expensive " ) ;
}
}
else
{
printf ( " invalid price %.8f \n " , price ) ;
jaddnum ( bestitem , " maxprice " , maxprice ) ;
jaddstr ( bestitem , " status " , " no response to request " ) ;
}
uint32_t LP_allocated ( bits256 txid , int32_t vout )
{
struct LP_utxoinfo * utxo ;
if ( ( utxo = _LP_utxofind ( 0 , txid , vout ) ) ! = 0 & & LP_isavailable ( utxo ) = = 0 )
{
//char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout);
return ( utxo ) ;
}
if ( ( utxo = _LP_utxo2find ( 0 , txid , vout ) ) ! = 0 & & LP_isavailable ( utxo ) = = 0 )
{
//char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout);
return ( utxo ) ;
}
if ( ( utxo = _LP_utxofind ( 1 , txid , vout ) ) ! = 0 & & LP_isavailable ( utxo ) = = 0 )
{
//char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout);
return ( utxo ) ;
}
if ( ( utxo = _LP_utxo2find ( 1 , txid , vout ) ) ! = 0 & & LP_isavailable ( utxo ) = = 0 )
{
//char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout);
return ( utxo ) ;
}
return ( 0 ) ;
}
int32_t LP_isavailable ( struct LP_utxoinfo * utxo )
{
if ( time ( NULL ) > utxo - > T . swappending )
utxo - > T . swappending = 0 ;
if ( utxo ! = 0 & & utxo - > T . swappending = = 0 & & utxo - > S . swap = = 0 )
return ( 1 ) ;
else return ( 0 ) ;
}
int32_t LP_utxoaddptrs ( struct LP_utxoinfo * ptrs [ ] , int32_t n , struct LP_utxoinfo * utxo )
{
int32_t i ;
for ( i = 0 ; i < n ; i + + )
if ( ptrs [ i ] = = utxo )
return ( n ) ;
ptrs [ n + + ] = utxo ;
return ( n ) ;
}
int32_t LP_utxocollisions ( struct LP_utxoinfo * ptrs [ ] , struct LP_utxoinfo * refutxo )
{
int32_t iambob , n = 0 ; struct LP_utxoinfo * utxo ; struct _LP_utxoinfo u ;
if ( refutxo = = 0 )
return ( 0 ) ;
portable_mutex_lock ( & LP_utxomutex ) ;
for ( iambob = 0 ; iambob < = 1 ; iambob + + )
{
if ( ( utxo = _LP_utxofind ( iambob , refutxo - > payment . txid , refutxo - > payment . vout ) ) ! = 0 & & utxo ! = refutxo )
n = LP_utxoaddptrs ( ptrs , n , utxo ) ;
if ( ( utxo = _LP_utxo2find ( iambob , refutxo - > payment . txid , refutxo - > payment . vout ) ) ! = 0 & & utxo ! = refutxo )
n = LP_utxoaddptrs ( ptrs , n , utxo ) ;
u = ( refutxo - > iambob ! = 0 ) ? refutxo - > deposit : refutxo - > fee ;
if ( ( utxo = _LP_utxofind ( iambob , u . txid , u . vout ) ) ! = 0 & & utxo ! = refutxo )
n = LP_utxoaddptrs ( ptrs , n , utxo ) ;
if ( ( utxo = _LP_utxo2find ( iambob , u . txid , u . vout ) ) ! = 0 & & utxo ! = refutxo )
n = LP_utxoaddptrs ( ptrs , n , utxo ) ;
}
portable_mutex_unlock ( & LP_utxomutex ) ;
if ( 0 & & n > 0 )
printf ( " LP_utxocollisions n.%d \n " , n ) ;
return ( n ) ;
}
int32_t _LP_availableset ( struct LP_utxoinfo * utxo )
{
int32_t flag = 0 ;
if ( utxo ! = 0 )
{
if ( bits256_nonz ( utxo - > S . otherpubkey ) ! = 0 )
flag = 1 , memset ( & utxo - > S . otherpubkey , 0 , sizeof ( utxo - > S . otherpubkey ) ) ;
if ( utxo - > S . swap ! = 0 )
flag = 1 , utxo - > S . swap = 0 ;
if ( utxo - > T . swappending ! = 0 )
flag = 1 , utxo - > T . swappending = 0 ;
return ( flag ) ;
}
return ( 0 ) ;
}
void _LP_unavailableset ( struct LP_utxoinfo * utxo , bits256 otherpubkey )
{
if ( utxo ! = 0 )
{
utxo - > T . swappending = ( uint32_t ) ( time ( NULL ) + LP_RESERVETIME ) ;
utxo - > S . otherpubkey = otherpubkey ;
}
}
void LP_unavailableset ( struct LP_utxoinfo * utxo , bits256 otherpubkey )
{
struct LP_utxoinfo * ptrs [ 8 ] ; int32_t i , n ; struct _LP_utxoinfo u ;
memset ( ptrs , 0 , sizeof ( ptrs ) ) ;
if ( ( n = LP_utxocollisions ( ptrs , utxo ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
_LP_unavailableset ( ptrs [ i ] , otherpubkey ) ;
}
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
char str [ 65 ] , str2 [ 65 ] ; printf ( " UTXO.[%d] RESERVED %s/v%d %s/v%d collisions.%d \n " , utxo - > iambob , bits256_str ( str , utxo - > payment . txid ) , utxo - > payment . vout , bits256_str ( str2 , u . txid ) , u . vout , n ) ;
_LP_unavailableset ( utxo , otherpubkey ) ;
}
void LP_availableset ( struct LP_utxoinfo * utxo )
{
struct LP_utxoinfo * ptrs [ 8 ] ; int32_t i , n , count = 0 ; struct _LP_utxoinfo u ;
if ( utxo ! = 0 )
{
memset ( ptrs , 0 , sizeof ( ptrs ) ) ;
if ( ( n = LP_utxocollisions ( ptrs , utxo ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
count + = _LP_availableset ( ptrs [ i ] ) ;
}
count + = _LP_availableset ( utxo ) ;
if ( count > 0 )
{
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
char str [ 65 ] , str2 [ 65 ] ; printf ( " UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d \n " , utxo - > iambob , bits256_str ( str , utxo - > payment . txid ) , utxo - > payment . vout , bits256_str ( str2 , u . txid ) , u . vout , n ) ;
}
}
}
cJSON * LP_inventoryjson ( cJSON * item , struct LP_utxoinfo * utxo )
{
struct _LP_utxoinfo u ;
//jaddstr(item,"method","oldutxo");
if ( utxo = = 0 )
return ( item ) ;
if ( utxo - > gui [ 0 ] ! = 0 )
jaddstr ( item , " gui " , utxo - > gui ) ;
jaddstr ( item , " coin " , utxo - > coin ) ;
//jaddnum(item,"now",time(NULL));
jaddnum ( item , " iambob " , utxo - > iambob ) ;
jaddstr ( item , " address " , utxo - > coinaddr ) ;
jaddbits256 ( item , " txid " , utxo - > payment . txid ) ;
jaddnum ( item , " vout " , utxo - > payment . vout ) ;
jadd64bits ( item , " value " , utxo - > payment . value ) ;
jadd64bits ( item , " satoshis " , utxo - > S . satoshis ) ;
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( bits256_nonz ( u . txid ) ! = 0 )
{
jaddbits256 ( item , " txid2 " , u . txid ) ;
jaddnum ( item , " vout2 " , u . vout ) ;
jadd64bits ( item , " value2 " , u . value ) ;
}
if ( utxo - > T . swappending ! = 0 )
jaddnum ( item , " pending " , utxo - > T . swappending ) ;
if ( utxo - > iambob ! = 0 )
{
jaddbits256 ( item , " srchash " , utxo - > pubkey ) ; //LP_mypub25519);
if ( bits256_nonz ( utxo - > S . otherpubkey ) ! = 0 )
jaddbits256 ( item , " desthash " , utxo - > S . otherpubkey ) ;
}
else
{
jaddbits256 ( item , " desthash " , utxo - > pubkey ) ; //LP_mypub25519);
if ( bits256_nonz ( utxo - > S . otherpubkey ) ! = 0 )
jaddbits256 ( item , " srchash " , utxo - > S . otherpubkey ) ;
}
//if ( utxo->S.swap != 0 )
// jaddstr(item,"swap","in progress");
if ( utxo - > T . spentflag ! = 0 )
jaddnum ( item , " spent " , utxo - > T . spentflag ) ;
jaddnum ( item , " session " , utxo - > T . sessionid ) ;
return ( item ) ;
}
cJSON * LP_utxojson ( struct LP_utxoinfo * utxo )
{
cJSON * item = cJSON_CreateObject ( ) ;
item = LP_inventoryjson ( item , utxo ) ;
jaddbits256 ( item , " pubkey " , utxo - > pubkey ) ;
//jaddnum(item,"profit",utxo->S.profitmargin);
jaddstr ( item , " base " , utxo - > coin ) ;
//jaddstr(item,"script",utxo->spendscript);
return ( item ) ;
}
struct LP_utxoinfo * LP_utxo_bestfit ( char * symbol , uint64_t destsatoshis )
{
uint64_t srcvalue , srcvalue2 ; struct LP_utxoinfo * utxo , * tmp , * bestutxo = 0 ; int32_t bestsize , iambob = 0 ;
if ( symbol = = 0 | | destsatoshis = = 0 )
{
printf ( " LP_utxo_bestfit error symbol.%p %.8f \n " , symbol , dstr ( destsatoshis ) ) ;
return ( 0 ) ;
}
HASH_ITER ( hh , G . LP_utxoinfos [ iambob ] , utxo , tmp )
{
if ( strcmp ( symbol , utxo - > coin ) ! = 0 )
continue ;
if ( LP_isavailable ( utxo ) > 0 & & LP_ismine ( utxo ) > 0 )
{
//printf("(%.8f %.8f %.8f)\n",dstr(utxo->payment.value),dstr(utxo->fee.value),dstr(utxo->S.satoshis));
//char str[65]; printf("s%u %d [%.8f vs %.8f] check %s.%s avail.%d ismine.%d >= %d\n",utxo->T.spentflag,LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout),dstr(destsatoshis),dstr(utxo->S.satoshis),utxo->coin,bits256_str(str,utxo->payment.txid),LP_isavailable(utxo) > 0,LP_ismine(utxo) > 0,utxo->S.satoshis >= destsatoshis);
bestsize = 0 ;
if ( bestutxo = = 0 )
{
if ( utxo - > S . satoshis > destsatoshis / LP_MINCLIENTVOL )
bestsize = 1 ;
}
else
{
if ( bestutxo - > S . satoshis < destsatoshis )
{
if ( utxo - > S . satoshis > destsatoshis )
bestsize = 1 ;
else if ( utxo - > S . satoshis > bestutxo - > S . satoshis )
bestsize = 1 ;
}
else
{
if ( utxo - > S . satoshis > destsatoshis & & utxo - > S . satoshis < bestutxo - > S . satoshis )
bestsize = 1 ;
}
}
if ( bestsize > 0 )
{
//printf("bestsize.%d %.8f %.8f -> %.8f\n",bestsize,dstr(utxo->payment.value),dstr(utxo->fee.value),dstr(utxo->S.satoshis));
if ( LP_iseligible ( & srcvalue , & srcvalue2 , utxo - > iambob , symbol , utxo - > payment . txid , utxo - > payment . vout , utxo - > S . satoshis , utxo - > fee . txid , utxo - > fee . vout ) = = 0 )
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
continue ;
}
bestutxo = utxo ;
} //else printf("skip alice utxo %.8f vs dest %.8f, bestsize.%d %p\n",dstr(utxo->S.satoshis),dstr(destsatoshis),bestsize,bestutxo);
}
}
return ( bestutxo ) ;
}
void LP_spentnotify ( struct LP_utxoinfo * utxo , int32_t selector )
{
if ( utxo = = 0 )
return ;
utxo - > T . spentflag = ( uint32_t ) time ( NULL ) ;
}
struct LP_utxoinfo * LP_utxofinds ( int32_t iambob , bits256 txid , int32_t vout , bits256 txid2 , int32_t vout2 )
{
struct LP_utxoinfo * utxo ;
if ( ( utxo = LP_utxofind ( iambob , txid , vout ) ) ! = 0 | | ( utxo = LP_utxofind ( iambob , txid2 , vout2 ) ) ! = 0 | | ( utxo = LP_utxo2find ( iambob , txid , vout ) ) ! = 0 | | ( utxo = LP_utxo2find ( iambob , txid2 , vout2 ) ) ! = 0 )
return ( utxo ) ;
else return ( 0 ) ;
}
struct LP_utxoinfo * LP_utxoadd ( int32_t iambob , char * symbol , bits256 txid , int32_t vout , int64_t value , bits256 txid2 , int32_t vout2 , int64_t value2 , char * coinaddr , bits256 pubkey , char * gui , uint32_t sessionid , uint64_t satoshis )
{
uint64_t val , val2 = 0 , txfee ; int32_t spendvini , numconfirms , selector ; bits256 spendtxid ; struct iguana_info * coin ; struct _LP_utxoinfo u ; struct LP_utxoinfo * utxo = 0 ;
if ( symbol = = 0 | | symbol [ 0 ] = = 0 | | coinaddr = = 0 | | coinaddr [ 0 ] = = 0 | | bits256_nonz ( txid ) = = 0 | | bits256_nonz ( txid2 ) = = 0 | | vout < 0 | | vout2 < 0 | | value < = 0 | | value2 < = 0 ) //|| sessionid == 0 )
{
char str [ 65 ] , str2 [ 65 ] ; printf ( " REJECT (%s) iambob.%d %s utxoadd.(%.8f %.8f) %s/v%d %s/v%d \n " , coinaddr , iambob , symbol , dstr ( value ) , dstr ( value2 ) , bits256_str ( str , txid ) , vout , bits256_str ( str2 , txid2 ) , vout2 ) ;
printf ( " session.%u addutxo %d %d %d %d %d %d %d %d \n " , sessionid , symbol = = 0 , coinaddr = = 0 , bits256_nonz ( txid ) = = 0 , bits256_nonz ( txid2 ) = = 0 , vout < 0 , vout2 < 0 , value < = 0 , value2 < = 0 ) ;
return ( 0 ) ;
}
if ( ( coin = LP_coinfind ( symbol ) ) = = 0 | | ( IAMLP = = 0 & & coin - > inactive ! = 0 ) )
{
//printf("LP_utxoadd reject inactive %s\n",symbol);
return ( 0 ) ;
}
txfee = LP_txfeecalc ( coin , 0 , 0 ) ;
char str [ 65 ] , str2 [ 65 ] , dispflag = 0 ; //(iambob == 0);
if ( iambob = = 0 & & bits256_cmp ( pubkey , G . LP_mypub25519 ) ! = 0 )
{
printf ( " trying to add Alice utxo when not mine? %s/v%d \n " , bits256_str ( str , txid ) , vout ) ;
return ( 0 ) ;
}
if ( coin - > inactive = = 0 )
{
if ( LP_iseligible ( & val , & val2 , iambob , symbol , txid , vout , satoshis , txid2 , vout2 ) < = 0 )
{
static uint32_t counter ;
if ( counter + + < 3 )
printf ( " iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f \n " , iambob , symbol , coin - > inactive , dstr ( value ) , dstr ( val ) , dstr ( value2 ) , dstr ( val2 ) , dstr ( satoshis ) ) ;
return ( 0 ) ;
}
if ( ( numconfirms = LP_numconfirms ( symbol , coinaddr , txid , vout , 0 ) ) < = 0 )
{
printf ( " LP_utxoadd reject numconfirms.%d %s.%s \n " , numconfirms , symbol , bits256_str ( str , txid ) ) ;
return ( 0 ) ;
}
if ( ( numconfirms = LP_numconfirms ( symbol , coinaddr , txid2 , vout2 , 0 ) ) < = 0 )
{
printf ( " LP_utxoadd reject2 numconfirms.%d %s %s/v%d \n " , numconfirms , symbol , bits256_str ( str , txid2 ) , vout2 ) ;
return ( 0 ) ;
}
}
else
{
val = value ;
val2 = value2 ;
}
dispflag = 0 ;
if ( dispflag ! = 0 )
printf ( " %.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s \n " , dstr ( val ) , dstr ( val2 ) , coinaddr , iambob , symbol , dstr ( value ) , dstr ( value2 ) , bits256_str ( str , txid ) , bits256_str ( str2 , txid2 ) ) ;
dispflag = 1 ;
if ( ( utxo = LP_utxofinds ( iambob , txid , vout , txid2 , vout2 ) ) ! = 0 )
{
if ( 0 & & LP_ismine ( utxo ) = = 0 )
{
char str2 [ 65 ] , str3 [ 65 ] ; printf ( " iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s \n " , iambob , bits256_str ( str3 , pubkey ) , symbol , dstr ( value ) , dstr ( value2 ) , bits256_str ( str , txid ) , bits256_str ( str2 , txid2 ) ) ;
printf ( " duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f) \n " , dstr ( value ) , dstr ( value2 ) , dstr ( satoshis ) , dstr ( utxo - > payment . value ) , dstr ( utxo - > deposit . value ) , dstr ( utxo - > S . satoshis ) ) ;
}
u = ( utxo - > iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( bits256_cmp ( txid , utxo - > payment . txid ) ! = 0 | | bits256_cmp ( txid2 , u . txid ) ! = 0 | | vout ! = utxo - > payment . vout | | value ! = utxo - > payment . value | | satoshis ! = utxo - > S . satoshis | | vout2 ! = u . vout | | value2 ! = u . value | | strcmp ( symbol , utxo - > coin ) ! = 0 | | strcmp ( coinaddr , utxo - > coinaddr ) ! = 0 | | bits256_cmp ( pubkey , utxo - > pubkey ) ! = 0 )
{
utxo - > T . errors + + ;
char str [ 65 ] , str2 [ 65 ] , str3 [ 65 ] , str4 [ 65 ] , str5 [ 65 ] , str6 [ 65 ] ;
if ( utxo - > T . spentflag ! = 0 | | LP_txvalue ( 0 , utxo - > coin , utxo - > payment . txid , utxo - > payment . vout ) < utxo - > payment . value | | LP_txvalue ( 0 , utxo - > coin , u . txid , u . vout ) < u . value )
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
printf ( " original utxo pair not valid \n " ) ;
if ( dispflag ! = 0 )
printf ( " error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s) \n " , iambob , dstr ( val ) , dstr ( val2 ) , bits256_str ( str , txid ) , bits256_str ( str2 , txid2 ) , bits256_str ( str3 , utxo - > payment . txid ) , bits256_str ( str4 , utxo - > deposit . txid ) , bits256_cmp ( txid , utxo - > payment . txid ) ! = 0 , bits256_cmp ( txid2 , u . txid ) ! = 0 , vout ! = utxo - > payment . vout , satoshis ! = utxo - > S . satoshis , vout2 ! = u . vout , value2 ! = u . value , strcmp ( symbol , utxo - > coin ) ! = 0 , strcmp ( coinaddr , utxo - > coinaddr ) ! = 0 , bits256_cmp ( pubkey , utxo - > pubkey ) ! = 0 , value ! = utxo - > payment . value , bits256_str ( str5 , pubkey ) , bits256_str ( str6 , utxo - > pubkey ) ) ;
utxo = 0 ;
}
}
if ( utxo ! = 0 )
{
if ( utxo - > T . sessionid = = 0 )
utxo - > T . sessionid = sessionid ;
//else if ( profitmargin > SMALLVAL )
// utxo->S.profitmargin = profitmargin;
utxo - > T . lasttime = ( uint32_t ) time ( NULL ) ;
//printf("return existing utxo[%d] %s %s\n",iambob,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid));
return ( utxo ) ;
}
}
utxo = calloc ( 1 , sizeof ( * utxo ) ) ;
//utxo->S.profitmargin = profitmargin;
utxo - > pubkey = pubkey ;
safecopy ( utxo - > gui , gui , sizeof ( utxo - > gui ) ) ;
safecopy ( utxo - > coin , symbol , sizeof ( utxo - > coin ) ) ;
safecopy ( utxo - > coinaddr , coinaddr , sizeof ( utxo - > coinaddr ) ) ;
//safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript));
utxo - > payment . txid = txid ;
utxo - > payment . vout = vout ;
utxo - > payment . value = value ;
utxo - > S . satoshis = satoshis ;
if ( ( utxo - > iambob = iambob ) ! = 0 )
{
utxo - > deposit . txid = txid2 ;
utxo - > deposit . vout = vout2 ;
utxo - > deposit . value = value2 ;
}
else
{
utxo - > fee . txid = txid2 ;
utxo - > fee . vout = vout2 ;
utxo - > fee . value = value2 ;
}
LP_utxosetkey ( utxo - > key , txid , vout ) ;
LP_utxosetkey ( utxo - > key2 , txid2 , vout2 ) ;
if ( LP_ismine ( utxo ) > 0 )
utxo - > T . sessionid = G . LP_sessionid ;
else utxo - > T . sessionid = sessionid ;
if ( coin - > inactive = = 0 & & ( selector = LP_mempool_vinscan ( & spendtxid , & spendvini , symbol , coinaddr , txid , vout , txid2 , vout2 ) ) > = 0 )
{
printf ( " utxoadd selector.%d spent in mempool %s vini.%d " , selector , bits256_str ( str , spendtxid ) , spendvini ) ;
utxo - > T . spentflag = ( uint32_t ) time ( NULL ) ;
}
//printf(" %s %.8f %.8f %p addutxo.%d (%s %s) session.%u iambob.%d <<<<<<<<<<<<<<< %.8f\n",symbol,dstr(value),dstr(value2),utxo,LP_ismine(utxo) > 0,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid),utxo->T.sessionid,iambob,dstr(satoshis));
portable_mutex_lock ( & LP_utxomutex ) ;
HASH_ADD_KEYPTR ( hh , G . LP_utxoinfos [ iambob ] , utxo - > key , sizeof ( utxo - > key ) , utxo ) ;
if ( _LP_utxo2find ( iambob , txid2 , vout2 ) = = 0 )
HASH_ADD_KEYPTR ( hh2 , G . LP_utxoinfos2 [ iambob ] , utxo - > key2 , sizeof ( utxo - > key2 ) , utxo ) ;
portable_mutex_unlock ( & LP_utxomutex ) ;
if ( iambob ! = 0 )
{
if ( LP_ismine ( utxo ) > 0 )
{
//LP_utxo_clientpublish(utxo);
if ( LP_mypeer ! = 0 )
utxo - > T . lasttime = ( uint32_t ) time ( NULL ) ;
}
}
return ( utxo ) ;
}
int32_t _LP_utxos_remove ( bits256 txid , int32_t vout )
{
struct LP_utxoinfo * utxo , * utxo2 ; int32_t retval = 0 , iambob = 1 ;
utxo = utxo2 = 0 ;
if ( ( utxo = _LP_utxofind ( iambob , txid , vout ) ) ! = 0 )
{
if ( LP_isavailable ( utxo ) = = 0 )
retval = - 1 ;
else
{
if ( ( utxo2 = _LP_utxo2find ( iambob , txid , vout ) ) ! = 0 )
{
if ( LP_isavailable ( utxo ) = = 0 )
retval = - 1 ;
else
{
_LP_utxo_delete ( iambob , utxo ) ;
_LP_utxo2_delete ( iambob , utxo2 ) ;
}
}
}
}
else if ( ( utxo2 = _LP_utxo2find ( iambob , txid , vout ) ) ! = 0 )
{
if ( LP_isavailable ( utxo2 ) = = 0 )
retval = - 1 ;
else _LP_utxo2_delete ( iambob , utxo2 ) ;
}
return ( retval ) ;
}
int32_t LP_utxos_remove ( bits256 txid , int32_t vout )
{
int32_t retval ;
portable_mutex_lock ( & LP_utxomutex ) ;
retval = _LP_utxos_remove ( txid , vout ) ;
portable_mutex_unlock ( & LP_utxomutex ) ;
return ( retval ) ;
}
cJSON * LP_inventory ( char * symbol )
{
struct LP_utxoinfo * utxo , * tmp ; struct _LP_utxoinfo u ; char * myipaddr ; cJSON * array ; uint64_t val , val2 ; int32_t iambob = 0 ; struct iguana_info * coin ;
array = cJSON_CreateArray ( ) ;
if ( LP_mypeer ! = 0 )
myipaddr = LP_mypeer - > ipaddr ;
else myipaddr = " 127.0.0.1 " ;
if ( ( coin = LP_coinfind ( symbol ) ) ! = 0 )
LP_listunspent_both ( symbol , coin - > smartaddr , 0 ) ;
HASH_ITER ( hh , G . LP_utxoinfos [ iambob ] , utxo , tmp )
{
char str [ 65 ] ;
//printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519));
if ( LP_isunspent ( utxo ) ! = 0 & & strcmp ( symbol , utxo - > coin ) = = 0 & & utxo - > iambob = = iambob & & LP_ismine ( utxo ) > 0 )
{
u = ( iambob ! = 0 ) ? utxo - > deposit : utxo - > fee ;
if ( LP_iseligible ( & val , & val2 , iambob , utxo - > coin , utxo - > payment . txid , utxo - > payment . vout , utxo - > S . satoshis , u . txid , u . vout ) = = 0 )
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
//printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2));
continue ;
}
//if ( iambob != 0 )
// LP_utxo_clientpublish(utxo);
jaddi ( array , LP_inventoryjson ( cJSON_CreateObject ( ) , utxo ) ) ;
}
else if ( 0 & & LP_ismine ( utxo ) > 0 & & strcmp ( symbol , utxo - > coin ) = = 0 )
printf ( " skip %s %s %d %d %d %d \n " , utxo - > coin , bits256_str ( str , utxo - > payment . txid ) , LP_isunspent ( utxo ) ! = 0 , strcmp ( symbol , utxo - > coin ) = = 0 , utxo - > iambob = = iambob , LP_ismine ( utxo ) > 0 ) ;
}
return ( array ) ;
}
/*while ( time(NULL) < expiration )
{
if ( ( price = LP_pricecache ( qp , qp - > srccoin , qp - > destcoin , qp - > txid , qp - > vout ) ) > SMALLVAL )
{
printf ( " break out of price %.8f %s/%s \n " , price , qp - > srccoin , qp - > destcoin ) ;
break ;
}
sleep ( 1 ) ;
} */
//struct LP_pubkey_info *pubp,*ptmp; //cJSON *retjson; struct iguana_info *coin,*tmp;
/*HASH_ITER(hh,LP_coins,coin,tmp) // firstrefht,firstscanht,lastscanht
{
if ( coin - > electrum ! = 0 & & time ( NULL ) > coin - > lastunspent + 30 )
{
//printf("call electrum listunspent.%s\n",coin->symbol);
if ( ( retjson = electrum_address_listunspent ( coin - > symbol , coin - > electrum , & retjson , coin - > smartaddr , 2 ) ) ! = 0 )
free_json ( retjson ) ;
coin - > lastunspent = ( uint32_t ) time ( NULL ) ;
}
} */
/*HASH_ITER(hh,LP_pubkeyinfos,pubp,ptmp)
{
pubp - > dynamictrust = LP_dynamictrust ( pubp - > pubkey , 0 ) ;
} */
/*void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj)
{
struct LP_pubkey_info * pubp ; struct LP_priceinfo * basepp , * relpp ; uint32_t timestamp ; bits256 pubkey ; cJSON * asks , * item ; uint8_t rmd160 [ 20 ] ; int32_t i , n , relid , mismatch ; char * base , * rel , * hexstr ; double askprice ; uint32_t now ;
now = ( uint32_t ) time ( NULL ) ;
pubkey = jbits256 ( obj , " pubkey " ) ;
if ( bits256_nonz ( pubkey ) ! = 0 & & ( pubp = LP_pubkeyadd ( pubkey ) ) ! = 0 )
{
if ( ( hexstr = jstr ( obj , " rmd160 " ) ) ! = 0 & & strlen ( hexstr ) = = 2 * sizeof ( rmd160 ) )
decode_hex ( rmd160 , sizeof ( rmd160 ) , hexstr ) ;
if ( memcmp ( pubp - > rmd160 , rmd160 , sizeof ( rmd160 ) ) ! = 0 )
mismatch = 1 ;
else mismatch = 0 ;
if ( bits256_cmp ( pubkey , G . LP_mypub25519 ) = = 0 & & mismatch = = 0 )
peer - > needping = 0 ;
LP_pubkey_sigcheck ( pubp , obj ) ;
timestamp = juint ( obj , " timestamp " ) ;
if ( timestamp > now )
timestamp = now ;
if ( timestamp > = pubp - > timestamp & & ( asks = jarray ( & n , obj , " asks " ) ) ! = 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( asks , i ) ;
base = jstri ( item , 0 ) ;
rel = jstri ( item , 1 ) ;
askprice = jdoublei ( item , 2 ) ;
if ( LP_pricevalid ( askprice ) > 0 )
{
if ( ( basepp = LP_priceinfoptr ( & relid , base , rel ) ) ! = 0 )
{
//char str[65]; printf("gotprice %s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice);
pubp - > matrix [ basepp - > ind ] [ relid ] = askprice ;
//pubp->timestamps[basepp->ind][relid] = timestamp;
if ( ( relpp = LP_priceinfofind ( rel ) ) ! = 0 )
{
dxblend ( & basepp - > relvals [ relpp - > ind ] , askprice , 0.9 ) ;
dxblend ( & relpp - > relvals [ basepp - > ind ] , 1. / askprice , 0.9 ) ;
}
}
}
}
}
}
}
void LP_peer_pricesquery ( struct LP_peerinfo * peer )
{
char * retstr ; cJSON * array ; int32_t i , n ;
if ( strcmp ( peer - > ipaddr , LP_myipaddr ) = = 0 )
return ;
peer - > needping = ( uint32_t ) time ( NULL ) ;
if ( ( retstr = issue_LP_getprices ( peer - > ipaddr , peer - > port ) ) ! = 0 )
{
if ( ( array = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( is_cJSON_Array ( array ) & & ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
LP_prices_parse ( peer , jitem ( array , i ) ) ;
}
free_json ( array ) ;
}
free ( retstr ) ;
}
if ( peer - > needping ! = 0 )
{
//printf("%s needs ping\n",peer->ipaddr);
}
} */
if ( aliceutxo - > S . swap = = 0 )
LP_availableset ( aliceutxo ) ;
return ( jprint ( bestitem , 0 ) ) ;
}
if ( 0 & & ( retstr = issue_LP_listunspent ( peer - > ipaddr , peer - > port , coin - > symbol , " " ) ) ! = 0 )
{
if ( ( array2 = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( m = cJSON_GetArraySize ( array2 ) ) > 0 )
{
for ( j = 0 ; j < m ; j + + )
{
item = jitem ( array2 , j ) ;
if ( ( coinaddr = jfieldname ( item ) ) ! = 0 )
{
metric = j64bits ( item , coinaddr ) ;
//printf("(%s) -> %.8f n.%d\n",coinaddr,dstr(metric>>16),(uint16_t)metric);
if ( ( ap = LP_addressfind ( coin , coinaddr ) ) = = 0 | | _LP_unspents_metric ( ap - > total , ap - > n ) ! = metric )
{
if ( ap = = 0 | | ap - > n < ( metric & 0xffff ) )
{
if ( ( retstr2 = issue_LP_listunspent ( peer - > ipaddr , peer - > port , coin - > symbol , coinaddr ) ) ! = 0 )
{
if ( ( array3 = cJSON_Parse ( retstr2 ) ) ! = 0 )
{
LP_unspents_array ( coin , coinaddr , array3 ) ;
//printf("pulled.(%s)\n",retstr2);
free_json ( array3 ) ;
}
free ( retstr2 ) ;
}
} //else printf("wait for %s to pull %d vs %d\n",peer->ipaddr,ap!=0?ap->n:-1,(uint16_t)metric);
}
}
}
}
free_json ( array2 ) ;
}
//printf("processed.(%s)\n",retstr);
free ( retstr ) ;
}
/*if ( time(NULL) > coin->lastmonitor+60 )
{
//portable_mutex_lock(&coin->addrmutex);
HASH_ITER ( hh , coin - > addresses , ap , atmp )
{
if ( coin - > electrum = = 0 )
{
LP_listunspent_issue ( coin - > symbol , ap - > coinaddr ) ;
DL_FOREACH_SAFE ( ap - > utxos , up , utmp )
{
if ( up - > spendheight < = 0 )
{
if ( LP_txvalue ( 0 , coin - > symbol , up - > U . txid , up - > U . vout ) = = 0 )
up - > spendheight = 1 ;
}
}
}
}
//portable_mutex_unlock(&coin->addrmutex);
coin - > lastmonitor = ( uint32_t ) time ( NULL ) ;
} */
/*cJSON *LP_tradecandidates(char *base)
{
struct LP_peerinfo * peer , * tmp ; struct LP_quoteinfo Q ; char * utxostr , coinstr [ 16 ] ; cJSON * array , * retarray = 0 , * item ; int32_t i , n , totaladded , added ;
totaladded = 0 ;
HASH_ITER ( hh , LP_peerinfos , peer , tmp )
{
printf ( " %s:%u %s \n " , peer - > ipaddr , peer - > port , base ) ;
n = added = 0 ;
if ( ( utxostr = issue_LP_clientgetutxos ( peer - > ipaddr , peer - > port , base , 100 ) ) ! = 0 )
{
printf ( " %s:%u %s %s \n " , peer - > ipaddr , peer - > port , base , utxostr ) ;
if ( ( array = cJSON_Parse ( utxostr ) ) ! = 0 )
{
if ( is_cJSON_Array ( array ) ! = 0 & & ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
retarray = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
LP_quoteparse ( & Q , item ) ;
safecopy ( coinstr , jstr ( item , " base " ) , sizeof ( coinstr ) ) ;
if ( strcmp ( coinstr , base ) = = 0 )
{
if ( LP_iseligible ( 1 , Q . srccoin , Q . txid , Q . vout , Q . satoshis , Q . txid2 , Q . vout2 ) ! = 0 )
{
if ( LP_arrayfind ( retarray , Q . txid , Q . vout ) < 0 )
{
jaddi ( retarray , jduplicate ( item ) ) ;
added + + ;
totaladded + + ;
}
} else printf ( " ineligible.(%s) \n " , jprint ( item , 0 ) ) ;
}
}
}
free_json ( array ) ;
}
free ( utxostr ) ;
}
if ( n = = totaladded & & added = = 0 )
{
printf ( " n.%d totaladded.%d vs added.%d \n " , n , totaladded , added ) ;
break ;
}
}
return ( retarray ) ;
}
void LP_quotesinit ( char * base , char * rel )
{
cJSON * array , * item ; struct LP_quoteinfo Q ; bits256 zero ; int32_t i , n , iter ;
memset ( & zero , 0 , sizeof ( zero ) ) ;
for ( iter = 0 ; iter < 2 ; iter + + )
if ( ( array = LP_tradecandidates ( iter = = 0 ? base : rel ) ) ! = 0 )
{
//printf("candidates.(%s)\nn.%d\n",jprint(array,0),cJSON_GetArraySize(array));
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
memset ( & Q , 0 , sizeof ( Q ) ) ;
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
LP_quoteparse ( & Q , item ) ;
if ( iter = = 0 )
LP_query ( " price " , & Q , base , rel , zero ) ;
else LP_query ( " price " , & Q , rel , base , zero ) ;
}
}
free_json ( array ) ;
}
} */
/*else if ( LP_ismine(utxo) > 0 )
{
printf ( " iterate through all locally generated quotes and update, or change to price feed \n " ) ;
// jl777: iterated Q's
if ( strcmp ( utxo - > coin , " KMD " ) = = 0 )
LP_priceping ( pubsock , utxo , " BTC " , profitmargin ) ;
else LP_priceping ( pubsock , utxo , " KMD " , profitmargin ) ;
} */
/*if ( LP_txvalue(destaddr,symbol,searchtxid,searchvout) > 0 )
return ( 0 ) ;
if ( ( txobj = LP_gettx ( symbol , searchtxid ) ) = = 0 )
return ( 0 ) ;
hash = jbits256 ( txobj , " blockhash " ) ;
free_json ( txobj ) ;
if ( bits256_nonz ( hash ) = = 0 )
return ( 0 ) ;
if ( ( blockjson = LP_getblock ( symbol , hash ) ) = = 0 )
return ( 0 ) ;
loadheight = jint ( blockjson , " height " ) ;
free_json ( blockjson ) ;
if ( loadheight < = 0 )
return ( 0 ) ;
while ( errs = = 0 & & * indp < 0 )
{
//printf("search %s ht.%d\n",symbol,loadheight);
if ( ( blockjson = LP_blockjson ( & h , symbol , 0 , loadheight ) ) ! = 0 & & h = = loadheight )
{
if ( ( txids = jarray ( & numtxids , blockjson , " tx " ) ) ! = 0 )
{
for ( i = 0 ; i < numtxids ; i + + )
{
txid = jbits256 ( jitem ( txids , i ) , 0 ) ;
if ( ( j = LP_vinscan ( spendtxidp , indp , symbol , txid , searchtxid , searchvout , searchtxid , searchvout ) ) > = 0 )
break ;
}
}
free_json ( blockjson ) ;
} else errs + + ;
loadheight + + ;
}
char str [ 65 ] ; printf ( " reached %s ht.%d %s/v%d \n " , symbol , loadheight , bits256_str ( str , * spendtxidp ) , * indp ) ;
if ( bits256_nonz ( * spendtxidp ) ! = 0 & & * indp > = 0 )
return ( loadheight ) ;
else return ( 0 ) ; */
/*if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
mempooltxid = jbits256i ( array , i ) ;
if ( ( selector = LP_vinscan ( spendtxidp , spendvinp , symbol , mempooltxid , searchtxid , searchvout , searchtxid2 , searchvout2 ) ) > = 0 )
return ( selector ) ;
}
} */
/*int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout)
{
int32_t i ;
for ( i = 0 ; i < num ; i + + )
if ( ( array [ i ] - > vout = = vout & & bits256_cmp ( array [ i ] - > txid , txid ) = = 0 ) | | ( array [ i ] - > vout2 = = vout & & bits256_cmp ( array [ i ] - > txid2 , txid ) = = 0 ) )
return ( i ) ;
return ( - 1 ) ;
} */
//char str[65],str2[65]; printf("check utxo.%s/v%d from %s\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,utxo->pubkey));
//if ( strcmp(base,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && pubp != 0 && (price= pubp->matrix[baseid][relid]) > SMALLVAL )
//if ( polarity > 0 )
// minsatoshis = utxo->S.satoshis;
//else minsatoshis = utxo->S.satoshis * price;
/*if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 )
{
if ( LP_iseligible ( & val , & val2 , utxo - > iambob , utxo - > coin , utxo - > payment . txid , utxo - > payment . vout , utxo - > S . satoshis , utxo - > deposit . txid , utxo - > deposit . vout ) = = 0 )
continue ;
if ( polarity > 0 )
basesatoshis = utxo - > S . satoshis ;
else basesatoshis = utxo - > S . satoshis * price ;
//char str[65]; printf("found utxo not in orderbook %s/v%d %.8f %.8f\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(basesatoshis),polarity > 0 ? price : 1./price);
if ( ( op = LP_orderbookentry ( base , rel , utxo - > payment . txid , utxo - > payment . vout , utxo - > deposit . txid , utxo - > deposit . vout , polarity > 0 ? price : 1. / price , basesatoshis , utxo - > pubkey , now - pubp - > timestamp ) ) ! = 0 )
{
* arrayp = realloc ( * arrayp , sizeof ( * ( * arrayp ) ) * ( num + 1 ) ) ;
( * arrayp ) [ num + + ] = op ;
if ( LP_ismine ( utxo ) > 0 & & utxo - > T . lasttime = = 0 )
LP_utxo_clientpublish ( utxo ) ;
}
} */
void LP_price_broadcastloop ( void * ctx )
{
struct LP_priceinfo * basepp , * relpp ; double price ; int32_t baseind , relind ;
sleep ( 30 ) ;
while ( 1 )
{
for ( baseind = 0 ; baseind < LP_MAXPRICEINFOS ; baseind + + )
{
basepp = LP_priceinfo ( baseind ) ;
if ( basepp - > symbol [ 0 ] = = 0 )
continue ;
for ( relind = 0 ; relind < LP_MAXPRICEINFOS ; relind + + )
{
relpp = LP_priceinfo ( relind ) ;
if ( relpp - > symbol [ 0 ] = = 0 )
continue ;
if ( basepp ! = 0 & & relpp ! = 0 & & ( price = relpp - > myprices [ basepp - > ind ] ) > SMALLVAL )
{
//printf("automated price broadcast %s/%s %.8f\n",relpp->symbol,basepp->symbol,price);
LP_pricepings ( ctx , LP_myipaddr , LP_mypubsock , relpp - > symbol , basepp - > symbol , price ) ;
}
}
}
sleep ( LP_ORDERBOOK_DURATION * .9 ) ;
}
}
/*if ( expiration != 0 )
{
redeemlen = LP_deposit_addr ( vinaddr , redeemscript , coin - > taddr , coin - > p2shtype , expiration , G . LP_pubsecp ) ;
if ( strcmp ( depositaddr , vinaddr ) = = 0 )
{
claimtime = ( uint32_t ) time ( NULL ) - 777 ;
if ( claimtime < = expiration )
{
printf ( " claimtime.%u vs locktime.%u, need to wait %d seconds \n " , claimtime , timestamp , ( int32_t ) timestamp - claimtime ) ;
return ( clonestr ( " { \" error \" : \" need to wait to claim \" } " ) ) ;
}
sum + = LP_claimtx ( ctx , coin , txids , utxotxid , utxovout , satoshis , vinaddr , claimtime , redeemscript , redeemlen ) ;
} */
/*timestamp = (now / LP_WEEKMULT) * LP_WEEKMULT + LP_WEEKMULT;
while ( timestamp > LP_FIRSTWEEKTIME )
{
if ( expiration ! = 0 )
timestamp = expiration ;
else timestamp - = LP_WEEKMULT ;
redeemlen = LP_deposit_addr ( vinaddr , redeemscript , coin - > taddr , coin - > p2shtype , timestamp , G . LP_pubsecp ) ;
if ( strcmp ( depositaddr , vinaddr ) = = 0 )
{
claimtime = ( uint32_t ) time ( NULL ) - 777 ;
if ( claimtime < = timestamp )
{
printf ( " claimtime.%u vs locktime.%u, need to wait %d seconds \n " , claimtime , timestamp , ( int32_t ) timestamp - claimtime ) ;
}
else
{
printf ( " found %s at timestamp.%u \n " , vinaddr , timestamp ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
if ( ( array = LP_listunspent ( coin - > symbol , vinaddr , zero , zero ) ) ! = 0 )
{
//printf("unspents.(%s)\n",jprint(array,0));
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
satoshis = LP_listunspent_parseitem ( coin , & utxotxid , & utxovout , & height , item ) ;
sum + = LP_claimtx ( ctx , coin , txids , utxotxid , utxovout , satoshis , vinaddr , claimtime , redeemscript , redeemlen ) ;
}
}
free_json ( array ) ;
retjson = cJSON_CreateObject ( ) ;
jaddstr ( retjson , " result " , " success " ) ;
jaddnum ( retjson , " claimed " , dstr ( sum ) ) ;
jadd ( retjson , " txids " , txids ) ;
return ( jprint ( retjson , 1 ) ) ;
}
}
}
if ( expiration ! = 0 )
break ;
}
return ( clonestr ( " { \" error \" : \" no instantdex deposits to claim \" } " ) ) ; */
/*else
{
if ( ( array = LP_address_utxos ( coin , coinaddr , 1 ) ) ! = 0 )
{
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
balance + = j64bits ( item , " value " ) ;
}
}
free_json ( array ) ;
}
} */
//else if ( strcmp(method,"checktxid") == 0 )
// retstr = LP_spentcheck(argjson);
//else if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
// return(clonestr("{\"result\":\"at least one of coins disabled\"}"));
//else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 )
// retstr = clonestr("{\"result\":\"coin is disabled\"}");
/*if ( strcmp(method,"broadcast") == 0 )
{
bits256 zero ; char * cipherstr ; int32_t cipherlen ; uint8_t cipher [ LP_ENCRYPTED_MAXSIZE ] ;
if ( ( reqjson = LP_dereference ( argjson , " broadcast " ) ) ! = 0 )
{
Broadcaststr = jprint ( reqjson , 0 ) ;
if ( ( cipherstr = jstr ( reqjson , " cipher " ) ) ! = 0 )
{
cipherlen = ( int32_t ) strlen ( cipherstr ) > > 1 ;
if ( cipherlen < = sizeof ( cipher ) )
{
decode_hex ( cipher , cipherlen , cipherstr ) ;
LP_queuesend ( calc_crc32 ( 0 , & cipher [ 2 ] , cipherlen - 2 ) , LP_mypubsock , base , rel , cipher , cipherlen ) ;
} else retstr = clonestr ( " { \" error \" : \" cipher too big \" } " ) ;
}
else
{
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
//printf("broadcast.(%s)\n",Broadcaststr);
LP_reserved_msg ( base ! = 0 ? base : jstr ( argjson , " coin " ) , rel , zero , jprint ( reqjson , 0 ) ) ;
}
retstr = clonestr ( " { \" result \" : \" success \" } " ) ;
} else retstr = clonestr ( " { \" error \" : \" couldnt dereference sendmessage \" } " ) ;
}
else */
/*relvol = bot->totalrelvolume * .1;
p = LP_pricevol_invert ( & v , bot - > maxprice , relvol ) ;
if ( bot - > dispdir > 0 )
{
printf ( " simulated trade buy %s/%s maxprice %.8f volume %.8f, %.8f %s -> %s, price %.8f relvol %.8f \n " , bot - > base , bot - > rel , bot - > maxprice , bot - > totalrelvolume - bot - > relsum , relvol , bot - > rel , bot - > base , bot - > maxprice , relvol ) ;
}
else
{
minprice = LP_pricevol_invert ( & basevol , bot - > maxprice , bot - > totalrelvolume - bot - > relsum ) ;
printf ( " simulated trade sell %s/%s minprice %.8f volume %.8f, %.8f %s -> %s price %.8f relvol %.8f \n " , bot - > rel , bot - > base , minprice , basevol , v , bot - > base , bot - > rel , p , relvol ) ;
}
if ( ( LP_rand ( ) % 2 ) = = 0 )
{
bot - > relsum + = relvol ;
bot - > basesum + = v ;
bot - > completed + + ;
}
else
{
bot - > pendrelsum + = relvol ;
bot - > pendbasesum + = v ;
bot - > numpending + + ;
}
bot - > numtrades + + ;
*/
# ifdef FROM_JS
int32_t sentbytes , sock , peerind , maxind ;
if ( ( maxind = LP_numpeers ( ) ) > 0 )
peerind = ( LP_rand ( ) % maxind ) + 1 ;
else peerind = 1 ;
sock = LP_peerindsock ( & peerind ) ;
if ( sock > = 0 )
{
if ( ( sentbytes = nn_send ( sock , msg , msglen , 0 ) ) ! = msglen )
printf ( " LP_send sent %d instead of %d \n " , sentbytes , msglen ) ;
else printf ( " sent %d bytes of %d to sock.%d \n " , sentbytes , msglen , sock ) ;
} else printf ( " couldnt get valid sock \n " ) ;
# else
void _LP_queuesend ( uint32_t crc32 , int32_t sock0 , int32_t sock1 , uint8_t * msg , int32_t msglen , int32_t needack )
{
int32_t maxind , peerind = 0 ; //sentbytes,
if ( sock0 > = 0 | | sock1 > = 0 )
{
/* if ( sock0 >= 0 && LP_sockcheck(sock0) > 0 )
{
if ( ( sentbytes = nn_send ( sock0 , msg , msglen , 0 ) ) ! = msglen )
printf ( " _LP_queuesend0 sent %d instead of %d \n " , sentbytes , msglen ) ;
else
{
printf ( " Q sent %u msglen.%d (%s) \n " , crc32 , msglen , msg ) ;
sock0 = - 1 ;
}
}
if ( sock1 > = 0 & & LP_sockcheck ( sock1 ) > 0 )
{
if ( ( sentbytes = nn_send ( sock1 , msg , msglen , 0 ) ) ! = msglen )
printf ( " _LP_queuesend1 sent %d instead of %d \n " , sentbytes , msglen ) ;
else
{
printf ( " Q sent1 %u msglen.%d (%s) \n " , crc32 , msglen , msg ) ;
sock1 = - 1 ;
}
}
if ( sock0 < 0 & & sock1 < 0 )
return ; */
}
else
{
if ( ( maxind = LP_numpeers ( ) ) > 0 )
peerind = ( LP_rand ( ) % maxind ) + 1 ;
else peerind = 1 ;
sock0 = LP_peerindsock ( & peerind ) ;
if ( ( maxind = LP_numpeers ( ) ) > 0 )
peerind = ( LP_rand ( ) % maxind ) + 1 ;
else peerind = 1 ;
sock1 = LP_peerindsock ( & peerind ) ;
}
if ( sock0 > = 0 )
_LP_sendqueueadd ( crc32 , sock0 , msg , msglen , needack * peerind ) ;
if ( sock1 > = 0 )
_LP_sendqueueadd ( crc32 , sock1 , msg , msglen , needack ) ;
}
if ( 0 & & OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_price_broadcastloop , ( void * ) ctx ) ! = 0 )
{
printf ( " error launching LP_swapsloop for port.%u \n " , myport ) ;
exit ( - 1 ) ;
}
void LP_queuesend ( uint32_t crc32 , int32_t pubsock , char * base , char * rel , uint8_t * msg , int32_t msglen )
{
//struct iguana_info *coin; int32_t flag=0,socks[2];
portable_mutex_lock ( & LP_networkmutex ) ;
if ( pubsock > = 0 )
{
//socks[0] = socks[1] = -1;
//if ( rel != 0 && rel[0] != 0 && (coin= LP_coinfind(rel)) != 0 && coin->bussock >= 0 )
// socks[flag++] = coin->bussock;
//if ( base != 0 && base[0] != 0 && (coin= LP_coinfind(base)) != 0 && coin->bussock >= 0 )
// socks[flag++] = coin->bussock;
//if ( flag == 0 && pubsock >= 0 )
_LP_queuesend ( crc32 , pubsock , - 1 , msg , msglen , 0 ) ;
//else _LP_queuesend(socks[0],socks[1],msg,msglen,0);
} else _LP_queuesend ( crc32 , - 1 , - 1 , msg , msglen , 1 ) ;
portable_mutex_unlock ( & LP_networkmutex ) ;
}
# ifdef oldway
struct LP_utxoinfo * LP_bestutxo ( double * ordermatchpricep , int64_t * bestsatoshisp , int64_t * bestdestsatoshisp , struct LP_utxoinfo * autxo , char * base , double maxprice , int32_t duration , uint64_t txfee , uint64_t desttxfee , uint64_t maxdestsatoshis )
{
int64_t satoshis , destsatoshis ; uint64_t val , val2 ; bits256 txid , pubkey ; char * obookstr ; cJSON * orderbook , * asks , * item ; struct LP_utxoinfo * butxo , * bestutxo = 0 ; int32_t i , n , j , vout , numasks ; double bestmetric = 0. , metric , vol , price , qprice , bestprice = 0. ; struct LP_pubkeyinfo * pubp ;
* ordermatchpricep = 0. ;
* bestsatoshisp = * bestdestsatoshisp = 0 ;
if ( duration < = 0 )
duration = LP_ORDERBOOK_DURATION ;
if ( maxprice < = 0. | | LP_priceinfofind ( base ) = = 0 )
return ( 0 ) ;
LP_txfees ( & txfee , & desttxfee , base , autxo - > coin ) ;
if ( ( obookstr = LP_orderbook ( base , autxo - > coin , duration ) ) ! = 0 )
{
if ( ( orderbook = cJSON_Parse ( obookstr ) ) ! = 0 )
{
if ( ( asks = jarray ( & numasks , orderbook , " asks " ) ) ! = 0 )
{
for ( i = 0 ; i < numasks ; i + + )
{
item = jitem ( asks , i ) ;
price = jdouble ( item , " price " ) ;
if ( LP_pricevalid ( price ) > 0 & & price < = maxprice )
{
//price *= 1.0001;
//if ( price > maxprice )
// price = maxprice;
pubkey = jbits256 ( item , " pubkey " ) ;
if ( bits256_cmp ( pubkey , LP_mypub25519 ) ! = 0 & & ( pubp = LP_pubkeyadd ( pubkey ) ) ! = 0 & & pubp - > numerrors < LP_MAXPUBKEY_ERRORS )
{
if ( bestprice = = 0. ) // assumes price ordered asks
bestprice = price ;
printf ( " item.[%d] %s \n " , i , jprint ( item , 0 ) ) ;
txid = jbits256 ( item , " txid " ) ;
vout = jint ( item , " vout " ) ;
vol = jdouble ( item , " volume " ) ;
metric = price / bestprice ;
printf ( " maxdest %.8f metric %f vol %f add pings numutxos.%d min %.8f max %.8f \n " , dstr ( maxdestsatoshis ) , metric , vol , jint ( item , " numutxos " ) , jdouble ( item , " minvolume " ) , jdouble ( item , " maxvolume " ) ) ;
// check utxos > 1 for pubkey, SPV validate recv'ed
/*if ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 && butxo->T.bestflag == 0 )
{
printf ( " got butxo? %p \n " , butxo ) ;
if ( LP_iseligible ( & val , & val2 , butxo - > iambob , butxo - > coin , butxo - > payment . txid , butxo - > payment . vout , butxo - > S . satoshis , butxo - > deposit . txid , butxo - > deposit . vout ) > 0 )
{
destsatoshis = ( ( butxo - > S . satoshis - txfee ) * price ) ;
satoshis = ( destsatoshis / price + 0.49 ) - txfee ;
if ( satoshis < = 0 )
continue ;
qprice = ( double ) destsatoshis / satoshis ;
n = ( int32_t ) ( ( double ) destsatoshis / desttxfee ) ;
if ( n < 10 )
n = 10 ;
else n = 3 ;
for ( j = 0 ; j < n ; j + + )
{
if ( ( qprice = LP_qprice_calc ( & destsatoshis , & satoshis , ( price * ( 100. + j ) ) / 100. , butxo - > S . satoshis , txfee , autxo - > payment . value , maxdestsatoshis , desttxfee ) ) > price + SMALLVAL )
break ;
}
//printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis));
if ( metric < 1.2 & & destsatoshis > desttxfee & & destsatoshis - desttxfee > ( autxo - > payment . value / LP_MINCLIENTVOL ) & & satoshis - txfee > ( butxo - > S . satoshis / LP_MINVOL ) & & satoshis < = butxo - > payment . value - txfee )
{
printf ( " value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f) \n " , dstr ( autxo - > payment . value ) , price , bestprice , bestmetric , dstr ( destsatoshis ) , metric , dstr ( destsatoshis ) * metric * metric * metric ) ;
metric = dstr ( destsatoshis ) * metric * metric * metric ;
if ( bestmetric = = 0. | | metric < bestmetric )
{
bestutxo = butxo ;
* ordermatchpricep = price ;
* bestdestsatoshisp = destsatoshis ;
* bestsatoshisp = satoshis ;
bestmetric = metric ;
printf ( " set best! \n " ) ;
}
} // else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis / LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis));
}
else
{
printf ( " ineligible.(%.8f %.8f) \n " , price , dstr ( butxo - > S . satoshis ) ) ;
//if ( butxo->T.spentflag == 0 )
// butxo->T.spentflag = (uint32_t)time(NULL);
}
}
else
{
if ( butxo ! = 0 )
printf ( " %llu %llu %d %d %d: " , ( long long ) ( vol * SATOSHIDEN ) , ( long long ) butxo - > S . satoshis , vol * SATOSHIDEN = = butxo - > S . satoshis , LP_isavailable ( butxo ) > 0 , LP_ismine ( butxo ) = = 0 ) ;
printf ( " cant find butxo.%p or value mismatch %.8f != %.8f or bestflag.%d \n " , butxo , vol , butxo ! = 0 ? dstr ( butxo - > S . satoshis ) : 0 , butxo - > T . bestflag ) ;
} */
} else printf ( " self trading or blacklisted peer \n " ) ;
}
else
{
if ( i = = 0 )
printf ( " maxprice %.8f vs %.8f \n " , maxprice , price ) ;
break ;
}
}
if ( bestutxo = = 0 )
{
int32_t numrestraints ;
for ( i = numrestraints = 0 ; i < numasks ; i + + )
{
item = jitem ( asks , i ) ;
pubkey = jbits256 ( item , " pubkey " ) ;
if ( bits256_cmp ( pubkey , LP_mypub25519 ) ! = 0 & & ( pubp = LP_pubkeyadd ( pubkey ) ) ! = 0 )
{
txid = jbits256 ( item , " txid " ) ;
vout = jint ( item , " vout " ) ;
if ( ( butxo = LP_utxofind ( 1 , txid , vout ) ) ! = 0 )
{
numrestraints + + ;
butxo - > T . bestflag = 0 ;
//pubp->numerrors = 0;
}
}
}
printf ( " no bob utxo found -> cleared %d restraints \n " , numrestraints ) ;
}
}
free_json ( orderbook ) ;
}
free ( obookstr ) ;
}
printf ( " bestutxo.%p %.8f %.8f \n " , bestutxo , * ordermatchpricep , dstr ( * bestdestsatoshisp ) ) ;
if ( bestutxo = = 0 | | * ordermatchpricep = = 0. | | * bestdestsatoshisp = = 0 )
return ( 0 ) ;
bestutxo - > T . bestflag = 1 ;
int32_t changed ;
LP_mypriceset ( & changed , autxo - > coin , base , 1. / * ordermatchpricep ) ;
return ( bestutxo ) ;
}
if ( ( 0 ) )
{
ep = LP_electrum_info ( & already , " BTC " , " 88.198.241.196 " , 50001 , IGUANA_MAXPACKETSIZE * 10 ) ;
if ( ep ! = 0 & & OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_dedicatedloop , ( void * ) ep ) ! = 0 )
{
printf ( " error launching LP_dedicatedloop (%s:%u) \n " , ep - > ipaddr , ep - > port ) ;
exit ( - 1 ) ;
} else printf ( " launched.(%s:%u) \n " , ep - > ipaddr , ep - > port ) ;
electrum_test ( ) ;
}
/*static int _LP_metric_eval(const void *a,const void *b)
{
# define aptr (*(struct LP_metricinfo **)a)
# define bptr (*(struct LP_metricinfo **)b)
if ( bptr - > metric > aptr - > metric )
return ( 1 ) ;
else if ( bptr - > metric < aptr - > metric )
return ( - 1 ) ;
return ( 0 ) ;
# undef aptr
# undef bptr
} */
/*if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0,targetval)) != 0 )
{
utxo - > S . satoshis = targetval ;
char str [ 65 ] , str2 [ 65 ] ; printf ( " butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s \n " , utxo , dstr ( targetval ) , dstr ( up - > U . value ) , bits256_str ( str , utxo - > payment . txid ) , dstr ( targetval2 ) , dstr ( up2 - > U . value ) , bits256_str ( str2 , utxo - > deposit . txid ) ) ;
return ( butxo ) ;
} */
/*if ( (sobj= jobj(v,"scriptPubKey")) != 0 )
{
if ( ( scriptstr = jstr ( sobj , " hex " ) ) ! = 0 )
{
printf ( " amount64 %.8f vout.%d (%s) weeki.%d %.8f (%s) \n " , dstr ( amount64 ) , vout , jprint ( v , 0 ) , weeki , dstr ( satoshis ) , scriptstr ) ;
len = ( int32_t ) strlen ( scriptstr ) > > 1 ;
if ( len < = sizeof ( spendscript ) / sizeof ( * spendscript ) )
{
decode_hex ( spendscript , len , scriptstr ) ;
if ( spendscript [ 11 ] = = 33 )
{
pub33 = & spendscript [ 12 ] ;
redeemlen = LP_deposit_addr ( p2shaddr , redeemscript , coin - > taddr , coin - > p2shtype , timestamp , pub33 ) ;
if ( len = = redeemlen & & ( timestamp % LP_WEEKMULT ) = = 0 )
{
bitcoin_address ( coinaddr , coin - > taddr , coin - > pubtype , pub33 , 33 ) ;
printf ( " %s -> matched %s script t.%u weeki.%d deposit %.8f \n " , coinaddr , p2shaddr , timestamp , ( timestamp - LP_FIRSTWEEKTIME ) / LP_WEEKMULT , dstr ( satoshis ) ) ;
// add to pubp->credits;
}
}
}
}
} */
/*portable_mutex_lock(&ep->pendingQ.mutex);
if ( ep - > pendingQ . list ! = 0 )
{
printf ( " list %p \n " , ep - > pendingQ . list ) ;
DL_FOREACH_SAFE ( ep - > pendingQ . list , item , tmp )
{
printf ( " item.%p \n " , item ) ;
if ( item - > type = = 0xffffffff )
{
printf ( " %p purge %s " , item , ( ( struct stritem * ) item ) - > str ) ;
DL_DELETE ( ep - > pendingQ . list , item ) ;
free ( item ) ;
}
}
}
DL_APPEND ( ep - > pendingQ . list , & sitem - > DL ) ;
portable_mutex_unlock ( & ep - > pendingQ . mutex ) ; */
//printf("%p SENT.(%s) to %s:%u\n",sitem,sitem->str,ep->ipaddr,ep->port);
# ifdef oldway
struct LP_utxoinfo * LP_ordermatch_iter ( struct LP_address_utxo * * utxos , int32_t max , double * ordermatchpricep , int64_t * bestsatoshisp , int64_t * bestdestsatoshisp , struct iguana_info * basecoin , char * coinaddr , uint64_t asatoshis , double price , uint64_t txfee , uint64_t desttxfee , bits256 pubkey , char * gui )
{
uint64_t basesatoshis ; struct LP_utxoinfo * bestutxo ;
basesatoshis = LP_basesatoshis ( dstr ( asatoshis ) , price , txfee , desttxfee ) ;
//printf("basesatoshis %.8f price %.8f txfee %.8f desttxfee %.8f\n",dstr(basesatoshis),price,dstr(txfee),dstr(desttxfee));
if ( basesatoshis ! = 0 & & ( bestutxo = LP_address_utxopair ( 0 , utxos , max , basecoin , coinaddr , txfee , dstr ( basesatoshis ) * price , price , desttxfee ) ) ! = 0 )
{
bestutxo - > pubkey = pubkey ;
safecopy ( bestutxo - > gui , gui , sizeof ( bestutxo - > gui ) ) ;
* bestsatoshisp = basesatoshis ;
* ordermatchpricep = price ;
* bestdestsatoshisp = asatoshis ;
return ( bestutxo ) ;
}
return ( 0 ) ;
}
struct LP_utxoinfo * LP_buyutxo ( double * ordermatchpricep , int64_t * bestsatoshisp , int64_t * bestdestsatoshisp , struct LP_utxoinfo * autxo , char * base , double maxprice , int32_t duration , uint64_t txfee , uint64_t desttxfee , char * gui , bits256 * avoids , int32_t numavoids , bits256 destpubkey )
{
bits256 pubkey ; char * obookstr , coinaddr [ 64 ] ; cJSON * orderbook , * asks , * rawasks , * item ; int32_t maxiters , i , j , numasks , max ; struct LP_address_utxo * * utxos ; double price ; struct LP_pubkey_info * pubp ; uint64_t asatoshis ; struct iguana_info * basecoin ; struct LP_utxoinfo * bestutxo = 0 ;
maxiters = 100 ;
* ordermatchpricep = 0. ;
* bestsatoshisp = * bestdestsatoshisp = 0 ;
basecoin = LP_coinfind ( base ) ;
if ( duration < = 0 )
duration = LP_ORDERBOOK_DURATION ;
if ( maxprice < = 0. | | LP_priceinfofind ( base ) = = 0 | | basecoin = = 0 )
return ( 0 ) ;
if ( basecoin - > electrum = = 0 )
max = 1000 ;
else max = LP_MAXDESIRED_UTXOS ;
utxos = calloc ( max , sizeof ( * utxos ) ) ;
LP_txfees ( & txfee , & desttxfee , base , autxo - > coin ) ;
printf ( " LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f \n " , maxprice , dstr ( autxo - > S . satoshis ) , base , autxo - > coin , dstr ( txfee ) , dstr ( desttxfee ) ) ;
if ( ( obookstr = LP_orderbook ( base , autxo - > coin , duration ) ) ! = 0 )
{
if ( ( orderbook = cJSON_Parse ( obookstr ) ) ! = 0 )
{
if ( ( rawasks = jarray ( & numasks , orderbook , " asks " ) ) ! = 0 )
{
if ( ( asks = LP_RTmetrics_sort ( base , autxo - > coin , rawasks , numasks , maxprice , dstr ( autxo - > S . satoshis ) ) ) = = 0 )
asks = rawasks ;
for ( i = 0 ; i < numasks ; i + + )
{
item = jitem ( asks , i ) ;
price = jdouble ( item , " price " ) ;
//if ( price < maxprice && price > maxprice*0.8)
// price = price * 0.9 + 0.1 * maxprice;
//else price *= 1.005;
pubkey = jbits256 ( item , " pubkey " ) ;
if ( bits256_nonz ( destpubkey ) ! = 0 & & bits256_cmp ( destpubkey , pubkey ) ! = 0 )
continue ;
if ( LP_RTmetrics_blacklisted ( pubkey ) > = 0 )
continue ;
//printf("[%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f asatoshis %.8f\n",i,numasks,jprint(item,0),bits256_cmp(pubkey,G.LP_mypub25519),price,maxprice,dstr(autxo->S.satoshis));
if ( LP_pricevalid ( price ) > 0 & & price < = maxprice )
{
if ( bits256_nonz ( destpubkey ) = = 0 )
{
for ( j = 0 ; j < numavoids ; j + + )
if ( bits256_cmp ( pubkey , avoids [ j ] ) = = 0 )
break ;
if ( j ! = numavoids )
continue ;
}
if ( bits256_cmp ( pubkey , G . LP_mypub25519 ) ! = 0 & & ( pubp = LP_pubkeyadd ( pubkey ) ) ! = 0 )
{
bitcoin_address ( coinaddr , basecoin - > taddr , basecoin - > pubtype , pubp - > rmd160 , sizeof ( pubp - > rmd160 ) ) ;
asatoshis = autxo - > S . satoshis ;
//LP_listunspent_query(base,coinaddr);
for ( j = 0 ; j < maxiters ; j + + )
{
if ( ( bestutxo = LP_ordermatch_iter ( utxos , max , ordermatchpricep , bestsatoshisp , bestdestsatoshisp , basecoin , coinaddr , asatoshis , maxprice * .999 , txfee , desttxfee , pubp - > pubkey , gui ) ) ! = 0 )
{
//printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee));
break ;
}
asatoshis = ( asatoshis / 64 ) * 63 ;
}
if ( j < maxiters )
break ;
} else printf ( " self trading or blacklisted peer \n " ) ;
}
else
{
if ( i = = 0 )
printf ( " too expensive maxprice %.8f vs %.8f \n " , maxprice , price ) ;
break ;
}
}
if ( asks ! = 0 & & asks ! = rawasks )
free_json ( asks ) ;
}
free_json ( orderbook ) ;
}
free ( obookstr ) ;
}
free ( utxos ) ;
if ( * ordermatchpricep = = 0. | | * bestdestsatoshisp = = 0 )
return ( 0 ) ;
int32_t changed ;
LP_mypriceset ( & changed , autxo - > coin , base , 1. / * ordermatchpricep ) ;
return ( bestutxo ) ;
}
# endif
# ifdef oldway
//LP_RTmetrics_update(base,rel);
while ( 1 )
{
if ( ( bestutxo = LP_buyutxo ( & ordermatchprice , & bestsatoshis , & bestdestsatoshis , autxo , base , maxprice , duration , txfee , desttxfee , gui , pubkeys , numpubs , destpubkey ) ) = = 0 | | ordermatchprice = = 0. | | bestdestsatoshis = = 0 )
{
printf ( " bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f \n " , bestutxo , ordermatchprice , dstr ( bestdestsatoshis ) ) ;
return ( clonestr ( " { \" error \" : \" cant find ordermatch utxo, need to change relvolume to be closer to available \" } " ) ) ;
}
pubkeys [ numpubs + + ] = bestutxo - > pubkey ;
if ( LP_quoteinfoinit ( & Q , bestutxo , rel , ordermatchprice , bestsatoshis , bestdestsatoshis ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote \" } " ) ) ;
if ( LP_quotedestinfo ( & Q , autxo - > payment . txid , autxo - > payment . vout , autxo - > fee . txid , autxo - > fee . vout , G . LP_mypub25519 , autxo - > coinaddr ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote info \" } " ) ) ;
maxiters = 200 ;
qprice = 1. / SMALLVAL ;
for ( i = 0 ; i < maxiters ; i + + )
{
if ( ( qprice = LP_quote_validate ( autxo , 0 , & Q , 0 ) ) < = SMALLVAL )
{
printf ( " quote validate error %.0f \n " , qprice ) ;
return ( clonestr ( " { \" error \" : \" quote validate error \" } " ) ) ;
}
if ( qprice / ordermatchprice < 1. + SMALLVAL )
{
//printf("i.%d/%d qprice %.8f < ordermatchprice %.8f\n",i,maxiters,qprice,ordermatchprice);
if ( strcmp ( " BTC " , Q . destcoin ) = = 0 | | strcmp ( " BTC " , Q . srccoin ) = = 0 )
Q . satoshis * = 0.999 ;
else Q . satoshis * = 0.9999 ;
} else break ;
}
if ( i = = maxiters | | qprice > maxprice )
{
printf ( " i.%d maxiters.%d qprice %.8f vs maxprice %.8f, no acceptable quote for this pubkey \n " , i , maxiters , dstr ( qprice ) , dstr ( maxprice ) ) ;
if ( bits256_nonz ( destpubkey ) = = 0 )
continue ;
else return ( clonestr ( " { \" error \" : \" cant ordermatch to destpubkey \" } " ) ) ;
}
printf ( " i.%d maxiters.%d qprice %.8f vs maxprice %.8f \n " , i , maxiters , dstr ( qprice ) , dstr ( maxprice ) ) ;
return ( LP_trade ( ctx , myipaddr , mypubsock , & Q , maxprice , timeout , duration , tradeid , destpubkey ) ) ;
}
return ( clonestr ( " { \" error \" : \" cant get here \" } " ) ) ;
# endif
if ( 0 )
{
char * p2sh = " bJVtQF2o8B6sdNjeXupzNw5rnidJUNwPJD " , p2shaddr [ 64 ] ; uint8_t script [ 512 ] , pub33 [ 33 ] ; uint32_t timestamp ;
decode_hex ( pub33 , 33 , " 03fe754763c176e1339a3f62ee6b9484720e17ee4646b65a119e9f6370c7004abc " ) ;
for ( timestamp = 1510934803 - 3600 * 24 ; timestamp < 1510934803 + 3600 * 24 ; timestamp + + )
{
LP_deposit_addr ( p2shaddr , script , 0 , 85 , timestamp , pub33 ) ;
if ( strcmp ( p2shaddr , p2sh ) = = 0 )
{
printf ( " matched timestamp.%u \n " , timestamp ) ;
break ;
} else printf ( " %s " , p2shaddr ) ;
}
}
/*DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
if ( up - > spendheight < = 0 )
{
if ( up - > U . value > * maxp )
* maxp = up - > U . value ;
if ( * minp = = 0 | | up - > U . value < * minp )
* minp = up - > U . value ;
* balancep + = up - > U . value ;
n + + ;
}
} */
char * LP_ordermatch ( char * base , int64_t txfee , double maxprice , double maxvolume , char * rel , bits256 txid , int32_t vout , bits256 feetxid , int32_t feevout , int64_t desttxfee , int32_t duration )
{
struct LP_quoteinfo Q ; int64_t bestsatoshis = 0 , bestdestsatoshis = 0 ; double ordermatchprice = 0. ; struct LP_utxoinfo * autxo , * bestutxo ;
txfee = LP_txfeecalc ( LP_coinfind ( base ) , txfee ) ;
desttxfee = LP_txfeecalc ( LP_coinfind ( rel ) , desttxfee ) ;
if ( ( autxo = LP_utxopairfind ( 0 , txid , vout , feetxid , feevout ) ) = = 0 )
return ( clonestr ( " { \" error \" : \" cant find alice utxopair \" } " ) ) ;
if ( ( bestutxo = LP_bestutxo ( & ordermatchprice , & bestsatoshis , & bestdestsatoshis , autxo , base , maxprice , duration , txfee , desttxfee , SATOSHIDEN * maxvolume ) ) = = 0 | | ordermatchprice = = 0. | | bestdestsatoshis = = 0 )
return ( clonestr ( " { \" error \" : \" cant find ordermatch utxo \" } " ) ) ;
if ( LP_quoteinfoinit ( & Q , bestutxo , rel , ordermatchprice , bestsatoshis , bestdestsatoshis ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote \" } " ) ) ;
if ( LP_quotedestinfo ( & Q , autxo - > payment . txid , autxo - > payment . vout , autxo - > fee . txid , autxo - > fee . vout , LP_mypub25519 , autxo - > coinaddr ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote info \" } " ) ) ;
return ( jprint ( LP_quotejson ( & Q ) , 1 ) ) ;
}
char * LP_autotrade ( void * ctx , char * myipaddr , int32_t mypubsock , char * base , char * rel , double maxprice , double relvolume , int32_t timeout , int32_t duration )
{
uint64_t desttxfee , txfee ; int64_t bestsatoshis = 0 , bestdestsatoshis = 0 ; struct LP_utxoinfo * autxo , * butxo , * bestutxo = 0 ; double qprice , ordermatchprice = 0. ; struct LP_quoteinfo Q ;
if ( duration < = 0 )
duration = LP_ORDERBOOK_DURATION ;
if ( timeout < = 0 )
timeout = LP_AUTOTRADE_TIMEOUT ;
if ( maxprice < = 0. | | relvolume < = 0. | | LP_priceinfofind ( base ) = = 0 | | LP_priceinfofind ( rel ) = = 0 )
return ( clonestr ( " { \" error \" : \" invalid parameter \" } " ) ) ;
if ( ( autxo = LP_utxo_bestfit ( rel , SATOSHIDEN * relvolume ) ) = = 0 )
return ( clonestr ( " { \" error \" : \" cant find utxo that is big enough \" } " ) ) ;
LP_txfees ( & txfee , & desttxfee , base , rel ) ;
if ( ( bestutxo = LP_bestutxo ( & ordermatchprice , & bestsatoshis , & bestdestsatoshis , autxo , base , maxprice , duration , txfee , desttxfee , SATOSHIDEN * relvolume ) ) = = 0 | | ordermatchprice = = 0. | | bestdestsatoshis = = 0 )
{
printf ( " bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f \n " , bestutxo , ordermatchprice , dstr ( bestdestsatoshis ) ) ;
return ( clonestr ( " { \" error \" : \" cant find ordermatch utxo \" } " ) ) ;
}
if ( LP_quoteinfoinit ( & Q , bestutxo , rel , ordermatchprice , bestsatoshis , bestdestsatoshis ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote \" } " ) ) ;
if ( LP_quotedestinfo ( & Q , autxo - > payment . txid , autxo - > payment . vout , autxo - > fee . txid , autxo - > fee . vout , LP_mypub25519 , autxo - > coinaddr ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote info \" } " ) ) ;
if ( ( qprice = LP_quote_validate ( & autxo , & butxo , & Q , 0 ) ) < = SMALLVAL )
{
printf ( " quote validate error %.0f \n " , qprice ) ;
return ( clonestr ( " { \" error \" : \" quote validation error \" } " ) ) ;
}
printf ( " do quote.(%s) \n " , jprint ( LP_quotejson ( & Q ) , 1 ) ) ;
return ( LP_trade ( ctx , myipaddr , mypubsock , & Q , maxprice , timeout , duration ) ) ;
}
# endif