/****************************************************************************** * 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_mmjson.c // marketmaker // #define MMJSON_IPADDR 255 #define MMJSON_BITS256 254 #define MMJSON_SECP33 253 #define MMJSON_SIG 252 #define MMJSON_RMD160 251 #define MMJSON_DECIMAL8 250 #define MMJSON_DECIMAL8STR 249 #define MMJSON_DECIMAL16 248 #define MMJSON_DECIMAL16STR 247 #define MMJSON_DECIMAL24 246 #define MMJSON_DECIMAL24STR 245 #define MMJSON_DECIMAL32 244 #define MMJSON_DECIMAL32STR 243 #define MMJSON_DECIMAL40 242 #define MMJSON_DECIMAL40STR 241 #define MMJSON_DECIMAL48 240 #define MMJSON_DECIMAL48STR 239 #define MMJSON_DOUBLE 238 #define MMJSON_DECIMAL64 237 #define MMJSON_DECIMAL64STR 236 #define MMJSON_TIMESTAMP 235 #define MMJSON_TIMEDIFF8 234 #define MMJSON_TIMEDIFF16 233 #define MMJSON_ZERO 232 #define MMJSON_ZEROSTR 231 #define MMJSON_COIN 230 #define MMJSON_STRING 229 #define MMJSON_ARRAY8 228 #define MMJSON_ARRAY16 227 #define MMJSON_ARRAY32 226 int32_t MM_numfields; char *MM_fields[] = { "timestamp", "getdPoW", "dPoW", "aliceid", "src", "base", "basevol", "dest", "rel", "relvol", "price", "requestid", "quoteid", "finished", "expired", "bobdeposit", "alicepayment", "bobpayment", "paymentspent", "Apaymentspent", "depositspent", "ind", "method", "swapstatus", "method2", "gettradestatus", "coin", "rmd160", "pub", "pubsecp", "sig", "session", "notify", "pubkey", "price64", "credits", "utxocoin", "n", "bal", "min", "max", "postprice", "notarized", "notarizedhash", "notarizationtxid", "wantnotify", "isLP", "gui", "nogui", "tradeid", "address", "txid", "vout", "srchash", "txfee", "quotetime", "satoshis", "desthash", "txid2", "vout2", "destaddr", "desttxid", "destvout", "feetxid", "feevout", "desttxfee", "destsatoshis", "pending", "reserved", "broadcast", "ismine", "simplegui", "request", "proof", "connect", "expiration", "iambob", "Bgui", "", "Agui", "bob", "srcamount", "bobtxfee", "alice", "destamount", "alicetxfee", "sentflags", "values", "result", "success", "status", "finishtime", "tradestatus", "pair", "connected", "warning", "critical", "endcritical", "cli", "etomic", "bobtomic", "alicetomic", "etomicsrc", "etomicdest" }; #define MMJSON_BOUNDARY ((int32_t)(sizeof(MM_fields)/sizeof(*MM_fields))) char *MM_coins[] = { "KMD", "BTC", "CRC", "VOT", "INN", "MOON", "CRW", "EFL", "GBX", "BCO", "BLK", "BTG", "BCH", "ABY", "STAK", "XZC", "QTUM", "PURA", "DSR", "MNZ", "BTCZ", "MAGA", "BSD", "IOP", "BLOCK", "CHIPS", "888", "ARG", "GLT", "ZER", "HODLC", "UIS", "HUC", "PIVX", "BDL", "ARC", "ZCL", "VIA", "ERC", "FAIR", "FLO", "SXC", "CREA", "TRC", "BTA", "SMC", "NMC", "NAV", "EMC2", "SYS", "I0C", "DASH", "STRAT", "MUE", "MONA", "XMY", "MAC", "BTX", "XRE", "LBC", "SIB", "VTC", "REVS", "JUMBLR", "DOGE", "HUSH", "ZEC", "DGB", "ZET", "GAME", "LTC", "SUPERNET", "WLC", "PANGEA", "DEX", "BET", "CRYPTO", "HODL", "MSHARK", "BOTS", "MGW", "COQUI", "KV", "CEAL", "MESH", "ETOMIC", "BTCH", "ETH" }; int32_t mmjson_coinfind(char *symbol) { int32_t i; for (i=0; i>= 8; } } else { for (i=n-1; i>=0; i--) { l <<= 8; l |= buf[i]; } *longp = l; } return(n); } int32_t MMJSON_decodeitem(cJSON *lineobj,uint8_t *linebuf,int32_t i,int32_t len,char *fieldstr,uint32_t *timestampp) { int32_t c,valind,j; char tmpstr[64],ipaddr[64],hexstr[256],arbstr[8192]; uint64_t l; switch ( (valind= linebuf[i++]) ) { case MMJSON_IPADDR: i += MMJSON_rwnum(0,&linebuf[i],&l,4); expand_ipbits(ipaddr,(uint32_t)l); jaddstr(lineobj,fieldstr,ipaddr); break; case MMJSON_BITS256: init_hexbytes_noT(hexstr,&linebuf[i],32); i += 32; jaddstr(lineobj,fieldstr,hexstr); break; case MMJSON_SECP33: init_hexbytes_noT(hexstr,&linebuf[i],33); i += 33; jaddstr(lineobj,fieldstr,hexstr); break; case MMJSON_SIG: init_hexbytes_noT(hexstr,&linebuf[i],65); i += 65; jaddstr(lineobj,fieldstr,hexstr); break; case MMJSON_RMD160: init_hexbytes_noT(hexstr,&linebuf[i],20); i += 20; jaddstr(lineobj,fieldstr,hexstr); break; case MMJSON_DECIMAL8: l = linebuf[i++]; jaddnum(lineobj,fieldstr,l); break; case MMJSON_DECIMAL8STR: l = linebuf[i++]; jadd64bits(lineobj,fieldstr,l); break; case MMJSON_DECIMAL16: i += MMJSON_rwnum(0,&linebuf[i],&l,2); jaddnum(lineobj,fieldstr,l); break; case MMJSON_DECIMAL16STR: i += MMJSON_rwnum(0,&linebuf[i],&l,2); jadd64bits(lineobj,fieldstr,l); break; case MMJSON_DECIMAL24: i += MMJSON_rwnum(0,&linebuf[i],&l,3); jaddnum(lineobj,fieldstr,l); break; case MMJSON_DECIMAL24STR: i += MMJSON_rwnum(0,&linebuf[i],&l,3); sprintf(tmpstr,"%llu",(long long)l); jaddstr(lineobj,fieldstr,tmpstr); break; case MMJSON_DECIMAL32: i += MMJSON_rwnum(0,&linebuf[i],&l,4); //printf("decimal32.%u %08x\n",(uint32_t)l,(uint32_t)l); jaddnum(lineobj,fieldstr,l); break; case MMJSON_DECIMAL32STR: i += MMJSON_rwnum(0,&linebuf[i],&l,4); //printf("decimal32.%u %08x\n",(uint32_t)l,(uint32_t)l); jadd64bits(lineobj,fieldstr,l); break; case MMJSON_DECIMAL40: i += MMJSON_rwnum(0,&linebuf[i],&l,5); jaddnum(lineobj,fieldstr,l); break; case MMJSON_DECIMAL40STR: i += MMJSON_rwnum(0,&linebuf[i],&l,5); jadd64bits(lineobj,fieldstr,l); break; case MMJSON_DECIMAL48: i += MMJSON_rwnum(0,&linebuf[i],&l,6); jaddnum(lineobj,fieldstr,l); break; case MMJSON_DECIMAL48STR: i += MMJSON_rwnum(0,&linebuf[i],&l,6); jadd64bits(lineobj,fieldstr,l); break; case MMJSON_DOUBLE: i += MMJSON_rwnum(0,&linebuf[i],&l,8); //printf("double %llu -> %.8f\n",(long long)l,dstr(l)); jaddnum(lineobj,fieldstr,dstr(l)); break; case MMJSON_DECIMAL64: i += MMJSON_rwnum(0,&linebuf[i],&l,8); jadd64bits(lineobj,fieldstr,l); break; case MMJSON_DECIMAL64STR: i += MMJSON_rwnum(0,&linebuf[i],&l,8); jadd64bits(lineobj,fieldstr,l); break; case MMJSON_TIMESTAMP: if ( *timestampp == 0 ) { i += MMJSON_rwnum(0,&linebuf[i],&l,4); *timestampp = (uint32_t)l; jaddnum(lineobj,fieldstr,l); } else { printf("timestamp %u already exists\n",*timestampp); free_json(lineobj); return(-1); } break; case MMJSON_TIMEDIFF8: jaddnum(lineobj,fieldstr,*timestampp + linebuf[i++]); break; case MMJSON_TIMEDIFF16: i += MMJSON_rwnum(0,&linebuf[i],&l,2); jaddnum(lineobj,fieldstr,*timestampp + l); break; case MMJSON_ZERO: jaddnum(lineobj,fieldstr,0); break; case MMJSON_ZEROSTR: //printf("%s.zerostr\n",fieldstr); jadd64bits(lineobj,fieldstr,0); break; case MMJSON_COIN: jaddstr(lineobj,fieldstr,MM_coins[linebuf[i++]]); break; case MMJSON_STRING: j = 0; while ( (c= linebuf[i++]) != 0 ) { if ( i > len ) { printf("string overflow i.%d vs len.%d\n",i,len); free_json(lineobj); return(-1); } arbstr[j++] = c; } arbstr[j] = 0; jaddstr(lineobj,fieldstr,arbstr); break; default: if ( valind < MMJSON_BOUNDARY ) jaddstr(lineobj,fieldstr,MM_fields[valind]); else { printf("%s unhandled valind.%d k.%d len.%d (%s)\n",fieldstr,valind,i,len,jprint(lineobj,0)); free_json(lineobj); return(-1); } break; } return(i); } char *MMJSON_decode(uint8_t *linebuf,int32_t len) { uint32_t timestamp = 0; char *fieldstr; uint64_t l; int32_t ind,i=0,j,m=-1; cJSON *obj,*item,*array,*lineobj = cJSON_CreateObject(); while ( i+1 < len ) { //printf("ind.%d i.%d vs len.%d\n",linebuf[i],i,len); if ( (ind= linebuf[i++]) >= MMJSON_BOUNDARY ) { if ( ind != MMJSON_STRING ) { printf("illegal field ind.%d (%s)\n",ind,jprint(lineobj,0)); free_json(lineobj); return(0); } else { fieldstr = (char *)&linebuf[i++]; while ( linebuf[i] != 0 ) i++; i++; } } else fieldstr = MM_fields[ind]; if ( linebuf[i] == MMJSON_ARRAY8 ) { i++; m = linebuf[i++]; } else if ( linebuf[i] == MMJSON_ARRAY16 ) { i++; i += MMJSON_rwnum(0,&linebuf[i],&l,2); m = (int32_t)l; } else if ( linebuf[i] == MMJSON_ARRAY32 ) { i++; i += MMJSON_rwnum(0,&linebuf[i],&l,4); m = (int32_t)l; } else m = -1; if ( m >= 0 ) { //printf("%s i.%d m.%d\n",fieldstr,i,m); array = cJSON_CreateArray(); for (j=0; j= 0 ) { fieldstr = MM_fields[ind]; if ( strcmp("utxocoin",fieldstr) == 0 || strcmp("alice",fieldstr) == 0 || strcmp("bob",fieldstr) == 0 || strcmp("base",fieldstr) == 0 || strcmp("rel",fieldstr) == 0 || strcmp("coin",fieldstr) == 0 || strcmp("txfee",fieldstr) == 0 || strcmp("desttxfee",fieldstr) == 0 || strcmp("price64",fieldstr) == 0 || strcmp("satoshis",fieldstr) == 0 || strcmp("destsatoshis",fieldstr) == 0 ) isstr = 1; else isstr = 0; } //printf("%s.(%s) k.%d\n",fieldstr,v,k); if ( (valind= mmfind(v)) >= 0 ) { linebuf[k++] = valind; return(k); } else if ( strcmp("0",v) == 0 ) { if ( isstr != 0 ) linebuf[k++] = MMJSON_ZEROSTR; else linebuf[k++] = MMJSON_ZERO; return(k); } for (j=dots=0; v[j]!=0; j++) { if ( (v[j] < '0' || v[j] > '9') && v[j] != '.' ) break; else if ( v[j] == '.' ) dots++; } if ( dots == 3 && v[j] == 0 && strlen(v) < 17 && is_ipaddr(v) != 0 ) { //printf(" "); linebuf[k++] = MMJSON_IPADDR; l = calc_ipbits(v); k += MMJSON_rwnum(1,&linebuf[k],&l,4); } else if ( dots == 1 && v[j] == 0 ) { if ( (val= atof(v)) > SMALLVAL ) { l = SATOSHIDEN * (val + 0.000000005); sprintf(checkstr,"%.8f",dstr(l)); if ( strcmp(checkstr,v) == 0 ) { //printf(" "); linebuf[k++] = MMJSON_DOUBLE; k += MMJSON_rwnum(1,&linebuf[k],&l,8); } else printf("ERR.<%s %s> ",v,checkstr); } } else if ( (len= is_hexstr(v,0)) == 64 ) { //printf(" "); linebuf[k++] = MMJSON_BITS256; decode_hex(&linebuf[k],32,v), k += 32; } else if ( len == 66 ) { //printf(" "); linebuf[k++] = MMJSON_SECP33; decode_hex(&linebuf[k],33,v), k += 33; } else if ( len == 65*2 ) { //printf(" "); linebuf[k++] = MMJSON_SIG; decode_hex(&linebuf[k],65,v), k += 65; } else if ( len == 40 ) { //printf(" "); linebuf[k++] = MMJSON_RMD160; decode_hex(&linebuf[k],20,v), k += 20; } else if ( len > 40 ) { printf("ERR. ",len/2); } else if ( is_decimalstr(v) != 0 && (l= calc_nxt64bits(v)) > 0 ) { if ( l < 0x100 ) { //printf(" "); if ( l == 0 ) { linebuf[k++] = isstr != 0 ? MMJSON_ZEROSTR : MMJSON_ZERO; } else { linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL8STR : MMJSON_DECIMAL8; linebuf[k++] = (uint8_t)l; } } else if ( l < 0x10000 ) { //printf(" "); linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL16STR : MMJSON_DECIMAL16; k += MMJSON_rwnum(1,&linebuf[k],&l,2); } else if ( l < 0x1000000 ) { linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL24STR : MMJSON_DECIMAL24; //printf("decimal24 %llu %s (%s) %d\n",(long long)l,v,fieldstr,linebuf[k-1]); k += MMJSON_rwnum(1,&linebuf[k],&l,3); } else if ( l < 0x100000000LL ) { if ( v[0] != '"' && *timestampp == 0 && strcmp(fieldstr,"timestamp") == 0 ) { *timestampp = (uint32_t)atol(v); //printf(" "); linebuf[k++] = MMJSON_TIMESTAMP; l = *timestampp; k += MMJSON_rwnum(1,&linebuf[k],&l,4); } else if ( v[0] != '"' && *timestampp != 0 && (diff= ((uint32_t)atol(v)-*timestampp)) < 0x100 && diff >= 0 ) { //printf(" "); linebuf[k++] = MMJSON_TIMEDIFF8; linebuf[k++] = (uint8_t)diff; } else if ( v[0] != '"' && *timestampp != 0 && (diff= ((uint32_t)atol(v)-*timestampp)) < 0x10000 && diff >= 0 ) { //printf(" "); linebuf[k++] = MMJSON_TIMEDIFF16; l = diff; k += MMJSON_rwnum(1,&linebuf[k],&l,2); } else { //printf(".%u %08x\n",(uint32_t)l,(uint32_t)l); linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL32STR : MMJSON_DECIMAL32; k += MMJSON_rwnum(1,&linebuf[k],&l,4); } } else if ( l < 0x10000000000LL ) { //printf(" "); linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL40STR : MMJSON_DECIMAL40; k += MMJSON_rwnum(1,&linebuf[k],&l,5); } else if ( l < 0x1000000000000LL ) { //printf(" "); linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL48STR : MMJSON_DECIMAL48; k += MMJSON_rwnum(1,&linebuf[k],&l,6); } //else if ( l < 0x100000000000000LL ) // printf(" "); else { //printf(" "); linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL64STR : MMJSON_DECIMAL64; k += MMJSON_rwnum(1,&linebuf[k],&l,8); } } else { if ( (ind= mmfind(v)) >= 0 ) linebuf[k++] = ind; else { for (j=0; v[j]!=0; j++) { if ( v[j] >= 'a' && v[j] <= 'z' ) continue; else break; } if ( v[j] == 0 ) { static uint32_t counter; if ( counter++ < 3 ) printf("unexpected missing string value.(%s)\n",v); //ind = mmadd(v); //printf("%s.<%s>.%d ",s,v,ind); //linebuf[k++] = ind; linebuf[k++] = MMJSON_STRING; memcpy(&linebuf[k],v,strlen(v)+1); k += (int32_t)strlen(v) + 1; } else { for (j=0; v[j]!=0; j++) { if ( v[j] >= 'A' && v[j] <= 'Z' ) continue; else break; } if ( v[j] == 0 && (coinind= mmjson_coinfind(v)) >= 0 ) { //printf(" "); linebuf[k++] = MMJSON_COIN; linebuf[k++] = coinind; } /*else if ( strlen(v) == 34 ) { printf(" "); k += 22; }*/ else { linebuf[k++] = MMJSON_STRING; if ( v[0] == '"' ) { v++; v[strlen(v)-1] = 0; } //printf("str.<%s> ",v); memcpy(&linebuf[k],v,strlen(v)+1); k += (int32_t)strlen(v) + 1; } } } } return(k); } int32_t MMJSON_encode(uint8_t *linebuf,char *line) { uint32_t timestamp; uint64_t l; char *decodestr,*s,*v=0; cJSON *lineobj,*array,*ptr; int32_t k=0,m,i,asize,ind,z,allocv_flag; timestamp = 0; if ( (lineobj= cJSON_Parse(line)) != 0 ) { if ( line[strlen(line)-1] == '\n' ) line[strlen(line)-1] = 0; //printf("%s\n",jprint(lineobj,0)); if ( (m= cJSON_GetArraySize(lineobj)) > 0 ) { ptr = lineobj->child; for (i=0; inext) { allocv_flag = 0; s = jfieldname(ptr); if ( (ind= mmfind(s)) < 0 ) { printf("missing field.(%s) add to MM_fields[]\n",s); linebuf[k++] = MMJSON_STRING; memcpy(&linebuf[k],s,strlen(s)+1); k += (int32_t)strlen(s) + 1; //ind = mmadd(s); } else linebuf[k++] = ind; //printf("%s ",s); if ( (array= jobj(lineobj,s)) != 0 && is_cJSON_Array(array) != 0 ) { asize = cJSON_GetArraySize(array); if ( asize < 0x100 ) { linebuf[k++] = MMJSON_ARRAY8; linebuf[k++] = asize; } else if ( asize < 0x10000 ) { linebuf[k++] = MMJSON_ARRAY16; l = asize; k += MMJSON_rwnum(1,&linebuf[k],&l,2); } else { linebuf[k++] = MMJSON_ARRAY32; l = asize; k += MMJSON_rwnum(1,&linebuf[k],&l,4); } for (z=0; z (%s)\n",k,line,decodestr==0?"":decodestr); if ( decodestr != 0 ) free(decodestr); return(-1); } //else printf("decoded\n"); free(decodestr); } return(k); } #ifndef FROM_MARKETMAKER #define packetout "/Users/mac/mmjson/packet.out" #define packetlog "/Users/mac/mmjson/packet.log" int main(int argc, const char * argv[]) { FILE *fp,*outfp; uint8_t linebuf[8192]; char line[8192],str[65]; int32_t i,k,compressed=0,n=0,total = 0; outfp = fopen(packetout,"wb"); if ( (fp= fopen(packetlog,"rb")) != 0 ) { while ( fgets(line,sizeof(line),fp) > 0 ) { n++; total += strlen(line); if ( (k= MMJSON_encode(linebuf,line)) > 0 ) { //printf("\n"); if ( outfp != 0 ) fwrite(linebuf,1,k,outfp); compressed += k; } else { compressed += strlen(line); //printf("error parsing.(%s)\n",line); } } fclose(fp); if ( outfp != 0 ) { uint8_t *data,*bits; int32_t numbits; bits256 seed; long fsize = ftell(outfp); fclose(outfp); if ( (0) && (outfp= fopen(packetout,"rb")) != 0 ) { data = calloc(1,fsize); bits = calloc(1,fsize); if ( fread(data,1,fsize,outfp) == fsize ) { memset(seed.bytes,0,sizeof(seed)); decode_hex(seed.bytes,32,"ffffff070000810478800084000800b200101400002001400404844402d29fc4"); numbits = ramcoder_compress(bits,(int32_t)fsize,data,(int32_t)fsize,seed); fclose(outfp); printf("numbits.%d %d bytes %.1f seed.%s\n",numbits,numbits/8+1,(double)compressed/(numbits/8),bits256_str(str,seed)); } } } } else printf("cant find packet.log\n"); printf("char *MM_fields[256] = \n{\n"); for (i=0; i