Browse Source

Fix spurious address in getaddressesbyaccount

etomic
jl777 8 years ago
parent
commit
dfd4e08807
  1. 10
      .gitignore
  2. 822
      iguana/exchanges/DEXstats.h
  3. 679
      iguana/exchanges/stats.c
  4. 3
      iguana/iguana_wallet.c
  5. BIN
      iguana/stats
  6. 2
      iguana/tests/statstest

10
.gitignore

@ -411,3 +411,13 @@ iguana/DB/SWAPS/912783809-2523701920
iguana/DB/SWAPS/1238069553-2363573428
iguana/DB/SWAPS/2895470622-2170247626
iguana/confs/ed476386688e486f359ce67e44ce4268a875125527e122ea9126ebc54f473d31
iguana/confs/f6e8e8ab82ed33b2de063d6820dcaefb99b95cf1aef6527b8f27e1e5b1fe882d
iguana/e
iguana/a
iguana/t

822
iguana/exchanges/DEXstats.h

@ -0,0 +1,822 @@
//
// DEXstats.h
// marketmaker
//
// Created by Mac on 5/7/17.
// Copyright © 2017 SuperNET. All rights reserved.
//
#ifndef DEXstats_h
#define DEXstats_h
#define LEFTMARGIN 40
#define MAX_SPLINES 1024
#define MAX_LOOKAHEAD 60
struct stats_spline { char name[64]; int32_t splineid,lasti,basenum,num,firstx,dispincr,spline32[MAX_SPLINES][4]; uint32_t utc32[MAX_SPLINES]; int64_t spline64[MAX_SPLINES][4]; double dSplines[MAX_SPLINES][4],pricevals[MAX_SPLINES+MAX_LOOKAHEAD],lastutc,lastval,aveslopeabs; };
#define _extrapolate_Spline(Splines,gap) ((double)(Splines)[0] + ((gap) * ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))))
#define _extrapolate_Slope(Splines,gap) ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))
#define dto64(x) ((int64_t)((x) * (double)SATOSHIDEN * SATOSHIDEN))
#define dto32(x) ((int32_t)((x) * (double)SATOSHIDEN))
#define i64tod(x) ((double)(x) / ((double)SATOSHIDEN * SATOSHIDEN))
#define i32tod(x) ((double)(x) / (double)SATOSHIDEN)
#define _extrapolate_spline64(spline64,gap) ((double)i64tod((spline64)[0]) + ((gap) * ((double)i64tod(.001*.001*(spline64)[1]) + ((gap) * ((double)i64tod(.001*.001*.001*.001*(spline64)[2]) + ((gap) * (double)i64tod(.001*.001*.001*.001*.001*.001*(spline64)[3])))))))
#define _extrapolate_spline32(spline32,gap) ((double)i32tod((spline32)[0]) + ((gap) * ((double)i32tod(.001*.001*(spline32)[1]) + ((gap) * ((double)i32tod(.001*.001*.001*.001*(spline32)[2]) + ((gap) * (double)i32tod(.001*.001*.001*.001*.001*.001*(spline32)[3])))))))
uint32_t forex_colors[16];
double Display_scale = 1.;
struct DEXstats_disp { double pricesum,volumesum; };
struct DEXstats_pricepoint
{
double price,volume;
uint32_t height:27,hour:5;
uint16_t seconds;
};
struct DEXstats_pairinfo
{
char dest[16];
int32_t numprices;
struct DEXstats_pricepoint *prices;
};
struct DEXstats_datenuminfo
{
int32_t numpairs,datenum;
struct DEXstats_pairinfo *pairs;
};
struct DEXstats_priceinfo
{
char symbol[16];
int32_t firstdatenum,numdates;
struct DEXstats_datenuminfo *dates;
} Prices[1024];
int32_t Num_priceinfos;
void stats_pricepoint(struct DEXstats_pricepoint *ptr,uint8_t hour,uint16_t seconds,int32_t height,double volume,double price)
{
ptr->price = price;
ptr->volume = volume;
ptr->height = height;
ptr->hour = hour;
ptr->seconds = seconds;
printf("h.%d s.%-4d %.8f %.6f\n",hour,seconds,price,volume);
}
void stats_pairupdate(struct DEXstats_datenuminfo *date,char *dest,int32_t datenum,int32_t hour,int32_t seconds,int32_t height,double volume,double price)
{
int32_t i; struct DEXstats_pairinfo *pair = 0;
if ( date->datenum != datenum || seconds < 0 || seconds >= 3600 || hour < 0 || hour >= 24 )
{
printf("date->datenum %d != %d? hour.%d seconds.%d\n",date->datenum,datenum,hour,seconds);
return;
}
for (i=0; i<date->numpairs; i++)
if ( strcmp(dest,date->pairs[i].dest) == 0 )
{
pair = &date->pairs[i];
break;
}
if ( i == date->numpairs )
{
date->pairs = realloc(date->pairs,sizeof(*date->pairs) * (date->numpairs + 1));
pair = &date->pairs[date->numpairs++];
memset(pair,0,sizeof(*pair));
strcpy(pair->dest,dest);
}
pair->prices = realloc(pair->prices,sizeof(*pair->prices) * (pair->numprices+1));
stats_pricepoint(&pair->prices[pair->numprices++],hour,seconds,height,volume,price);
}
void stats_datenumupdate(struct DEXstats_priceinfo *pp,int32_t datenum,int32_t hour,int32_t seconds,int32_t height,double volume,char *dest,double price)
{
int32_t offset,i,n; struct DEXstats_datenuminfo *date;
if ( (offset= datenum - pp->firstdatenum) < 0 )
{
printf("illegal datenum.%d for %s when 1st.%d\n",datenum,pp->symbol,pp->firstdatenum);
return;
}
if ( offset > pp->numdates )
{
pp->dates = realloc(pp->dates,sizeof(*pp->dates) * (offset+1));
n = (offset - pp->numdates);
for (i=0; i<=n; i++)
{
date = &pp->dates[pp->numdates + i];
memset(date,0,sizeof(*date));
date->datenum = pp->firstdatenum + pp->numdates + i;
}
}
stats_pairupdate(&pp->dates[offset],dest,datenum,hour,seconds,height,volume,price);
}
struct DEXstats_priceinfo *stats_priceinfo(char *symbol,int32_t datenum)
{
int32_t i; struct DEXstats_priceinfo *pp = 0;
if ( Num_priceinfos >= sizeof(Prices)/sizeof(*Prices) )
return(0);
for (i=0; i<Num_priceinfos; i++)
if ( strcmp(Prices[i].symbol,symbol) == 0 )
{
pp = &Prices[i];
break;
}
if ( i == Num_priceinfos )
{
pp = &Prices[Num_priceinfos++];
strcpy(pp->symbol,symbol);
pp->firstdatenum = datenum;
}
return(pp);
}
void stats_LPpubkeyupdate(char *LPpubkey,uint32_t timestamp)
{
printf("LP.(%s) t.%u\n",LPpubkey,timestamp);
}
void stats_priceupdate(int32_t datenum,int32_t hour,int32_t seconds,uint32_t timestamp,int32_t height,char *key,char *LPpubkey,cJSON *tradejson)
{
uint64_t srcamount,destamount; char *source,*dest; double price; struct DEXstats_priceinfo *pp;
if ( LPpubkey != 0 )
stats_LPpubkeyupdate(LPpubkey,timestamp);
if ( tradejson != 0 )
{
source = jstr(jitem(tradejson,0),0);
srcamount = SATOSHIDEN * jdouble(jitem(tradejson,1),0);
dest = jstr(jitem(tradejson,2),0);
destamount = SATOSHIDEN * jdouble(jitem(tradejson,3),0);
if ( srcamount != 0 && destamount != 0 )
{
price = (double)destamount / srcamount;
if ( (pp= stats_priceinfo(source,datenum)) != 0 )
stats_datenumupdate(pp,datenum,hour,seconds,height,dstr(srcamount),dest,price);
if ( (pp= stats_priceinfo(dest,datenum)) != 0 )
stats_datenumupdate(pp,datenum,hour,seconds,height,dstr(destamount),source,1. / price);
} else price = 0.;
printf("%d.%02d.%04d ht.%-4d %s (%s %12.8f) -> (%s %12.8f) %16.8f %16.8f\n",datenum,hour,seconds,height,key,source,dstr(srcamount),dest,dstr(destamount),price,1./price);
}
}
double _pairaved(double valA,double valB)
{
if ( valA != 0. && valB != 0. )
return((valA + valB) / 2.);
else if ( valA != 0. ) return(valA);
else return(valB);
}
double calc_loganswer(double pastlogprice,double futurelogprice)
{
if ( fabs(pastlogprice) < .0000001 || fabs(futurelogprice) < .0000001 )
return(0);
return(10000. * (exp(futurelogprice - pastlogprice)-1.));
}
double _pairdiff(register double valA,register double valB)
{
if ( valA != 0. && valB != 0. )
return((valA - valB));
else return(0.);
}
double balanced_ave(double buf[],int32_t i,int32_t width)
{
register int32_t nonz,j; register double sum,price;
nonz = 0;
sum = 0.0;
for (j=-width; j<=width; j++)
{
price = buf[i + j];
if ( price != 0.0 )
{
sum += price;
nonz++;
}
}
if ( nonz != 0 )
sum /= nonz;
return(sum);
}
void buf_trioave(double dest[],double src[],int32_t n)
{
register int32_t i,j,width = 3;
for (i=0; i<128; i++)
src[i] = 0;
//for (i=n-width-1; i>width; i--)
// dest[i] = balanced_ave(src,i,width);
//for (i=width; i>0; i--)
// dest[i] = balanced_ave(src,i,i);
for (i=1; i<width; i++)
dest[i] = balanced_ave(src,i,i);
for (i=width; i<1024-width; i++)
dest[i] = balanced_ave(src,i,width);
dest[0] = _pairaved(dest[0],dest[1] - _pairdiff(dest[2],dest[1]));
j = width-1;
for (i=1024-width; i<1023; i++,j--)
dest[i] = balanced_ave(src,i,j);
if ( dest[1021] != 0. && dest[1021] != 0. )
dest[1023] = ((2.0 * dest[1022]) - dest[1021]);
else dest[1023] = 0.;
}
void smooth1024(double dest[],double src[],int32_t smoothiters)
{
double smoothbufA[1024],smoothbufB[1024]; int32_t i;
buf_trioave(smoothbufA,src,1024);
for (i=0; i<smoothiters; i++)
{
buf_trioave(smoothbufB,smoothbufA,1024);
buf_trioave(smoothbufA,smoothbufB,1024);
}
buf_trioave(dest,smoothbufA,1024);
}
float _calc_pricey(register double price,register double weekave)
{
if ( price != 0. && weekave != 0. )
return(.2 * calc_loganswer(weekave,price));
else return(0.f);
}
float pixelwt(register int32_t color)
{
return(((float)((color>>16)&0x0ff) + (float)((color>>8)&0x0ff) + (float)((color>>0)&0x0ff))/0x300);
}
int32_t pixel_ratios(uint32_t red,uint32_t green,uint32_t blue)
{
float max;
/*if ( red > green )
max = red;
else
max = green;
if ( blue > max )
max = blue;*/
max = (red + green + blue);
if ( max == 0. )
return(0);
if ( max > 0xff )
{
red = (uint32_t)(((float)red / max) * 0xff);
green = (uint32_t)(((float)green / max) * 0xff);
blue = (uint32_t)(((float)blue / max) * 0xff);
}
if ( red > 0xff )
red = 0xff;
if ( green > 0xff )
green = 0xff;
if ( blue > 0xff )
blue = 0xff;
return((red << 16) | (green << 8) | blue);
}
int32_t conv_yval_to_y(register float yval,register int32_t height)
{
register int32_t y;
height = (height>>1) - 2;
y = (int32_t)-yval;
if ( y > height )
y = height;
else if ( y < -height )
y = -height;
y += height;
if ( y < 0 )
y = 0;
height <<= 1;
if ( y >= height-1 )
y = height-1;
return(y);
}
uint32_t scale_color(uint32_t color,float strength)
{
int32_t red,green,blue;
if ( strength < 0. )
strength = -strength;
red = (color>>16) & 0xff;
green = (color>>8) & 0xff;
blue = color & 0xff;
red = (int32_t)((float)red * (strength/100.f));
green = (int32_t)((float)green * (strength/100.f));
blue = (int32_t)((float)blue * (strength/100.f));
if ( red > 0xff )
red = 0xff;
if ( green > 0xff )
green = 0xff;
if ( blue > 0xff )
blue = 0xff;
return((red<<16) | (green<<8) | blue);
}
uint32_t pixel_blend(uint32_t pixel,uint32_t color)//,int32_t groupsize)
{
int32_t red,green,blue,sum,n,n2,groupsize = 1;
float red2,green2,blue2,sum2;
if ( color == 0 )
return(pixel);
if ( pixel == 0 )
{
return((1<<24) | scale_color(color,100.f/(float)groupsize));
}
n = (pixel>>24) & 0xff;
if ( n == 0 )
n = 1;
pixel &= 0xffffff;
red = (pixel>>16) & 0xff;
green = (pixel>>8) & 0xff;
blue = pixel & 0xff;
sum = red + green + blue;
n2 = (color>>24) & 0xff;
if ( n2 == 0 )
n2 = 1;
red2 = ((float)((color>>16) & 0xff)) / groupsize;
green2 = ((float)((color>>8) & 0xff)) / groupsize;
blue2 = ((float)(color & 0xff)) / groupsize;
sum2 = (red2 + green2 + blue2);
//printf("gs %d (%d x %d,%d,%d: %d) + (%d x %.1f,%.1f,%.1f: %.1f) = ",groupsize,n,red,green,blue,sum,n2,red2,green2,blue2,sum2);
red = (uint32_t)(((((((float)red / (float) sum) * n) + (((float)red2 / (float) sum2) * n2)) / (n+n2)) * ((sum+sum2)/2)));
green = (uint32_t)(((((((float)green / (float) sum) * n) + (((float)green2 / (float) sum2) * n2)) / (n+n2)) * ((sum+sum2)/2)));
blue = (uint32_t)(((((((float)blue / (float) sum) * n) + (((float)blue2 / (float) sum2) * n2)) / (n+n2)) * ((sum+sum2)/2)));
n += n2;
if ( n > 0xff )
n = 0xff;
///printf("%x (%d,%d,%d) ",color,red,green,blue);
color = (n<<24) | pixel_ratios(red,green,blue);//pixel_overflow(&red,&green,&blue);
//printf("%x (%d,%d,%d)\n",color,(color>>16)&0xff,(color>>8)&0xff,color&0xff);
return(color);
}
void init_forex_colors(uint32_t *forex_colors)
{
int32_t i;
forex_colors[0] = 0x00ff00;
forex_colors[1] = 0x0033ff;
forex_colors[2] = 0xff0000;
forex_colors[3] = 0x00ffff;
forex_colors[4] = 0xffff00;
forex_colors[5] = 0xff00ff;
forex_colors[6] = 0xffffff;
forex_colors[7] = 0xff8800;
forex_colors[8] = 0xff88ff;
for (i=9; i<16; i++)
forex_colors[i] = pixel_blend(forex_colors[i-8],0xffffff);
}
int32_t is_primary_color(register uint32_t color)
{
static uint32_t forex_colors[16];
register int32_t i;
if ( forex_colors[0] == 0 )
init_forex_colors(forex_colors);
for (i=0; i<8; i++)
if ( color == forex_colors[i] )
return(1);
return(0);
}
void disp_yval(register int32_t color,register float yval,register uint32_t *bitmap,register int32_t x,register int32_t rowwidth,register int32_t height)
{
register int32_t y;
if ( forex_colors[0] == 0 )
init_forex_colors(forex_colors);
x += LEFTMARGIN;
if ( x < 0 || x >= rowwidth )
return;
//y = conv_yval_to_y(yval,height/Display_scale) * Display_scale;
y = conv_yval_to_y(yval * Display_scale,height);
if ( 1 && is_primary_color(color) != 0 )
{
bitmap[y*rowwidth + x] = color;
return;
}
//if ( pixelwt(color) > pixelwt(bitmap[y*rowwidth + x]) )
bitmap[y*rowwidth + x] = pixel_blend(bitmap[y*rowwidth + x],color);
return;
//if ( is_primary_color(color) != 0 || (is_primary_color(bitmap[y*rowwidth+x]) == 0 && pixelwt(color) > pixelwt(bitmap[y*rowwidth + x])) )
// bitmap[y*rowwidth + x] = color;
}
void disp_yvalsum(register int32_t color,register float yval,register uint32_t *bitmap,register int32_t x,register int32_t rowwidth,register int32_t height)
{
int32_t y,red,green,blue,dispcolor;
x += LEFTMARGIN;
if ( x < 0 || x >= rowwidth )
return;
y = conv_yval_to_y(yval * Display_scale,height);
red = (color>>16) & 0xff;
green = (color>>8) & 0xff;
blue = color & 0xff;
dispcolor = bitmap[y*rowwidth + x];
red += (dispcolor>>16) & 0xff;
green += (dispcolor>>8) & 0xff;
blue += dispcolor & 0xff;
bitmap[y*rowwidth + x] = pixel_ratios(red,green,blue);
}
void disp_dot(register float radius,register int32_t color,register float yval,register uint32_t *bitmap,register int32_t x,register int32_t rowwidth,register int32_t height)
{
register float i,j,sq,val;
if ( radius > 1 )
{
sq = radius * radius;
for (i=-radius; i<=radius; i++)
{
for (j=-radius; j<=radius; j++)
{
val = ((j*j + i*i) / sq);
if ( val <= 1. )
{
val = 1. - val;
disp_yval(scale_color(color,(100 * val * val * val * val)),yval+j,bitmap,x+i,rowwidth,height);
}
}
}
}
else disp_yval(color,yval,bitmap,x,rowwidth,height);
}
void horizline(int32_t calclogflag,int32_t rowwidth,int32_t height,uint32_t *bitmap,double rawprice,double ave)
{
int32_t x;
double yval;
if ( calclogflag != 0 )
yval = _calc_pricey(log(rawprice),log(ave));
else yval = _calc_pricey(rawprice,ave);
for (x=0; x<rowwidth; x++)
disp_yval(0x888888,yval,bitmap,x,rowwidth,height);
}
void rescale_floats(float *line,int32_t width,double scale)
{
int32_t i;
for (i=0; i<width; i++)
line[i] *= scale;
}
void rescale_doubles(double *line,int32_t width,double scale)
{
int32_t i;
for (i=0; i<width; i++)
line[i] *= scale;
}
double _output_line(int32_t calclogflag,double ave,double *output,double *buf,int32_t n,int32_t color,uint32_t *bitmap,int32_t rowwidth,int32_t height)
{
int32_t x,nonz = 0;
double yval,val,aveabs = 0.;
if ( ave == 0. )
return(0.);
if ( calclogflag != 0 )
ave = log(ave);
for (x=0; x<n; x++)
{
if ( (val= buf[x]) != 0 )
{
if ( calclogflag != 0 )
val = log(buf[x]);
if ( ave != 1. )
yval = _calc_pricey(val,ave);
else yval = val;
printf("%f ",yval);
if ( fabs(yval) > .0000000001 )
{
aveabs += fabs(yval);
nonz++;
if ( color != 0 )
disp_yval(color,yval,bitmap,x,rowwidth,height);
}
} else yval = 0.;
output[x] = yval;
}
if ( nonz != 0 )
aveabs /= nonz;
return(aveabs);
//
//printf("ave %f rowwidth.%d\n",ave,rowwidth);
}
double stats_splineval(struct stats_spline *spline,uint32_t timestamp,int32_t lookahead)
{
int32_t i,gap,ind = (spline->num - 1);
if ( timestamp >= spline->utc32[ind] )
{
gap = (timestamp - spline->utc32[ind]);
if ( gap < lookahead )
return(_extrapolate_spline64(spline->spline64[ind],gap));
else return(0.);
}
else if ( timestamp <= spline->utc32[0] )
{
gap = (spline->utc32[0] - timestamp);
if ( gap < lookahead )
return(_extrapolate_spline64(spline->spline64[0],gap));
else return(0.);
}
for (i=0; i<spline->num-1; i++)
{
ind = (i + spline->lasti) % (spline->num - 1);
if ( timestamp >= spline->utc32[ind] && timestamp < spline->utc32[ind+1] )
{
spline->lasti = ind;
return(_extrapolate_spline64(spline->spline64[ind],timestamp - spline->utc32[ind]));
}
}
return(0.);
}
double stats_calcspline(struct stats_spline *spline,double *outputs,double *slopes,int32_t dispwidth,uint32_t *utc32,double *splinevals,int32_t num)
{
static double errsums[3]; static int errcount;
double c[MAX_SPLINES],f[MAX_SPLINES],dd[MAX_SPLINES],dl[MAX_SPLINES],du[MAX_SPLINES],gaps[MAX_SPLINES];
int32_t n,i,lasti,x,numsplines,nonz; double vx,vy,vw,vz,gap,sum,xval,yval,abssum,lastval,lastxval,yval64,yval32,yval3; uint32_t gap32;
sum = lastxval = n = lasti = nonz = 0;
for (i=0; i<MAX_SPLINES&&i<num; i++)
{
if ( (f[n]= splinevals[i]) != 0. && utc32[i] != 0 )
{
//printf("i%d.(%u %f) ",i,utc32[i],splinevals[i]);
//printf("%f ",splinevals[i]);
if ( n > 0 )
{
if ( (gaps[n-1]= utc32[i] - lastxval) < 0 )
{
printf("illegal gap %f to t%d\n",lastxval,utc32[i]);
return(0);
}
}
spline->utc32[n] = lastxval = utc32[i];
n++;
}
}
if ( (numsplines= n) < 4 )
return(0);
for (i=0; i<n-3; i++)
dl[i] = du[i] = gaps[i+1];
for (i=0; i<n-2; i++)
{
dd[i] = 2.0 * (gaps[i] + gaps[i+1]);
c[i] = (3.0 / (double)gaps[i+1]) * (f[i+2] - f[i+1]) - (3.0 / (double)gaps[i]) * (f[i+1] - f[i]);
}
//for (i=0; i<n; i++)
// printf("%f ",f[i]);
//printf("F2[%d]\n",n);
dd[0] += (gaps[0] + (double)gaps[0]*gaps[0] / gaps[1]);
du[0] -= ((double)gaps[0]*gaps[0] / gaps[1]);
dd[n-3] += (gaps[n-2] + (double)gaps[n-2]*gaps[n-2] / gaps[n-3]);
dl[n-4] -= ((double)gaps[n-2]*gaps[n-2] / gaps[n-3]);
//tridiagonal(n-2, dl, dd, du, c);
for (i=0; i<n-1-2; i++)
{
du[i] /= dd[i];
dd[i+1] -= dl[i]*du[i];
}
c[0] /= dd[0];
for (i=1; i<n-2; i++)
c[i] = (c[i] - dl[i-1] * c[i-1]) / dd[i];
for (i=n-2-4; i>=0; i--)
c[i] -= c[i+1] * du[i];
//tridiagonal(n-2, dl, dd, du, c);
for (i=n-3; i>=0; i--)
c[i+1] = c[i];
c[0] = (1.0 + (double)gaps[0] / gaps[1]) * c[1] - ((double)gaps[0] / gaps[1] * c[2]);
c[n-1] = (1.0 + (double)gaps[n-2] / gaps[n-3] ) * c[n-2] - ((double)gaps[n-2] / gaps[n-3] * c[n-3]);
//printf("c[n-1] %f, n-2 %f, n-3 %f\n",c[n-1],c[n-2],c[n-3]);
abssum = nonz = lastval = 0;
outputs[spline->firstx] = f[0];
spline->num = numsplines;
for (i=0; i<n; i++)
{
vx = f[i];
vz = c[i];
if ( i < n-1 )
{
gap = gaps[i];
vy = ((f[i+1] - f[i]) / gap) - (gap * (c[i+1] + 2.*c[i]) / 3.);
vw = (c[i+1] - c[i]) / (3. * gap);
}
else
{
vy = 0;
vw = 0;
}
//printf("%3d: t%u [%14.11f %14.11f %14.11f %14.11f] gap %f | %d\n",i,spline->utc32[i],(vx),vy*1000*1000,vz*1000*1000*1000*1000,vw*1000*1000*1000*1000*1000*1000,gap,conv_unixtime(&tmp,spline->utc32[i]));
spline->dSplines[i][0] = vx, spline->dSplines[i][1] = vy, spline->dSplines[i][2] = vz, spline->dSplines[i][3] = vw;
spline->spline64[i][0] = dto64(vx), spline->spline64[i][1] = dto64(vy*1000*1000), spline->spline64[i][2] = dto64(vz*1000*1000*1000*1000), spline->spline64[i][3] = dto64(vw*1000*1000*1000*1000*1000*1000);
spline->spline32[i][0] = dto32(vx), spline->spline32[i][1] = dto32(vy*1000*1000), spline->spline32[i][2] = dto32(vz*1000*1000*1000*1000), spline->spline32[i][3] = dto32(vw*1000*1000*1000*1000*1000*1000);
gap32 = gap = spline->dispincr;
xval = spline->utc32[i] + gap;
lastval = vx;
while ( i < n-1 )
{
x = spline->firstx + ((xval - spline->utc32[0]) / spline->dispincr);
if ( x > dispwidth-1 ) x = dispwidth-1;
if ( x < 0 ) x = 0;
if ( (i < n-2 && gap > gaps[i] + spline->dispincr) )
break;
if ( i == n-2 && xval > spline->utc32[n-1] + MAX_LOOKAHEAD*spline->dispincr )
{
//printf("x.%d dispwidth.%d xval %f > utc[n-1] %f + %f\n",x,dispwidth,xval,utc[n-1],MAX_LOOKAHEAD*incr);
break;
}
if ( x >= 0 )
{
yval = _extrapolate_Spline(spline->dSplines[i],gap);
yval64 = _extrapolate_spline64(spline->spline64[i],gap32);
if ( (yval3 = stats_splineval(spline,gap32 + spline->utc32[i],MAX_LOOKAHEAD*spline->dispincr)) != 0 )
{
yval32 = _extrapolate_spline32(spline->spline32[i],gap32);
errsums[0] += fabs(yval - yval64), errsums[1] += fabs(yval - yval32), errsums[2] += fabs(yval - yval3), errcount++;
if ( fabs(yval - yval3) > SMALLVAL )
printf("(%.10f vs %.10f %.10f %.10f [%.16f %.16f %.16f]) ",yval,yval64,yval32,yval3, errsums[0]/errcount,errsums[1]/errcount,errsums[2]/errcount);
}
if ( yval > 5000. ) yval = 5000.;
else if ( yval < -5000. ) yval = -5000.;
if ( isnan(yval) == 0 )
{
outputs[x] = yval;
spline->lastval = outputs[x], spline->lastutc = xval;
if ( 1 && fabs(lastval) > SMALLVAL )
{
if ( lastval != 0 && outputs[x] != 0 )
{
if ( slopes != 0 )
slopes[x] = (outputs[x] - lastval), abssum += fabs(slopes[x]);
nonz++;
}
}
}
//else outputs[x] = 0.;
//printf("x.%-4d %d %f %f %f i%-4d: gap %9.6f %9.6f last %9.6f slope %9.6f | %9.1f [%9.1f %9.6f %9.6f %9.6f %9.6f]\n",x,firstx,xval,utc[0],incr,i,gap,yval,lastval,slopes[x],xval,utc[i+1],dSplines[i][0],dSplines[i][1]*1000*1000,dSplines[i][2]*1000*1000*1000*1000,dSplines[i][3]*1000*1000*1000*1000*1000*1000);
}
gap32 += spline->dispincr, gap += spline->dispincr, xval += spline->dispincr;
}
//double pred = (i>0) ? _extrapolate_Spline(dSplines[i-1],gaps[i-1]) : 0.;
//printf("%2d: w%8.1f [gap %f -> %9.6f | %9.6f %9.6f %9.6f %9.6f %9.6f]\n",i,weekinds[i],gap,pred,f[i],dSplines[i].x,1000000*dSplines[i].y,1000000*1000000*dSplines[i].z,1000000*1000000*1000*dSplines[i].w);
}
if ( nonz != 0 )
abssum /= nonz;
spline->aveslopeabs = abssum;
return(lastval);
}
int32_t stats_genspline(double output[2048],double slopes[2048],struct stats_spline *spline,int32_t splineid,char *name,uint32_t *utc32,double *splinevals,int32_t numsplines,double *refvals)
{
int32_t i; double origvals[MAX_SPLINES];
if ( numsplines > MAX_SPLINES )
{
printf("numsplines.%d > MAX_SPLINES.%d\n",numsplines,MAX_SPLINES);
return(-1);
}
memset(spline,0,sizeof(*spline)), memset(output,0,sizeof(*output)*2048), memset(slopes,0,sizeof(*slopes)*2048);
spline->dispincr = 3600, spline->basenum = splineid, strcpy(spline->name,name);
memcpy(origvals,splinevals,sizeof(*splinevals) * MAX_SPLINES);
spline->lastval = stats_calcspline(spline,output,slopes,2048,utc32,splinevals,numsplines);
if ( refvals != 0 )
{
for (i=0; i<spline->num; i++)
{
if ( i < spline->num )
{
if ( 0 && refvals[i] != 0 && output[i * 24] != refvals[i] )
printf("{%.8f != %.8f}.%d ",output[i * 24],refvals[i],i);
spline->pricevals[i] = output[i * 24];
}
}
}
//printf("spline.%s num.%d\n",name,spline->num);
return(spline->num);
}
void output_line(int32_t calclogflag,double ave,double *buf,int32_t n,int32_t color,uint32_t *bitmap,int32_t rowwidth,int32_t height)
{
double src[1024],dest[1024]; int32_t i;
memset(src,0,sizeof(src));
memset(dest,0,sizeof(dest));
if ( (1) )
{
for (i=0; i<1024; i++)
src[1023-i] = dest[1023-i] = buf[i];
smooth1024(dest,src,3);
for (i=0; i<1024; i++)
src[1023-i] = dest[i];
}
else
{
for (i=0; i<1024; i++)
src[i] = buf[i];
}
_output_line(calclogflag,ave,buf,src,1024,color,bitmap,rowwidth,height);
}
void stats_updatedisp(struct DEXstats_disp *disp,int32_t seconds,double price,double volume)
{
if ( price > SMALLVAL && volume > SMALLVAL )
{
disp->pricesum += (price * volume);
disp->volumesum += volume;
}
}
void stats_dispprices(struct DEXstats_disp *prices,int32_t leftdatenum,int32_t numdates,struct DEXstats_datenuminfo *date,char *dest,int32_t current_daysecond)
{
int32_t i,j,seconds,hour,offset,delta,datenum = date->datenum; struct DEXstats_pairinfo *pair; struct DEXstats_pricepoint *ptr; uint32_t timestamp;
if ( datenum >= leftdatenum-1 && datenum <= leftdatenum+numdates )
{
offset = datenum - leftdatenum;
for (i=0; i<date->numpairs; i++)
if ( strcmp(dest,date->pairs[i].dest) == 0 )
{
pair = &date->pairs[i];
for (j=0; j<pair->numprices; j++)
{
ptr = &pair->prices[j];
seconds = 3600*ptr->hour + ptr->seconds + (24*3600 - current_daysecond);
if ( seconds >= 24*3600 )
delta = 1;
else delta = 0;
seconds -= delta*24*3600;
if ( offset+delta >= leftdatenum && offset+delta < leftdatenum+numdates )
stats_updatedisp(&prices[offset+delta],seconds,ptr->price,ptr->volume);
}
break;
}
}
}
struct DEXstats_priceinfo *stats_prices(char *symbol,char *dest,struct DEXstats_disp *prices,int32_t leftdatenum,int32_t numdates)
{
int32_t i,j,datenum,n; struct DEXstats_priceinfo *pp; uint32_t *utc32,tmp,timestamp; double *splinevals;
timestamp = (uint32_t)time(NULL);
if ( Num_priceinfos >= sizeof(Prices)/sizeof(*Prices) )
return(0);
for (i=0; i<Num_priceinfos; i++)
if ( strcmp(Prices[i].symbol,symbol) == 0 )
{
pp = &Prices[i];
if ( datenum >= pp->firstdatenum && datenum < pp->firstdatenum+pp->numdates )
{
for (j=0; j<pp->numdates; j++)
{
datenum = pp->firstdatenum+j;
if ( datenum < leftdatenum ) // can speed up by calculating offset 0
continue;
if ( datenum >= leftdatenum+numdates )
break;
stats_dispprices(prices,leftdatenum,numdates,&pp->dates[j],dest,timestamp % (3600*24));
}
}
break;
}
tmp = OS_conv_datenum(leftdatenum,0,0,0);
utc32 = calloc(sizeof(*utc32),numdates);
splinevals = calloc(sizeof(*splinevals),numdates);
for (i=n=0; i<numdates; i++,tmp+=24*3600)
{
if ( prices[i].volumesum != 0. )
{
splinevals[n] = (prices[i].pricesum / prices[i].volumesum);
utc32[n] = tmp;
n++;
} else memset(&prices[i],0,sizeof(prices[i]));
}
if ( n > 3 )
{
double output[2048],slopes[2048]; struct stats_spline spline; int32_t splineid = 0;
memset(&spline,0,sizeof(spline));
stats_genspline(output,slopes,&spline,splineid,"spline",utc32,splinevals,n,0);
}
free(utc32);
free(splinevals);
return(0);
}
char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port)
{
char *method,*agent;
if ( (method= jstr(argjson,"method")) == 0 )
return(clonestr("{\"error\":\"need method in request\"}"));
if ( (agent= jstr(argjson,"agent")) == 0 )
agent = "stats";
return(clonestr(jprint(argjson,0)));
}
#endif /* DEXstats_h */

