|
|
|
/******************************************************************************
|
|
|
|
* 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 datachain.c
|
|
|
|
|
|
|
|
int32_t datachain_rwgenesis(int32_t rwflag,uint8_t *serialized,struct gecko_genesis_opreturn *opret)
|
|
|
|
{
|
|
|
|
int32_t len = 0;
|
|
|
|
if ( rwflag == 0 )
|
|
|
|
{
|
|
|
|
memcpy(opret->type,&serialized[len],sizeof(opret->type)), len += sizeof(opret->type);
|
|
|
|
memcpy(opret->symbol,&serialized[len],sizeof(opret->symbol)), len += sizeof(opret->symbol);
|
|
|
|
memcpy(opret->name,&serialized[len],sizeof(opret->name)), len += sizeof(opret->name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(&serialized[len],opret->type,sizeof(opret->type)), len += sizeof(opret->type);
|
|
|
|
memcpy(&serialized[len],opret->symbol,sizeof(opret->symbol)), len += sizeof(opret->symbol);
|
|
|
|
memcpy(&serialized[len],opret->name,sizeof(opret->name)), len += sizeof(opret->name);
|
|
|
|
}
|
|
|
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(opret->PoSvalue),&opret->PoSvalue);
|
|
|
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(opret->netmagic),&opret->netmagic);
|
|
|
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(opret->timestamp),&opret->timestamp);
|
|
|
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(opret->nBits),&opret->nBits);
|
|
|
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(opret->nonce),&opret->nonce);
|
|
|
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(opret->blocktime),&opret->blocktime);
|
|
|
|
len += iguana_rwnum(rwflag,&serialized[len],sizeof(opret->port),&opret->port);
|
|
|
|
if ( rwflag == 0 )
|
|
|
|
{
|
|
|
|
opret->version = serialized[len++];
|
|
|
|
opret->pubval = serialized[len++];
|
|
|
|
opret->p2shval = serialized[len++];
|
|
|
|
opret->wifval = serialized[len++];
|
|
|
|
memcpy(opret->rmd160,&serialized[len],20), len += 20;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serialized[len++] = opret->version;
|
|
|
|
serialized[len++] = opret->pubval;
|
|
|
|
serialized[len++] = opret->p2shval;
|
|
|
|
serialized[len++] = opret->wifval;
|
|
|
|
memcpy(&serialized[len],opret->rmd160,20), len += 20;
|
|
|
|
}
|
|
|
|
//printf("opreturn len.%d\n",len);
|
|
|
|
return(len);
|
|
|
|
}
|
|
|
|
|
|
|
|
bits256 datachain_opreturn_convert(uint8_t *txidbytes,int32_t *txlenp,struct iguana_msgblock *msg,struct gecko_genesis_opreturn *opret)
|
|
|
|
{
|
|
|
|
bits256 txid,zero; int32_t minerpaymentlen=0; uint8_t minerpayment[512]; char coinbasestr[128],name[64],symbol[64];
|
|
|
|
if ( opret->PoSvalue > 0 )
|
|
|
|
minerpaymentlen = bitcoin_standardspend(minerpayment,0,opret->rmd160);
|
|
|
|
memset(zero.bytes,0,sizeof(zero));
|
|
|
|
memset(symbol,0,sizeof(symbol)), memcpy(symbol,opret->symbol,sizeof(opret->symbol));
|
|
|
|
memset(name,0,sizeof(name)), memcpy(name,opret->name,sizeof(opret->name));
|
|
|
|
sprintf(coinbasestr,"%s_%s",symbol,name);
|
|
|
|
*txlenp = iguana_coinbase(1,GECKO_DEFAULTVERSION,txidbytes,opret->timestamp,zero,(uint8_t *)coinbasestr,(int32_t)strlen(coinbasestr)+1,minerpayment,minerpaymentlen,opret->PoSvalue,&txid);
|
|
|
|
memset(msg,0,sizeof(*msg));
|
|
|
|
msg->H.version = opret->version;
|
|
|
|
msg->H.merkle_root = txid;
|
|
|
|
msg->H.timestamp = opret->timestamp;
|
|
|
|
msg->H.bits = opret->nBits;
|
|
|
|
msg->H.nonce = opret->nonce;
|
|
|
|
return(txid);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t datachain_genesis_verify(struct gecko_genesis_opreturn *opret)
|
|
|
|
{
|
|
|
|
int32_t txlen,datalen; bits256 txid,threshold,hash2; uint8_t serialized[1024],txidbytes[1024]; struct iguana_msgzblock zmsg; char str[65],str2[65];
|
|
|
|
txid = datachain_opreturn_convert(txidbytes,&txlen,(void *)&zmsg,opret);
|
|
|
|
if ( opret->nBits >= GECKO_EASIESTDIFF )
|
|
|
|
threshold = bits256_from_compact(GECKO_EASIESTDIFF);
|
|
|
|
else threshold = bits256_from_compact(opret->nBits);
|
|
|
|
datalen = iguana_rwblockhdr(1,0,serialized,&zmsg);
|
|
|
|
hash2 = iguana_calcblockhash("virtual",blockhash_sha256,serialized,datalen);
|
|
|
|
//for (i=0; i<datalen; i++)
|
|
|
|
// printf("%02x",serialized[i]);
|
|
|
|
if ( bits256_cmp(threshold,hash2) > 0 )
|
|
|
|
{
|
|
|
|
//printf(" valid blockhash!\n");
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf(" ERROR invalid blockhash! txid.%s %s\n",bits256_str(str2,txid),bits256_str(str,hash2));
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t datachain_opreturn_create(uint8_t *serialized,char *symbol,char *name,char *coinaddr,int64_t PoSvalue,uint32_t nBits,uint16_t blocktime,uint16_t port,uint8_t p2shval,uint8_t wifval)
|
|
|
|
{
|
|
|
|
int32_t i,len,datalen,txlen; struct gecko_genesis_opreturn opret; bits256 threshold,txid,hash2; struct iguana_info *btcd; struct iguana_msgzblock zmsg; struct iguana_msgblock *msg = (void *)&zmsg; uint8_t txidbytes[1024];
|
|
|
|
btcd = iguana_coinfind("BTCD");
|
|
|
|
memset(&opret,0,sizeof(opret));
|
|
|
|
opret.type[0] = 'N', opret.type[1] = 'E', opret.type[2] = 'W';
|
|
|
|
memcpy(opret.symbol,symbol,sizeof(opret.symbol));
|
|
|
|
memcpy(opret.name,name,sizeof(opret.name));
|
|
|
|
opret.version = GECKO_DEFAULTVERSION;
|
|
|
|
opret.PoSvalue = PoSvalue;
|
|
|
|
opret.nBits = nBits;
|
|
|
|
opret.p2shval = p2shval;
|
|
|
|
opret.wifval = wifval;
|
|
|
|
opret.blocktime = blocktime;
|
|
|
|
opret.port = port;
|
|
|
|
opret.timestamp = (uint32_t)time(NULL);
|
|
|
|
OS_randombytes((void *)&opret.netmagic,sizeof(opret.netmagic));
|
|
|
|
bitcoin_addr2rmd160(&opret.pubval,opret.rmd160,coinaddr);
|
|
|
|
txid = datachain_opreturn_convert(txidbytes,&txlen,msg,&opret);
|
|
|
|
if ( nBits >= GECKO_EASIESTDIFF )
|
|
|
|
threshold = bits256_from_compact(GECKO_EASIESTDIFF);
|
|
|
|
else threshold = bits256_from_compact(nBits);
|
|
|
|
for (i=0; i<100000000; i++)
|
|
|
|
{
|
|
|
|
opret.nonce = msg->H.nonce = i;
|
|
|
|
datalen = iguana_rwblockhdr(1,0,serialized,&zmsg);
|
|
|
|
hash2 = iguana_calcblockhash(symbol,btcd->chain->hashalgo,serialized,datalen);
|
|
|
|
if ( bits256_cmp(threshold,hash2) > 0 )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//char str[65],str2[65];
|
|
|
|
//for (i=0; i<datalen; i++)
|
|
|
|
// printf("%02x",serialized[i]);
|
|
|
|
//printf(" <- msgblock datalen.%d txid.%s hash2.%s\n",datalen,bits256_str(str,txid),bits256_str(str2,hash2));
|
|
|
|
len = datachain_rwgenesis(1,serialized,&opret);
|
|
|
|
datachain_genesis_verify(&opret);
|
|
|
|
return(len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void datachain_events_processKOMODO(struct supernet_info *myinfo,struct datachain_info *dPoW,struct datachain_event *event)
|
|
|
|
{
|
|
|
|
struct gecko_chain *chain; bits256 hash2,threshold; struct gecko_genesis_opreturn opret; int32_t datalen,i,j,len,txlen; char symbol[16],name[64],magicstr[16],blockstr[8192],nbitstr[16],issuer[64],hashstr[65],str2[65],argbuf[1024],chainname[GECKO_MAXNAMELEN]; cJSON *valsobj; struct iguana_msgzblock zmsg; uint8_t serialized[256],txidbytes[1024],buf[4]; struct iguana_info *virt,*btcd;
|
|
|
|
if ( (btcd= iguana_coinfind("BTCD")) != 0 && memcmp(event->opreturn,"NEW",3) == 0 )
|
|
|
|
{
|
|
|
|
//int32_t i; for (i=0; i<76; i++)
|
|
|
|
// printf("%02x",event->opreturn[i]);
|
|
|
|
//printf(" <- event\n");
|
|
|
|
if ( (len= datachain_rwgenesis(0,event->opreturn,&opret)) <= event->oplen )
|
|
|
|
{
|
|
|
|
datachain_genesis_verify(&opret);
|
|
|
|
memset(symbol,0,sizeof(symbol)), memcpy(symbol,opret.symbol,sizeof(opret.symbol));
|
|
|
|
memset(name,0,sizeof(name)), memcpy(name,opret.name,sizeof(opret.name));
|
|
|
|
hash2 = datachain_opreturn_convert(txidbytes,&txlen,(void *)&zmsg,&opret);
|
|
|
|
if ( opret.nBits >= GECKO_EASIESTDIFF )
|
|
|
|
threshold = bits256_from_compact(GECKO_EASIESTDIFF);
|
|
|
|
else threshold = bits256_from_compact(opret.nBits);
|
|
|
|
zmsg.txn_count = 1;
|
|
|
|
//n = iguana_serialize_block(virt->chain,&hash2,serialized,newblock);
|
|
|
|
datalen = iguana_rwblockhdr(1,0,serialized,&zmsg);
|
|
|
|
hash2 = iguana_calcblockhash(symbol,btcd->chain->hashalgo,serialized,datalen);
|
|
|
|
for (i=0; i<datalen; i++)
|
|
|
|
printf("%02x",serialized[i]);
|
|
|
|
printf(" <- genhdr.%d\n",datalen);
|
|
|
|
for (i=0; i<txlen; i++)
|
|
|
|
printf("%02x",txidbytes[i]);
|
|
|
|
printf(" <- genesistx\n");
|
|
|
|
//char str[65]; printf("komodo datalen.%d %s\n",datalen,bits256_str(str,hash2));
|
|
|
|
if ( bits256_cmp(threshold,hash2) > 0 )
|
|
|
|
{
|
|
|
|
bitcoin_address(issuer,60,opret.rmd160,20);
|
|
|
|
bits256_str(hashstr,hash2);
|
|
|
|
for (j=0,i=3; i>=0; i--,j++)
|
|
|
|
buf[i] = (opret.netmagic >> (j*8));
|
|
|
|
init_hexbytes_noT(magicstr,buf,4);
|
|
|
|
for (j=0,i=3; i>=0; i--,j++)
|
|
|
|
buf[i] = (opret.nBits >> (j*8));
|
|
|
|
init_hexbytes_noT(nbitstr,buf,4);
|
|
|
|
init_hexbytes_noT(blockstr,serialized,datalen);
|
|
|
|
strcat(blockstr,"01"), datalen++;
|
|
|
|
init_hexbytes_noT(&blockstr[datalen << 1],txidbytes,txlen);
|
|
|
|
sprintf(argbuf,"{\"name\":\"%s\",\"symbol\":\"%s\",\"netmagic\":\"%s\",\"port\":%u,\"blocktime\":%u,\"pubval\":\"%02x\",\"p2shval\":\"%02x\",\"wifval\":\"%02x\",\"unitval\":\"%02x\",\"genesishash\":\"%s\",\"genesis\":{\"version\":1,\"timestamp\":%u,\"nBits\":\"%s\",\"nonce\":%d,\"merkle_root\":\"%s\"},\"genesisblock\":\"%s\"}",name,symbol,magicstr,opret.port,opret.blocktime,opret.pubval,opret.p2shval,opret.wifval,(opret.nBits >> 24) & 0xff,hashstr,opret.timestamp,nbitstr,opret.nonce,bits256_str(str2,zmsg.zH.merkle_root),blockstr);
|
|
|
|
if ( (valsobj= cJSON_Parse(argbuf)) != 0 )
|
|
|
|
{
|
|
|
|
printf("datachain.NEW (%s/%s port.%u blocktime.%d) issuer.%s (%s)\n",opret.symbol,opret.name,opret.port,opret.blocktime,issuer,jprint(valsobj,0));
|
|
|
|
if ( (chain= gecko_chain(myinfo,chainname,valsobj)) != 0 && (virt= chain->info) != 0 )
|
|
|
|
printf("duplicate chain.%s rejected\n",opret.symbol);
|
|
|
|
else if ( (virt= basilisk_geckochain(myinfo,symbol,chainname,valsobj)) != 0 )
|
|
|
|
chain->info = virt;
|
|
|
|
free_json(valsobj);
|
|
|
|
}
|
|
|
|
} else printf("failed PoW test for genesis.%s\n",opret.symbol);
|
|
|
|
} else printf("opret unexpected len.%d vs %d\n",len,event->oplen);
|
|
|
|
}
|
|
|
|
}
|