jl777
9 years ago
18 changed files with 1145 additions and 1044 deletions
@ -0,0 +1,202 @@ |
|||||
|
/******************************************************************************
|
||||
|
* Copyright © 2014-2016 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. * |
||||
|
* * |
||||
|
******************************************************************************/ |
||||
|
|
||||
|
// included from basilisk.c
|
||||
|
|
||||
|
uint32_t basilisk_requestid(struct basilisk_request *rp) |
||||
|
{ |
||||
|
struct basilisk_request R; |
||||
|
R = *rp; |
||||
|
R.requestid = R.quoteid = R.quotetime = 0; |
||||
|
R.destamount = 0; |
||||
|
R.relaybits = 0; |
||||
|
memset(R.desthash.bytes,0,sizeof(R.desthash.bytes)); |
||||
|
if ( 0 ) |
||||
|
{ |
||||
|
int32_t i; |
||||
|
for (i=0; i<sizeof(R); i++) |
||||
|
printf("%02x",((uint8_t *)&R)[i]); |
||||
|
printf(" <- crc.%u\n",calc_crc32(0,(void *)&R,sizeof(R))); |
||||
|
char str[65],str2[65]; printf("B REQUESTID: t.%u r.%u q.%u %s %.8f %s -> %s %.8f %s crc.%u\n",R.timestamp,R.requestid,R.quoteid,R.src,dstr(R.srcamount),bits256_str(str,R.hash),R.dest,dstr(R.destamount),bits256_str(str2,R.desthash),calc_crc32(0,(void *)&R,sizeof(R))); |
||||
|
} |
||||
|
return(calc_crc32(0,(void *)&R,sizeof(R))); |
||||
|
} |
||||
|
|
||||
|
uint32_t basilisk_quoteid(struct basilisk_request *rp) |
||||
|
{ |
||||
|
struct basilisk_request R; |
||||
|
R = *rp; |
||||
|
R.requestid = R.quoteid = R.relaybits = 0; |
||||
|
return(calc_crc32(0,(void *)&R,sizeof(R))); |
||||
|
} |
||||
|
|
||||
|
struct basilisk_request *basilisk_parsejson(struct basilisk_request *rp,cJSON *reqjson) |
||||
|
{ |
||||
|
uint32_t requestid,quoteid; |
||||
|
memset(rp,0,sizeof(*rp)); |
||||
|
rp->hash = jbits256(reqjson,"hash"); |
||||
|
rp->desthash = jbits256(reqjson,"desthash"); |
||||
|
rp->srcamount = j64bits(reqjson,"srcamount"); |
||||
|
rp->minamount = j64bits(reqjson,"minamount"); |
||||
|
rp->destamount = j64bits(reqjson,"destamount"); |
||||
|
requestid = juint(reqjson,"requestid"); |
||||
|
quoteid = juint(reqjson,"quoteid"); |
||||
|
if ( jstr(reqjson,"relay") != 0 ) |
||||
|
rp->relaybits = (uint32_t)calc_ipbits(jstr(reqjson,"relay")); |
||||
|
rp->timestamp = juint(reqjson,"timestamp"); |
||||
|
rp->quotetime = juint(reqjson,"quotetime"); |
||||
|
safecopy(rp->src,jstr(reqjson,"src"),sizeof(rp->src)); |
||||
|
safecopy(rp->dest,jstr(reqjson,"dest"),sizeof(rp->dest)); |
||||
|
if ( quoteid != 0 ) |
||||
|
{ |
||||
|
rp->quoteid = basilisk_quoteid(rp); |
||||
|
if ( quoteid != rp->quoteid ) |
||||
|
printf("basilisk_parsejson quoteid.%u != %u error\n",quoteid,rp->quoteid); |
||||
|
} |
||||
|
rp->requestid = basilisk_requestid(rp); |
||||
|
if ( requestid != rp->requestid ) |
||||
|
printf("basilisk_parsejson requestid.%u != %u error\n",requestid,rp->requestid); |
||||
|
return(rp); |
||||
|
} |
||||
|
|
||||
|
void basilisk_swap_balancingtrade(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob) |
||||
|
{ |
||||
|
// update balance, compare to target balance, issue balancing trade via central exchanges, if needed
|
||||
|
if ( iambob != 0 ) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
struct basilisk_swap *basilisk_request_started(struct supernet_info *myinfo,uint32_t requestid) |
||||
|
{ |
||||
|
int32_t i; struct basilisk_swap *active = 0; |
||||
|
portable_mutex_lock(&myinfo->DEX_swapmutex); |
||||
|
for (i=0; i<myinfo->numswaps; i++) |
||||
|
if ( myinfo->swaps[i]->req.requestid == requestid ) |
||||
|
{ |
||||
|
//printf("REQUEST STARTED.[%d] <- req.%u\n",i,requestid);
|
||||
|
active = myinfo->swaps[i]; |
||||
|
break; |
||||
|
} |
||||
|
portable_mutex_unlock(&myinfo->DEX_swapmutex); |
||||
|
return(active); |
||||
|
} |
||||
|
|
||||
|
int32_t basilisk_request_cmpref(struct basilisk_request *ref,struct basilisk_request *rp) |
||||
|
{ |
||||
|
if ( bits256_cmp(rp->hash,ref->hash) != 0 || memcmp(rp->src,ref->src,sizeof(ref->src)) != 0 || memcmp(rp->dest,ref->dest,sizeof(ref->dest)) != 0 || rp->srcamount != ref->srcamount || rp->timestamp != ref->timestamp ) |
||||
|
{ |
||||
|
printf("basilisk_request_listprocess mismatched hash\n"); |
||||
|
return(-1); |
||||
|
} else return(0); |
||||
|
} |
||||
|
|
||||
|
double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk_request *issueR,struct basilisk_request *list,int32_t n) |
||||
|
{ |
||||
|
int32_t i,noquoteflag=0,havequoteflag=0,myrequest=0,maxi=-1; uint64_t destamount,minamount = 0,maxamount = 0; uint32_t pendingid=0; struct basilisk_swap *active; double metric = 0.; |
||||
|
memset(issueR,0,sizeof(*issueR)); |
||||
|
minamount = list[0].minamount; |
||||
|
//printf("need to verify null quoteid is list[0] requestid.%u quoteid.%u\n",list[0].requestid,list[0].quoteid);
|
||||
|
if ( (active= basilisk_request_started(myinfo,list[0].requestid)) != 0 ) |
||||
|
pendingid = active->req.quoteid; |
||||
|
if ( bits256_cmp(myinfo->myaddr.persistent,list[0].hash) == 0 ) // my request
|
||||
|
myrequest = 1; |
||||
|
for (i=0; i<n; i++) |
||||
|
{ |
||||
|
if ( basilisk_request_cmpref(&list[0],&list[i]) != 0 ) |
||||
|
return(-1); |
||||
|
if ( list[i].quoteid != 0 ) |
||||
|
{ |
||||
|
if ( bits256_cmp(myinfo->myaddr.persistent,list[i].desthash) == 0 ) // my quoteid
|
||||
|
myrequest |= 2; |
||||
|
havequoteflag++; |
||||
|
if ( pendingid == 0 ) |
||||
|
{ |
||||
|
if ( list[i].destamount > maxamount ) |
||||
|
{ |
||||
|
maxamount = list[i].destamount; |
||||
|
maxi = i; |
||||
|
} |
||||
|
} |
||||
|
else if ( active != 0 && pendingid == list[i].quoteid ) |
||||
|
{ |
||||
|
} |
||||
|
} else noquoteflag++; |
||||
|
} |
||||
|
//printf("myrequest.%d pendingid.%u noquoteflag.%d havequoteflag.%d maxi.%d %.8f\n",myrequest,pendingid,noquoteflag,havequoteflag,maxi,dstr(maxamount));
|
||||
|
if ( myrequest == 0 && pendingid == 0 && noquoteflag != 0 ) |
||||
|
{ |
||||
|
double retvals[4],aveprice; |
||||
|
aveprice = instantdex_avehbla(myinfo,retvals,list[0].src,list[0].dest,1.3 * dstr(list[0].srcamount)); |
||||
|
destamount = 0.99 * aveprice * list[0].srcamount; |
||||
|
printf("destamount %.8f aveprice %.8f minamount %.8f\n",dstr(destamount),aveprice,dstr(minamount)); |
||||
|
if ( destamount > 0 && destamount >= maxamount && destamount >= minamount ) |
||||
|
{ |
||||
|
metric = 1.; |
||||
|
*issueR = list[0]; |
||||
|
issueR->desthash = myinfo->myaddr.persistent; |
||||
|
issueR->destamount = destamount; |
||||
|
issueR->quotetime = (uint32_t)time(NULL); |
||||
|
} |
||||
|
} |
||||
|
else if ( myrequest != 0 && pendingid == 0 && maxi >= 0 ) // automatch best quote
|
||||
|
{ |
||||
|
if ( minamount != 0 && maxamount > minamount && time(NULL) > BASILISK_DEXDURATION/2 ) |
||||
|
{ |
||||
|
printf("automatch quoteid.%u triggered %.8f > %.8f\n",list[maxi].quoteid,dstr(maxamount),dstr(minamount)); |
||||
|
*issueR = list[maxi]; |
||||
|
if ( minamount > 0 ) |
||||
|
metric = (dstr(maxamount) / dstr(minamount)) - 1.; |
||||
|
else metric = 1.; |
||||
|
} |
||||
|
} |
||||
|
return(metric); |
||||
|
} |
||||
|
|
||||
|
double basilisk_process_results(struct supernet_info *myinfo,struct basilisk_request *issueR,cJSON *retjson,double hwm) |
||||
|
{ |
||||
|
cJSON *array,*item; int32_t i,n,m; struct basilisk_request tmpR,R,refR,list[BASILISK_MAXRELAYS]; double metric=0.; |
||||
|
if ( (array= jarray(&n,retjson,"result")) != 0 ) |
||||
|
{ |
||||
|
for (i=m=0; i<n; i++) |
||||
|
{ |
||||
|
item = jitem(array,i); |
||||
|
if ( i != 0 ) |
||||
|
{ |
||||
|
basilisk_parsejson(&R,item); |
||||
|
if ( refR.requestid == R.requestid ) |
||||
|
list[m++] = R; |
||||
|
else |
||||
|
{ |
||||
|
if ( (metric= basilisk_request_listprocess(myinfo,&tmpR,list,m)) > hwm ) |
||||
|
*issueR = tmpR, hwm = metric; |
||||
|
m = 0; |
||||
|
} |
||||
|
} |
||||
|
if ( m < sizeof(list)/sizeof(*list) ) |
||||
|
basilisk_parsejson(&list[m++],item); |
||||
|
} |
||||
|
if ( m > 0 && m < sizeof(list)/sizeof(*list) ) |
||||
|
if ( (metric= basilisk_request_listprocess(myinfo,&tmpR,list,m)) > hwm ) |
||||
|
*issueR = tmpR, hwm = metric; |
||||
|
} |
||||
|
return(hwm); |
||||
|
} |
@ -0,0 +1,789 @@ |
|||||
|
|
||||
|
/*
|
||||
|
* 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 "iguana777.h" |
||||
|
#include "secp256k1/include/secp256k1.h" |
||||
|
#include "secp256k1/include/secp256k1_schnorr.h" |
||||
|
#include "secp256k1/include/secp256k1_rangeproof.h" |
||||
|
|
||||
|
// ------------------------------------------------------[ Preparation ]----
|
||||
|
|
||||
|
static gfshare_ctx *_gfshare_ctx_init_core(uint8_t *sharenrs,uint32_t sharecount,uint8_t threshold,uint32_t size,void *space,int32_t spacesize) |
||||
|
{ |
||||
|
gfshare_ctx *ctx; int32_t allocsize; |
||||
|
allocsize = (int32_t)(sizeof(struct _gfshare_ctx) + threshold * size); |
||||
|
if ( allocsize > spacesize ) |
||||
|
{ |
||||
|
printf("malloc allocsize %d vs spacesize.%d\n",allocsize,spacesize); |
||||
|
ctx = malloc(allocsize); |
||||
|
if( ctx == NULL ) |
||||
|
return NULL; // errno should still be set from XMALLOC()
|
||||
|
ctx->allocsize = allocsize; |
||||
|
} else ctx = space; |
||||
|
memset(ctx,0,allocsize); |
||||
|
ctx->sharecount = sharecount; |
||||
|
ctx->threshold = threshold; |
||||
|
ctx->size = size; |
||||
|
memcpy(ctx->sharenrs,sharenrs,sharecount); |
||||
|
ctx->buffersize = threshold * size; |
||||
|
return(ctx); |
||||
|
} |
||||
|
|
||||
|
// Initialise a gfshare context for producing shares
|
||||
|
gfshare_ctx *gfshare_ctx_initenc(uint8_t *sharenrs,uint32_t sharecount,uint8_t threshold,uint32_t size,void *space,int32_t spacesize) |
||||
|
{ |
||||
|
uint32_t 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,space,spacesize)); |
||||
|
} |
||||
|
|
||||
|
// Initialise a gfshare context for recombining shares
|
||||
|
gfshare_ctx *gfshare_ctx_initdec(uint8_t *sharenrs,uint32_t sharecount,uint32_t size,void *space,int32_t spacesize) |
||||
|
{ |
||||
|
gfshare_ctx *ctx = _gfshare_ctx_init_core(sharenrs,sharecount,sharecount,size,space,spacesize); |
||||
|
if ( ctx != NULL ) |
||||
|
ctx->threshold = 0; |
||||
|
return(ctx); |
||||
|
} |
||||
|
|
||||
|
// Free a share context's memory
|
||||
|
void gfshare_ctx_free(gfshare_ctx *ctx) |
||||
|
{ |
||||
|
OS_randombytes(ctx->buffer,ctx->buffersize); |
||||
|
OS_randombytes(ctx->sharenrs,ctx->sharecount); |
||||
|
if ( ctx->allocsize != 0 ) |
||||
|
{ |
||||
|
OS_randombytes((uint8_t *)ctx,sizeof(struct _gfshare_ctx)); |
||||
|
free(ctx); |
||||
|
} |
||||
|
OS_randombytes((uint8_t *)ctx,sizeof(struct _gfshare_ctx)); |
||||
|
} |
||||
|
|
||||
|
// --------------------------------------------------------[ Splitting ]----
|
||||
|
|
||||
|
// Provide a secret to the encoder. (this re-scrambles the coefficients)
|
||||
|
void gfshare_ctx_enc_setsecret(gfshare_ctx *ctx,uint8_t *secret) |
||||
|
{ |
||||
|
memcpy(ctx->buffer + ((ctx->threshold-1) * ctx->size),secret,ctx->size); |
||||
|
OS_randombytes(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_encgetshare(uint8_t *_logs,uint8_t *_exps,gfshare_ctx *ctx,uint8_t sharenr,uint8_t *share) |
||||
|
{ |
||||
|
uint32_t pos,coefficient,ilog = _logs[ctx->sharenrs[sharenr]]; |
||||
|
uint8_t *share_ptr,*coefficient_ptr = ctx->buffer; |
||||
|
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 != 0 ) |
||||
|
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) |
||||
|
{ |
||||
|
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) |
||||
|
{ |
||||
|
memcpy(ctx->buffer + (sharenr * ctx->size),share,ctx->size); |
||||
|
} |
||||
|
|
||||
|
// Extract the secret by interpolating the shares. secretbuf must be allocated and at least 'size' bytes
|
||||
|
void gfshare_ctx_decextract(uint8_t *_logs,uint8_t *_exps,gfshare_ctx *ctx,uint8_t *secretbuf) |
||||
|
{ |
||||
|
uint32_t 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++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int32_t gfshare_test(struct supernet_info *myinfo,int32_t M,int32_t N,int32_t datasize) |
||||
|
{ |
||||
|
int ok = 1, i,k; |
||||
|
uint8_t * secret = malloc(datasize); |
||||
|
uint8_t *shares[255]; |
||||
|
uint8_t *recomb = malloc(datasize); |
||||
|
uint8_t space[8192],sharenrs[255],newsharenrs[255];// = (uint8_t *)strdup("0124z89abehtr");
|
||||
|
gfshare_ctx *G; |
||||
|
for (i=0; i<N; i++) |
||||
|
{ |
||||
|
sharenrs[i] = i+1; |
||||
|
shares[i] = malloc(datasize); |
||||
|
} |
||||
|
init_sharenrs(sharenrs,0,N,N); |
||||
|
/* Stage 1, make a secret */ |
||||
|
for( i = 0; i < datasize; ++i ) |
||||
|
secret[i] = (rand() & 0xff00) >> 8; |
||||
|
/* Stage 2, split it N ways with a threshold of M */ |
||||
|
G = gfshare_ctx_initenc( sharenrs, N, M, datasize,space,sizeof(space) ); |
||||
|
gfshare_ctx_enc_setsecret( G, secret ); |
||||
|
for (i=0; i<N; i++) |
||||
|
gfshare_ctx_encgetshare(myinfo->logs,myinfo->exps, G, i, shares[i] ); |
||||
|
gfshare_ctx_free( G ); |
||||
|
/* Prep the decode shape */ |
||||
|
uint8_t save[255]; |
||||
|
memcpy(save,sharenrs,sizeof(sharenrs)); |
||||
|
G = gfshare_ctx_initdec( sharenrs, N, datasize,space,sizeof(space) ); |
||||
|
for (k=0; k<10; k++) |
||||
|
{ |
||||
|
memcpy(sharenrs,save,sizeof(sharenrs)); |
||||
|
memset(newsharenrs,0,N); |
||||
|
int32_t j,r,m; |
||||
|
m = M + (rand() % (N-M+1)); |
||||
|
for (i=0; i<m && i<N; 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 ) |
||||
|
{ |
||||
|
fprintf(stderr,"%d ",newsharenrs[i]); |
||||
|
gfshare_ctx_dec_giveshare( G, i, shares[i] ); |
||||
|
} |
||||
|
//newsharenrs[i] = sharenrs[i];
|
||||
|
} |
||||
|
gfshare_ctx_dec_newshares( G, newsharenrs ); |
||||
|
gfshare_ctx_decextract(myinfo->logs,myinfo->exps, G, recomb ); |
||||
|
for (i=0; i<datasize; i++) |
||||
|
if ( secret[i] != recomb[i] ) |
||||
|
ok = 0; |
||||
|
printf("m.%d M.%-3d N.%-3d ok.%d datalen.%d\n",m,M,N,ok,datasize); |
||||
|
} |
||||
|
free(recomb), free(secret); |
||||
|
for (i=0; i<N; i++) |
||||
|
free(shares[i]); |
||||
|
return ok!=1; |
||||
|
} |
||||
|
|
||||
|
void libgfshare_init(struct supernet_info *myinfo,uint8_t _logs[256],uint8_t _exps[510]) |
||||
|
{ |
||||
|
uint32_t i,x = 1; |
||||
|
myinfo->ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); |
||||
|
secp256k1_pedersen_context_initialize(myinfo->ctx); |
||||
|
secp256k1_rangeproof_context_initialize(myinfo->ctx); |
||||
|
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
|
||||
|
} |
||||
|
for (i=255; i<510; i++) |
||||
|
_exps[i] = _exps[i % 255]; |
||||
|
_logs[0] = 0; // can't log(0) so just set it neatly to 0
|
||||
|
if ( 0 ) |
||||
|
{ |
||||
|
void test_mofn(struct supernet_info *myinfo); |
||||
|
gfshare_test(myinfo,6,11,32); |
||||
|
test_mofn(myinfo); |
||||
|
getchar(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Construct and write out the tables for the gfshare code
|
||||
|
int maingen(int argc,char **argv) |
||||
|
{ |
||||
|
uint8_t logs[256],exps[255]; uint32_t i; |
||||
|
libgfshare_init(0,logs,exps); |
||||
|
// 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; |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************
|
||||
|
* Copyright © 2014-2016 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. * |
||||
|
* * |
||||
|
******************************************************************************/ |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
uint8_t *recoverdata(struct supernet_info *myinfo,uint8_t *shares[],uint8_t *sharenrs,int32_t M,uint8_t *recover,int32_t datasize,int32_t N) |
||||
|
{ |
||||
|
void *G; int32_t i,m=0; uint8_t recovernrs[255],space[8192]; |
||||
|
memset(recovernrs,0,sizeof(recovernrs)); |
||||
|
for (i=0; i<N; i++) |
||||
|
if ( shares[i] != 0 ) |
||||
|
recovernrs[i] = sharenrs[i], m++; |
||||
|
if ( m >= M ) |
||||
|
{ |
||||
|
G = gfshare_ctx_initdec(recovernrs,N,datasize,space,sizeof(space)); |
||||
|
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_decextract(myinfo->logs,myinfo->exps,G,recover); |
||||
|
gfshare_ctx_free(G); |
||||
|
return(recover); |
||||
|
} else return(0); |
||||
|
} |
||||
|
|
||||
|
void calc_share(struct supernet_info *myinfo,uint8_t *buffer,int32_t size,int32_t M,uint32_t ilog,uint8_t *share) |
||||
|
{ |
||||
|
uint32_t pos,coefficient; 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 = myinfo->exps[ilog + myinfo->logs[share_byte]]; |
||||
|
*share_ptr++ = (share_byte ^ *buffer++); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void calc_shares(struct supernet_info *myinfo,uint8_t *shares,uint8_t *secret,int32_t size,int32_t width,int32_t M,int32_t N,uint8_t *sharenrs,uint8_t *space,int32_t spacesize) |
||||
|
{ |
||||
|
int32_t i; uint8_t *buffer; |
||||
|
if ( M*width > spacesize ) |
||||
|
{ |
||||
|
buffer = calloc(M,width); |
||||
|
printf("calloc M.%d width.%d\n",M,width); |
||||
|
} else buffer = space; |
||||
|
memset(shares,0,N * width); |
||||
|
memcpy(buffer + ((M - 1) * size),secret,size); |
||||
|
OS_randombytes(buffer,(M - 1) * size); |
||||
|
for (i=0; i<N; i++) |
||||
|
{ |
||||
|
calc_share(myinfo,buffer,size,M,myinfo->logs[sharenrs[i]],&shares[i * width]); |
||||
|
//printf("(%03d %08x) ",sharenrs[i],calc_crc32(0,&shares[i * width],size));
|
||||
|
} |
||||
|
if ( buffer != space ) |
||||
|
free(buffer); |
||||
|
} |
||||
|
|
||||
|
int32_t calc_sharenrs(uint8_t *sharenrs,int32_t N,uint8_t *data,int32_t datasize) |
||||
|
{ |
||||
|
bits256 hash,hash2; uint8_t r; int32_t i,j,n = sizeof(hash); |
||||
|
vcalc_sha256(0,hash.bytes,data,datasize); |
||||
|
vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash)); |
||||
|
for (i=0; i<N; i++) |
||||
|
{ |
||||
|
while ( 1 ) |
||||
|
{ |
||||
|
if ( n >= sizeof(hash) ) |
||||
|
{ |
||||
|
vcalc_sha256(0,hash.bytes,hash2.bytes,sizeof(hash2)); |
||||
|
vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash)); |
||||
|
n = 0; |
||||
|
} |
||||
|
r = hash2.bytes[n++]; |
||||
|
if ( (sharenrs[i]= r) == 0 || sharenrs[i] == 0xff ) |
||||
|
continue; |
||||
|
for (j=0; j<i; j++) |
||||
|
if ( sharenrs[j] == sharenrs[i] ) |
||||
|
break; |
||||
|
if ( j == i ) |
||||
|
break; |
||||
|
} |
||||
|
//printf("%3d ",sharenrs[i]);
|
||||
|
} |
||||
|
return(N); |
||||
|
} |
||||
|
|
||||
|
int32_t calcmofn(struct supernet_info *myinfo,uint8_t *allshares,uint8_t *sharenrs,int32_t M,uint8_t *data,int32_t datasize,int32_t N) |
||||
|
{ |
||||
|
uint8_t space[8192]; |
||||
|
calc_sharenrs(sharenrs,N,data,datasize); |
||||
|
calc_shares(myinfo,allshares,(void *)data,datasize,datasize,M,N,sharenrs,space,sizeof(space)); |
||||
|
return(datasize); |
||||
|
} |
||||
|
|
||||
|
struct mofn256_info |
||||
|
{ |
||||
|
bits256 secret; |
||||
|
uint8_t *sharenrs; |
||||
|
int32_t M,N,allocsize; |
||||
|
bits256 allshares[]; |
||||
|
}; |
||||
|
|
||||
|
int32_t mofn256_size(uint8_t M,uint8_t N) |
||||
|
{ |
||||
|
int32_t allocsize; |
||||
|
allocsize = ((int32_t)(sizeof(struct mofn256_info) + sizeof(bits256) * N + N)); |
||||
|
if ( (allocsize & 0xf) != 0 ) |
||||
|
allocsize += 0x10 - (allocsize & 0xf); |
||||
|
return(allocsize); |
||||
|
} |
||||
|
|
||||
|
struct mofn256_info *mofn256_init(struct supernet_info *myinfo,bits256 secret,uint8_t M,uint8_t N,int32_t calcflag,uint8_t *space,int32_t spacesize) |
||||
|
{ |
||||
|
int32_t allocsize; struct mofn256_info *mofn = 0; |
||||
|
if ( M > N || N == 0 || N == 0xff ) |
||||
|
return(0); |
||||
|
allocsize = mofn256_size(M,N); |
||||
|
if ( allocsize > spacesize ) |
||||
|
{ |
||||
|
mofn = calloc(1,allocsize); |
||||
|
mofn->allocsize = allocsize; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
mofn = (void *)space; |
||||
|
memset(mofn,0,allocsize); |
||||
|
} |
||||
|
mofn->M = M; |
||||
|
mofn->N = N; |
||||
|
mofn->sharenrs = (void *)&mofn->allshares[N]; |
||||
|
if ( calcflag != 0 ) |
||||
|
{ |
||||
|
mofn->secret = secret; |
||||
|
calcmofn(myinfo,mofn->allshares[0].bytes,mofn->sharenrs,M,secret.bytes,sizeof(secret),N); |
||||
|
} |
||||
|
return(mofn); |
||||
|
} |
||||
|
|
||||
|
bits256 mofn256_recover(struct supernet_info *myinfo,struct mofn256_info *mofn) |
||||
|
{ |
||||
|
uint8_t *shares[255]; bits256 recover; int32_t i; |
||||
|
for (i=0; i<mofn->N; i++) |
||||
|
{ |
||||
|
if ( bits256_nonz(mofn->allshares[i]) != 0 ) |
||||
|
shares[i] = mofn->allshares[i].bytes; |
||||
|
else shares[i] = 0; |
||||
|
} |
||||
|
if ( recoverdata(myinfo,shares,mofn->sharenrs,mofn->M,recover.bytes,sizeof(recover),mofn->N) == 0 ) |
||||
|
memset(recover.bytes,0,sizeof(recover)); |
||||
|
return(recover); |
||||
|
} |
||||
|
|
||||
|
int32_t test_mofn256(struct supernet_info *myinfo,int32_t M,int32_t N) |
||||
|
{ |
||||
|
uint8_t space[8192]; char str[65],str2[65]; struct mofn256_info *mofn,*cmp; bits256 secret,recover; int32_t i,allocsize,retval,m = 0; |
||||
|
allocsize = mofn256_size(M,N); |
||||
|
cmp = mofn256_init(myinfo,GENESIS_PUBKEY,M,N,0,space,sizeof(space)); |
||||
|
secret = rand256(0); |
||||
|
mofn = mofn256_init(myinfo,secret,M,N,1,&space[allocsize],sizeof(space) - allocsize); |
||||
|
memcpy(cmp->sharenrs,mofn->sharenrs,mofn->N); |
||||
|
for (i=0; i<N; i++) |
||||
|
if ( (rand() % 100) < 50 ) |
||||
|
cmp->allshares[i] = mofn->allshares[i], m++; |
||||
|
recover = mofn256_recover(myinfo,cmp); |
||||
|
retval = -1 * (bits256_cmp(recover,mofn->secret) != 0); |
||||
|
if ( bits256_cmp(recover,mofn->secret) != 0 ) |
||||
|
{ |
||||
|
if ( m >= M ) |
||||
|
printf("%s %s error m.%d vs M.%d N.%d\n",bits256_str(str,secret),bits256_str(str2,recover),m,mofn->M,mofn->N); |
||||
|
} |
||||
|
if ( ((long)mofn - (long)space) >= sizeof(space) || ((long)mofn - (long)space) < 0 ) |
||||
|
free(mofn); |
||||
|
if ( ((long)cmp - (long)space) >= sizeof(space) || ((long)cmp - (long)space) < 0 ) |
||||
|
free(cmp); |
||||
|
return(retval); |
||||
|
} |
||||
|
|
||||
|
#define N 11 |
||||
|
#define M 6 |
||||
|
void test_mofn(struct supernet_info *myinfo) |
||||
|
{ |
||||
|
bits256 allshares[N],secret,recover; uint8_t *shares[N],sharenrs[N]; int32_t i,j,m; |
||||
|
secret = rand256(0); |
||||
|
srand(secret.uints[0]); |
||||
|
calcmofn(myinfo,allshares[0].bytes,sharenrs,M,secret.bytes,sizeof(secret),N); |
||||
|
for (i=0; i<10000; i++) |
||||
|
{ |
||||
|
memset(shares,0,sizeof(shares)); |
||||
|
for (j=m=0; j<N; j++) |
||||
|
if ( (rand() % 100) < 55 ) |
||||
|
shares[j] = allshares[j].bytes, m++; |
||||
|
if ( recoverdata(myinfo,shares,sharenrs,M,recover.bytes,sizeof(secret),N) != 0 ) |
||||
|
{ |
||||
|
if ( memcmp(secret.bytes,recover.bytes,sizeof(secret)) != 0 ) |
||||
|
printf("FAILED m.%d M.%d N.%d\n",m,M,N); |
||||
|
else if ( 0 ) |
||||
|
{ |
||||
|
char str[65]; |
||||
|
printf("%s PASSED m.%d M.%d N.%d\n",bits256_str(str,recover),m,M,N); |
||||
|
} |
||||
|
} //else printf("not enough shares m.%d M.%d N.%d\n",m,M,N);
|
||||
|
} |
||||
|
printf("finished %d tests\n",i); |
||||
|
for (i=0; i<10000; i++) |
||||
|
test_mofn256(myinfo,M,N); |
||||
|
printf("finished %d tests256\n",i); |
||||
|
} |
||||
|
#undef M |
||||
|
#undef N |
||||
|
|
||||
|
#define SECP_ENSURE_CTX int32_t flag = 0; if ( ctx == 0 ) { ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); secp256k1_pedersen_context_initialize(ctx); secp256k1_rangeproof_context_initialize(ctx); flag++; } else flag = 0; if ( ctx != 0 ) |
||||
|
#define ENDSECP_ENSURE_CTX if ( flag != 0 ) secp256k1_context_destroy(ctx); |
||||
|
|
||||
|
int32_t iguana_schnorr_peersign(void *ctx,uint8_t *allpub33,uint8_t *partialsig64,int32_t peeri,bits256 mypriv,bits256 privnonce,bits256 *nonces,int32_t n,bits256 msg256) |
||||
|
{ |
||||
|
secp256k1_pubkey Rall,ALL,PUBS[256],*PUBptrs[256]; int32_t i,num,retval = -1; size_t plen; uint8_t pubkey[33]; |
||||
|
pubkey[0] = 2; |
||||
|
SECP_ENSURE_CTX |
||||
|
{ |
||||
|
for (i=num=0; i<n; i++) |
||||
|
{ |
||||
|
plen = 33; |
||||
|
memcpy(pubkey+1,nonces[i].bytes,32); |
||||
|
if ( secp256k1_ec_pubkey_parse(ctx,&PUBS[i],pubkey,plen) == 0 ) |
||||
|
printf("error extracting pubkey.%d of %d\n",i,n); |
||||
|
if ( i != peeri ) |
||||
|
PUBptrs[num++] = &PUBS[i]; |
||||
|
} |
||||
|
PUBptrs[num] = &PUBS[peeri]; |
||||
|
if ( secp256k1_ec_pubkey_combine(ctx,&ALL,(void *)PUBptrs,num+1) != 0 ) |
||||
|
{ |
||||
|
plen = 33; |
||||
|
secp256k1_ec_pubkey_serialize(ctx,allpub33,&plen,&ALL,SECP256K1_EC_COMPRESSED); |
||||
|
//for (i=0; i<33; i++)
|
||||
|
// printf("%02x",allpub33[i]);
|
||||
|
//printf("\n");
|
||||
|
} else printf("error combining ALL\n"); |
||||
|
if ( secp256k1_ec_pubkey_combine(ctx,&Rall,(void *)PUBptrs,num) != 0 ) |
||||
|
{ |
||||
|
if ( secp256k1_schnorr_partial_sign(ctx,partialsig64,msg256.bytes,mypriv.bytes,&Rall,privnonce.bytes) == 0 ) |
||||
|
printf("iguana_schnorr_peersign: err %d of num.%d\n",peeri,n); |
||||
|
else retval = 0; |
||||
|
} else printf("error parsing pubkey.%d\n",peeri); |
||||
|
ENDSECP_ENSURE_CTX |
||||
|
} |
||||
|
return(retval); |
||||
|
} |
||||
|
|
||||
|
bits256 iguana_schnorr_noncepair(void *ctx,bits256 *pubkey,uint8_t odd_even,bits256 msg256,bits256 privkey,int32_t maxj) |
||||
|
{ |
||||
|
bits256 privnonce; int32_t j; uint8_t pubkey33[33]; |
||||
|
for (j=0; j<maxj; j++) |
||||
|
{ |
||||
|
privnonce = bitcoin_schnorr_noncepair(ctx,pubkey33,msg256,privkey); |
||||
|
if ( pubkey33[0] == (odd_even + 2) ) |
||||
|
{ |
||||
|
memcpy(pubkey->bytes,pubkey33+1,32); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
if ( j == maxj ) |
||||
|
{ |
||||
|
printf("couldnt generate even noncepair\n"); |
||||
|
exit(-1); |
||||
|
} |
||||
|
return(privnonce); |
||||
|
} |
||||
|
|
||||
|
struct schnorr_info |
||||
|
{ |
||||
|
bits256 msg256,privkey,pubkey,privnonce,pubnonce,serhash2; |
||||
|
int32_t M,N; uint32_t msgid; |
||||
|
uint8_t sig64[64],combinedsig64[64],allpub[33],combined_allpub[33]; |
||||
|
uint16_t ind,nonz; |
||||
|
bits256 *pubkeys,*pubnonces; |
||||
|
uint8_t serialized[65 + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(bits256)*4]; |
||||
|
uint8_t sigs[]; |
||||
|
}; |
||||
|
|
||||
|
int32_t schnorr_rwinitdata(int32_t rwflag,uint8_t *serialized,uint16_t *indp,uint32_t *msgidp,bits256 hashes[4]) |
||||
|
{ |
||||
|
int32_t i,j,len = 0; |
||||
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(*indp),indp); |
||||
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(*msgidp),msgidp); |
||||
|
for (j=0; j<4; j++) |
||||
|
for (i=0; i<32; i++) |
||||
|
iguana_rwnum(rwflag,&serialized[len++],1,&hashes[j].bytes[i]); |
||||
|
return(len); |
||||
|
} |
||||
|
|
||||
|
struct schnorr_info *schnorr_init(struct supernet_info *myinfo,uint32_t msgid,uint16_t ind,int32_t M,int32_t N,void *space,int32_t spacesize,bits256 msg256) |
||||
|
{ |
||||
|
uint8_t *serialized; bits256 hashes[4]; int32_t len,odd_even = 0; struct schnorr_info *si = space; |
||||
|
si->pubnonces = (void *)&si->sigs[N * 64]; |
||||
|
si->pubkeys = &si->pubnonces[N]; |
||||
|
si->M = M; |
||||
|
si->N = N; |
||||
|
si->ind = ind; |
||||
|
si->msgid = msgid; |
||||
|
si->msg256 = msg256; |
||||
|
si->pubkey = bitcoin_pub256(myinfo->ctx,&si->privkey,odd_even); |
||||
|
si->privnonce = iguana_schnorr_noncepair(myinfo->ctx,&si->pubnonce,odd_even,msg256,si->privkey,100); |
||||
|
len = 0; |
||||
|
serialized = &si->serialized[65]; |
||||
|
hashes[0] = myinfo->myaddr.persistent; |
||||
|
hashes[1] = si->pubkey; |
||||
|
hashes[2] = si->pubnonce; |
||||
|
hashes[3] = msg256; |
||||
|
len = schnorr_rwinitdata(1,serialized,&ind,&msgid,hashes); |
||||
|
blockhash_sha256(si->serhash2.bytes,serialized,len); |
||||
|
if ( bitcoin_sign(myinfo->ctx,"SCHNORR",si->serialized,si->serhash2,myinfo->persistent_priv,1) != 65 ) |
||||
|
printf("error signing schnorr initdata\n"); |
||||
|
return(si); |
||||
|
} |
||||
|
|
||||
|
int32_t schnorr_update(struct supernet_info *myinfo,struct schnorr_info *si,uint8_t *serialized,int32_t recvlen) |
||||
|
{ |
||||
|
int32_t len; uint16_t ind; uint32_t msgid; bits256 hashes[4]; |
||||
|
// verify compact sig
|
||||
|
len = schnorr_rwinitdata(0,&serialized[65],&ind,&msgid,hashes); |
||||
|
// verify persistent pubkey matches ind
|
||||
|
if ( bits256_cmp(hashes[3],si->msg256) == 0 && msgid == si->msgid && bits256_nonz(si->pubkeys[ind]) == 0 && bits256_nonz(si->pubnonces[ind]) == 0 ) |
||||
|
{ |
||||
|
si->pubkeys[ind] = hashes[1]; |
||||
|
si->pubnonces[ind] = hashes[2]; |
||||
|
if ( ++si->nonz >= si->M ) |
||||
|
{ |
||||
|
iguana_schnorr_peersign(myinfo->ctx,si->allpub,si->sig64,si->ind,si->privkey,si->privnonce,si->pubnonces,si->M,si->msg256); |
||||
|
// broadcast si->sig64 + ind + msgid
|
||||
|
} |
||||
|
} |
||||
|
return(si->M); |
||||
|
} |
||||
|
|
||||
|
/*{
|
||||
|
if ( bitcoin_schnorr_combine(myinfo->ctx,si->combinedsig64,si->combined_allpub,si->sigs,si->M,si->msg256) < 0 ) |
||||
|
printf("error combining k.%d sig64 iter.%d\n",k,iter); |
||||
|
if ( bitcoin_schnorr_verify(myinfo->ctx,si->combinedsig64,si->msg256,si->combined_allpub,33) < 0 ) |
||||
|
printf("allpub2 error verifying combined sig k.%d\n",k); |
||||
|
}*/ |
||||
|
|
||||
|
void iguana_schnorr(struct supernet_info *myinfo) |
||||
|
{ |
||||
|
uint8_t allpubs[256][33],allpub[33],allpub2[33],sig64s[256][64],sig64[64],*sigs[256]; bits256 msg256,privnonces[256],signers,privkeys[256],pubkeys[256],pubkeysB[256],nonces[256]; int32_t i,iter,n,k,maxj = 100; |
||||
|
OS_randombytes((void *)&n,sizeof(n)); |
||||
|
srand(n); |
||||
|
n = 1 + (rand() % 255); |
||||
|
// generate onetime keypairs
|
||||
|
for (i=0; i<n; i++) |
||||
|
pubkeys[i] = bitcoin_pub256(myinfo->ctx,&privkeys[i],0); |
||||
|
msg256 = rand256(0); |
||||
|
for (i=0; i<n; i++) |
||||
|
privnonces[i] = iguana_schnorr_noncepair(myinfo->ctx,&nonces[i],0,msg256,privkeys[i],maxj); |
||||
|
for (i=0; i<n; i++) |
||||
|
iguana_schnorr_peersign(myinfo->ctx,allpubs[i],sig64s[i],i,privkeys[i],privnonces[i],nonces,n,msg256); |
||||
|
for (iter=0; iter<1; iter++) |
||||
|
{ |
||||
|
memset(signers.bytes,0,sizeof(signers)); |
||||
|
for (i=k=0; i<n; i++) |
||||
|
{ |
||||
|
if ( (rand() % 100) < 50 ) |
||||
|
{ |
||||
|
printf("%2d ",i); |
||||
|
sigs[k] = sig64s[i]; |
||||
|
pubkeysB[k] = pubkeys[i]; |
||||
|
k++; |
||||
|
SETBIT(signers.bytes,i); |
||||
|
} |
||||
|
} |
||||
|
if ( bitcoin_schnorr_combine(myinfo->ctx,sig64,allpub2,sigs,k,msg256) < 0 ) |
||||
|
printf("error combining k.%d sig64 iter.%d\n",k,iter); |
||||
|
else if ( bitcoin_schnorr_verify(myinfo->ctx,sig64,msg256,allpub2,33) < 0 ) |
||||
|
printf("allpub2 error verifying combined sig k.%d\n",k); |
||||
|
else if ( 0 ) // doesnt replicate with subsets
|
||||
|
{ |
||||
|
if ( bitcoin_pubkey_combine(myinfo->ctx,allpub,0,pubkeys,n,0,0) == 0 ) |
||||
|
{ |
||||
|
if ( memcmp(allpub,allpubs[0],33) != 0 ) |
||||
|
{ |
||||
|
printf("\n"); |
||||
|
for (k=0; k<33; k++) |
||||
|
printf("%02x",allpubs[0][k]); |
||||
|
printf(" combined\n"); |
||||
|
for (k=0; k<33; k++) |
||||
|
printf("%02x",allpub[k]); |
||||
|
printf(" allpub, "); |
||||
|
printf("allpub mismatch iter.%d i.%d n.%d\n",iter,i,n); |
||||
|
} else printf("validated iter.%d k.%d %llx\n",iter,k,(long long)signers.txid); |
||||
|
} //else printf("error combining\n");
|
||||
|
} else printf("passed n.%d\n",n); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
Loading…
Reference in new issue