679
iguana/exchanges/stats.c

@ -23,11 +23,19 @@
#include <stdint.h>
#include "OS_portable.h"
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#include "DEXstats.h"
#ifndef WIN32
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0x4000 // Do not generate SIGPIPE
#endif
#else
#define MSG_NOSIGNAL 0
#endif
#define IGUANA_URL "http://127.0.0.1:7778"
#define STATS_DESTDIR "/var/www/html"
#define STATS_DEST "/var/www/html/DEXstats.json"
#define GLOBAL_HELPDIR "/root/SuperNET/iguana/help"
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
@ -48,26 +56,648 @@ struct komodo_state
struct komodo_state KOMODO_STATE;
void stats_LPpubkeyupdate(char *LPpubkey,uint32_t timestamp)
int32_t iguana_socket(int32_t bindflag,char *hostname,uint16_t port)
{
printf("LP.(%s) t.%u\n",LPpubkey,timestamp);
int32_t opt,sock,result; char ipaddr[64],checkipaddr[64]; struct timeval timeout;
struct sockaddr_in saddr; socklen_t addrlen,slen;
addrlen = sizeof(saddr);
struct hostent *hostent;
/**
* gethostbyname() is deprecated and cause crash on x64 windows
* the solution is to implement similar functionality by using getaddrinfo()
* it is standard posix function and is correctly supported in win32/win64/linux
* @author - fadedreamz@gmail.com
*/
#if defined(_M_X64)
struct addrinfo *addrresult = NULL;
struct addrinfo *returnptr = NULL;
struct addrinfo hints;
struct sockaddr_in * sockaddr_ipv4;
int retVal;
int found = 0;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
#endif
if ( parse_ipaddr(ipaddr,hostname) != 0 )
port = parse_ipaddr(ipaddr,hostname);
#if defined(_M_X64)
retVal = getaddrinfo(ipaddr, NULL, &hints, &addrresult);
for (returnptr = addrresult; returnptr != NULL && found == 0; returnptr = returnptr->ai_next) {
switch (returnptr->ai_family) {
case AF_INET:
sockaddr_ipv4 = (struct sockaddr_in *) returnptr->ai_addr;
// we want to break from the loop after founding the first ipv4 address
found = 1;
break;
}
}
// if we iterate through the loop and didn't find anything,
// that means we failed in the dns lookup
if (found == 0) {
printf("getaddrinfo(%s) returned error\n", hostname);
freeaddrinfo(addrresult);
return(-1);
}
#else
hostent = gethostbyname(ipaddr);
if ( hostent == NULL )
{
printf("gethostbyname(%s) returned error: %d port.%d ipaddr.(%s)\n",hostname,errno,port,ipaddr);
return(-1);
}
#endif
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
//#ifdef WIN32
// saddr.sin_addr.s_addr = (uint32_t)calc_ipbits("127.0.0.1");
//#else
#if defined(_M_X64)
saddr.sin_addr.s_addr = sockaddr_ipv4->sin_addr.s_addr;
// graceful cleanup
sockaddr_ipv4 = NULL;
freeaddrinfo(addrresult);
#else
memcpy(&saddr.sin_addr.s_addr,hostent->h_addr_list[0],hostent->h_length);
#endif
expand_ipbits(checkipaddr,saddr.sin_addr.s_addr);
if ( strcmp(ipaddr,checkipaddr) != 0 )
printf("bindflag.%d iguana_socket mismatch (%s) -> (%s)?\n",bindflag,checkipaddr,ipaddr);
//#endif
if ( (sock= socket(AF_INET,SOCK_STREAM,0)) < 0 )
{
if ( errno != ETIMEDOUT )
printf("socket() failed: %s errno.%d", strerror(errno),errno);
return(-1);
}
opt = 1;
slen = sizeof(opt);
//printf("set keepalive.%d\n",setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(void *)&opt,slen));
#ifndef WIN32
if ( 1 )//&& bindflag != 0 )
{
opt = 0;
getsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(void *)&opt,&slen);
opt = 1;
//printf("keepalive.%d\n",opt);
}
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void *)&opt,sizeof(opt));
#ifdef __APPLE__
setsockopt(sock,SOL_SOCKET,SO_NOSIGPIPE,&opt,sizeof(opt));
#endif
#endif
if ( bindflag == 0 )
{
timeout.tv_sec = 10;
timeout.tv_usec = 0;
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout));
result = connect(sock,(struct sockaddr *)&saddr,addrlen);
if ( result != 0 )
{
if ( errno != ECONNRESET && errno != ENOTCONN && errno != ECONNREFUSED && errno != ETIMEDOUT && errno != EHOSTUNREACH )
{
//printf("%s(%s) port.%d failed: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno);
}
if ( sock >= 0 )
closesocket(sock);
return(-1);
}
timeout.tv_sec = 10000000;
timeout.tv_usec = 0;
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout));
}
else
{
while ( (result= bind(sock,(struct sockaddr*)&saddr,addrlen)) != 0 )
{
if ( errno == EADDRINUSE )
{
sleep(1);
printf("ERROR BINDING PORT.%d. this is normal tcp timeout, unless another process is using port\n",port);
sleep(3);
printf("%s(%s) port.%d try again: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno);
if ( bindflag == 1 )
{
closesocket(sock);
return(-1);
}
sleep(13);
//continue;
}
if ( errno != ECONNRESET && errno != ENOTCONN && errno != ECONNREFUSED && errno != ETIMEDOUT && errno != EHOSTUNREACH )
{
printf("%s(%s) port.%d failed: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno);
closesocket(sock);
return(-1);
}
}
if ( listen(sock,64) != 0 )
{
printf("listen(%s) port.%d failed: %s sock.%d. errno.%d\n",hostname,port,strerror(errno),sock,errno);
if ( sock >= 0 )
closesocket(sock);
return(-1);
}
}
#ifdef __APPLE__
//timeout.tv_sec = 0;
//timeout.tv_usec = 30000;
//setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout));
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(void *)&timeout,sizeof(timeout));
#endif
return(sock);
}
void stats_datenumupdate(int32_t datenum,int32_t hour,int32_t seconds,uint32_t timestamp,int32_t height,char *key,char *LPpubkey,cJSON *tradejson)
int32_t Supernet_lineparse(char *key,int32_t keymax,char *value,int32_t valuemax,char *src)
{
uint64_t srcamount,destamount; char *source,*dest; double price;
if ( LPpubkey != 0 )
stats_LPpubkeyupdate(LPpubkey,timestamp);
if ( tradejson != 0 )
int32_t a,b,c,n = 0; //char *origkey=key,*origvalue=value;
key[0] = value[0] = 0;
while ( (c= src[n]) == ' ' || c == '\t' || c == '\n' || c == '\t' )
n++;
while ( (c= src[n]) != ':' && c != 0 )
{
*key++ = c;
//printf("(%c) ",c);
if ( ++n >= keymax-1 )
{
*key = 0;
printf("lineparse overflow key.(%s)\n",src);
return(-1);
}
}
*key = 0;
//printf("-> key.(%s)\n",origkey);
if ( src[n] != ':' )
return(n);
n++;
while ( (c= src[n]) == ' ' || c == '\t' )
n++;
while ( (c= src[n]) != 0 && c != '\r' && c != '\n' )
{
source = jstr(jitem(tradejson,0),0);
srcamount = SATOSHIDEN * jdouble(jitem(tradejson,1),0);
dest = jstr(jitem(tradejson,2),0);
destamount = SATOSHIDEN * jdouble(jitem(tradejson,3),0);
if ( srcamount != 0 && destamount != 0 )
price = (double)destamount / srcamount;
else price = 0.;
printf("%d.%02d.%04d ht.%-4d %s (%s %12.8f) -> (%s %12.8f) %16.8f %16.8f\n",datenum,hour,seconds,height,key,source,dstr(srcamount),dest,dstr(destamount),price,1/price);
if ( c == '%' && (a= src[n+1]) != 0 && (b= src[n+2]) != 0 )
c = ((unhex(a) << 4) | unhex(b)), n += 2;
*value++ = c;
n++;
if ( n >= valuemax-1 )
{
*value = 0;
printf("lineparse overflow.(%s)\n",src);
return(-1);
}
}
*value = 0;
if ( src[n] != 0 )
{
n++;
while ( (c= src[n]) == '\r' || c == '\n' )
n++;
}
//printf("key.(%s) value.(%s)\n",origkey,origvalue);
return(n);
}
cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr)
{
int32_t i,n,totallen,datalen,len = 0; cJSON *json,*array; char key[8192],*data;
json = cJSON_CreateObject();
array = cJSON_CreateArray();
totallen = (int32_t)strlen(urlstr);
while ( 1 )
{
for (i=len; urlstr[i]!=0; i++)
if ( urlstr[i] == '\r' || urlstr[i] == '\n' )
break;
if ( i == len && (urlstr[len] == '\r' || urlstr[len] == '\n') )
{
len++;
continue;
}
urlstr[i] = 0;
//printf("URLSTR[%d]=%s\n",i,&urlstr[len]);
if ( (n= Supernet_lineparse(key,sizeof(key),value,bufsize,&urlstr[len])) > 0 )
{
if ( value[0] != 0 )
jaddstr(json,key,value);
else jaddistr(array,key);
len += (n + 1);
if ( strcmp(key,"Content-Length") == 0 && (datalen= atoi(value)) > 0 )
{
data = &urlstr[totallen - datalen];
data[-1] = 0;
//printf("post.(%s) (%c)\n",data,data[0]);
jaddstr(json,"POST",data);
}
} else break;
}
jadd(json,"lines",array);
//printf("urlconv.(%s)\n",jprint(json,0));
return(json);
}
char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port)
{
cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize;
char symbol[64],buf[4096],*originstr,*fieldstr,*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,iter,num=0;
//printf("rpcparse.(%s)\n",urlstr);
for (i=0; i<sizeof(urlmethod)-1&&urlstr[i]!=0&&urlstr[i]!=' '; i++)
urlmethod[i] = urlstr[i];
urlmethod[i++] = 0;
n = i;
//printf("URLMETHOD.(%s)\n",urlmethod);
*postflagp = (strcmp(urlmethod,"POST") == 0);
for (i=0; i<sizeof(url)-1&&urlstr[n+i]!=0&&urlstr[n+i]!=' '; i++)
url[i] = urlstr[n+i];
url[i++] = 0;
n += i;
j = i = 0;
filetype[0] = 0;
//printf("url.(%s) method.(%s)\n",&url[i],urlmethod);
#ifdef __PNACL__
snprintf(furl,sizeof(furl),"%s/%s",GLOBAL_DBDIR,url+1);
#else
snprintf(furl,sizeof(furl),"%s",url+1);
#endif
if ( strcmp(&url[i],"/") == 0 && strcmp(urlmethod,"GET") == 0 )
{
*jsonflagp = 1;
if ( (filestr= OS_filestr(&filesize,"index7779.html")) == 0 )
return(clonestr("{\"error\":\"cant find index7779\"}"));
else return(filestr);
}
else if ( (filestr= OS_filestr(&filesize,furl)) != 0 )
{
*jsonflagp = 1;
for (i=(int32_t)strlen(url)-1; i>0; i--)
if ( url[i] == '.' || url[i] == '/' )
break;
if ( url[i] == '.' )
strcpy(filetype,url+i+1);
//printf("return filetype.(%s) size.%ld\n",filetype,filesize);
return(filestr);
}
if ( strncmp(&url[i],"/api",strlen("/api")) == 0 )
{
*jsonflagp = 1;
i += strlen("/api");
} else *jsonflagp = 0;
if ( strcmp(url,"/favicon.ico") == 0 )
{
*jsonflagp = 1;
return(0);
}
if ( url[i] != '/' )
token = &url[i];
n = i;
tokens = cJSON_CreateArray();
for (; url[i]!=0; i++)
{
//printf("i.%d (%c)\n",i,url[i]);
if ( url[i] == '/' )
{
url[i] = 0;
if ( token != 0 )
{
//printf("TOKEN.(%s) i.%d\n",token,i);
jaddistr(tokens,token);
num++;
}
token = &url[i+1];
i++;
//printf("new token.(%s) i.%d\n",token,i+1);
continue;
}
}
if ( token != 0 )
{
//printf("add token.(%s)\n",token);
jaddistr(tokens,token);
num++;
}
argjson = cJSON_CreateObject();
if ( num > 0 )
jaddstr(argjson,"agent",jstri(tokens,0));
if ( num > 1 )
jaddstr(argjson,"method",jstri(tokens,1));
if ( (json= SuperNET_urlconv(retbuf,bufsize,urlstr+n)) != 0 )
{
jadd(json,"tokens",tokens);
jaddstr(json,"urlmethod",urlmethod);
if ( (data= jstr(json,"POST")) == 0 || (argjson= cJSON_Parse(data)) == 0 )
{
userpass = jstr(argjson,"userpass");
//printf("userpass.(%s)\n",userpass);
if ( (n= cJSON_GetArraySize(tokens)) > 0 )
{
if ( n > 1 )
{
if ( jstri(tokens,1) != 0 )
{
char *key,*value;
strcpy(buf,jstri(tokens,1));
key = value = 0;
i = 0;
for (; buf[i]!=0; i++)
{
if ( buf[i] == '?' )
{
buf[i] = 0;
jdelete(argjson,"method");
jaddstr(argjson,"method",buf);
i++;
key = &buf[i];
break;
}
}
while ( buf[i] != 0 )
{
//printf("iter.[%s]\n",&buf[i]);
if ( buf[i] != 0 && key != 0 )
{
for (; buf[i]!=0; i++)
{
if ( buf[i] == '=' )
{
buf[i] = 0;
i++;
//printf("got key.(%s)\n",key);
value = &buf[i];
break;
}
}
if ( buf[i] != 0 && value != 0 )
{
for (; buf[i]!=0; i++)
{
if ( buf[i] == '&' )
{
buf[i] = 0;
jaddstr(argjson,key,value);
i++;
//printf("got value.(%s)\n",value);
value = 0;
key = &buf[i];
break;
}
else if ( buf[i] == '+' )
buf[i] = ' ';
}
}
}
}
if ( key != 0 && value != 0 )
jaddstr(argjson,key,value);
}
else
{
//jdelete(argjson,"method");
//jaddstr(argjson,"method",buf);
}
}
for (i=2; i<n; i++)
{
if ( i == n-1 )
jaddstr(argjson,"data",jstri(tokens,i));
else
{
if ( strcmp(jstri(tokens,i),"coin") == 0 && strlen(jstri(tokens,i+1)) < sizeof(symbol)-1 )
{
strcpy(symbol,jstri(tokens,i+1));
touppercase(symbol);
jaddstr(argjson,jstri(tokens,i),symbol);
} else jaddstr(argjson,jstri(tokens,i),jstri(tokens,i+1));
i++;
}
}
}
}
if ( is_cJSON_Array(argjson) != 0 && (n= cJSON_GetArraySize(argjson)) > 0 )
{
cJSON *retitem,*retarray = cJSON_CreateArray();
origargjson = argjson;
symbol[0] = 0;
for (i=0; i<n; i++)
{
argjson = jitem(origargjson,i);
if ( userpass != 0 && jstr(argjson,"userpass") == 0 )
jaddstr(argjson,"userpass",userpass);
//printf("after urlconv.(%s) argjson.(%s)\n",jprint(json,0),jprint(argjson,0));
if ( (retstr= stats_JSON(argjson,remoteaddr,port)) != 0 )
{
if ( (retitem= cJSON_Parse(retstr)) != 0 )
jaddi(retarray,retitem);
free(retstr);
}
//printf("(%s) {%s} -> (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),cJSON_Print(json),*postflagp,retstr);
}
free_json(origargjson);
retstr = jprint(retarray,1);
}
else
{
cJSON *arg;
if ( jstr(argjson,"agent") != 0 && strcmp(jstr(argjson,"agent"),"bitcoinrpc") != 0 && jobj(argjson,"params") != 0 )
{
arg = jobj(argjson,"params");
if ( is_cJSON_Array(arg) != 0 && cJSON_GetArraySize(arg) == 1 )
arg = jitem(arg,0);
} else arg = argjson;
//printf("ARGJSON.(%s)\n",jprint(arg,0));
if ( userpass != 0 && jstr(arg,"userpass") == 0 )
jaddstr(arg,"userpass",userpass);
retstr = stats_JSON(arg,remoteaddr,port);
}
free_json(argjson);
free_json(json);
if ( tmpjson != 0 )
free(tmpjson);
return(retstr);
}
free_json(argjson);
if ( tmpjson != 0 )
free(tmpjson);
*jsonflagp = 1;
return(clonestr("{\"error\":\"couldnt process packet\"}"));
}
int32_t iguana_getcontentlen(char *buf,int32_t recvlen)
{
char *str,*clenstr = "Content-Length: "; int32_t len = -1;
if ( (str= strstr(buf,clenstr)) != 0 )
{
//printf("strstr.(%s)\n",str);
str += strlen(clenstr);
len = atoi(str);
//printf("len.%d\n",len);
}
return(len);
}
int32_t iguana_getheadersize(char *buf,int32_t recvlen)
{
char *str,*delim = "\r\n\r\n";
if ( (str= strstr(buf,delim)) != 0 )
return((int32_t)(((long)str - (long)buf) + strlen(delim)));
return(recvlen);
}
void stats_rpcloop(void *args)
{
static char *jsonbuf;
uint16_t port; char filetype[128],content_type[128];
int32_t recvlen,flag,bindsock,postflag=0,contentlen,sock,remains,numsent,jsonflag=0,hdrsize,len;
socklen_t clilen; char helpname[512],remoteaddr[64],*buf,*retstr,*space;
struct sockaddr_in cli_addr; uint32_t ipbits,i,size = IGUANA_MAXPACKETSIZE + 512;
if ( (port= *(uint16_t *)args) == 0 )
port = 7779;
if ( jsonbuf == 0 )
jsonbuf = calloc(1,IGUANA_MAXPACKETSIZE);
while ( (bindsock= iguana_socket(1,"127.0.0.1",port)) < 0 )
{
//if ( coin->MAXPEERS == 1 )
// break;
//exit(-1);
sleep(3);
}
printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock);
space = calloc(1,size);
while ( bindsock >= 0 )
{
clilen = sizeof(cli_addr);
sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen);
if ( sock < 0 )
{
//printf("iguana_rpcloop ERROR on accept usock.%d errno %d %s\n",sock,errno,strerror(errno));
continue;
}
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
expand_ipbits(remoteaddr,ipbits);
printf("remote RPC request from (%s) %x\n",remoteaddr,ipbits);
memset(jsonbuf,0,IGUANA_MAXPACKETSIZE);
remains = (int32_t)(IGUANA_MAXPACKETSIZE - 1);
buf = jsonbuf;
recvlen = flag = 0;
retstr = 0;
while ( remains > 0 )
{
//printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen);
if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 )
{
if ( errno == EAGAIN )
{
printf("EAGAIN for len %d, remains.%d\n",len,remains);
usleep(10000);
}
break;
}
else
{
if ( len > 0 )
{
buf[len] = 0;
if ( recvlen == 0 )
{
if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 )
{
hdrsize = iguana_getheadersize(buf,recvlen);
if ( hdrsize > 0 )
{
if ( len < (hdrsize + contentlen) )
{
remains = (hdrsize + contentlen) - len;
buf = &buf[len];
flag = 1;
//printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len);
continue;
}
}
}
}
recvlen += len;
remains -= len;
buf = &buf[len];
if ( flag == 0 || remains <= 0 )
break;
}
else
{
usleep(10000);
//printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len);
//retstr = iguana_rpcparse(space,size,&postflag,jsonbuf);
if ( flag == 0 )
break;
}
}
}
content_type[0] = 0;
if ( recvlen > 0 )
{
retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,port);
if ( filetype[0] != 0 )
{
static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize;
sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR);
if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 )
{
mimejson = cJSON_Parse(tmp);
free(tmp);
}
if ( mimejson != 0 )
{
if ( (typestr= jstr(mimejson,filetype)) != 0 )
sprintf(content_type,"Content-Type: %s\r\n",typestr);
} else printf("parse error.(%s)\n",tmp);
//printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type);
}
}
if ( retstr != 0 )
{
char *response,hdrs[1024];
//printf("RETURN.(%s)\n",retstr);
if ( jsonflag != 0 || postflag != 0 )
{
response = malloc(strlen(retstr)+1024+1+1);
sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr));
response[0] = '\0';
strcat(response,hdrs);
strcat(response,retstr);
strcat(response,"\n");
if ( retstr != space )
free(retstr);
retstr = response;
}
remains = (int32_t)strlen(retstr);
i = 0;
while ( remains > 0 )
{
if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 )
{
if ( errno != EAGAIN && errno != EWOULDBLOCK )
{
//printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock);
break;
}
}
else if ( remains > 0 )
{
remains -= numsent;
i += numsent;
if ( remains > 0 )
printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen);
}
}
if ( retstr != space)
free(retstr);
}
closesocket(sock);
}
}
@ -83,7 +713,7 @@ void stats_kvjson(FILE *logfp,int32_t height,int32_t savedheight,uint32_t timest
//printf("(%s)\n",jprint(kvjson,0));
if ( logfp != 0 )
{
stats_datenumupdate(datenum,seconds/3600,seconds % 3600,timestamp,height,key,jstr(kvjson,"pubkey"),jarray(&n,kvjson,"trade"));
stats_priceupdate(datenum,seconds/3600,seconds % 3600,timestamp,height,key,jstr(kvjson,"pubkey"),jarray(&n,kvjson,"trade"));
fprintf(logfp,"%s\n",jprint(kvjson,0));
fflush(logfp);
}
@ -132,7 +762,7 @@ void komodo_kvupdate(FILE *logfp,struct komodo_state *sp,int32_t ht,bits256 txid
}*/
//for (i=0; i<coresize; i++)
// printf("%c",(char)valueptr[i]);
decode_hex(decodestr,coresize/2,valueptr);
decode_hex((uint8_t *)decodestr,coresize/2,(char *)valueptr);
if ( (kvjson= cJSON_Parse(decodestr)) != 0 )
{
//char str[65];
@ -355,18 +985,27 @@ char *stats_update(FILE *logfp,char *destdir,char *statefname)
int main(int argc, const char * argv[])
{
FILE *fp,*logfp; char *filestr,*statefname,logfname[512];
struct tai T; uint32_t timestamp; struct DEXstats_disp prices[365]; int32_t seconds,leftdatenum; FILE *fp,*logfp; char *filestr,*statefname,logfname[512]; uint16_t port = 7779;
if ( argc < 2 )
statefname = "/root/.komodo/KV/komodostate";
else statefname = (char *)argv[1];
sprintf(logfname,"%s/logfile",STATS_DESTDIR);
logfp = fopen(logfname,"wb");
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&port) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",port);
exit(-1);
}
printf("DEX stats running\n");
while ( 1 )
{
if ( (filestr= stats_update(logfp,STATS_DEST,statefname)) != 0 )
{
printf("%u: %s\n",(uint32_t)time(NULL),filestr);
timestamp = (uint32_t)time(NULL);
leftdatenum = OS_conv_unixtime(&T,&seconds,timestamp - 1024*3600);
printf("%u: leftdatenum.%d %s\n",timestamp,leftdatenum,filestr);
memset(prices,0,sizeof(prices));
stats_prices("KMD","BTC",prices,leftdatenum,(int32_t)(sizeof(prices)/sizeof(*prices)));
if ( (fp= fopen(STATS_DEST,"wb")) != 0 )
{
fwrite(filestr,1,strlen(filestr)+1,fp);

3
iguana/iguana_wallet.c

@ -1358,6 +1358,8 @@ TWOSTRINGS_AND_INT(bitcoinrpc,walletpassphrase,password,permanentfile,timeout)
strcpy(myinfo->password,password);
if ( permanentfile != 0 )
strcpy(myinfo->permanentfile,permanentfile);
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,myinfo->password)) != 0 )
free(retstr);
retstr = SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,myinfo->password);
myinfo->expiration = (uint32_t)time(NULL) + timeout;
iguana_walletinitcheck(myinfo,coin);
@ -1382,7 +1384,6 @@ TWOSTRINGS_AND_INT(bitcoinrpc,walletpassphrase,password,permanentfile,timeout)
privkey = jumblr_privkey(myinfo,coinaddr,0,KMDaddr,"btc ");
smartaddress_add(myinfo,privkey,"btc","KMD",0.,0.);
}
//basilisk_unspents_update(myinfo,coin);
return(retstr);
}

BIN
iguana/stats

Binary file not shown.

2
iguana/tests/statstest

@ -0,0 +1,2 @@
#!/bin/bash
curl --url "http://127.0.0.1:7779" --data "{\"method\":\"start\"}"
Loading…
Cancel
Save