Browse Source

Merge pull request #389 from jl777/spvdex

stable barterDEX
etomic
jl777 7 years ago
committed by GitHub
parent
commit
752441a14f
  1. 6
      iguana/exchanges/LP_coins.c
  2. 136
      iguana/exchanges/LP_commands.c
  3. 5
      iguana/exchanges/LP_include.h
  4. 83
      iguana/exchanges/LP_nativeDEX.c
  5. 391
      iguana/exchanges/LP_ordermatch.c
  6. 50
      iguana/exchanges/LP_prices.c
  7. 2
      iguana/exchanges/LP_rpc.c
  8. 388
      iguana/exchanges/LP_signatures.c
  9. 7
      iguana/exchanges/LP_transaction.c
  10. 38
      iguana/exchanges/LP_utxo.c
  11. 4
      iguana/exchanges/LP_utxos.c
  12. 5
      iguana/exchanges/coins

6
iguana/exchanges/LP_coins.c

@ -184,7 +184,7 @@ uint16_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,
cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
{
struct electrum_info *ep; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
struct electrum_info *ep; uint64_t balance; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
if ( showwif != 0 )
{
@ -198,7 +198,9 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
if ( coin->userpass[0] != 0 )
{
jaddnum(item,"height",LP_getheight(coin));
jaddnum(item,"balance",dstr(LP_smartbalance(coin)));
balance = LP_smartbalance(coin);
jaddnum(item,"balance",dstr(balance));
jaddnum(item,"KMDvalue",dstr(LP_KMDvalue(coin,balance)));
}
else
{

136
iguana/exchanges/LP_commands.c

@ -63,6 +63,8 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
}
if ( method == 0 )
{
if ( is_cJSON_Array(argjson) != 0 )
printf("RAWARRAY command? %s\n",jprint(argjson,0));
if ( flag == 0 || jobj(argjson,"result") != 0 )
printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport);
return(0);
@ -94,24 +96,24 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
// return(clonestr("{\"result\":\"success\"}"));
else if ( strcmp(method,"help") == 0 )
return(clonestr("{\"result\":\" \
available localhost RPC commands: * means it needs to be a signed request\n \
available localhost RPC commands: \n \
pricearray(base, rel, firsttime=0, lasttime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
setprice(base, rel, price)*\n\
setprice(base, rel, price)\n\
autoprice(base, rel, minprice, margin, refbase, refrel, factor, offset)*\n\
goal(coin=*, val=<autocalc>)*\n\
goal(coin=*, val=<autocalc>)\n\
myprice(base, rel)\n\
enable(coin)*\n\
disable(coin)*\n\
enable(coin)\n\
disable(coin)\n\
inventory(coin)\n\
bestfit(rel, relvolume)\n\
lastnonce()\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)*\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)*\n\
withdraw(coin, outputs[])*\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)\n\
withdraw(coin, outputs[])\n\
sendrawtransaction(coin, signedtx)\n\
swapstatus()*\n\
swapstatus()\n\
recentswaps(limit=3)\n\
swapstatus(requestid, quoteid)*\n\
swapstatus(requestid, quoteid)\n\
public API:\n \
getcoins()\n\
getcoin(coin)\n\
@ -119,8 +121,8 @@ portfolio()\n\
getpeers()\n\
passphrase(passphrase, gui)\n\
listunspent(coin, address)\n\
setconfirms(coin, numconfirms, maxconfirms=6)*\n\
trust(pubkey, trust)*\n\
setconfirms(coin, numconfirms, maxconfirms=6)\n\
trust(pubkey, trust)\n\
balance(coin, address)\n\
orderbook(base, rel, duration=3600)\n\
getprices(base, rel)\n\
@ -128,7 +130,7 @@ sendmessage(base=coin, rel="", pubkey=zero, <argjson method2>)\n\
getmessages(firsti=0, num=100)\n\
deletemessages(firsti=0, num=100)\n\
secretaddresses(prefix='secretaddress', passphrase, num=10, pubtype=60, taddr=0)\n\
electrum(coin, ipaddr, port)*\n\
electrum(coin, ipaddr, port)\n\
snapshot(coin, height)\n\
snapshot_balance(coin, height, addresses[])\n\
dividends(coin, height, <args>)\n\
@ -139,7 +141,7 @@ stop()\n\
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
coin = jstr(argjson,"coin");
if ( G.USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 )
if ( G.USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) // protected localhost
{
if ( G.USERPASS_COUNTER == 0 )
{
@ -228,7 +230,6 @@ stop()\n\
{
if ( price > SMALLVAL )
{
//LP_signature_add(argjson,base,rel,(uint64_t)price * SATOSHIDEN);
if ( LP_mypriceset(&changed,base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
@ -238,7 +239,6 @@ stop()\n\
}
else if ( strcmp(method,"autoprice") == 0 )
{
//LP_signature_add(argjson,base,rel,(uint64_t)price * SATOSHIDEN);
if ( LP_autoprice(base,rel,argjson) < 0 )
return(clonestr("{\"error\":\"couldnt set autoprice\"}"));
else return(clonestr("{\"result\":\"success\"}"));
@ -319,7 +319,6 @@ stop()\n\
}
else if ( strcmp(method,"electrum") == 0 )
{
//*
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
ptr->inactive = 0;
@ -332,7 +331,6 @@ stop()\n\
}
else if ( strcmp(method,"withdraw") == 0 )
{
///*
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
if ( jobj(argjson,"outputs") == 0 )
@ -344,7 +342,6 @@ stop()\n\
else if ( strcmp(method,"setconfirms") == 0 )
{
int32_t n;
//*
n = jint(argjson,"numconfirms");
if ( n < 0 )
return(clonestr("{\"error\":\"illegal numconfirms\"}"));
@ -399,22 +396,15 @@ stop()\n\
}
}
else if ( strcmp(method,"goal") == 0 )
{
//*
return(LP_portfolio_goal(coin,jdouble(argjson,"val")));
}
else if ( strcmp(method,"getcoin") == 0 )
return(LP_getcoin(coin));
}
else if ( strcmp(method,"goal") == 0 )
{
//*
return(LP_portfolio_goal("*",100.));
}
else if ( strcmp(method,"swapstatus") == 0 )
{
uint32_t requestid,quoteid;
//*
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
return(basilisk_swapentry(requestid,quoteid));
else return(basilisk_swaplist(0,0));
@ -429,13 +419,10 @@ stop()\n\
else if ( strcmp(method,"myprices") == 0 )
return(LP_myprices());
else if ( strcmp(method,"trust") == 0 )
{
//*
return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust")));
}
else if ( strcmp(method,"trusted") == 0 )
return(LP_pubkey_trusted());
}
} // end of protected localhost commands
if ( IAMLP == 0 )
{
if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 )
@ -449,32 +436,42 @@ stop()\n\
argjson = reqjson;
}
}
// received response
if ( strcmp(method,"postprice") == 0 )
{
// LP_checksig
retstr = LP_postedprice(argjson);
}
retstr = LP_postprice_recv(argjson);
else if ( strcmp(method,"postutxos") == 0 )
retstr = LP_postedutxos(argjson);
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
retstr = LP_postutxos_recv(argjson);
else if ( strcmp(method,"uitem") == 0 )
retstr = LP_uitem_recv(argjson);
else if ( strcmp(method,"notify") == 0 )
retstr = LP_notify_recv(argjson);
// end received response
// public access, even from http
else if ( strcmp(method,"balance") == 0 )
{
bits256 txid; int32_t vout,height; uint64_t value; char *coinaddr;
txid = jbits256(argjson,"txid");
vout = jint(argjson,"vout");
height = jint(argjson,"ht");
value = j64bits(argjson,"value");
coinaddr = jstr(argjson,"coinaddr");
if ( coin != 0 && coinaddr != 0 )
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"pricearray") == 0 )
{
uint32_t firsttime;
if ( base != 0 && rel != 0 )
{
//char str[65]; printf("uitem %s %s %s/v%d %.8f ht.%d\n",coin,coinaddr,bits256_str(str,txid),vout,dstr(value),height);
LP_address_utxoadd(LP_coinfind(coin),coinaddr,txid,vout,value,height,-1);
}
return(clonestr("{\"result\":\"success\"}"));
if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 )
firsttime = (uint32_t)(time(NULL)-30*24*3600);
return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1));
} else return(clonestr("{\"error\":\"pricearray needs base and rel\"}"));
}
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers());
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"listunspent") == 0 )
{
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
@ -500,14 +497,6 @@ stop()\n\
} else return(clonestr("{\"error\":\"no address specified\"}"));
} else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"balance") == 0 )
{
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"checktxid") == 0 )
retstr = LP_spentcheck(argjson);
else if ( strcmp(method,"addr_unspents") == 0 )
{
//printf("GOT ADDR_UNSPENTS %s %s\n",jstr(argjson,"coin"),jstr(argjson,"address"));
@ -529,45 +518,16 @@ stop()\n\
}
retstr = clonestr("{\"result\":\"success\"}");
}
//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\"}");
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"encrypted") == 0 )
retstr = clonestr("{\"result\":\"success\"}");
else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers());
else
else // special handling requests
{
if ( base != 0 && rel != 0 && strcmp(method,"pricearray") == 0 )
{
uint32_t firsttime;
if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 )
firsttime = (uint32_t)(time(NULL)-30*24*3600);
return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1));
}
else if ( strcmp(method,"notify") == 0 )
{
char *rmd160str,*secpstr; bits256 pub; struct LP_pubkeyinfo *pubp;
pub = jbits256(argjson,"pub");
// LP_checksig
if ( bits256_nonz(pub) != 0 && (rmd160str= jstr(argjson,"rmd160")) != 0 && strlen(rmd160str) == 40 )
{
if ( (pubp= LP_pubkeyadd(pub)) != 0 )
{
decode_hex(pubp->rmd160,20,rmd160str);
if ( (secpstr= jstr(argjson,"pubsecp")) != 0 )
{
decode_hex(pubp->pubsecp,sizeof(pubp->pubsecp),secpstr);
//printf("got pubkey.(%s)\n",secpstr);
}
}
//printf("NOTIFIED pub %s rmd160 %s\n",bits256_str(str,pub),rmd160str);
}
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
}
if ( IAMLP != 0 )
{
if ( strcmp(method,"broadcast") == 0 )

5
iguana/exchanges/LP_include.h

@ -44,7 +44,7 @@
#define LP_PEERGOOD_ERRORDECAY 0.9
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 10
#define LP_AUTOTRADE_TIMEOUT 20
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 50
@ -185,7 +185,7 @@ struct iguana_info
portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses;
uint64_t txfee;
int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport;
uint32_t addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime;
uint32_t lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms;
char symbol[16],smartaddr[64],userpass[1024],serverport[128],lastunspent[64];
// portfolio
@ -320,6 +320,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS
int32_t LP_mempoolscan(char *symbol,bits256 searchtxid);
int32_t LP_txheight(struct iguana_info *coin,bits256 txid);
int32_t LP_numpeers();
uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance);
int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight);
void LP_smartutxos_push(struct iguana_info *coin);
cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret);

