|
|
@ -93,7 +93,7 @@ void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *retjson,cJSON *j |
|
|
|
{ |
|
|
|
if ( cat->processfunc != 0 ) |
|
|
|
{ |
|
|
|
if ( (str= (*cat->processfunc)(myinfo,buf,len,remoteaddr)) != 0 ) |
|
|
|
if ( (str= (*cat->processfunc)(myinfo,cat,buf,len,remoteaddr)) != 0 ) |
|
|
|
{ |
|
|
|
if ( retjson != 0 ) |
|
|
|
jaddstr(retjson,"processfunc",str); |
|
|
@ -114,3 +114,277 @@ void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *retjson,cJSON *j |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int32_t category_default_blockhash(struct category_chain *catchain,void *blockhashp,void *data,int32_t datalen) |
|
|
|
{ |
|
|
|
bits256 hash; |
|
|
|
vcalc_sha256(0,hash.bytes,data,datalen); |
|
|
|
vcalc_sha256(0,blockhashp,hash.bytes,sizeof(hash)); |
|
|
|
return(sizeof(*blockhashp)); |
|
|
|
} |
|
|
|
|
|
|
|
bits256 category_default_stake(struct category_chain *catchain,void *addr,int32_t addrlen) |
|
|
|
{ |
|
|
|
bits256 stake; |
|
|
|
memset(stake.bytes,0,sizeof(stake)); |
|
|
|
stake.txid = ((uint64_t)1 << 63); |
|
|
|
return(stake); |
|
|
|
} |
|
|
|
|
|
|
|
bits256 catgory_default_hit(struct category_chain *catchain,int32_t height,void *prevgenerator,void *addr,void *blockhashp) |
|
|
|
{ |
|
|
|
bits256 hash; bits256 rawhit,hit; |
|
|
|
memset(rawhit.bytes,0,sizeof(rawhit)); |
|
|
|
memset(hit.bytes,0,sizeof(hit)); |
|
|
|
vcalc_sha256cat(hash.bytes,prevgenerator,catchain->addrlen,addr,catchain->addrlen); |
|
|
|
hit = (*catchain->stake_func)(catchain,addr,catchain->addrlen); |
|
|
|
rawhit.txid = hash.txid % ((uint64_t)1 << 42); |
|
|
|
if ( rawhit.txid != 0 ) |
|
|
|
hit.txid /= rawhit.txid; |
|
|
|
return(hit); |
|
|
|
} |
|
|
|
|
|
|
|
#define category_default_heaviest() (*catchain->default_func)(catchain,'H',0,0,0,0,zero) |
|
|
|
#define category_default_latest() (*catchain->default_func)(catchain,'L',0,0,0,0,zero) |
|
|
|
#define category_default_setheaviest(height,blockhashp,heaviest) (*catchain->default_func)(catchain,'S',height,0,0,blockhashp,zero) |
|
|
|
#define category_default_weight(height) (*catchain->default_func)(catchain,'W',height,0,0,0,zero) |
|
|
|
#define category_default_blockfind(height) (*catchain->default_func)(catchain,'B',height,0,0,0,zero) |
|
|
|
|
|
|
|
bits256 category_default_func(struct category_chain *catchain,int32_t func,int32_t height,void *prevgenerator,void *addr,void *blockhashp,bits256 heaviest) |
|
|
|
{ |
|
|
|
static bits256 zero; |
|
|
|
if ( catchain->hashlen != sizeof(bits256) || catchain->addrlen != sizeof(bits256) ) |
|
|
|
{ |
|
|
|
printf("unsupported hashlen.%d or addrlen.%d\n",catchain->hashlen,catchain->addrlen); |
|
|
|
return(zero); |
|
|
|
} |
|
|
|
if ( height > catchain->maxblocknum + (func == 'S') ) |
|
|
|
{ |
|
|
|
printf("error func.%c setting heaviest. skipped %d -> %d?\n",func,catchain->maxblocknum,height); |
|
|
|
return(catchain->category_hwm); |
|
|
|
} |
|
|
|
if ( func == 'H' ) |
|
|
|
return(catchain->category_hwm); |
|
|
|
else if ( func == 'L' ) |
|
|
|
{ |
|
|
|
if ( catchain->maxblocknum < 0 ) |
|
|
|
return(catchain->genesishash); |
|
|
|
else return(catchain->blocks[catchain->maxblocknum]); |
|
|
|
} |
|
|
|
else if ( func == 'S' ) |
|
|
|
{ |
|
|
|
catchain->category_hwm = heaviest; |
|
|
|
if ( height > catchain->maxblocknum ) |
|
|
|
{ |
|
|
|
catchain->weights = realloc(catchain->weights,(catchain->maxblocknum+1) * sizeof(*catchain->weights)); |
|
|
|
catchain->blocks = realloc(catchain->blocks,(catchain->maxblocknum+1) * sizeof(*catchain->blocks)); |
|
|
|
} |
|
|
|
catchain->maxblocknum = height; |
|
|
|
catchain->weights[height] = heaviest; |
|
|
|
if ( blockhashp != 0 ) |
|
|
|
memcpy(&catchain->blocks[height],blockhashp,sizeof(catchain->blocks[height])); |
|
|
|
} |
|
|
|
else if ( func == 'B' ) |
|
|
|
{ |
|
|
|
if ( height <= catchain->maxblocknum ) |
|
|
|
return(catchain->blocks[height]); |
|
|
|
else |
|
|
|
{ |
|
|
|
printf("error: illegal height.%d vs max.%d\n",height,catchain->maxblocknum); |
|
|
|
return(zero); |
|
|
|
} |
|
|
|
} |
|
|
|
else if ( func == 'W' ) |
|
|
|
{ |
|
|
|
if ( height >= 0 && height < catchain->maxblocknum ) |
|
|
|
return(catchain->weights[height]); |
|
|
|
else printf("error getting weight for height.%d vs maxblocknum.%d\n",height,catchain->maxblocknum); |
|
|
|
} |
|
|
|
return(catchain->category_hwm); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t category_default_ishwm(struct category_chain *catchain,int32_t prevheight,void *prevblockhashp,void *blockhashp,void *prevgenerator,void *addr) |
|
|
|
{ |
|
|
|
bits256 checkhash,prevwt,oldhit,hit,heaviest; static bits256 zero; |
|
|
|
checkhash = category_default_blockfind(prevheight); |
|
|
|
if ( memcmp(checkhash.bytes,prevblockhashp,catchain->hashlen) == 0 ) |
|
|
|
{ |
|
|
|
heaviest = category_default_heaviest(); |
|
|
|
prevwt = category_default_weight(prevheight); |
|
|
|
oldhit = category_default_weight(prevheight+1); |
|
|
|
hit = (*catchain->hit_func)(catchain,prevheight+1,prevgenerator,addr,blockhashp); |
|
|
|
if ( hit.txid > oldhit.txid && prevwt.txid+hit.txid > heaviest.txid ) |
|
|
|
{ |
|
|
|
heaviest.txid = (prevwt.txid + hit.txid); |
|
|
|
category_default_setheaviest(prevheight+1,blockhashp,heaviest); |
|
|
|
return(prevheight+1); |
|
|
|
} |
|
|
|
|
|
|
|
} else return(-2); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t category_default_payment(struct category_chain *catchain,void *src,void *dest,uint64_t amount) |
|
|
|
{ |
|
|
|
uint32_t srcind=0,destind=0; |
|
|
|
// catchain->balances[destind] += amount;
|
|
|
|
// catchain->balances[srcind] -= amount;
|
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
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,void *ishwm_func,void *payment_func) |
|
|
|
{ |
|
|
|
struct category_info *cat; struct category_chain *catchain = calloc(1,sizeof(*catchain)); |
|
|
|
if ( (cat= category_find(categoryhash,subhash)) != 0 ) |
|
|
|
{ |
|
|
|
catchain->maxblocknum = -1; |
|
|
|
catchain->myinfo = myinfo, catchain->subinfo = cat->info; |
|
|
|
if ( bits256_cmp(subhash,GENESIS_PUBKEY) == 0 ) |
|
|
|
catchain->categoryinfo = cat->info, catchain->genesishash = categoryhash; |
|
|
|
else catchain->categoryinfo = category_find(categoryhash,GENESIS_PUBKEY), catchain->genesishash = subhash; |
|
|
|
if ( catchain->myinfo == 0 || catchain->categoryinfo || catchain->subinfo ) |
|
|
|
{ |
|
|
|
printf("error with catchain pointers\n"); |
|
|
|
return(0); |
|
|
|
} |
|
|
|
if ( (catchain->addrlen= addrlen) <= 0 || (catchain->hashlen= hashlen) <= 0 ) |
|
|
|
{ |
|
|
|
printf("error with catchain lens.%d %d\n",addrlen,hashlen); |
|
|
|
return(0); |
|
|
|
} |
|
|
|
if ( (catchain->blockhash_func= hash_func) == 0 || (catchain->stake_func= stake_func) == 0 || (catchain->hit_func= hit_func) == 0 || (catchain->default_func= default_func) == 0 || (catchain->ishwm_func= ishwm_func) == 0 || (catchain->payment_func= payment_func) == 0 ) |
|
|
|
{ |
|
|
|
if ( addrlen == sizeof(bits256) && hashlen == sizeof(bits256) ) |
|
|
|
{ |
|
|
|
catchain->blockhash_func = category_default_blockhash; |
|
|
|
catchain->stake_func = category_default_stake; |
|
|
|
catchain->hit_func = catgory_default_hit; |
|
|
|
catchain->default_func = category_default_func; |
|
|
|
catchain->ishwm_func = category_default_ishwm; |
|
|
|
catchain->payment_func = category_default_payment; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
printf("no category chain functions and addrlen.%d hashlen.%d not 32\n",addrlen,hashlen); |
|
|
|
return(0); |
|
|
|
} |
|
|
|
} |
|
|
|
cat->catchain = catchain; |
|
|
|
return(catchain); |
|
|
|
} |
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
struct crypto777_msghdr *crypto777_msgcreate(struct supernet_info *myinfo,struct crypto777_msghdr *msg,int32_t datalen) |
|
|
|
{ |
|
|
|
bits256 otherpubkey; uint64_t signerbits; uint32_t timestamp; uint8_t buf[sizeof(msg->sig)],*data; |
|
|
|
memset(&msg->sig,0,sizeof(msg->sig)); |
|
|
|
datalen += (int32_t)(sizeof(*msg) - sizeof(msg->sig)); |
|
|
|
data = (void *)((long)msg + sizeof(msg->sig)); |
|
|
|
otherpubkey = acct777_msgpubkey(data,datalen); |
|
|
|
timestamp = (uint32_t)time(NULL); |
|
|
|
acct777_sign(&msg->sig,myinfo->privkey,otherpubkey,timestamp,data,datalen); |
|
|
|
if ( (signerbits= acct777_validate(&msg->sig,acct777_msgprivkey(data,datalen),msg->sig.pubkey)) != 0 ) |
|
|
|
{ |
|
|
|
//int32_t i;
|
|
|
|
//char str[65],str2[65];
|
|
|
|
//for (i=0; i<datalen; i++)
|
|
|
|
// printf("%02x",data[i]);
|
|
|
|
//printf(">>>>>>>>>>>>>>>> validated [%ld] len.%d (%s + %s)\n",(long)data-(long)msg,datalen,bits256_str(str,acct777_msgprivkey(data,datalen)),bits256_str(str2,msg->sig.pubkey));
|
|
|
|
memset(buf,0,sizeof(buf)); |
|
|
|
acct777_rwsig(1,buf,&msg->sig); |
|
|
|
memcpy(&msg->sig,buf,sizeof(buf)); |
|
|
|
return(msg); |
|
|
|
} else printf("error validating crypto777_msgcreate msg\n"); |
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
void crypto777_catchain(struct supernet_info *myinfo,struct category_info *cat,bits256 *prevhashp,bits256 *btchashp) |
|
|
|
{ |
|
|
|
*btchashp = myinfo->BTCmarkerhash; |
|
|
|
*prevhashp = cat->catchain->hwmhash; |
|
|
|
} |
|
|
|
|
|
|
|
char *crypto777_sendmsg(struct supernet_info *myinfo,bits256 category,bits256 subhash,uint8_t *data,int32_t datalen,int32_t hops,char cmdstr[8]) |
|
|
|
{ |
|
|
|
char *hexstr,*retstr; int32_t i; struct crypto777_msghdr *msg; bits256 prevhash,btchash; struct category_info *cat; |
|
|
|
msg = calloc(1,datalen + sizeof(*msg)); |
|
|
|
for (i=0; i<sizeof(msg->cmd); i++) |
|
|
|
if ( (msg->cmd[i]= cmdstr[i]) == 0 ) |
|
|
|
break; |
|
|
|
cat = category_info(category,subhash); |
|
|
|
crypto777_catchain(myinfo,cat,&prevhash,&btchash); |
|
|
|
iguana_rwbignum(1,msg->prevhash.bytes,sizeof(bits256),prevhash.bytes); |
|
|
|
iguana_rwbignum(1,msg->btchash.bytes,sizeof(bits256),btchash.bytes); |
|
|
|
memcpy(msg->serialized,data,datalen); |
|
|
|
if ( crypto777_msgcreate(myinfo,msg,datalen) != 0 ) |
|
|
|
{ |
|
|
|
printf(">>>>>>>>>>>> crypto777_send.(%s) datalen.%d allocsize.%d crc.%x\n",cmdstr,datalen,msg->sig.allocsize,calc_crc32(0,(void *)((long)msg + 8),datalen-8)); |
|
|
|
hexstr = malloc(msg->sig.allocsize*2 + 1); |
|
|
|
init_hexbytes_noT(hexstr,(uint8_t *)msg,msg->sig.allocsize); |
|
|
|
retstr = SuperNET_categorymulticast(myinfo,0,category,subhash,hexstr,0,hops,1,0,0); |
|
|
|
free(hexstr), free(msg); |
|
|
|
return(retstr); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
free(msg); |
|
|
|
printf("cant crypto777 msgcreate datalen.%d\n",datalen); |
|
|
|
return(clonestr("{\"error\":\"couldnt create crypto777 message\"}")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
char *crypto777_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char *remoteaddr) |
|
|
|
{ |
|
|
|
struct crypto777_msghdr *msg = ptr; int32_t slen,datalen,newlen,flag = 0; bits256 prevhash,btchash; |
|
|
|
uint8_t *serdata; uint64_t signerbits; uint8_t tmp[sizeof(msg->sig)]; cJSON *argjson = 0; |
|
|
|
datalen = len - (int32_t)sizeof(msg->sig); |
|
|
|
serdata = (void *)((long)msg + sizeof(msg->sig)); |
|
|
|
acct777_rwsig(0,(void *)&msg->sig,(void *)tmp); |
|
|
|
memcpy(&msg->sig,tmp,sizeof(msg->sig)); |
|
|
|
/*if ( remoteaddr != 0 && remoteaddr[0] == 0 && strcmp("127.0.0.1",remoteaddr) == 0 && ((uint8_t *)msg)[len-1] == 0 && (argjson= cJSON_Parse((char *)msg)) != 0 )
|
|
|
|
{ |
|
|
|
printf("string crypto777_hexmsg RESULT.(%s)\n",jprint(argjson,0)); |
|
|
|
free_json(argjson); |
|
|
|
return(clonestr("{\"error\":\"string base packets deprecated\"}")); |
|
|
|
} |
|
|
|
else*/ if ( (signerbits= acct777_validate(&msg->sig,acct777_msgprivkey(serdata,datalen),msg->sig.pubkey)) != 0 ) |
|
|
|
{ |
|
|
|
flag++; |
|
|
|
iguana_rwbignum(0,msg->prevhash.bytes,sizeof(bits256),prevhash.bytes); |
|
|
|
iguana_rwbignum(0,msg->btchash.bytes,sizeof(bits256),btchash.bytes); |
|
|
|
printf("crypto777_hexmsg <<<<<<<<<<<<< sigsize.%ld VALIDATED [%ld] len.%d t%u allocsize.%d (%s) [%d]\n",sizeof(msg->sig),(long)serdata-(long)msg,datalen,msg->sig.timestamp,msg->sig.allocsize,(char *)msg->serialized,serdata[datalen-1]); |
|
|
|
newlen = (int32_t)(msg->sig.allocsize - ((long)msg->serialized - (long)msg)); |
|
|
|
serdata = msg->serialized; |
|
|
|
if ( (argjson= cJSON_Parse((char *)serdata)) != 0 ) |
|
|
|
{ |
|
|
|
slen = (int32_t)strlen((char *)serdata) + 1; |
|
|
|
serdata = &serdata[slen]; |
|
|
|
newlen -= slen; |
|
|
|
free_json(argjson); |
|
|
|
} |
|
|
|
} |
|
|
|
return(clonestr("{\"result\":\"test packet\"}")); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
Consensus rules: |
|
|
|
0. Valid burn protocol or new issuance with small fee to crypto777 account -> OP_RETURN on BTCD with txid of payment/burn |
|
|
|
Ti boundary - Balances reconciled and signed by issuer or super majority vote. Only amounts marked as frozen eligible for atomic swaps. |
|
|
|
tx via p2p, signed payment to dest acct, based on balance. no outputs to double spend |
|
|
|
payment valid during Ti and Ti+1 |
|
|
|
atomic cross chain: both sides freeze trade amount, wait for this to be confirmed in BTC OP_RETURN, then a joint swap tx is signed by both and submitted to both chains |
|
|
|
|
|
|
|
valid tx must be accepted and sig added with Ti slippage. It is valid if signed, and balance is available. |
|
|
|
|
|
|
|
When Ti boundary changes, all online nodes reconcile the submitted tx to make sure all are confirmed and balances updated. Special tx like freezing, atomics, etc. |
|
|
|
|
|
|
|
Top PoS account publishes balance changes and majority stake approves. Next trade period starts at Ti+2 |
|
|
|
|
|
|
|
Split into odd/even offset periods to allow nonstop tx |
|
|
|
|
|
|
|
1. all nodes must ntp and all tx must be timestamped within 50 seconds in the past and cant be more than 10 seconds from the future. |
|
|
|
2. tx spends cannot exceed available balance/2 as of prior Ti. |
|
|
|
2. all tx must refer to the latest BTC.Ti and BTCD.Ti and BTC.RTblock. any tx received that has older BTC.Ti is rejected. |
|
|
|
3. |
|
|
|
*/ |
|
|
|