From 10dac4ab97796051d8c7c8540348a9b28abc8b2b Mon Sep 17 00:00:00 2001 From: jl777 Date: Fri, 17 Nov 2017 15:57:19 +0200 Subject: [PATCH] Add back utxo info --- iguana/exchanges/LP_include.h | 11 +++- iguana/exchanges/LP_nativeDEX.c | 7 +- iguana/exchanges/LP_prices.c | 110 +++++++++++++++++++++++++------ iguana/exchanges/LP_signatures.c | 15 ++++- 4 files changed, 119 insertions(+), 24 deletions(-) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index f66fcc9c1..2d928676f 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -364,12 +364,21 @@ struct basilisk_swap }; +struct LP_pubkey_quote +{ + struct LP_pubkey_quote *next,*prev; + float price; + uint32_t maxutxo,aveutxo; + uint8_t baseind,relind,numutxos,scale; +}; + #define LP_MAXPRICEINFOS 256 struct LP_pubkeyinfo { UT_hash_handle hh; bits256 pubkey; - float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; + struct LP_pubkey_quote *quotes; + //float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; //uint32_t timestamps[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; uint32_t timestamp,numerrors,lasttime; int32_t istrusted; diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 3ca6cb879..5b44da252 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -533,8 +533,6 @@ void LP_coinsloop(void *_coins) { if ( (backupep= ep->prev) == 0 ) backupep = ep; - // skip cLP_address MNZ bXcSsYBiVKtTzYErqxvma4UsojZTEf5L6H - //printf("electrum %s\n",coin->symbol); if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) { if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) @@ -892,6 +890,11 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu char *myipaddr=0,version[64]; long filesize,n; int32_t valid,timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx(); sprintf(version,"Marketmaker %s.%s %s rsize.%ld",LP_MAJOR_VERSION,LP_MINOR_VERSION,LP_BUILD_NUMBER,sizeof(struct basilisk_request)); printf("%s %u\n",version,calc_crc32(0,version,(int32_t)strlen(version))); + if ( LP_MAXPRICEINFOS > 256 ) + { + printf("LP_MAXPRICEINFOS %d wont fit in a uint8_t, need to increase the width of the baseind and relind for struct LP_pubkey_quote\n",LP_MAXPRICEINFOS); + exit(-1); + } LP_showwif = juint(argjson,"wif"); if ( passphrase == 0 || passphrase[0] == 0 ) { diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index ade6b75f5..4962d2972 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,7 +18,7 @@ // marketmaker // -struct LP_orderbookentry { bits256 pubkey; double price; uint64_t minsatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; }; +struct LP_orderbookentry { bits256 pubkey; double price; uint64_t avesatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; }; struct LP_priceinfo { @@ -48,6 +48,75 @@ struct LP_cacheinfo uint32_t timestamp; } *LP_cacheinfos; + +float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind) +{ + struct LP_pubkey_quote *pq,*tmp; int32_t scale; int64_t scale64; + *numutxosp = 0; + *avesatoshisp = *maxsatoshisp = 0; + DL_FOREACH_SAFE(pubp->quotes,pq,tmp) + { + if ( baseind == pq->baseind && relind == pq->relind ) + { + if ( (scale= pq->scale) == 0 ) + pq->scale = scale = 6; + scale64 = 1; + while ( scale > 0 ) + { + scale64 *= 10; + scale--; + } + *numutxosp = pq->numutxos; + *avesatoshisp = pq->aveutxo * scale64; + *maxsatoshisp = pq->maxutxo * scale64; + return(pq->price); + } + } + return(0); +} + +void LP_pubkey_update(struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,int32_t numutxos,int64_t minutxo,int64_t maxutxo) +{ + struct LP_pubkey_quote *pq,*tmp; int64_t aveutxo,scale64,ave64,max64; int32_t scale; + DL_FOREACH_SAFE(pubp->quotes,pq,tmp) + { + if ( baseind == pq->baseind && relind == pq->relind ) + break; + pq = 0; + } + if ( pq == 0 ) + { + pq = calloc(1,sizeof(*pq)); + pq->baseind = baseind; + pq->relind = relind; + pq->scale = 6; // millions of SATOSHIS, ie. 0.01 + DL_APPEND(pubp->quotes,pq); // already serialized as only path is via stats_JSON() + } + pq->price = price; + if ( numutxos != 0 ) + { + if ( (scale= pq->scale) == 0 ) + pq->scale = scale = 6; + scale64 = 1; + while ( scale > 0 ) + { + scale64 *= 10; + scale--; + } + if ( numutxos > (1L << sizeof(pq->numutxos)) ) + pq->numutxos = (1L << sizeof(pq->numutxos)) - 1; + else pq->numutxos = numutxos; + aveutxo = balance / numutxos; + if ( (ave64= (aveutxo / scale64)) > (1LL << 32) ) + ave64 = (1LL << 32) - 1; + if ( (max64= (maxutxo / scale64)) > (1LL << 32) ) + max64 = (1LL << 32) - 1; + pq->aveutxo = (uint32_t)ave64; + pq->maxutxo = (uint32_t)max64; + printf("scale64 = %llu, ave %llu, ave32 %u (%llu) max32 %u (%llu)\n",(long long)scale64,(long long)aveutxo,pq->aveutxo,(long long)pq->aveutxo * scale64,pq->maxutxo,(long long)pq->maxutxo * scale64); + } +} + struct LP_priceinfo *LP_priceinfo(int32_t ind) { if ( ind < 0 || ind >= LP_MAXPRICEINFOS ) @@ -272,7 +341,7 @@ uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) { - int32_t baseid,relid; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj; + int32_t baseid,relid,numutxos; int64_t avesatoshis,maxsatoshis; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj; obj = cJSON_CreateObject(); array = cJSON_CreateArray(); for (baseid=0; baseidmatrix[baseid][relid]; + price = LP_pubkey_price(&numutxos,&avesatoshis,&maxsatoshis,pubp,baseid,relid);//pubp->matrix[baseid][relid]; if ( LP_pricevalid(price) > 0 ) { item = cJSON_CreateArray(); @@ -495,7 +564,8 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price) if ( (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 ) { pubp->timestamp = (uint32_t)time(NULL); - pubp->matrix[basepp->ind][relpp->ind] = price; + LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,0,0,0,0); + //pubp->matrix[basepp->ind][relpp->ind] = price; //pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp; //pubp->matrix[relpp->ind][basepp->ind] = (1. / price); } @@ -671,7 +741,7 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op) jaddstr(item,"address",op->coinaddr); jaddnum(item,"price",op->price); jaddnum(item,"numutxos",op->numutxos); - jaddnum(item,"minvolume",dstr(op->minsatoshis)*0.8); + jaddnum(item,"avevolume",dstr(op->avesatoshis)*0.8); jaddnum(item,"maxvolume",dstr(op->maxsatoshis)*0.8); jaddnum(item,"depth",dstr(op->depth)*0.8); jaddbits256(item,"pubkey",op->pubkey); @@ -680,7 +750,7 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op) return(item); } -struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t minsatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance) +struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t avesatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance) { struct LP_orderbookentry *op; if ( (op= calloc(1,sizeof(*op))) != 0 ) @@ -688,8 +758,8 @@ struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,d safecopy(op->coinaddr,address,sizeof(op->coinaddr)); op->price = price; op->numutxos = numutxos; - op->minsatoshis = minsatoshis; - op->maxsatoshis = maxsatoshis; + op->avesatoshis = avesatoshis; + op->maxsatoshis = avesatoshis; op->pubkey = pubkey; op->timestamp = timestamp; op->depth = balance; @@ -718,7 +788,7 @@ void LP_pubkeys_query() int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration) { - char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; uint64_t minsatoshis,maxsatoshis,balance; + char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis; if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) baseid = basepp->ind; else return(num); @@ -737,23 +807,23 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char * if ( pubp->timestamp < oldest ) continue; bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); - minsatoshis = maxsatoshis = n = 0; + avesatoshis = maxsatoshis = n = 0; ap = 0; - if ( (price= pubp->matrix[baseid][relid]) > SMALLVAL )//&& pubp->timestamps[baseid][relid] >= oldest ) + if ( (price= LP_pubkey_price(&n,&avesatoshis,&maxsatoshis,pubp,baseid,relid)) > SMALLVAL ) //pubp->matrix[baseid][relid]) > SMALLVAL )//&& pubp->timestamps[baseid][relid] >= oldest ) { - balance = 0; - if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 ) + balance = avesatoshis * n; + //if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 ) { - n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap); + //n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap); if ( polarity > 0 ) { balance *= price; - minsatoshis *= price; + avesatoshis *= price; maxsatoshis *= price; } //printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total)); } - if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,minsatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance)) != 0 ) + if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance)) != 0 ) { *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); (*arrayp)[num++] = op; @@ -1036,7 +1106,7 @@ cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,i return(retarray); } -void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) +void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,int32_t numutxos,int64_t balance,int64_t minutxo,int64_t maxutxo) { struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *pubp; char str[65],fname[512]; FILE *fp; //printf("check PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey)); @@ -1073,9 +1143,11 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) if ( (LP_rand() % 1000) == 0 ) printf("PRICEFEED UPDATE.(%-6s/%6s) %12.8f %s %12.8f\n",base,rel,price,bits256_str(str,pubkey),1./price); pubp->timestamp = (uint32_t)time(NULL); - if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL ) + LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,balance,numutxos,minutxo,maxutxo); + //pubp->depthinfo[basepp->ind][relpp->ind] = LP_depthinfo_compact(); + //if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL ) { - pubp->matrix[basepp->ind][relpp->ind] = price; + //pubp->matrix[basepp->ind][relpp->ind] = price; //pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp; dxblend(&basepp->relvals[relpp->ind],price,0.9); dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c index e729421ad..5a7ab184d 100644 --- a/iguana/exchanges/LP_signatures.c +++ b/iguana/exchanges/LP_signatures.c @@ -451,7 +451,8 @@ int32_t LP_price_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pub char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price) { - struct iguana_info *basecoin,*relcoin; char pubsecpstr[67]; uint32_t timestamp; uint64_t price64; bits256 zero; cJSON *reqjson = cJSON_CreateObject(); + struct iguana_info *basecoin,*relcoin; struct LP_address *ap; char pubsecpstr[67]; uint32_t numutxos,timestamp; uint64_t price64,balance,minsize,maxsize; bits256 zero; cJSON *reqjson; + reqjson = cJSON_CreateObject(); // LP_addsig if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 )//&& relcoin->electrum == 0 ) { @@ -467,6 +468,16 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re jaddnum(reqjson,"timestamp",timestamp); init_hexbytes_noT(pubsecpstr,G.LP_pubsecp,33); jaddstr(reqjson,"pubsecp",pubsecpstr); + if ( (ap= LP_address(basecoin,basecoin->smartaddr)) != 0 ) + { + if ( (numutxos= LP_address_minmax(&balance,&minsize,&maxsize,ap)) != 0 ) + { + jaddnum(reqjson,"n",numutxos); + jaddnum(reqjson,"bal",dstr(balance)); + jaddnum(reqjson,"min",dstr(minsize)); + jaddnum(reqjson,"max",dstr(maxsize)); + } + } LP_price_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_pubsecp,G.LP_mypub25519,base,rel,price64); LP_reserved_msg(0,base,rel,zero,jprint(reqjson,1)); return(clonestr("{\"result\":\"success\"}")); @@ -484,7 +495,7 @@ char *LP_postprice_recv(cJSON *argjson) { if ( LP_price_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,base,rel,j64bits(argjson,"price64")) == 0 ) { - LP_pricefeedupdate(pubkey,base,rel,price); + LP_pricefeedupdate(pubkey,base,rel,price,jint(argjson,"n"),jdouble(argjson,"bal")*SATOSHIDEN,jdouble(argjson,"min")*SATOSHIDEN,jdouble(argjson,"max")*SATOSHIDEN); return(clonestr("{\"result\":\"success\"}")); } else return(clonestr("{\"error\":\"sig failure\"}")); }