83
iguana/exchanges/LP_nativeDEX.c

@ -19,14 +19,14 @@
// marketmaker
//
// sign critical api calls (pubkey reg, listunspent, orders?)
// dPoW security -> 4: KMD notarized, 5: BTC notarized
// new testchain
// process stats.log local file -> map of realtime activity!
// handles <-> pubkeys, deal with offline pubkeys, reputations, bonds etc.
//
// alice only coins GAME UNO BTM ANC: GAME BTCD PPC RDD XZC POT EAC FTC BASH SPR WDC UNO XPM XCN BELA CHC DIME MEC NAUT MED AUR MAX DGC RIC EB3 DOT BTM GEO ANC CANN ICASH WBB SRC PTC ADZ TIPS EQT START EFL FST FJC NYC GCN
// verify portfolio, pricearray, interest to KMD withdraw
// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections
#include <stdio.h>
#include "LP_include.h"
@ -54,6 +54,7 @@ int32_t LP_mypubsock = -1;
int32_t LP_mypullsock = -1;
int32_t LP_showwif,IAMLP = 0;
double LP_profitratio = 1.;
char *LP_lastcommand;
struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; };
@ -105,6 +106,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_peers.c"
#include "LP_utxos.c"
#include "LP_forwarding.c"
#include "LP_signatures.c"
#include "LP_ordermatch.c"
#include "LP_portfolio.c"
#include "LP_messages.c"
@ -229,12 +231,12 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,
return(retstr);
}
int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr)
int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr,int32_t maxdepth)
{
int32_t recvlen=1,nonz = 0; cJSON *argjson; void *ptr; char *retstr,*str; struct nn_pollfd pfd;
if ( sock >= 0 )
{
while ( nonz < 100 && recvlen > 0 )
while ( nonz < maxdepth && recvlen > 0 )
{
memset(&pfd,0,sizeof(pfd));
pfd.fd = sock;
@ -257,6 +259,9 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
}
}
nonz++;
if ( LP_lastcommand != 0 )
free(LP_lastcommand);
LP_lastcommand = clonestr((char *)ptr);
if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 )
free(retstr);
if ( Broadcaststr != 0 )
@ -268,6 +273,9 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
{
if ( jobj(argjson,"method") != 0 && strcmp("connect",jstr(argjson,"method")) == 0 )
printf("self.(%s)\n",str);
if ( LP_lastcommand != 0 )
free(LP_lastcommand);
LP_lastcommand = clonestr(str);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
{
portable_mutex_lock(&LP_commandmutex);
@ -292,8 +300,8 @@ int32_t LP_nanomsg_recvs(void *ctx)
if ( (origipaddr= LP_myipaddr) == 0 )
origipaddr = "127.0.0.1";
milli = OS_milliseconds();
if ( lastmilli > 0. && milli > lastmilli+3000 )
fprintf(stderr,">>>>>>>>>>>>>>>>> BIG latency lag %.3f milliseconds\n",milli-lastmilli);
if ( lastmilli > 0. && milli > lastmilli+1000 )
fprintf(stderr,">>>>>>>>>>>>>>>>> BIG latency lag %.3f milliseconds: (%s)\n",milli-lastmilli,LP_lastcommand!=0?LP_lastcommand:"");
lastmilli = milli;
//portable_mutex_lock(&LP_nanorecvsmutex);
HASH_ITER(hh,LP_peerinfos,peer,tmp)
@ -309,7 +317,7 @@ int32_t LP_nanomsg_recvs(void *ctx)
}
}
//printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr,1);
}
/*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
@ -319,7 +327,7 @@ int32_t LP_nanomsg_recvs(void *ctx)
nonz += LP_sock_check(coin->symbol,ctx,origipaddr,-1,coin->bussock,LP_profitratio - 1.);
}*/
if ( LP_mypullsock >= 0 )
nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1");
nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1",1);
//portable_mutex_unlock(&LP_nanorecvsmutex);
return(nonz);
}
@ -341,48 +349,7 @@ void command_rpcloop(void *myipaddr)
}
else if ( IAMLP == 0 )
usleep(1000);
}
}
void LP_smartutxos_push(struct iguana_info *coin)
{
struct LP_peerinfo *peer,*tmp; uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; char *retstr; cJSON *array,*item,*req;
if ( coin->smartaddr[0] == 0 )
return;
if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
//printf("PUSH %s %s\n",coin->symbol,coin->smartaddr);
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
vout = jint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
if ( (rand() % 100) == 0 && IAMLP == 0 )
{
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( (retstr= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,vout,height,value)) != 0 )
free(retstr);
}
}
req = cJSON_CreateObject();
jaddstr(req,"method","uitem");
jaddstr(req,"coin",coin->symbol);
jaddstr(req,"coinaddr",coin->smartaddr);
jaddbits256(req,"txid",txid);
jaddnum(req,"vout",vout);
jaddnum(req,"ht",height);
jadd64bits(req,"value",value);
//printf("ADDR_UNSPENTS[] <- %s\n",jprint(req,0));
LP_reserved_msg("","",zero,jprint(req,1));
}
}
free_json(array);
else usleep(10);
}
}
@ -715,7 +682,7 @@ int32_t LP_reserved_msgs()
bits256 zero; int32_t n = 0; //struct nn_pollfd pfd;
memset(zero.bytes,0,sizeof(zero));
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs > 0 )
while ( num_Reserved_msgs > 0 )
{
/*memset(&pfd,0,sizeof(pfd));
pfd.fd = LP_mypubsock;
@ -728,12 +695,14 @@ int32_t LP_reserved_msgs()
#endif
LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[num_Reserved_msgs]);
Reserved_msgs[num_Reserved_msgs] = 0;
n++;
#ifdef __APPLE__
usleep(5000);
#else
usleep(100);
usleep(1000);
#endif
n++;
if ( n > 0 )
break;
}
portable_mutex_unlock(&LP_reservedmutex);
return(n);
@ -820,10 +789,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
portable_mutex_init(&LP_reservedmutex);
portable_mutex_init(&LP_nanorecvsmutex);
#ifndef _WIN32
if ( system("curl -s4 checkip.amazonaws.com > DB/myipaddr") == 0 )
if ( system("curl -s4 checkip.amazonaws.com > myipaddr") == 0 )
{
char ipfname[64];
strcpy(ipfname,"DB/myipaddr");
strcpy(ipfname,"myipaddr");
if ( (myipaddr= OS_filestr(&filesize,ipfname)) != 0 && myipaddr[0] != 0 )
{
n = strlen(myipaddr);
@ -928,7 +897,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
if ( nonz == 0 )
usleep(10000);
else if ( IAMLP != 0 )
usleep(1000);
usleep(10);
else usleep(10000);
}
}

391
iguana/exchanges/LP_ordermatch.c

@ -42,13 +42,6 @@ uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen)
return(txfee);
}
void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel)
{
*txfeep = LP_txfeecalc(LP_coinfind(base),0,0);
*desttxfeep = LP_txfeecalc(LP_coinfind(rel),0,0);
printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep));
}
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;
@ -66,212 +59,6 @@ double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uin
else return(0.);
}
struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector)
{
struct basilisk_request R;
memset(rp,0,sizeof(*rp));
rp->srchash = srchash;
rp->srcamount = srcsatoshis;
rp->timestamp = timestamp;
rp->DEXselector = DEXselector;
safecopy(rp->src,src,sizeof(rp->src));
safecopy(rp->dest,dest,sizeof(rp->dest));
R = *rp;
rp->requestid = basilisk_requestid(rp);
rp->quotetime = quotetime;
rp->desthash = desthash;
rp->destamount = destsatoshis;
rp->quoteid = basilisk_quoteid(rp);
printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount));
return(rp);
}
cJSON *LP_quotejson(struct LP_quoteinfo *qp)
{
double price; cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"base",qp->srccoin);
jaddstr(retjson,"rel",qp->destcoin);
if ( qp->coinaddr[0] != 0 )
jaddstr(retjson,"address",qp->coinaddr);
if ( qp->timestamp != 0 )
jaddnum(retjson,"timestamp",qp->timestamp);
if ( bits256_nonz(qp->txid) != 0 )
{
jaddbits256(retjson,"txid",qp->txid);
jaddnum(retjson,"vout",qp->vout);
}
if ( bits256_nonz(qp->srchash) != 0 )
jaddbits256(retjson,"srchash",qp->srchash);
if ( qp->txfee != 0 )
jadd64bits(retjson,"txfee",qp->txfee);
if ( qp->quotetime != 0 )
jaddnum(retjson,"quotetime",qp->quotetime);
if ( qp->satoshis != 0 )
jadd64bits(retjson,"satoshis",qp->satoshis);
if ( bits256_nonz(qp->desthash) != 0 )
jaddbits256(retjson,"desthash",qp->desthash);
if ( bits256_nonz(qp->txid2) != 0 )
{
jaddbits256(retjson,"txid2",qp->txid2);
jaddnum(retjson,"vout2",qp->vout2);
}
if ( bits256_nonz(qp->desttxid) != 0 )
{
if ( qp->destaddr[0] != 0 )
jaddstr(retjson,"destaddr",qp->destaddr);
jaddbits256(retjson,"desttxid",qp->desttxid);
jaddnum(retjson,"destvout",qp->destvout);
}
if ( bits256_nonz(qp->feetxid) != 0 )
{
jaddbits256(retjson,"feetxid",qp->feetxid);
jaddnum(retjson,"feevout",qp->feevout);
}
if ( qp->desttxfee != 0 )
jadd64bits(retjson,"desttxfee",qp->desttxfee);
if ( qp->destsatoshis != 0 )
{
jadd64bits(retjson,"destsatoshis",qp->destsatoshis);
if ( qp->satoshis != 0 )
{
price = (double)qp->destsatoshis / (qp->satoshis - qp->txfee);
jaddnum(retjson,"price",price);
}
}
return(retjson);
}
int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
{
safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin));
safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr));
safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin));
safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr));
qp->timestamp = juint(argjson,"timestamp");
qp->quotetime = juint(argjson,"quotetime");
qp->txid = jbits256(argjson,"txid");
qp->txid2 = jbits256(argjson,"txid2");
qp->vout = jint(argjson,"vout");
qp->vout2 = jint(argjson,"vout2");
qp->feevout = jint(argjson,"feevout");
qp->srchash = jbits256(argjson,"srchash");
qp->desttxid = jbits256(argjson,"desttxid");
qp->feetxid = jbits256(argjson,"feetxid");
qp->destvout = jint(argjson,"destvout");
qp->desthash = jbits256(argjson,"desthash");
qp->satoshis = j64bits(argjson,"satoshis");
qp->destsatoshis = j64bits(argjson,"destsatoshis");
qp->txfee = j64bits(argjson,"txfee");
qp->desttxfee = j64bits(argjson,"desttxfee");
return(0);
}
int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t satoshis,uint64_t destsatoshis)
{
memset(qp,0,sizeof(*qp));
if ( qp->timestamp == 0 )
qp->timestamp = (uint32_t)time(NULL);
safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin));
LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin);
qp->satoshis = satoshis;//(destsatoshis / price) + 0.49;
qp->destsatoshis = destsatoshis;
/*if ( qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) //utxo->iambob == 0 ||
{
printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis)));
return(-1);
}*/
qp->txid = utxo->payment.txid;
qp->vout = utxo->payment.vout;
qp->txid2 = utxo->deposit.txid;
qp->vout2 = utxo->deposit.vout;
if ( qp->desttxfee >= qp->destsatoshis )
{
printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis));
return(-2);
}
safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin));
safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr));
qp->srchash = utxo->pubkey;
return(0);
}
int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvout,bits256 feetxid,int32_t feevout,bits256 desthash,char *destaddr)
{
qp->desttxid = desttxid;
qp->destvout = destvout;
qp->desthash = desthash;
qp->feetxid = feetxid;
qp->feevout = feevout;
safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr));
return(0);
}
char *LP_quotereceived(cJSON *argjson)
{
struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q;
LP_quoteparse(&Q,argjson);
price = (double)Q.destsatoshis / (Q.satoshis - Q.txfee);
if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 )
{
ptr->Q = Q;
printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price);
return(clonestr("{\"result\":\"updated\"}"));
} else return(clonestr("{\"error\":\"nullptr\"}"));
}
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price)
{
bits256 zero; cJSON *reqjson = cJSON_CreateObject();
// LP_addsig
memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
jaddstr(reqjson,"base",base);
jaddstr(reqjson,"rel",rel);
jaddnum(reqjson,"price",price);
jaddstr(reqjson,"method","postprice");
LP_reserved_msg(base,rel,zero,jprint(reqjson,1));
return(clonestr("{\"result\":\"success\"}"));
}
void LP_notify_pubkeys(void *ctx,int32_t pubsock)
{
bits256 zero; char secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
// LP_addsig
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","notify");
jaddstr(reqjson,"rmd160",G.LP_myrmd160str);
jaddbits256(reqjson,"pub",G.LP_mypub25519);
init_hexbytes_noT(secpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",secpstr);
LP_reserved_msg("","",zero,jprint(reqjson,1));
}
void LP_listunspent_query(char *symbol,char *coinaddr)
{
bits256 zero; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","addr_unspents");
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"address",coinaddr);
LP_reserved_msg("","",zero,jprint(reqjson,1));
}
char *LP_postedprice(cJSON *argjson)
{
bits256 pubkey; double price; char *base,*rel;
//printf("PRICE POSTED.(%s)\n",jprint(argjson,0));
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && (price= jdouble(argjson,"price")) > SMALLVAL )
{
pubkey = jbits256(argjson,"pubkey");
if ( bits256_nonz(pubkey) != 0 )
{
LP_pricefeedupdate(pubkey,base,rel,price);
return(clonestr("{\"result\":\"success\"}"));
}
}
return(clonestr("{\"error\":\"missing fields in posted price\"}"));
}
int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo)
{
int32_t selector,spendvini; bits256 spendtxid;
@ -379,40 +166,6 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout)
return(-1);
}
void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp)
{
cJSON *reqjson; bits256 zero; char *msg; int32_t flag = 0; struct LP_utxoinfo *utxo;
if ( strcmp(method,"request") == 0 )
{
if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 )
LP_unavailableset(utxo,qp->srchash);
else
{
printf("couldnt find my txid to make request\n");
return;
}
}
reqjson = LP_quotejson(qp);
if ( bits256_nonz(qp->desthash) != 0 )
flag = 1;
jaddbits256(reqjson,"pubkey",qp->srchash);
jaddstr(reqjson,"method",method);
msg = jprint(reqjson,1);
// LP_addsig
printf("QUERY.(%s)\n",msg);
memset(&zero,0,sizeof(zero));
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs) )
Reserved_msgs[num_Reserved_msgs++] = msg;
else
{
//if ( 1 && strcmp(method,"request") == 0 )
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg);
//else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
}
portable_mutex_unlock(&LP_reservedmutex);
}
int32_t LP_nanobind(void *ctx,char *pairstr)
{
int32_t i,r,pairsock = -1; uint16_t mypullport; char bindaddr[128];
@ -629,6 +382,58 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
return(retval);
}
struct LP_quoteinfo LP_Alicequery;
double LP_Alicemaxprice;
uint32_t Alice_expiration;
char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration)
{
struct LP_utxoinfo *aliceutxo; double price; //cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap;
if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 )
{
char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout);
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
}
price = 0.;
LP_query(ctx,myipaddr,mypubsock,"request",qp);
LP_Alicequery = *qp, LP_Alicemaxprice = maxprice, Alice_expiration = qp->timestamp + timeout;
return(clonestr("{\"result\":\"success\"}"));
}
int32_t LP_quotecmp(struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2)
{
if ( bits256_cmp(qp->srchash,qp2->srchash) == 0 && bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee )
return(0);
else return(-1);
}
int32_t LP_alice_eligible()
{
if ( Alice_expiration != 0 && time(NULL) > Alice_expiration )
{
printf("time expired for Alice_request\n");
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
Alice_expiration = 0;
}
return(Alice_expiration == 0 || time(NULL) < Alice_expiration);
}
void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp)
{
double price=0.,maxprice = LP_Alicemaxprice;
if ( LP_alice_eligible() > 0 && LP_quotecmp(qp,&LP_Alicequery) == 0 )
{
price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout);
if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice )
{
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
Alice_expiration = 0;
LP_query(ctx,myipaddr,mypubsock,"connect",qp);
}
} else printf("reject reserved due to not eligible.%d or mismatched quote price %.8f vs maxprice %.8f\n",LP_alice_eligible(),price,maxprice);
}
char *LP_connectedalice(cJSON *argjson) // alice
{
cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,B,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; //uint64_t value,value2;
@ -637,11 +442,14 @@ char *LP_connectedalice(cJSON *argjson) // alice
if ( bits256_cmp(Q.desthash,G.LP_mypub25519) != 0 )
return(clonestr("{\"result\",\"update stats\"}"));
printf("CONNECTED.(%s) numpending.%d\n",jprint(argjson,0),G.LP_pendingswaps);
/*if ( G.LP_pendingswaps > 0 )
/*if ( LP_alice_eligible() == 0 || LP_quotecmp(&Q,&LP_Alicequery) != 0 )
{
printf("swap already pending\n");
return(clonestr("{\"error\":\"swap already pending\"}"));
}*/
printf("reject mismatched alice query\n");
return(clonestr("{\"error\",\"mismatched alice query\"}"));
}
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
Alice_expiration = 0;*/
if ( (autxo= LP_utxopairfind(0,Q.desttxid,Q.destvout,Q.feetxid,Q.feevout)) == 0 )
{
printf("cant find autxo\n");
@ -779,51 +587,11 @@ char *LP_bestfit(char *rel,double relvolume)
return(jprint(LP_utxojson(autxo),1));
}
struct LP_quoteinfo LP_Alicequery;
double LP_Alicemaxprice;
uint32_t Alice_expiration;
char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration)
{
struct LP_utxoinfo *aliceutxo; double price; //cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap;
if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 )
{
char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout);
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
}
price = 0.;
LP_query(ctx,myipaddr,mypubsock,"request",qp);
LP_Alicequery = *qp, LP_Alicemaxprice = maxprice, Alice_expiration = qp->timestamp + timeout;
return(clonestr("{\"result\":\"success\"}"));
}
int32_t LP_quotecmp(struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2)
int32_t LP_aliceonly(char *symbol)
{
if ( bits256_cmp(qp->srchash,qp2->srchash) == 0 && bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee )
return(0);
else return(-1);
}
void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp)
{
double price,maxprice = LP_Alicemaxprice;
if ( time(NULL) > Alice_expiration )
{
printf("time expired for Alice_request\n");
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
Alice_expiration = 0;
}
else if ( LP_quotecmp(qp,&LP_Alicequery) == 0 )
{
price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout);
if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice )
{
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
Alice_expiration = 0;
LP_query(ctx,myipaddr,mypubsock,"connect",qp);
}
}
if ( strcmp(symbol,"GAME") == 0 )
return(1);
else return(0);
}
int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
@ -839,7 +607,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
retval = 1;
if ( strcmp(method,"reserved") == 0 )
{
if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 )
if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && LP_alice_eligible() > 0 )
{
printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
if ( (retstr= LP_quotereceived(argjson)) != 0 )
@ -865,19 +633,31 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin);
return(retval);
}
if ( coin->electrum != 0 )
{
printf("electrum can only be for alice\n");
return(retval);
}
if ( LP_aliceonly(Q.srccoin) > 0 )
{
printf("{\"error\":\"GAME can only be alice coin\"}\n");
return(retval);
}
price = ask;
autxo = &A;
butxo = &B;
memset(autxo,0,sizeof(*autxo));
memset(butxo,0,sizeof(*butxo));
LP_abutxo_set(autxo,butxo,&Q);
printf("utxopairfind\n");
if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 )
butxo = &B;
//LP_butxo_swapfields(butxo);
if ( strcmp(method,"request") == 0 )
{
char str[65],str2[65];
if ( LP_allocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_allocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
printf("request.(%s)\n",jprint(argjson,0));
if ( 1 )//LP_allocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_allocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
{
printf("butxo.%p replace path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1));
LP_listunspent_both(Q.srccoin,Q.coinaddr,0);
@ -895,12 +675,18 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
else
{
printf("other path %p %p %.8f\n",LP_allocated(butxo->payment.txid,butxo->payment.vout),LP_allocated(butxo->deposit.txid,butxo->deposit.vout), LP_quote_validate(autxo,butxo,&Q,1));
value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout);
value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2);
if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,G.LP_mypub25519,G.gui,0)) == 0 )
printf("couldnt create bob's utxopair\n");
else printf("created butxo.(%s %s)\n",bits256_str(str,butxo->payment.txid),bits256_str(str2,butxo->deposit.txid));
}
}
if ( butxo == 0 || butxo == &B )
butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2);
if ( butxo == 0 )
if ( butxo == 0 || bits256_cmp(Q.txid,butxo->payment.txid) != 0 || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 )
{
printf("null butxo.%p case\n",butxo);
value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout);
value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2);
butxo = LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0);
@ -1002,6 +788,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
{
item = jitem(asks,i);
price = jdouble(item,"price");
price *= 1.005;
pubkey = jbits256(item,"pubkey");
//printf("[%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f\n",i,numasks,jprint(item,0),bits256_cmp(pubkey,G.LP_mypub25519),price,maxprice);
if ( LP_pricevalid(price) > 0 && price <= maxprice )
@ -1053,6 +840,8 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui,uint32_t nonce)
{
uint64_t desttxfee,txfee; uint32_t lastnonce; int32_t i,maxiters,numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100];
if ( LP_aliceonly(base) > 0 )
return(clonestr("{\"error\":\"GAME can only be alice coin\"}"));
printf("LP_autobuy %s/%s price %.8f vol %.8f nonce %u\n",base,rel,maxprice,relvolume,nonce);
if ( (lastnonce= LP_lastnonce) != 0 && nonce <= lastnonce )
{
@ -1074,9 +863,9 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
}
if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 )
return(clonestr("{\"error\":\"invalid parameter\"}"));
//if ( strcmp("BTC",rel) == 0 )
// maxprice *= 1.01;
//else maxprice *= 1.001;
if ( strcmp("BTC",rel) == 0 )
maxprice *= 1.01;
else maxprice *= 1.001;
memset(pubkeys,0,sizeof(pubkeys));
LP_txfees(&txfee,&desttxfee,base,rel);
destsatoshis = SATOSHIDEN * relvolume + 2*desttxfee;

