You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1245 lines
47 KiB

9 years ago
/******************************************************************************
9 years ago
* Copyright © 2014-2016 The SuperNET Developers. *
9 years ago
* *
* 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. *
* *
******************************************************************************/
#define CHROMEAPP_NAME iguana
#define CHROMEAPP_STR "iguana"
#define CHROMEAPP_CONF "iguana.conf"
#define CHROMEAPP_MAIN iguana_main
#define CHROMEAPP_JSON iguana_JSON
#define CHROMEAPP_HANDLER Handler_iguana
#include "../pnacl_main.h"
#include "iguana777.h"
9 years ago
#include "SuperNET.h"
#include <stdio.h>
9 years ago
// ALL globals must be here!
9 years ago
char *Iguana_validcommands[] =
{
"SuperNET", "SuperNETb",
"version", "verack", "getaddr", "addr", "inv", "getdata", "notfound", "getblocks", "getheaders", "headers", "tx", "block", "mempool", "ping", "pong",
"reject", "filterload", "filteradd", "filterclear", "merkleblock", "alert", ""
};
9 years ago
int32_t Showmode,Autofold,PANGEA_MAXTHREADS = 1;
9 years ago
9 years ago
struct category_info *Categories;
9 years ago
struct iguana_info *Coins[IGUANA_MAXCOINS];
9 years ago
char Userhome[512],GLOBALTMPDIR[512] = "tmp";
9 years ago
int32_t USE_JAY,FIRST_EXTERNAL,IGUANA_disableNXT,Debuglevel;
uint32_t prices777_NXTBLOCK,MAX_DEPTH = 100;
9 years ago
queue_t helperQ,jsonQ,finishedQ,bundlesQ,validateQ,emitQ,balancesQ,TerminateQ,spendvectorsQ,convertQ;
9 years ago
struct supernet_info MYINFO,**MYINFOS;
9 years ago
static int32_t initflag;
9 years ago
int32_t HDRnet,netBLOCKS;
cJSON *API_json;
9 years ago
#ifdef __linux__
9 years ago
int32_t IGUANA_NUMHELPERS = 16;
9 years ago
#else
9 years ago
int32_t IGUANA_NUMHELPERS = 8;
9 years ago
#endif
9 years ago
struct iguana_jsonitem { struct queueitem DL; struct supernet_info *myinfo; uint32_t fallback,expired,allocsize; char **retjsonstrp; char remoteaddr[64]; uint16_t port; char jsonstr[]; };
9 years ago
uint16_t SuperNET_API2num(char *agent,char *method)
{
int32_t i,n = 0; cJSON *item;
if ( agent != 0 && method != 0 && API_json != 0 && (n= cJSON_GetArraySize(API_json)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(API_json,i);
if ( strcmp(agent,jstr(item,"agent")) == 0 && strcmp(method,jstr(item,"method")) == 0 )
9 years ago
return((i << 5) | (SUPERNET_APIVERSION & 0x1f));
}
}
return(-1);
}
int32_t SuperNET_num2API(char *agent,char *method,uint16_t num)
{
9 years ago
int32_t n,apiversion; cJSON *item;
if ( (apiversion= (num & 0x1f)) != SUPERNET_APIVERSION )
{
printf("need to make sure all released api help returns are indexed here!\n");
return(-1);
}
num >>= 5;
if ( API_json != 0 && (n= cJSON_GetArraySize(API_json)) > 0 && num < n )
{
item = jitem(API_json,num);
strcpy(agent,jstr(item,"agent"));
strcpy(method,jstr(item,"method"));
return(num);
}
return(-1);
}
9 years ago
9 years ago
int32_t SuperNET_str2hex(uint8_t *hex,char *str)
{
int32_t len;
len = (int32_t)strlen(str)+1;
decode_hex(hex,len,str);
return(len);
}
void SuperNET_hex2str(char *str,uint8_t *hex,int32_t len)
{
init_hexbytes_noT(str,hex,len);
}
9 years ago
struct supernet_info *SuperNET_MYINFO(char *passphrase)
{
if ( passphrase == 0 || passphrase[0] == 0 )
return(&MYINFO);
else
{
// search saved accounts
}
9 years ago
return(&MYINFO);
9 years ago
return(0);
}
9 years ago
struct supernet_info *SuperNET_MYINFOfind(int32_t *nump,bits256 pubkey)
{
int32_t i;
*nump = 0;
if ( MYINFOS != 0 )
{
for (i=0; MYINFOS[i]!=0; i++)
{
*nump = i;
if ( bits256_cmp(pubkey,MYINFOS[i]->myaddr.persistent) == 0 )
return(MYINFOS[i]);
}
*nump = i;
}
return(0);
}
int32_t SuperNET_MYINFOS(struct supernet_info **myinfos,int32_t max)
{
9 years ago
int32_t i = 0;
if ( MYINFOS != 0 )
{
for (i=0; i<max; i++)
if ( (myinfos[i]= MYINFOS[i]) == 0 )
break;
}
9 years ago
return(i);
}
void SuperNET_MYINFOadd(struct supernet_info *myinfo)
{
int32_t num;
if ( SuperNET_MYINFOfind(&num,myinfo->myaddr.persistent) == 0 )
{
MYINFOS = realloc(MYINFOS,(num + 2) * sizeof(*MYINFOS));
char str[65]; printf("MYNFOadd[%d] <- %s\n",num,bits256_str(str,myinfo->myaddr.persistent));
MYINFOS[num] = calloc(1,sizeof(*myinfo));
*MYINFOS[num] = *myinfo;
MYINFOS[++num] = 0;
}
}
9 years ago
char *iguana_JSON(char *jsonstr,uint16_t port)
9 years ago
{
char *retstr=0; cJSON *json;
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
9 years ago
retstr = SuperNET_JSON(0,json,"127.0.0.1",port);
9 years ago
free_json(json);
}
if ( retstr == 0 )
retstr = clonestr("{\"error\":\"cant parse jsonstr from pnacl\"}");
return(retstr);
}
9 years ago
9 years ago
char *SuperNET_jsonstr(struct supernet_info *myinfo,char *jsonstr,char *remoteaddr,uint16_t port)
9 years ago
{
9 years ago
cJSON *json; char *agent,*method,*retstr = 0;
9 years ago
//char str[65]; printf("SuperNET_jsonstr %p %s\n",&myinfo->privkey,bits256_str(str,myinfo->privkey));
9 years ago
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
9 years ago
method = jstr(json,"method");
if ( (agent= jstr(json,"agent")) != 0 && method != 0 )
9 years ago
retstr = SuperNET_parser(myinfo,agent,method,json,remoteaddr);
else if ( method != 0 && is_bitcoinrpc(myinfo,method,remoteaddr) >= 0 )
retstr = iguana_bitcoinRPC(myinfo,method,json,remoteaddr,port);
else retstr = clonestr("{\"error\":\"need both agent and method\"}");
free_json(json);
} else retstr = clonestr("{\"error\":\"couldnt parse SuperNET_JSON\"}");
return(retstr);
9 years ago
}
9 years ago
int32_t iguana_jsonQ()
9 years ago
{
9 years ago
struct iguana_jsonitem *ptr;
if ( (ptr= queue_dequeue(&finishedQ,0)) != 0 )
{
if ( ptr->expired != 0 )
{
*ptr->retjsonstrp = clonestr("{\"error\":\"request timeout\"}");
printf("garbage collection: expired.(%s)\n",ptr->jsonstr);
myfree(ptr,ptr->allocsize);
} else queue_enqueue("finishedQ",&finishedQ,&ptr->DL,0);
}
if ( (ptr= queue_dequeue(&jsonQ,0)) != 0 )
{
9 years ago
if ( *ptr->retjsonstrp != 0 && (*ptr->retjsonstrp= SuperNET_jsonstr(ptr->myinfo,ptr->jsonstr,ptr->remoteaddr,ptr->port)) == 0 )
9 years ago
*ptr->retjsonstrp = clonestr("{\"error\":\"null return from iguana_jsonstr\"}");
9 years ago
printf("finished.(%s) -> (%s)\n",ptr->jsonstr,*ptr->retjsonstrp!=0?*ptr->retjsonstrp:"null return");
9 years ago
queue_enqueue("finishedQ",&finishedQ,&ptr->DL,0);
9 years ago
return(1);
9 years ago
}
9 years ago
return(0);
}
9 years ago
char *iguana_blockingjsonstr(struct supernet_info *myinfo,char *jsonstr,uint64_t tag,int32_t maxmillis,char *remoteaddr,uint16_t port)
9 years ago
{
9 years ago
struct iguana_jsonitem *ptr; char *retjsonstr = 0; int32_t len,allocsize; double expiration;
expiration = OS_milliseconds() + maxmillis;
//printf("blocking case.(%s)\n",jsonstr);
len = (int32_t)strlen(jsonstr);
allocsize = sizeof(*ptr) + len + 1;
ptr = mycalloc('J',1,allocsize);
ptr->allocsize = allocsize;
ptr->myinfo = myinfo;
9 years ago
ptr->port = port;
9 years ago
ptr->retjsonstrp = &retjsonstr;
safecopy(ptr->remoteaddr,remoteaddr,sizeof(ptr->remoteaddr));
memcpy(ptr->jsonstr,jsonstr,len+1);
queue_enqueue("jsonQ",&jsonQ,&ptr->DL,0);
while ( OS_milliseconds() < expiration )
9 years ago
{
9 years ago
usleep(100);
if ( retjsonstr != 0 )
{
9 years ago
//printf("got blocking retjsonstr.(%s) delete allocsize.%d:%d\n",retjsonstr,allocsize,ptr->allocsize);
9 years ago
queue_delete(&finishedQ,&ptr->DL,ptr->allocsize,1);
9 years ago
return(retjsonstr);
}
usleep(1000);
9 years ago
}
9 years ago
//printf("(%s) expired\n",jsonstr);
ptr->expired = (uint32_t)time(NULL);
return(clonestr("{\"error\":\"iguana jsonstr expired\"}"));
9 years ago
}
9 years ago
char *SuperNET_processJSON(struct supernet_info *myinfo,cJSON *json,char *remoteaddr,uint16_t port)
9 years ago
{
9 years ago
cJSON *retjson; uint64_t tag; uint32_t timeout; char *jsonstr,*method,*retjsonstr,*retstr = 0;
9 years ago
//char str[65]; printf("processJSON %p %s\n",&myinfo->privkey,bits256_str(str,myinfo->privkey));
9 years ago
if ( json != 0 )
9 years ago
{
9 years ago
if ( (tag= j64bits(json,"tag")) == 0 )
9 years ago
{
9 years ago
OS_randombytes((uint8_t *)&tag,sizeof(tag));
9 years ago
jadd64bits(json,"tag",tag);
}
9 years ago
if ( (timeout= juint(json,"timeout")) == 0 )
timeout = IGUANA_JSONTIMEOUT;
9 years ago
if ( (method= jstr(json,"method")) != 0 && strcmp(method,"DHT") == 0 && remoteaddr != 0 )
{
9 years ago
SuperNET_hexmsgprocess(myinfo,0,json,jstr(json,"hexmsg"),remoteaddr);
9 years ago
return(clonestr("{\"result\":\"processed remote DHT\"}"));
}
9 years ago
jsonstr = jprint(json,0);
//printf("RPC? (%s)\n",jsonstr);
9 years ago
if ( remoteaddr == 0 || jstr(json,"immediate") != 0 )
9 years ago
retjsonstr = SuperNET_jsonstr(myinfo,jsonstr,remoteaddr,port);
else retjsonstr = iguana_blockingjsonstr(myinfo,jsonstr,tag,timeout,remoteaddr,port);
9 years ago
if ( retjsonstr != 0 )
9 years ago
{
if ( (retjsonstr[0] == '{' || retjsonstr[0] == '[') && (retjson= cJSON_Parse(retjsonstr)) != 0 )
9 years ago
{
if ( j64bits(retjson,"tag") != tag )
{
jdelete(retjson,"tag");
jadd64bits(retjson,"tag",tag);
}
9 years ago
retstr = jprint(retjson,1);
9 years ago
//printf("retstr.(%s) retjsonstr.%p retjson.%p\n",retstr,retjsonstr,retjson);
9 years ago
free(retjsonstr);//,strlen(retjsonstr)+1);
} else retstr = retjsonstr;
9 years ago
}
9 years ago
free(jsonstr);
} else retstr = clonestr("{\"error\":\"cant parse JSON\"}");
if ( retstr == 0 )
retstr = clonestr("{\"error\":\"null return\"}");
return(retstr);
9 years ago
}
9 years ago
void iguana_exit()
{
9 years ago
int32_t i,j,iter; char *stopstr = SUPERNET_STOPSTR;
9 years ago
printf("start EXIT\n");
9 years ago
for (iter=0; iter<3; iter++)
9 years ago
{
9 years ago
for (i=0; i<IGUANA_MAXCOINS; i++)
9 years ago
{
9 years ago
if ( Coins[i] != 0 )
9 years ago
{
9 years ago
for (j=0; j<IGUANA_MAXPEERS; j++)
9 years ago
{
9 years ago
switch ( iter )
{
case 0:
if ( Coins[i]->peers.active[j].usock >= 0 && Coins[i]->peers.active[j].supernet != 0 )
9 years ago
iguana_send_supernet(Coins[i],&Coins[i]->peers.active[j],stopstr,0);
9 years ago
break;
case 1: Coins[i]->peers.active[j].dead = (uint32_t)time(NULL); break;
case 2:
if ( Coins[i]->peers.active[j].usock >= 0 )
closesocket(Coins[i]->peers.active[j].usock);
break;
}
9 years ago
}
}
}
9 years ago
sleep(5);
9 years ago
}
9 years ago
printf("sockets closed, now EXIT\n");
9 years ago
exit(0);
}
#ifndef _WIN32
#include <signal.h>
9 years ago
void sigint_func() { printf("\nSIGINT\n"); iguana_exit(); }
void sigillegal_func() { printf("\nSIGILL\n"); iguana_exit(); }
void sighangup_func() { printf("\nSIGHUP\n"); iguana_exit(); }
void sigkill_func() { printf("\nSIGKILL\n"); iguana_exit(); }
void sigabort_func() { printf("\nSIGABRT\n"); iguana_exit(); }
void sigquit_func() { printf("\nSIGQUIT\n"); iguana_exit(); }
void sigchild_func() { printf("\nSIGCHLD\n"); signal(SIGCHLD,sigchild_func); }
void sigalarm_func() { printf("\nSIGALRM\n"); signal(SIGALRM,sigalarm_func); }
void sigcontinue_func() { printf("\nSIGCONT\n"); signal(SIGCONT,sigcontinue_func); }
#endif
9 years ago
9 years ago
// mksquashfs DB/BTC BTC.squash -b 1048576 -> 19GB?
// mksquashfs DB/BTC BTC.lzo -comp lzo -b 1048576 -> takes a really long time -> 20GB
// mksquashfs DB/BTC BTC.xz -b 1048576 -comp xz -Xdict-size 512K -> takes a long time -> 16GB
// mksquashfs DB/BTC BTC.xz1m -b 1048576 -comp xz -Xdict-size 1024K -> takes a long time ->
/*
mksquashfs DB/BTC BTC.xz -comp xz
9 years ago
mksquashfs DB/BTC BTC.xzs -b 16384 -comp xz -Xdict-size 8K
mksquashfs DB/BTC BTC.xz1m -b 1048576 -comp xz -Xdict-size 1024K
mksquashfs DB/BTC BTC.xz8k -comp xz -Xdict-size 8K
9 years ago
mksquashfs DB/BTC BTC.lzo -comp lzo
mksquashfs DB/BTC BTC.lzo1m -comp lzo -b 1048576
mksquashfs DB/BTC BTC.squash
mksquashfs DB/BTC BTC.squash1M -b 1048576
9 years ago
9 years ago
mksquashfs DB/BTC BTC.xz -comp xz
9 years ago
sudo mount BTC.xz DB/ro/BTC -t squashfs -o loop
9 years ago
*/
9 years ago
9 years ago
void mainloop(struct supernet_info *myinfo)
9 years ago
{
9 years ago
int32_t i,n,iter,flag,isRT,numpeers; struct iguana_info *coin; struct iguana_helper *ptr; struct iguana_bundle *bp;
9 years ago
sleep(3);
printf("mainloop\n");
while ( 1 )
{
9 years ago
if ( myinfo->expiration != 0 && time(NULL) > myinfo->expiration )
iguana_walletlock(myinfo);
flag = 0;
9 years ago
isRT = 1;
numpeers = 0;
9 years ago
if ( 1 )
{
9 years ago
for (i=0; i<IGUANA_MAXCOINS; i++)
9 years ago
if ( (coin= Coins[i]) != 0 && coin->current != 0 )
9 years ago
{
9 years ago
if ( coin->active != 0 && coin->started != 0 )
9 years ago
{
9 years ago
isRT *= coin->isRT;
numpeers += coin->peers.numranked;
9 years ago
n = queue_size(&balancesQ);
for (iter=0; iter<n; iter++)
9 years ago
{
9 years ago
if ( queue_size(&bundlesQ) < 2 && (ptr= queue_dequeue(&balancesQ,0)) != 0 )
9 years ago
{
9 years ago
bp = ptr->bp;
if ( ptr->coin != coin || bp == 0 || time(NULL) < bp->nexttime )
{
if ( 0 && bp != 0 )
printf("skip.%d lag.%ld\n",bp->hdrsi,bp->nexttime-time(NULL));
//bp->nexttime = (uint32_t)time(NULL);
queue_enqueue("balanceQ",&balancesQ,&ptr->DL,0);
continue;
}
flag++;
if ( coin != 0 )
9 years ago
{
9 years ago
iguana_balancecalc(coin,bp,bp->bundleheight,bp->bundleheight+bp->n-1);
if ( coin->active == 0 )
{
printf("detected autopurge after account filecreation. restarting.%s\n",coin->symbol);
coin->active = 1;
}
9 years ago
}
9 years ago
myfree(ptr,ptr->allocsize);
9 years ago
}
9 years ago
}
9 years ago
if ( (bp= coin->current) != 0 && coin->stucktime != 0 && coin->isRT == 0 && coin->RTheight == 0 && (time(NULL) - coin->stucktime) > coin->MAXSTUCKTIME )
9 years ago
{
9 years ago
if ( 0 )
9 years ago
{
9 years ago
printf("%s is stuck too long, restarting due to %d\n",coin->symbol,bp->hdrsi);
9 years ago
if ( coin->started != 0 )
{
iguana_coinpurge(coin);
9 years ago
sleep(3);
9 years ago
while ( coin->started == 0 )
9 years ago
{
9 years ago
printf("wait for coin to reactivate\n");
sleep(1);
9 years ago
}
9 years ago
sleep(3);
9 years ago
}
9 years ago
}
9 years ago
}
9 years ago
if ( 0 && flag != 0 )
9 years ago
printf("call RT update busy.%d\n",coin->RTramchain_busy);
9 years ago
}
}
}
9 years ago
pangea_queues(SuperNET_MYINFO(0));
9 years ago
if ( flag == 0 )
9 years ago
{
9 years ago
usleep(1000 + isRT*100000 + (numpeers == 0)*1000000);
9 years ago
iguana_jsonQ(); // cant do this here safely, need to send to coin specific queue
}
}
}
9 years ago
int32_t calcmofn(uint8_t *allshares,uint8_t *myshares[],uint8_t *sharenrs,int32_t M,uint8_t *data,int32_t datasize,int32_t N)
{
int32_t j;
calc_shares(allshares,(void *)data,datasize,datasize,M,N,sharenrs);
for (j=0; j<N; j++)
myshares[j] = &allshares[j * datasize];
return(datasize);
}
uint8_t *recoverdata(uint8_t *shares[],uint8_t *sharenrs,int32_t M,int32_t datasize,int32_t N)
{
void *G; int32_t i; uint8_t *recover,recovernrs[255];
if ( (recover= calloc(1,datasize)) == 0 )
{
printf("cards777_recover: unexpected out of memory error\n");
return(0);
}
memset(recovernrs,0,sizeof(recovernrs));
for (i=0; i<N; i++)
if ( shares[i] != 0 )
recovernrs[i] = sharenrs[i];
G = gfshare_ctx_init_dec(recovernrs,N,datasize);
for (i=0; i<N; i++)
if ( shares[i] != 0 )
gfshare_ctx_dec_giveshare(G,i,shares[i]);
gfshare_ctx_dec_newshares(G,recovernrs);
gfshare_ctx_dec_extract(G,recover);
gfshare_ctx_free(G);
return(recover);
}
static uint8_t logs[256] = {
0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81,
0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21,
0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9,
0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd,
0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd,
0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e,
0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b,
0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d,
0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c,
0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd,
0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e,
0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76,
0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa,
0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51,
0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8,
0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf };
static uint8_t exps[510] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9,
0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35,
0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0,
0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc,
0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f,
0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88,
0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93,
0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9,
0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa,
0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e,
0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4,
0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e,
0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef,
0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5,
0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83,
0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01,
0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d,
0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c,
0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f,
0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x9d,
0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a,
0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46,
0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d,
0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, 0x5f,
0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65,
0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0xfd,
0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe,
0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9,
0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d,
0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, 0x81,
0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b,
0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85,
0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f,
0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, 0xa8,
0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49,
0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, 0xe6,
0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc,
0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3,
0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95,
0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, 0x82,
0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c,
0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51,
0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3,
0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, 0x12,
0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7,
0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, 0x2c,
0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b,
0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e };
/*
* This file is Copyright Daniel Silverstone <dsilvers@digital-scurf.org> 2006,2015
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
//#include "config.h"
//#include "libgfshare.h"
//#include "libgfshare_tables.h"
#ifndef LIBGFSHARE_H
#define LIBGFSHARE_H
typedef struct _gfshare_ctx gfshare_ctx;
typedef void (*gfshare_rand_func_t)(uint8_t*, unsigned int);
/* This will, use random(). It's not very good so you should not use it unless
* you must. If you can't be bothered to write your own, be sure to srandom()
* before you use any of the gfshare_ctx_enc_* functions
*/
extern const gfshare_rand_func_t gfshare_bad_idea_but_fill_rand_using_random;
/* This must be filled out before running any of the gfshare_ctx_enc_* calls
* or bad things will happen since it is initialised to NULL be default.
* You should fill this with a routine which uses urandom or similar ideally.
* If you cannot do that on your platform, you can use the function provided
* which does random() calls, but I recommend against it unless you must.
*/
extern gfshare_rand_func_t gfshare_fill_rand;
/* ------------------------------------------------------[ Preparation ]---- */
/* Initialise a gfshare context for producing shares */
gfshare_ctx* gfshare_ctx_init_enc(uint8_t* /* sharenrs */,unsigned int /* sharecount */, uint8_t /* threshold */,unsigned int /* size */);
9 years ago
/* Initialise a gfshare context for recombining shares */
gfshare_ctx* gfshare_ctx_init_dec(uint8_t* /* sharenrs */,unsigned int /* sharecount */,unsigned int /* size */);
9 years ago
/* Free a share context's memory. */
void gfshare_ctx_free(gfshare_ctx* /* ctx */);
/* --------------------------------------------------------[ Splitting ]---- */
/* Provide a secret to the encoder. (this re-scrambles the coefficients) */
void gfshare_ctx_enc_setsecret(gfshare_ctx* /* ctx */,uint8_t* /* secret */);
9 years ago
/* Extract a share from the context.
* 'share' must be preallocated and at least 'size' bytes long.
* 'sharenr' is the index into the 'sharenrs' array of the share you want.
*/
void gfshare_ctx_enc_getshare(gfshare_ctx* /* ctx */,uint8_t /* sharenr */,uint8_t* /* share */);
9 years ago
/* ----------------------------------------------------[ Recombination ]---- */
/* Inform a recombination context of a change in share indexes */
void gfshare_ctx_dec_newshares(gfshare_ctx* /* ctx */, uint8_t* /* sharenrs */);
9 years ago
/* Provide a share context with one of the shares.
* The 'sharenr' is the index into the 'sharenrs' array
*/
void gfshare_ctx_dec_giveshare(gfshare_ctx* /* ctx */,uint8_t /* sharenr */,uint8_t* /* share */);
9 years ago
/* Extract the secret by interpolation of the shares.
* secretbuf must be allocated and at least 'size' bytes long
*/
void gfshare_ctx_dec_extract(gfshare_ctx* /* ctx */,uint8_t* /* secretbuf */);
9 years ago
#endif /* LIBGFSHARE_H */
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#define XMALLOC malloc
#define XFREE free
struct _gfshare_ctx {
unsigned int sharecount;
unsigned int threshold;
unsigned int size;
uint8_t* sharenrs;
uint8_t* buffer;
unsigned int buffersize;
};
static void _gfshare_fill_rand_using_random( uint8_t* buffer,unsigned int count )
9 years ago
{
9 years ago
OS_randombytes(buffer,count);
/*unsigned int i;
9 years ago
for( i = 0; i < count; ++i )
9 years ago
buffer[i] = (random() & 0xff00) >> 8; apparently the bottom 8 aren't
9 years ago
* very random but the middles ones
* are
*/
}
9 years ago
const gfshare_rand_func_t gfshare_bad_idea_but_fill_rand_using_random = (void *)_gfshare_fill_rand_using_random;
9 years ago
gfshare_rand_func_t gfshare_fill_rand = NULL;
/* ------------------------------------------------------[ Preparation ]---- */
static gfshare_ctx * _gfshare_ctx_init_core( uint8_t *sharenrs,unsigned int sharecount,uint8_t threshold,unsigned int size )
9 years ago
{
gfshare_ctx *ctx;
ctx = XMALLOC( sizeof(struct _gfshare_ctx) );
if( ctx == NULL )
return NULL; /* errno should still be set from XMALLOC() */
ctx->sharecount = sharecount;
ctx->threshold = threshold;
ctx->size = size;
ctx->sharenrs = XMALLOC( sharecount );
if( ctx->sharenrs == NULL ) {
int saved_errno = errno;
XFREE( ctx );
errno = saved_errno;
return NULL;
}
memcpy( ctx->sharenrs, sharenrs, sharecount );
ctx->buffersize = threshold * size;
ctx->buffer = XMALLOC( ctx->buffersize );
if( ctx->buffer == NULL ) {
int saved_errno = errno;
XFREE( ctx->sharenrs );
XFREE( ctx );
errno = saved_errno;
return NULL;
}
return ctx;
}
/* Initialise a gfshare context for producing shares */
gfshare_ctx * gfshare_ctx_init_enc( uint8_t* sharenrs,unsigned int sharecount,uint8_t threshold,unsigned int size )
9 years ago
{
unsigned int i;
for (i = 0; i < sharecount; i++) {
if (sharenrs[i] == 0) {
/* can't have x[i] = 0 - that would just be a copy of the secret, in
* theory (in fact, due to the way we use exp/log for multiplication and
* treat log(0) as 0, it ends up as a copy of x[i] = 1) */
errno = EINVAL;
return NULL;
}
}
return _gfshare_ctx_init_core( sharenrs, sharecount, threshold, size );
}
/* Initialise a gfshare context for recombining shares */
gfshare_ctx* gfshare_ctx_init_dec( uint8_t* sharenrs,unsigned int sharecount,unsigned int size )
9 years ago
{
gfshare_ctx *ctx = _gfshare_ctx_init_core( sharenrs, sharecount, sharecount, size );
if( ctx != NULL )
ctx->threshold = 0;
return ctx;
}
/* Free a share context's memory. */
void gfshare_ctx_free( gfshare_ctx* ctx )
9 years ago
{
gfshare_fill_rand( ctx->buffer, ctx->buffersize );
gfshare_fill_rand( ctx->sharenrs, ctx->sharecount );
XFREE( ctx->sharenrs );
XFREE( ctx->buffer );
gfshare_fill_rand( (uint8_t*)ctx, sizeof(struct _gfshare_ctx) );
XFREE( ctx );
}
/* --------------------------------------------------------[ Splitting ]---- */
/* Provide a secret to the encoder. (this re-scrambles the coefficients) */
void gfshare_ctx_enc_setsecret( gfshare_ctx* ctx,uint8_t* secret)
9 years ago
{
memcpy( ctx->buffer + ((ctx->threshold-1) * ctx->size),
secret,
ctx->size );
gfshare_fill_rand( ctx->buffer, (ctx->threshold-1) * ctx->size );
}
/* Extract a share from the context.
* 'share' must be preallocated and at least 'size' bytes long.
* 'sharenr' is the index into the 'sharenrs' array of the share you want.
*/
void gfshare_ctx_enc_getshare( gfshare_ctx* ctx,uint8_t sharenr,uint8_t* share)
9 years ago
{
unsigned int pos, coefficient;
unsigned int ilog = logs[ctx->sharenrs[sharenr]];
uint8_t *coefficient_ptr = ctx->buffer;
uint8_t *share_ptr;
for( pos = 0; pos < ctx->size; ++pos )
share[pos] = *(coefficient_ptr++);
for( coefficient = 1; coefficient < ctx->threshold; ++coefficient ) {
share_ptr = share;
for( pos = 0; pos < ctx->size; ++pos ) {
uint8_t share_byte = *share_ptr;
if( share_byte )
share_byte = exps[ilog + logs[share_byte]];
*share_ptr++ = share_byte ^ *coefficient_ptr++;
}
}
}
/* ----------------------------------------------------[ Recombination ]---- */
/* Inform a recombination context of a change in share indexes */
void gfshare_ctx_dec_newshares( gfshare_ctx* ctx,uint8_t* sharenrs)
9 years ago
{
memcpy( ctx->sharenrs, sharenrs, ctx->sharecount );
}
/* Provide a share context with one of the shares.
* The 'sharenr' is the index into the 'sharenrs' array
*/
void gfshare_ctx_dec_giveshare( gfshare_ctx* ctx,uint8_t sharenr,uint8_t* share )
9 years ago
{
memcpy( ctx->buffer + (sharenr * ctx->size), share, ctx->size );
}
/* Extract the secret by interpolation of the shares.
* secretbuf must be allocated and at least 'size' bytes long
*/
void gfshare_ctx_dec_extract( gfshare_ctx* ctx,uint8_t* secretbuf )
9 years ago
{
unsigned int i, j;
uint8_t *secret_ptr, *share_ptr, sharei,sharej;
for( i = 0; i < ctx->size; ++i )
secretbuf[i] = 0;
for( i = 0; i < ctx->sharecount; ++i )
{
// Compute L(i) as per Lagrange Interpolation
unsigned Li_top = 0, Li_bottom = 0;
if ( (sharei= ctx->sharenrs[i]) != 0 )
{
for ( j = 0; j < ctx->sharecount; ++j )
{
if ( i != j && sharei != (sharej= ctx->sharenrs[j]) )
{
if ( sharej == 0 )
continue; // skip empty share */
Li_top += logs[sharej];
if ( Li_top >= 0xff )
Li_top -= 0xff;
Li_bottom += logs[sharei ^ sharej];
if ( Li_bottom >= 0xff )
Li_bottom -= 0xff;
}
}
if ( Li_bottom > Li_top )
Li_top += 0xff;
Li_top -= Li_bottom; // Li_top is now log(L(i))
secret_ptr = secretbuf, share_ptr = ctx->buffer + (ctx->size * i);
for (j=0; j<ctx->size; j++)
{
if ( *share_ptr != 0 )
*secret_ptr ^= exps[Li_top + logs[*share_ptr]];
share_ptr++, secret_ptr++;
}
}
}
}
void calc_share(uint8_t *buffer,int32_t size,int32_t M,uint32_t ilog,uint8_t *share)
{
uint32_t pos,coefficient;//,ilog = ctx_logs[ctx->sharenrs[sharenr]];
//uint8_t *coefficient_ptr = buffer;
uint8_t *share_ptr,share_byte;
for (pos=0; pos<size; pos++)
share[pos] = *(buffer++);
for (coefficient=1; coefficient<M; coefficient++)
{
share_ptr = share;
for (pos=0; pos<size; pos++)
{
share_byte = *share_ptr;
if ( share_byte != 0 )
share_byte = exps[ilog + logs[share_byte]];
*share_ptr++ = (share_byte ^ *buffer++);
}
}
}
void calc_shares(uint8_t *shares,uint8_t *secret,int32_t size,int32_t width,int32_t M,int32_t N,uint8_t *sharenrs)
{
int32_t i;
uint8_t *buffer = calloc(M,width);
memset(shares,0,N*width);
memcpy(buffer + ((M - 1) * size),secret,size);
//gfshare_fill_rand(buffer,(M - 1) * size);
OS_randombytes(buffer,(M - 1) * size);
for (i=0; i<N; i++)
{
//uint32_t _crc32(uint32_t crc, const void *buf, size_t size);
calc_share(buffer,size,M,logs[sharenrs[i]],&shares[i * width]);
printf("(%02x %08x) ",sharenrs[i],calc_crc32(0,&shares[i*width],size));
}
free(buffer);
}
//#include <stdio.h>
9 years ago
int32_t test(int32_t M,int32_t N,int32_t datasize)
{
int ok = 1, i;
uint8_t * secret = malloc(datasize);
uint8_t *shares[255];
uint8_t *recomb = malloc(datasize);
uint8_t sharenrs[255],newsharenrs[255];// = (uint8_t *)strdup("0124z89abehtr");
gfshare_ctx *G;
gfshare_fill_rand = gfshare_bad_idea_but_fill_rand_using_random;
for (i=0; i<N; i++)
{
sharenrs[i] = i+1;
shares[i] = malloc(datasize);
}
/* Stage 1, make a secret */
for( i = 0; i < datasize; ++i )
9 years ago
secret[i] = (rand() & 0xff00) >> 8;
9 years ago
/* Stage 2, split it N ways with a threshold of M */
G = gfshare_ctx_init_enc( sharenrs, N, M, datasize );
gfshare_ctx_enc_setsecret( G, secret );
for (i=0; i<N; i++)
gfshare_ctx_enc_getshare( G, i, shares[i] );
gfshare_ctx_free( G );
/* Prep the decode shape */
G = gfshare_ctx_init_dec( sharenrs, N, datasize );
memset(newsharenrs,0,N);
int32_t j,r;
for (i=0; i<M; i++)
{
r = rand() % N;
while ( (j= sharenrs[r]) == 0 || newsharenrs[r] != 0 )
r = rand() % N;
newsharenrs[r] = j;
sharenrs[r] = 0;
}
for (i=0; i<N; i++)
{
if ( newsharenrs[i] != 0 )
gfshare_ctx_dec_giveshare( G, i, shares[i] );
//newsharenrs[i] = sharenrs[i];
}
/* Stage 3, attempt a recombination with shares 1 and 2 */
//sharenrs[2] = 0;
gfshare_ctx_dec_newshares( G, newsharenrs );
gfshare_ctx_dec_extract( G, recomb );
for( i = 0; i < datasize; ++i )
if( secret[i] != recomb[i] )
ok = 0;
printf("M.%-3d N.%-3d ok.%d datalen.%d\n",M,N,ok,datasize);
free(recomb), free(secret);
for (i=0; i<N; i++)
free(shares[i]);
return ok!=1;
}
int32_t init_sharenrs(uint8_t sharenrs[255],uint8_t *orig,int32_t m,int32_t n)
{
uint8_t *randvals,valid[255];
int32_t i,j,r,remains,orign;
if ( m > n || n >= 0xff ) // reserve 255 for illegal sharei
{
printf("illegal M.%d of N.%d\n",m,n);
return(-1);
}
randvals = calloc(1,65536);
OS_randombytes(randvals,65536);
if ( orig == 0 && n == m )
{
memset(sharenrs,0,n);
for (i=0; i<255; i++)
valid[i] = (i + 1);
remains = orign = 255;
for (i=0; i<n; i++)
{
r = (randvals[i] % remains);
sharenrs[i] = valid[r];
printf("%d ",sharenrs[i]);
valid[r] = valid[--remains];
}
printf("FULL SET\n");
}
else
{
memcpy(valid,orig,n);
memset(sharenrs,0,n);
for (i=0; i<n; i++)
printf("%d ",valid[i]);
printf("valid\n");
for (i=0; i<m; i++)
{
r = rand() % n;
while ( (j= valid[r]) == 0 )
{
//printf("i.%d j.%d m.%d n.%d r.%d\n",i,j,m,n,r);
r = rand() % n;
}
sharenrs[i] = j;
valid[r] = 0;
}
for (i=0; i<n; i++)
printf("%d ",valid[i]);
printf("valid\n");
for (i=0; i<m; i++)
printf("%d ",sharenrs[i]);
printf("sharenrs vals m.%d of n.%d\n",m,n);
//getchar();
}
free(randvals);
for (i=0; i<m; i++)
{
for (j=0; j<m; j++)
{
if ( i == j )
continue;
if ( sharenrs[i] != 0 && sharenrs[i] == sharenrs[j] )
{
printf("FATAL: duplicate entry sharenrs[%d] %d vs %d sharenrs[%d]\n",i,sharenrs[i],sharenrs[j],j);
return(-1);
}
}
}
return(0);
}
/* Construct and write out the tables for the gfshare code */
int maingen(int argc, char** argv)
9 years ago
{
uint8_t logs[256];
uint8_t exps[255];
unsigned int x;
unsigned int i;
x = 1;
for( i = 0; i < 255; ++i ) {
exps[i] = x;
logs[x] = i;
x <<= 1;
if( x & 0x100 )
x ^= 0x11d; /* Unset the 8th bit and mix in 0x1d */
}
logs[0] = 0; /* can't log(0) so just set it neatly to 0 */
/* The above generation algorithm clearly demonstrates that
* logs[exps[i]] == i for 0 <= i <= 254
* exps[logs[i]] == i for 1 <= i <= 255
*/
/* Spew out the tables */
fprintf(stdout, "\
/*\n\
* This file is autogenerated by gfshare_maketable.\n\
*/\n\
\n\
static uint8_t logs[256] = {\n ");
for( i = 0; i < 256; ++i ) {
fprintf(stdout, "0x%02x", logs[i]);
if( i == 255 )
fprintf(stdout, " };\n");
else if( (i % 8) == 7 )
fprintf(stdout, ",\n ");
else
fprintf(stdout, ", ");
}
/* The exp table we output from 0 to 509 because that way when we
* do the lagrange interpolation we don't have to be quite so strict
* with staying inside the field which makes it quicker
*/
fprintf(stdout, "\
\n\
static uint8_t exps[510] = {\n ");
for( i = 0; i < 510; ++i ) {
fprintf(stdout, "0x%02x", exps[i % 255]); /* exps[255]==exps[0] */
if( i == 509 )
fprintf(stdout, " };\n");
else if( (i % 8) == 7)
fprintf(stdout, ",\n ");
else
fprintf(stdout, ", ");
}
return 0;
}
void iguana_main(void *arg)
{
9 years ago
int32_t usessl = 0, ismainnet = 1; int32_t i; struct iguana_info *btc,*btcd;
9 years ago
struct supernet_info *myinfo; char *tmpstr,*helperargs,*coinargs,helperstr[512];
mycalloc(0,0,0);
myinfo = SuperNET_MYINFO(0);
9 years ago
FILE *fp; int32_t iter; void ztest(); ztest();
9 years ago
strcpy(myinfo->NXTAPIURL,"http://127.0.0.1:7876/nxt");
9 years ago
for (iter=0; iter<2; iter++)
{
if ( (fp= fopen(iter == 0 ? "nxtpasswords" : "fimpasswords","rb")) != 0 )
{
char line[4096],NXTaddr[64]; int32_t j; uint8_t pubkey[32];
while ( fgets(line,sizeof(line),fp) > 0 )
{
j = (int32_t)strlen(line) - 1;
line[j] = 0;
calc_NXTaddr(NXTaddr,pubkey,(uint8_t *)line,j);
printf("FORGING %s (%s)\n",NXTaddr,issue_startForging(myinfo,line));
}
fclose(fp);
}
9 years ago
strcpy(myinfo->NXTAPIURL,"http://127.0.0.1:7886/nxt");
9 years ago
}
9 years ago
if ( usessl == 0 )
strcpy(myinfo->NXTAPIURL,"http://127.0.0.1:");
else strcpy(myinfo->NXTAPIURL,"https://127.0.0.1:");
if ( ismainnet != 0 )
strcat(myinfo->NXTAPIURL,"7876/nxt");
else strcat(myinfo->NXTAPIURL,"6876/nxt");
9 years ago
9 years ago
if ( 0 )
{
#ifndef _WIN32
signal(SIGABRT,sigabort_func);
9 years ago
signal(SIGINT,sigint_func);
signal(SIGILL,sigillegal_func);
signal(SIGHUP,sighangup_func);
//signal(SIGKILL,sigkill_func);
signal(SIGQUIT,sigquit_func);
signal(SIGCHLD,sigchild_func);
signal(SIGALRM,sigalarm_func);
signal(SIGCONT,sigcontinue_func);
#endif
9 years ago
}
//iguana_chaingenesis(1,1403138561,0x1e0fffff,8359109,bits256_conv("fd1751cc6963d88feca94c0d01da8883852647a37a0a67ce254d62dd8c9d5b2b")); // BTCD
//iguana_chaingenesis(1,1409839200,0x1e0fffff,64881664,bits256_conv("698a93a1cacd495a7a4fb3864ad8d06ed4421dedbc57f9aaad733ea53b1b5828")); // VPN
9 years ago
//char genesisblock[1024];
//iguana_chaingenesis(genesisblock,"sha256",1,1317972665,0x1e0ffff0,2084524493,bits256_conv("97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9")); // LTC
iguana_initQ(&helperQ,"helperQ");
9 years ago
iguana_initQ(&jsonQ,"jsonQ");
9 years ago
iguana_initQ(&emitQ,"emitQ");
9 years ago
iguana_initQ(&finishedQ,"finishedQ");
iguana_initQ(&bundlesQ,"bundlesQ");
iguana_initQ(&validateQ,"validateQ");
9 years ago
iguana_initQ(&balancesQ,"balancesQ");
9 years ago
myinfo->rpcport = IGUANA_RPCPORT;
strcpy(myinfo->rpcsymbol,"BTCD");
if ( arg != 0 )
9 years ago
{
9 years ago
cJSON *argjson;
if ( (argjson= cJSON_Parse(arg)) != 0 )
9 years ago
{
9 years ago
IGUANA_NUMHELPERS = juint(argjson,"numhelpers");
9 years ago
if ( (myinfo->rpcport= juint(argjson,"port")) == 0 )
myinfo->rpcport = IGUANA_RPCPORT;
if ( (myinfo->publicRPC= juint(argjson,"publicRPC")) != 0 && myinfo->publicRPC != myinfo->rpcport )
myinfo->publicRPC = 0;
if ( jstr(argjson,"rpccoin") != 0 )
safecopy(myinfo->rpcsymbol,jstr(argjson,"rpccoin"),sizeof(myinfo->rpcsymbol));
safecopy(Userhome,jstr(argjson,"userhome"),sizeof(Userhome));
if ( jstr(argjson,"tmpdir") != 0 )
{
safecopy(GLOBALTMPDIR,jstr(argjson,"tmpdir"),sizeof(GLOBALTMPDIR));
printf("GLOBAL tmpdir.(%s)\n",GLOBALTMPDIR);
}
printf("call argv JSON.(%s)\n",(char *)arg);
SuperNET_JSON(myinfo,argjson,0,myinfo->rpcport);
free_json(argjson);
} else printf("error parsing.(%s)\n",(char *)arg);
9 years ago
}
OS_ensure_directory("help");
OS_ensure_directory("confs");
9 years ago
OS_ensure_directory("accounts");
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
OS_ensure_directory("DB"), OS_ensure_directory("DB/ECB");
OS_ensure_directory("tmp");
9 years ago
OS_ensure_directory("purgeable");
9 years ago
OS_ensure_directory(GLOBALTMPDIR);
9 years ago
btc = iguana_coinadd("BTC",0);
btcd = iguana_coinadd("BTCD",0);
if ( btc == 0 || btcd == 0 )
{
printf("error adding BTC.%p or BTCD.%p\n",btc,btcd);
exit(-1);
}
9 years ago
if ( (tmpstr= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"help\"}"),0,myinfo->rpcport)) != 0 )
{
if ( (API_json= cJSON_Parse(tmpstr)) != 0 && (API_json= jobj(API_json,"result")) != 0 )
API_json = jobj(API_json,"API");
free(tmpstr);
}
9 years ago
printf("generated API_json\n");
9 years ago
if ( IGUANA_NUMHELPERS == 0 )
IGUANA_NUMHELPERS = 1;
9 years ago
iguana_initQ(&TerminateQ,"TerminateQ");
9 years ago
category_init(myinfo);
if ( (coinargs= SuperNET_keysinit(myinfo,arg)) != 0 )
9 years ago
iguana_launch(btcd,"iguana_coins",iguana_coins,coinargs,IGUANA_PERMTHREAD);
9 years ago
char *str;
9 years ago
if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"prefetchlag\":2,\"VALIDATE\":1,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"newcoin\":\"BTC\",\"startpend\":166,\"services\":1}"),0,myinfo->rpcport)) != 0 )
9 years ago
free(str);
9 years ago
#ifdef __APPLE__
9 years ago
if ( 1 )
9 years ago
{
9 years ago
sleep(1);
9 years ago
if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"VALIDATE\":1,\"prefetchlag\":13,\"startpend\":512,\"endpend\":512,\"userhome\":\"/Users/jimbolaptop/Library/Application Support\",\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":129,\"maxpeers\":256,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":8,\"poll\":1}"),0,myinfo->rpcport)) != 0 )
9 years ago
{
9 years ago
free(str);
9 years ago
if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"userhome\":\"/Users/jimbolaptop/Library/Application Support\",\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":1024,\"maxpeers\":256,\"newcoin\":\"BTCD\",\"active\":1}"),0,myinfo->rpcport)) != 0 )
9 years ago
{
free(str);
9 years ago
if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"alice\",\"password\":\"alice\",\"passphrase\":\"alice\"}"),0,myinfo->rpcport)) != 0 )
9 years ago
{
free(str);
9 years ago
if ( (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"bob\",\"password\":\"bob\",\"passphrase\":\"bob\"}"),0,myinfo->rpcport)) != 0 )
9 years ago
free(str);
}
}
9 years ago
printf("BTC active.%d BTCD active.%d\n",iguana_coinfind("BTC")->active,iguana_coinfind("BTCD")->active);
9 years ago
//iguana_coinfind("BTC")->active = iguana_coinfind("BTCD")->active = 0;
9 years ago
}
9 years ago
sleep(1);
9 years ago
}
9 years ago
{
int32_t i,n; int64_t total; char *coinaddr; struct iguana_pkhash *P; struct iguana_info *coin; uint8_t rmd160[20],addrtype,pubkey33[33]; double startmillis;
9 years ago
coin = iguana_coinfind("BTCD");
if ( 0 && coin != 0 )
9 years ago
{
9 years ago
getchar();
9 years ago
for (i=0; i<coin->bundlescount; i++)
if ( coin->bundles[i] == 0 )
break;
if ( i > 0 )
iguana_spentsfile(coin,i);
coinaddr = "RUZ9AKxy6J2okcBd1PZm4YH6atmPwqV4bo";
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
P = calloc(coin->bundlescount,sizeof(*P));
memset(pubkey33,0,sizeof(pubkey33));
n = iguana_pkhasharray(coin,0,0,0,&total,P,coin->bundlescount,rmd160,coinaddr,pubkey33);
9 years ago
printf("%s has total outputs %.8f from %d bundles\n",coinaddr,dstr(total),n);
9 years ago
startmillis = OS_milliseconds();
for (i=0; i<1000; i++)
n = iguana_pkhasharray(coin,0,0,0,&total,P,coin->bundlescount,rmd160,coinaddr,pubkey33);
9 years ago
printf("%s has total outputs %.8f from %d bundles %.3f millis\n",coinaddr,dstr(total),n,OS_milliseconds()-startmillis);
9 years ago
getchar();
}
}
9 years ago
#endif
9 years ago
for (i=0; i<IGUANA_NUMHELPERS; i++)
{
9 years ago
sprintf(helperstr,"{\"helperid\":%d}",i);
9 years ago
helperargs = clonestr(helperstr);
printf("launch[%d] of %d (%s)\n",i,IGUANA_NUMHELPERS,helperstr);
iguana_launch(btcd,"iguana_helper",iguana_helper,helperargs,IGUANA_PERMTHREAD);
}
9 years ago
iguana_launch(btcd,"rpcloop",iguana_rpcloop,myinfo,IGUANA_PERMTHREAD);
mainloop(myinfo);
9 years ago
}