|
@ -85,15 +85,6 @@ struct category_info *category_processfunc(bits256 categoryhash,int32_t (*proces |
|
|
return(0); |
|
|
return(0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct category_chain |
|
|
|
|
|
{ |
|
|
|
|
|
int32_t hashlen,addrlen; |
|
|
|
|
|
struct supernet_info *myinfo; |
|
|
|
|
|
void *categoryinfo,*subinfo; |
|
|
|
|
|
int32_t (*blockhash_func)(struct category_chain *cchain,void *blockhashp,void *data,int32_t datalen); |
|
|
|
|
|
bits256 (*stake_func)(struct category_chain *cchain,void *addr,int32_t addrlen); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
int32_t category_default_blockhash(struct category_chain *cchain,void *blockhashp,void *data,int32_t datalen) |
|
|
int32_t category_default_blockhash(struct category_chain *cchain,void *blockhashp,void *data,int32_t datalen) |
|
|
{ |
|
|
{ |
|
|
bits256 hash; |
|
|
bits256 hash; |
|
@ -110,82 +101,88 @@ bits256 category_default_stake(struct category_chain *cchain,void *addr,int32_t |
|
|
return(stake); |
|
|
return(stake); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bits256 catgory_default_hit(struct supernet_info *myinfo,void *categoryinfo,void *subinfo,int32_t height,void *prevgenerator,void *addr,int32_t addrlen,void *blockhashp,int32_t hashlen) |
|
|
bits256 catgory_default_hit(struct category_chain *cchain,int32_t height,void *prevgenerator,void *addr,void *blockhashp) |
|
|
{ |
|
|
{ |
|
|
bits256 hash; bits256 rawhit,hit; |
|
|
bits256 hash; bits256 rawhit,hit; |
|
|
memset(rawhit.bytes,0,sizeof(rawhit)); |
|
|
memset(rawhit.bytes,0,sizeof(rawhit)); |
|
|
memset(hit.bytes,0,sizeof(hit)); |
|
|
memset(hit.bytes,0,sizeof(hit)); |
|
|
vcalc_sha256cat(hash.bytes,prevgenerator,addrlen,addr,addrlen); |
|
|
vcalc_sha256cat(hash.bytes,prevgenerator,cchain->addrlen,addr,cchain->addrlen); |
|
|
hit = category_default_stake(*(void **)categoryinfo,addr,addrlen); |
|
|
hit = (*cchain->stake_func)(cchain,addr,cchain->addrlen); |
|
|
rawhit.txid = hash.txid % ((uint64_t)1 << 42); |
|
|
rawhit.txid = hash.txid % ((uint64_t)1 << 42); |
|
|
if ( rawhit.txid != 0 ) |
|
|
if ( rawhit.txid != 0 ) |
|
|
hit.txid /= rawhit.txid; |
|
|
hit.txid /= rawhit.txid; |
|
|
return(hit); |
|
|
return(hit); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// WARNING: toy implementation assumes only one category chain
|
|
|
#define category_default_heaviest() (*cchain->default_func)(cchain,'H',0,0,0,0,zero) |
|
|
bits256 category_default_func(struct supernet_info *myinfo,int32_t func,void *categoryinfo,void *subinfo,int32_t height,void *prevgenerator,void *addr,int32_t addrlen,void *blockhashp,int32_t hashlen,bits256 heaviest) |
|
|
#define category_default_latest() (*cchain->default_func)(cchain,'L',0,0,0,0,zero) |
|
|
|
|
|
#define category_default_setheaviest(height,blockhashp,heaviest) (*cchain->default_func)(cchain,'S',height,0,0,blockhashp,zero) |
|
|
|
|
|
#define category_default_weight(height) (*cchain->default_func)(cchain,'W',height,0,0,0,zero) |
|
|
|
|
|
#define category_default_blockfind(height) (*cchain->default_func)(cchain,'B',height,0,0,0,zero) |
|
|
|
|
|
|
|
|
|
|
|
bits256 category_default_func(struct category_chain *cchain,int32_t func,int32_t height,void *prevgenerator,void *addr,void *blockhashp,bits256 heaviest) |
|
|
{ |
|
|
{ |
|
|
static int maxblocknum; static bits256 *weights,*blocks,category_hwm,zero; |
|
|
static bits256 zero; |
|
|
if ( hashlen != sizeof(bits256) || addrlen != sizeof(bits256) ) |
|
|
if ( cchain->hashlen != sizeof(bits256) || cchain->addrlen != sizeof(bits256) ) |
|
|
{ |
|
|
{ |
|
|
printf("unsupported hashlen.%d or addrlen.%d\n",hashlen,addrlen); |
|
|
printf("unsupported hashlen.%d or addrlen.%d\n",cchain->hashlen,cchain->addrlen); |
|
|
return(zero); |
|
|
return(zero); |
|
|
} |
|
|
} |
|
|
if ( height > maxblocknum + (func == 'S') ) |
|
|
if ( height > cchain->maxblocknum + (func == 'S') ) |
|
|
{ |
|
|
{ |
|
|
printf("error func.%c setting heaviest. skipped %d -> %d?\n",func,maxblocknum,height); |
|
|
printf("error func.%c setting heaviest. skipped %d -> %d?\n",func,cchain->maxblocknum,height); |
|
|
return(category_hwm); |
|
|
return(cchain->category_hwm); |
|
|
} |
|
|
} |
|
|
if ( func == 'H' ) |
|
|
if ( func == 'H' ) |
|
|
return(category_hwm); |
|
|
return(cchain->category_hwm); |
|
|
|
|
|
else if ( func == 'L' ) |
|
|
|
|
|
{ |
|
|
|
|
|
if ( cchain->maxblocknum < 0 ) |
|
|
|
|
|
return(cchain->cchainhash); |
|
|
|
|
|
else return(cchain->blocks[cchain->maxblocknum]); |
|
|
|
|
|
} |
|
|
else if ( func == 'S' ) |
|
|
else if ( func == 'S' ) |
|
|
{ |
|
|
{ |
|
|
category_hwm = heaviest; |
|
|
cchain->category_hwm = heaviest; |
|
|
if ( height > maxblocknum ) |
|
|
if ( height > cchain->maxblocknum ) |
|
|
{ |
|
|
{ |
|
|
weights = realloc(weights,(maxblocknum+1) * sizeof(*weights)); |
|
|
cchain->weights = realloc(cchain->weights,(cchain->maxblocknum+1) * sizeof(*cchain->weights)); |
|
|
blocks = realloc(blocks,(maxblocknum+1) * sizeof(*blocks)); |
|
|
cchain->blocks = realloc(cchain->blocks,(cchain->maxblocknum+1) * sizeof(*cchain->blocks)); |
|
|
} |
|
|
} |
|
|
maxblocknum = height; |
|
|
cchain->maxblocknum = height; |
|
|
weights[height] = heaviest; |
|
|
cchain->weights[height] = heaviest; |
|
|
if ( blockhashp != 0 ) |
|
|
if ( blockhashp != 0 ) |
|
|
memcpy(&blocks[height],blockhashp,sizeof(blocks[height])); |
|
|
memcpy(&cchain->blocks[height],blockhashp,sizeof(cchain->blocks[height])); |
|
|
} |
|
|
} |
|
|
else if ( func == 'B' ) |
|
|
else if ( func == 'B' ) |
|
|
{ |
|
|
{ |
|
|
if ( height <= maxblocknum ) |
|
|
if ( height <= cchain->maxblocknum ) |
|
|
return(blocks[height]); |
|
|
return(cchain->blocks[height]); |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
printf("error: illegal height.%d vs max.%d\n",height,maxblocknum); |
|
|
printf("error: illegal height.%d vs max.%d\n",height,cchain->maxblocknum); |
|
|
return(zero); |
|
|
return(zero); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if ( func == 'W' ) |
|
|
else if ( func == 'W' ) |
|
|
{ |
|
|
{ |
|
|
if ( height >= 0 && height < maxblocknum ) |
|
|
if ( height >= 0 && height < cchain->maxblocknum ) |
|
|
return(weights[height]); |
|
|
return(cchain->weights[height]); |
|
|
else printf("error getting weight for height.%d vs maxblocknum.%d\n",height,maxblocknum); |
|
|
else printf("error getting weight for height.%d vs maxblocknum.%d\n",height,cchain->maxblocknum); |
|
|
} |
|
|
} |
|
|
return(category_hwm); |
|
|
return(cchain->category_hwm); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#define category_default_heaviest() category_default_func(myinfo,'H',categoryinfo,subinfo,0,0,0,0,0,0,zero) |
|
|
int32_t category_default_ishwm(struct category_chain *cchain,int32_t prevheight,void *prevblockhashp,void *blockhashp,void *prevgenerator,void *addr) |
|
|
#define category_default_setheaviest(height,blockhashp,heaviest) category_default_func(myinfo,'S',categoryinfo,subinfo,height,0,0,0,blockhashp,hashlen,zero) |
|
|
|
|
|
#define category_default_weight(height) category_default_func(myinfo,'W',categoryinfo,subinfo,height,0,0,0,0,0,zero) |
|
|
|
|
|
#define category_default_blockfind(height) category_default_func(myinfo,'B',categoryinfo,subinfo,height,0,0,0,0,0,zero) |
|
|
|
|
|
|
|
|
|
|
|
int32_t category_default_ishwm(struct supernet_info *myinfo,void *categoryinfo,void *subinfo,int32_t prevheight,void *prevblockhashp,void *blockhashp,int32_t hashlen,void *prevgenerator,void *addr,int32_t addrlen) |
|
|
|
|
|
{ |
|
|
{ |
|
|
bits256 checkhash,prevwt,oldhit,hit,heaviest; static bits256 zero; |
|
|
bits256 checkhash,prevwt,oldhit,hit,heaviest; static bits256 zero; |
|
|
checkhash = category_default_blockfind(prevheight); |
|
|
checkhash = category_default_blockfind(prevheight); |
|
|
if ( memcmp(checkhash.bytes,prevblockhashp,hashlen) == 0 ) |
|
|
if ( memcmp(checkhash.bytes,prevblockhashp,cchain->hashlen) == 0 ) |
|
|
{ |
|
|
{ |
|
|
heaviest = category_default_heaviest(); |
|
|
heaviest = category_default_heaviest(); |
|
|
prevwt = category_default_weight(prevheight); |
|
|
prevwt = category_default_weight(prevheight); |
|
|
oldhit = category_default_weight(prevheight+1); |
|
|
oldhit = category_default_weight(prevheight+1); |
|
|
hit = catgory_default_hit(myinfo,categoryinfo,subinfo,prevheight+1,prevgenerator,addr,addrlen,blockhashp,hashlen); |
|
|
hit = (*cchain->hit_func)(cchain,prevheight+1,prevgenerator,addr,blockhashp); |
|
|
if ( hit.txid > oldhit.txid && prevwt.txid+hit.txid > heaviest.txid ) |
|
|
if ( hit.txid > oldhit.txid && prevwt.txid+hit.txid > heaviest.txid ) |
|
|
{ |
|
|
{ |
|
|
heaviest.txid = (prevwt.txid + hit.txid); |
|
|
heaviest.txid = (prevwt.txid + hit.txid); |
|
@ -197,13 +194,43 @@ int32_t category_default_ishwm(struct supernet_info *myinfo,void *categoryinfo,v |
|
|
return(-1); |
|
|
return(-1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct category_info *category_chain_functions(bits256 categoryhash,bits256 subhash,int32_t (*blockhash_func)(void *blockhashp,void *data,int32_t datalen)) |
|
|
struct category_chain *category_chain_functions(struct supernet_info *myinfo,bits256 categoryhash,bits256 subhash,int32_t hashlen,int32_t addrlen,void *hash_func,void *stake_func,void *hit_func,void *default_func) |
|
|
{ |
|
|
{ |
|
|
struct category_info *cat; |
|
|
struct category_info *cat; struct category_chain *cchain = calloc(1,sizeof(*cchain)); |
|
|
if ( (cat= category_find(categoryhash,subhash)) != 0 ) |
|
|
if ( (cat= category_find(categoryhash,subhash)) != 0 ) |
|
|
{ |
|
|
{ |
|
|
cat->blockhash_func = blockhash_func; |
|
|
cchain->maxblocknum = -1; |
|
|
return(cat); |
|
|
cchain->myinfo = myinfo, cchain->subinfo = cat->info; |
|
|
|
|
|
if ( bits256_cmp(subhash,GENESIS_PUBKEY) == 0 ) |
|
|
|
|
|
cchain->categoryinfo = cat->info, cchain->cchainhash = categoryhash; |
|
|
|
|
|
else cchain->categoryinfo = category_find(categoryhash,GENESIS_PUBKEY), cchain->cchainhash = subhash; |
|
|
|
|
|
if ( cchain->myinfo == 0 || cchain->categoryinfo || cchain->subinfo ) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("error with cchain pointers\n"); |
|
|
|
|
|
return(0); |
|
|
|
|
|
} |
|
|
|
|
|
if ( (cchain->addrlen= addrlen) <= 0 || (cchain->hashlen= hashlen) <= 0 ) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("error with cchain lens.%d %d\n",addrlen,hashlen); |
|
|
|
|
|
return(0); |
|
|
|
|
|
} |
|
|
|
|
|
if ( (cchain->blockhash_func= hash_func) == 0 || (cchain->stake_func= stake_func) == 0 || (cchain->hit_func= hit_func) == 0 || (cchain->default_func= default_func) == 0 ) |
|
|
|
|
|
{ |
|
|
|
|
|
if ( addrlen == sizeof(bits256) && hashlen == sizeof(bits256) ) |
|
|
|
|
|
{ |
|
|
|
|
|
cchain->blockhash_func = category_default_blockhash; |
|
|
|
|
|
cchain->stake_func = category_default_stake; |
|
|
|
|
|
cchain->hit_func = catgory_default_hit; |
|
|
|
|
|
cchain->default_func = category_default_func; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
printf("no category chain functions and addrlen.%d hashlen.%d not 32\n",addrlen,hashlen); |
|
|
|
|
|
return(0); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
cat->cchain = cchain; |
|
|
|
|
|
return(cchain); |
|
|
} |
|
|
} |
|
|
return(0); |
|
|
return(0); |
|
|
} |
|
|
} |
|
|