50
iguana/exchanges/LP_prices.c

@ -752,7 +752,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
char *LP_orderbook(char *base,char *rel,int32_t duration)
{
uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid;
uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid,suppress_prefetch=0;
basecoin = LP_coinfind(base);
relcoin = LP_coinfind(rel);
if ( basecoin == 0 || relcoin == 0 )
@ -760,7 +760,11 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
if ( (basepp= LP_priceinfofind(base)) == 0 || (relpp= LP_priceinfofind(rel)) == 0 )
return(clonestr("{\"error\":\"base or rel not added\"}"));
if ( duration <= 0 )
{
if ( duration < 0 )
suppress_prefetch = 1;
duration = LP_ORDERBOOK_DURATION;
}
baseid = basepp->ind;
relid = relpp->ind;
now = (uint32_t)time(NULL);
@ -787,7 +791,7 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
for (i=n=0; i<numbids; i++)
{
jaddi(array,LP_orderbookjson(rel,bids[i]));
if ( n < 10 && bids[i]->numutxos == 0 )//|| relcoin->electrum == 0 )
if ( suppress_prefetch == 0 && n < 10 && bids[i]->numutxos == 0 )
{
//printf("bid ping %s %s\n",rel,bids[i]->coinaddr);
LP_address(relcoin,bids[i]->coinaddr);
@ -807,7 +811,7 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
for (i=n=0; i<numasks; i++)
{
jaddi(array,LP_orderbookjson(base,asks[i]));
if ( n < 10 && asks[i]->numutxos == 0 )//|| basecoin->electrum == 0 )
if ( suppress_prefetch == 0 && n < 10 && asks[i]->numutxos == 0 )
{
//printf("ask ping %s %s\n",base,asks[i]->coinaddr);
LP_address(basecoin,asks[i]->coinaddr);
@ -833,7 +837,42 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
return(jprint(retjson,1));
}
char *LP_pricestr(char *base,char *rel,double origprice)
uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance)
{
cJSON *bids,*asks,*orderbook,*item; double bid=0,ask=0,price = 0.; int32_t numasks,numbids; char *retstr; uint64_t KMDvalue=0;
if ( balance != 0 )
{
if ( strcmp(coin->symbol,"KMD") == 0 )
KMDvalue = balance;
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);
}
}
return(KMDvalue);
}
/*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 )
@ -845,7 +884,6 @@ char *LP_pricestr(char *base,char *rel,double origprice)
if ( LP_pricevalid(price) > 0 )
{
retjson = cJSON_CreateObject();
// LP_addsig
jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",G.LP_mypub25519);
@ -856,7 +894,7 @@ char *LP_pricestr(char *base,char *rel,double origprice)
jadd(retjson,"quotes",LP_priceinfomatrix(1));
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"cant find baserel pair\"}"));
}
}*/
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32])
{

2
iguana/exchanges/LP_rpc.c

@ -230,7 +230,7 @@ uint64_t LP_smartbalance(struct iguana_info *coin)
cJSON *array,*item; char buf[512],*retstr; int32_t i,n; uint64_t valuesum,value;
valuesum = 0;
sprintf(buf,"[0, 99999999, [\"%s\"]]",coin->smartaddr);
retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,"listunspent","[]");
retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,"listunspent",buf);
if ( retstr != 0 && retstr[0] != 0 )
{
array = cJSON_Parse(retstr);

388
iguana/exchanges/LP_signatures.c

@ -0,0 +1,388 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_signatures.c
// marketmaker
//
struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector)
{
struct basilisk_request R;
memset(rp,0,sizeof(*rp));
rp->srchash = srchash;
rp->srcamount = srcsatoshis;
rp->timestamp = timestamp;
rp->DEXselector = DEXselector;
safecopy(rp->src,src,sizeof(rp->src));
safecopy(rp->dest,dest,sizeof(rp->dest));
R = *rp;
rp->requestid = basilisk_requestid(rp);
rp->quotetime = quotetime;
rp->desthash = desthash;
rp->destamount = destsatoshis;
rp->quoteid = basilisk_quoteid(rp);
printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount));
return(rp);
}
cJSON *LP_quotejson(struct LP_quoteinfo *qp)
{
double price; cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"base",qp->srccoin);
jaddstr(retjson,"rel",qp->destcoin);
if ( qp->coinaddr[0] != 0 )
jaddstr(retjson,"address",qp->coinaddr);
if ( qp->timestamp != 0 )
jaddnum(retjson,"timestamp",qp->timestamp);
if ( bits256_nonz(qp->txid) != 0 )
{
jaddbits256(retjson,"txid",qp->txid);
jaddnum(retjson,"vout",qp->vout);
}
if ( bits256_nonz(qp->srchash) != 0 )
jaddbits256(retjson,"srchash",qp->srchash);
if ( qp->txfee != 0 )
jadd64bits(retjson,"txfee",qp->txfee);
if ( qp->quotetime != 0 )
jaddnum(retjson,"quotetime",qp->quotetime);
if ( qp->satoshis != 0 )
jadd64bits(retjson,"satoshis",qp->satoshis);
if ( bits256_nonz(qp->desthash) != 0 )
jaddbits256(retjson,"desthash",qp->desthash);
if ( bits256_nonz(qp->txid2) != 0 )
{
jaddbits256(retjson,"txid2",qp->txid2);
jaddnum(retjson,"vout2",qp->vout2);
}
if ( bits256_nonz(qp->desttxid) != 0 )
{
if ( qp->destaddr[0] != 0 )
jaddstr(retjson,"destaddr",qp->destaddr);
jaddbits256(retjson,"desttxid",qp->desttxid);
jaddnum(retjson,"destvout",qp->destvout);
}
if ( bits256_nonz(qp->feetxid) != 0 )
{
jaddbits256(retjson,"feetxid",qp->feetxid);
jaddnum(retjson,"feevout",qp->feevout);
}
if ( qp->desttxfee != 0 )
jadd64bits(retjson,"desttxfee",qp->desttxfee);
if ( qp->destsatoshis != 0 )
{
jadd64bits(retjson,"destsatoshis",qp->destsatoshis);
if ( qp->satoshis != 0 )
{
price = (double)qp->destsatoshis / (qp->satoshis - qp->txfee);
jaddnum(retjson,"price",price);
}
}
return(retjson);
}
int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
{
safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin));
safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr));
safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin));
safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr));
qp->timestamp = juint(argjson,"timestamp");
qp->quotetime = juint(argjson,"quotetime");
qp->txid = jbits256(argjson,"txid");
qp->txid2 = jbits256(argjson,"txid2");
qp->vout = jint(argjson,"vout");
qp->vout2 = jint(argjson,"vout2");
qp->feevout = jint(argjson,"feevout");
qp->srchash = jbits256(argjson,"srchash");
qp->desttxid = jbits256(argjson,"desttxid");
qp->feetxid = jbits256(argjson,"feetxid");
qp->destvout = jint(argjson,"destvout");
qp->desthash = jbits256(argjson,"desthash");
qp->satoshis = j64bits(argjson,"satoshis");
qp->destsatoshis = j64bits(argjson,"destsatoshis");
qp->txfee = j64bits(argjson,"txfee");
qp->desttxfee = j64bits(argjson,"desttxfee");
return(0);
}
void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel)
{
*txfeep = LP_txfeecalc(LP_coinfind(base),0,0);
*desttxfeep = LP_txfeecalc(LP_coinfind(rel),0,0);
printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep));
}
int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t satoshis,uint64_t destsatoshis)
{
memset(qp,0,sizeof(*qp));
if ( qp->timestamp == 0 )
qp->timestamp = (uint32_t)time(NULL);
safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin));
LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin);
qp->satoshis = satoshis;//(destsatoshis / price) + 0.49;
qp->destsatoshis = destsatoshis;
/*if ( qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) //utxo->iambob == 0 ||
{
printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis)));
return(-1);
}*/
qp->txid = utxo->payment.txid;
qp->vout = utxo->payment.vout;
qp->txid2 = utxo->deposit.txid;
qp->vout2 = utxo->deposit.vout;
if ( qp->desttxfee >= qp->destsatoshis )
{
printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis));
return(-2);
}
safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin));
safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr));
qp->srchash = utxo->pubkey;
return(0);
}
int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvout,bits256 feetxid,int32_t feevout,bits256 desthash,char *destaddr)
{
qp->desttxid = desttxid;
qp->destvout = destvout;
qp->desthash = desthash;
qp->feetxid = feetxid;
qp->feevout = feevout;
safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr));
return(0);
}
char *LP_quotereceived(cJSON *argjson)
{
struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q;
LP_quoteparse(&Q,argjson);
price = (double)Q.destsatoshis / (Q.satoshis - Q.txfee);
if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 )
{
ptr->Q = Q;
printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price);
return(clonestr("{\"result\":\"updated\"}"));
} else return(clonestr("{\"error\":\"nullptr\"}"));
}
void LP_smartutxos_push(struct iguana_info *coin)
{
struct LP_peerinfo *peer,*tmp; uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; char *retstr; cJSON *array,*item,*req;
if ( coin->smartaddr[0] == 0 )
return;
if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
//printf("PUSH %s %s\n",coin->symbol,coin->smartaddr);
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
vout = jint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
if ( 0 && (rand() % 100) == 0 && IAMLP == 0 )
{
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( (retstr= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,vout,height,value)) != 0 )
free(retstr);
}
}
req = cJSON_CreateObject();
jaddstr(req,"method","uitem");
jaddstr(req,"coin",coin->symbol);
jaddstr(req,"coinaddr",coin->smartaddr);
jaddbits256(req,"txid",txid);
jaddnum(req,"vout",vout);
jaddnum(req,"ht",height);
jadd64bits(req,"value",value);
//printf("ADDR_UNSPENTS[] <- %s\n",jprint(req,0));
LP_reserved_msg("","",zero,jprint(req,1));
}
}
free_json(array);
}
}
char *LP_uitem_recv(cJSON *argjson)
{
bits256 txid; int32_t vout,height; uint64_t value; char *coinaddr,*symbol;
txid = jbits256(argjson,"txid");
vout = jint(argjson,"vout");
height = jint(argjson,"ht");
value = j64bits(argjson,"value");
coinaddr = jstr(argjson,"coinaddr");
if ( (symbol= jstr(argjson,"coin")) != 0 && coinaddr != 0 )
{
//char str[65]; printf("uitem %s %s %s/v%d %.8f ht.%d\n",coin,coinaddr,bits256_str(str,txid),vout,dstr(value),height);
LP_address_utxoadd(LP_coinfind(symbol),coinaddr,txid,vout,value,height,-1);
}
return(clonestr("{\"result\":\"success\"}"));
}
void LP_postutxos(char *symbol,char *coinaddr)
{
bits256 zero; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
if ( (coin= LP_coinfind(symbol)) != 0 && (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
//printf("LP_postutxos pubsock.%d %s %s\n",pubsock,symbol,coin->smartaddr);
if ( cJSON_GetArraySize(array) == 0 )
free_json(array);
else
{
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","postutxos");
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"coinaddr",coinaddr);
jadd(reqjson,"utxos",array);
//printf("post (%s) -> %d\n",msg,LP_mypubsock);
LP_reserved_msg(symbol,symbol,zero,jprint(reqjson,1));
}
}
}
char *LP_postutxos_recv(cJSON *argjson)
{
int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array;
//printf("posted.(%s)\n",jprint(argjson,0));
if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) // addsig
{
if ( coin->electrum == 0 || (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( (array= jarray(&n,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);
}
return(clonestr("{\"result\":\"success\"}"));
}
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price)
{
struct iguana_info *basecoin,*relcoin; bits256 zero; cJSON *reqjson = cJSON_CreateObject();
// LP_addsig
if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 && relcoin->electrum == 0 )
{
memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
jaddstr(reqjson,"base",base);
jaddstr(reqjson,"rel",rel);
jaddnum(reqjson,"price",price);
jaddstr(reqjson,"method","postprice");
LP_reserved_msg(base,rel,zero,jprint(reqjson,1));
return(clonestr("{\"result\":\"success\"}"));
} else return(clonestr("{\"error\":\"electrum node cant post bob asks\"}"));
}
char *LP_postprice_recv(cJSON *argjson)
{
bits256 pubkey; double price; char *base,*rel;
//printf("PRICE POSTED.(%s)\n",jprint(argjson,0));
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && (price= jdouble(argjson,"price")) > SMALLVAL )
{
pubkey = jbits256(argjson,"pubkey");
if ( bits256_nonz(pubkey) != 0 )
{
LP_pricefeedupdate(pubkey,base,rel,price);
return(clonestr("{\"result\":\"success\"}"));
}
}
return(clonestr("{\"error\":\"missing fields in posted price\"}"));
}
void LP_notify_pubkeys(void *ctx,int32_t pubsock)
{
bits256 zero; char secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
// LP_addsig
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","notify");
jaddstr(reqjson,"rmd160",G.LP_myrmd160str);
jaddbits256(reqjson,"pub",G.LP_mypub25519);
init_hexbytes_noT(secpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",secpstr);
LP_reserved_msg("","",zero,jprint(reqjson,1));
}
char *LP_notify_recv(cJSON *argjson)
{
char *rmd160str,*secpstr; bits256 pub; struct LP_pubkeyinfo *pubp;
pub = jbits256(argjson,"pub");
// LP_checksig
if ( bits256_nonz(pub) != 0 && (rmd160str= jstr(argjson,"rmd160")) != 0 && strlen(rmd160str) == 40 )
{
if ( (pubp= LP_pubkeyadd(pub)) != 0 )
{
decode_hex(pubp->rmd160,20,rmd160str);
if ( (secpstr= jstr(argjson,"pubsecp")) != 0 )
{
decode_hex(pubp->pubsecp,sizeof(pubp->pubsecp),secpstr);
//printf("got pubkey.(%s)\n",secpstr);
}
}
//printf("NOTIFIED pub %s rmd160 %s\n",bits256_str(str,pub),rmd160str);
}
return(clonestr("{\"result\":\"success\",\"notify\":\"received\"}"));
}
void LP_listunspent_query(char *symbol,char *coinaddr)
{
bits256 zero; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","addr_unspents");
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"address",coinaddr);
LP_reserved_msg("","",zero,jprint(reqjson,1));
}
void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp)
{
cJSON *reqjson; bits256 zero; char *msg; int32_t flag = 0; struct LP_utxoinfo *utxo;
if ( strcmp(method,"request") == 0 )
{
if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 )
LP_unavailableset(utxo,qp->srchash);
else
{
printf("couldnt find my txid to make request\n");
return;
}
}
reqjson = LP_quotejson(qp);
if ( bits256_nonz(qp->desthash) != 0 )
flag = 1;
jaddbits256(reqjson,"pubkey",qp->srchash);
jaddstr(reqjson,"method",method);
msg = jprint(reqjson,1);
// LP_addsig
printf("QUERY.(%s)\n",msg);
memset(&zero,0,sizeof(zero));
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs) )
Reserved_msgs[num_Reserved_msgs++] = msg;
else
{
//if ( 1 && strcmp(method,"request") == 0 )
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg);
//else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
}
portable_mutex_unlock(&LP_reservedmutex);
}

7
iguana/exchanges/LP_transaction.c

@ -923,6 +923,12 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
suppress_pubkeys = 1;
scriptlen = bitcoin_standardspend(script,0,G.LP_myrmd160);
numvins = LP_vins_select(ctx,coin,&total,amount,V,utxos,numutxos,suppress_pubkeys,ignore_cltverr,privkey,privkeys,vins,script,scriptlen);
if ( total < amount )
{
printf("change %.8f = total %.8f - amount %.8f, adjust %.8f numvouts.%d, txfee %.8f\n",dstr(change),dstr(total),dstr(amount),dstr(adjust),numvouts,dstr(txfee));
printf("not enough inputs for amount %.8f < %.8f txfee %.8f\n",dstr(total),dstr(amount),dstr(txfee));
return(0);
}
change = (total - amount);
timestamp = (uint32_t)time(NULL);
if ( strcmp("KMD",coin->symbol) == 0 )
@ -936,6 +942,7 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
adjust = change / numvouts;
change = 0;
}
printf("change %.8f = total %.8f - amount %.8f, adjust %.8f numvouts.%d\n",dstr(change),dstr(total),dstr(amount),dstr(adjust),numvouts);
for (i=0; i<numvouts; i++)
{
item = jitem(outputs,i);

38
iguana/exchanges/LP_utxo.c

@ -429,27 +429,6 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
return(retjson);
}
void LP_postutxos(char *symbol,char *coinaddr)
{
bits256 zero; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
if ( (coin= LP_coinfind(symbol)) != 0 && (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
//printf("LP_postutxos pubsock.%d %s %s\n",pubsock,symbol,coin->smartaddr);
if ( cJSON_GetArraySize(array) == 0 )
free_json(array);
else
{
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","postutxos");
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"coinaddr",coinaddr);
jadd(reqjson,"utxos",array);
//printf("post (%s) -> %d\n",msg,LP_mypubsock);
LP_reserved_msg(symbol,symbol,zero,jprint(reqjson,1));
}
}
}
int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
{
int32_t i,n,v,ht,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid;
@ -493,23 +472,6 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
return(count);
}
char *LP_postedutxos(cJSON *argjson)
{
int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array;
//printf("posted.(%s)\n",jprint(argjson,0));
if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) // addsig
{
if ( coin->electrum == 0 || (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( (array= jarray(&n,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);
}
return(clonestr("{\"result\":\"success\"}"));
}
void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout)
{
memcpy(key,txid.bytes,sizeof(txid));

4
iguana/exchanges/LP_utxos.c

@ -262,7 +262,7 @@ void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
utxo->T.spentflag = (uint32_t)time(NULL);
}
char *LP_spentcheck(cJSON *argjson)
/*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");
@ -291,7 +291,7 @@ char *LP_spentcheck(cJSON *argjson)
if ( retval > 0 )
return(clonestr("{\"result\":\"marked as spent\"}"));
return(clonestr("{\"error\":\"cant find txid to check spent status\"}"));
}
}*/
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)
{

5
iguana/exchanges/coins

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