Browse Source

VRSC iguana sapling changes [part 1]

- already implemented unsigned raw tx creation (thx @artemii235 for mm codebase)
  tested on iguana_utxoduplicates (dpow is still untested)
- todo: bitcoin_sigtxid implement signing for overwintered & sapling
- todo: check bitcoin_verifyvins
- todo: remove debug printouts
blackjok3r
DeckerSU 6 years ago
parent
commit
ec6d3aae31
  1. 19
      basilisk/basilisk_bitcoin.c
  2. 367
      iguana/iguana_sign.c
  3. 37
      includes/iguana_structs.h

19
basilisk/basilisk_bitcoin.c

@ -591,18 +591,25 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi
bitcoin_address(changeaddr, coin->chain->pubtype, myinfo->persistent_pubkey33, 33); bitcoin_address(changeaddr, coin->chain->pubtype, myinfo->persistent_pubkey33, 33);
txfee = (coin->txfee + duplicates*coin->txfee/10); txfee = (coin->txfee + duplicates*coin->txfee/10);
if ( strcmp(coin->symbol,"GAME") == 0 ) if (strcmp(coin->symbol, "GAME") == 0 || strcmp(coin->symbol, "EMC2") == 0)
printf("GAME txfee %.8f\n",dstr(txfee)); printf("%s txfee %.8f\n", coin->symbol, dstr(txfee));
if ( strcmp(coin->symbol,"EMC2") == 0 )
printf("EMC2 txfee %.8f\n",dstr(txfee)); uint32_t txversion = 1; // txversion = 1 for non-overwintered and non-sapling coins
if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,1,0)) != 0 ) if (strcmp(coin->symbol, "VRSC") == 0 || strcmp(coin->symbol, "VRSCTEST") == 0)
txversion = 4;
if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,txversion,0)) != 0 )
{ {
if ( duplicates <= 0 ) printf("JSON: %s\n", cJSON_Print(txobj));
if ( duplicates <= 0 )
duplicates = 1; duplicates = 1;
spendlen = bitcoin_pubkeyspend(script,0,pubkey33); spendlen = bitcoin_pubkeyspend(script,0,pubkey33);
for (i=0; i<duplicates; i++) for (i=0; i<duplicates; i++)
bitcoin_txoutput(txobj,script,spendlen,satoshis); bitcoin_txoutput(txobj,script,spendlen,satoshis);
printf("JSON: %s\n", cJSON_Print(txobj));
printf("addresses: %s\n", cJSON_Print(addresses));
rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,satoshis * duplicates,changeaddr,txfee,addresses,0,0,0,0,"127.0.0.1",0,1); rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,satoshis * duplicates,changeaddr,txfee,addresses,0,0,0,0,"127.0.0.1",0,1);
printf("JSON: %s\n", cJSON_Print(txobj));
if ( strcmp(coin->chain->symbol,"BTC") == 0 && cJSON_GetArraySize(vins) > duplicates/2 ) if ( strcmp(coin->chain->symbol,"BTC") == 0 && cJSON_GetArraySize(vins) > duplicates/2 )
{ {
free(rawtx); free(rawtx);

367
iguana/iguana_sign.c

@ -486,7 +486,9 @@ cJSON *iguana_voutjson(struct iguana_info *coin,struct iguana_msgvout *vout,int3
return(json); return(json);
} }
bits256 bitcoin_sigtxid(struct iguana_info *coin,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys) // TODO: with changes it bitcoin_sigtxid need additionally check bitcoin_verifyvins (!)
// Old args: bits256 bitcoin_sigtxid(struct iguana_info *coin,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys)
bits256 bitcoin_sigtxid(struct iguana_info *coin, int32_t height, uint8_t *serialized, int32_t maxlen, struct iguana_msgtx *msgtx, int32_t vini, uint8_t *spendscript, int32_t spendlen, uint64_t spendamount, int32_t hashtype, char *vpnstr, int32_t suppress_pubkeys, int32_t zcash)
{ {
int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest; int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest;
dest = *msgtx; dest = *msgtx;
@ -500,42 +502,51 @@ bits256 bitcoin_sigtxid(struct iguana_info *coin,int32_t height,uint8_t *seriali
printf("currently only SIGHASH_ALL supported, not %d\n",hashtype); printf("currently only SIGHASH_ALL supported, not %d\n",hashtype);
return(sigtxid); return(sigtxid);
} }
for (i=0; i<dest.tx_in; i++) uint32_t overwintered = dest.version >> 31;
{ uint32_t version = dest.version & 0x7FFFFFFF;
if ( i == vini )
{ if (overwintered && version >= 3) {
dest.vins[i].vinscript = spendscript; // TODO: implement signing for overwintered & sapling
dest.vins[i].scriptlen = spendlen;
//int32_t j; for (j=0; j<spendlen; j++) }
// printf("%02x",spendscript[j]); else {
//printf(" tmpscript.%d vini.%d\n",spendlen,vini); for (i = 0; i<dest.tx_in; i++)
} {
else if (i == vini)
{ {
dest.vins[i].vinscript = (uint8_t *)""; dest.vins[i].vinscript = spendscript;
dest.vins[i].scriptlen = 0; dest.vins[i].scriptlen = spendlen;
} //int32_t j; for (j=0; j<spendlen; j++)
dest.vins[i].p2shlen = 0; // printf("%02x",spendscript[j]);
dest.vins[i].redeemscript = 0; //printf(" tmpscript.%d vini.%d\n",spendlen,vini);
dest.vins[i].userdata = 0; }
dest.vins[i].userdatalen = 0; else
} {
len = iguana_rwmsgtx(coin,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys); dest.vins[i].vinscript = (uint8_t *)"";
//for (i=0; i<len; i++) dest.vins[i].scriptlen = 0;
// printf("%02x",serialized[i]); }
//printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen); dest.vins[i].p2shlen = 0;
if ( len > 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 && dest.vins[i].redeemscript = 0;
{ dest.vins[i].userdata = 0;
#ifdef BTC2_VERSION dest.vins[i].userdatalen = 0;
if ( height >= BTC2_HARDFORK_HEIGHT ) }
hashtype |= (0x777 << 20); len = iguana_rwmsgtx(coin, height, 1, 0, serialized, maxlen, &dest, &txid, vpnstr, 0, 0, 0, suppress_pubkeys);
#endif //for (i=0; i<len; i++)
len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype); // printf("%02x",serialized[i]);
revsigtxid = bits256_doublesha256(0,serialized,len); //printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen);
for (i=0; i<sizeof(revsigtxid); i++) if (len > 0) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 &&
sigtxid.bytes[31-i] = revsigtxid.bytes[i]; {
//char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out); #ifdef BTC2_VERSION
} if (height >= BTC2_HARDFORK_HEIGHT)
hashtype |= (0x777 << 20);
#endif
len += iguana_rwnum(1, &serialized[len], sizeof(hashtype), &hashtype);
revsigtxid = bits256_doublesha256(0, serialized, len);
for (i = 0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31 - i] = revsigtxid.bytes[i];
//char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out);
}
}
free(dest.vins); free(dest.vins);
free(dest.vouts); free(dest.vouts);
return(sigtxid); return(sigtxid);
@ -587,11 +598,40 @@ int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout)
int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys) int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys)
{ {
int32_t i,n,len = 0,extraused=0; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE],*txstart = serialized,*sigser=0; char txidstr[65]; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid; int32_t i,n,len = 0,extraused=0; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE],*txstart = serialized,*sigser=0; char txidstr[65]; uint64_t spendamount; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid;
uint32_t zcash = (strcmp(coin->symbol, "VRSC") == 0 || strcmp(coin->symbol, "VRSCTEST") == 0); // we definitely need to determine somehow zcash-based coins here instead of compare coin names
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version);
uint32_t overwintered = msg->version >> 31;
uint32_t version = msg->version;
// for version 4 the ZK proof size is 192, otherwise 296
uint32_t zksnark_proof_size = ZKSNARK_PROOF_SIZE;
if (zcash) {
if (overwintered) {
version = msg->version & 0x7FFFFFFF;
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->version_group_id), &msg->version_group_id);
if (version >= 4) {
zksnark_proof_size = GROTH_PROOF_SIZE;
}
}
}
if ( json != 0 ) if ( json != 0 )
{ {
jaddnum(json,"version",msg->version); if (overwintered) {
jaddnum(json, "version", msg->version & 0x7FFFFFFF);
}
else {
jaddnum(json, "version", msg->version);
}
cJSON_AddBoolToObject(json, "overwintered", overwintered);
if (overwintered) {
char group_id_str[10];
sprintf(group_id_str, "%x", msg->version_group_id);
jaddstr(json, "versiongroupid", group_id_str);
}
vinarray = cJSON_CreateArray(); vinarray = cJSON_CreateArray();
voutarray = cJSON_CreateArray(); voutarray = cJSON_CreateArray();
if ( rwflag == 0 ) if ( rwflag == 0 )
@ -674,7 +714,160 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t height,int32_t rwflag,cJ
jaddi(voutarray,iguana_voutjson(coin,&msg->vouts[i],i,*txidp)); jaddi(voutarray,iguana_voutjson(coin,&msg->vouts[i],i,*txidp));
} }
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time);
//printf("lock_time.%08x len.%d\n",msg->lock_time,len);
if (zcash && overwintered) {
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->expiry_height), &msg->expiry_height);
if (json != 0) {
jaddnum(json, "expiryheight", msg->expiry_height);
}
if (version >= 4) {
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->value_balance), &msg->value_balance);
if (json != 0) {
jaddnum(json, "valueBalance", dstr(msg->value_balance));
}
cJSON *v_shielded_spend = cJSON_CreateArray();
cJSON *v_shielded_output = cJSON_CreateArray();
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->shielded_spend_num), &msg->shielded_spend_num);
if (msg->shielded_spend_num > 0) {
if (extraused + sizeof(struct sapling_spend_description) * msg->shielded_spend_num > extralen) {
printf("extraused.%d + shielded_spend.%d > extralen.%d\n", extraused, msg->shielded_spend_num,
extralen);
return (-1);
}
msg->shielded_spends = (struct sapling_spend_description *) &extraspace[extraused];
extraused += (sizeof(struct sapling_spend_description) * msg->shielded_spend_num);
for (i = 0; i < msg->shielded_spend_num; i++) {
len += iguana_rwbignum(rwflag, &serialized[len], sizeof(msg->shielded_spends[i].cv), msg->shielded_spends[i].cv.bytes);
len += iguana_rwbignum(rwflag, &serialized[len], sizeof(msg->shielded_spends[i].anchor), msg->shielded_spends[i].anchor.bytes);
len += iguana_rwbignum(rwflag, &serialized[len], sizeof(msg->shielded_spends[i].nullifier), msg->shielded_spends[i].nullifier.bytes);
len += iguana_rwbignum(rwflag, &serialized[len], sizeof(msg->shielded_spends[i].rk), msg->shielded_spends[i].rk.bytes);
if (rwflag == 1) {
memcpy(&serialized[len], msg->shielded_spends[i].zkproof, GROTH_PROOF_SIZE);
}
else {
memcpy(msg->shielded_spends[i].zkproof, &serialized[len], GROTH_PROOF_SIZE);
}
len += GROTH_PROOF_SIZE;
if (rwflag == 1) {
memcpy(&serialized[len], msg->shielded_spends[i].spend_auth_sig, SAPLING_AUTH_SIG_SIZE);
}
else {
memcpy(msg->shielded_spends[i].spend_auth_sig, &serialized[len], SAPLING_AUTH_SIG_SIZE);
}
len += SAPLING_AUTH_SIG_SIZE;
if (json != 0) {
cJSON *spend_item = cJSON_CreateObject();
jaddbits256(spend_item, "cv", msg->shielded_spends[i].cv);
jaddbits256(spend_item, "anchor", msg->shielded_spends[i].anchor);
jaddbits256(spend_item, "nullifier", msg->shielded_spends[i].nullifier);
jaddbits256(spend_item, "rk", msg->shielded_spends[i].rk);
char proof_str[GROTH_PROOF_SIZE * 2 + 1];
init_hexbytes_noT(proof_str, msg->shielded_spends[i].zkproof, GROTH_PROOF_SIZE);
jaddstr(spend_item, "proof", proof_str);
char auth_sig_str[SAPLING_AUTH_SIG_SIZE * 2 + 1];
init_hexbytes_noT(auth_sig_str, msg->shielded_spends[i].spend_auth_sig, SAPLING_AUTH_SIG_SIZE);
jaddstr(spend_item, "spendAuthSig", auth_sig_str);
jaddi(v_shielded_spend, spend_item);
}
}
}
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->shielded_output_num), &msg->shielded_output_num);
if (msg->shielded_output_num > 0) {
if (extraused + sizeof(struct sapling_output_description) * msg->shielded_output_num > extralen) {
printf("extraused.%d + shielded_output.%d > extralen.%d\n", extraused, msg->shielded_output_num,
extralen);
return (-1);
}
msg->shielded_outputs = (struct sapling_output_description *) &extraspace[extraused];
extraused += (sizeof(struct sapling_output_description) * msg->shielded_output_num);
for (i = 0; i < msg->shielded_output_num; i++) {
len += iguana_rwbignum(rwflag, &serialized[len], sizeof(msg->shielded_outputs[i].cv), msg->shielded_outputs[i].cv.bytes);
len += iguana_rwbignum(rwflag, &serialized[len], sizeof(msg->shielded_outputs[i].cm), msg->shielded_outputs[i].cm.bytes);
len += iguana_rwbignum(rwflag, &serialized[len], sizeof(msg->shielded_outputs[i].ephemeral_key), msg->shielded_outputs[i].ephemeral_key.bytes);
if (rwflag == 1) {
memcpy(&serialized[len], msg->shielded_outputs[i].enc_ciphertext, ENC_CIPHER_SIZE);
}
else {
memcpy(msg->shielded_outputs[i].enc_ciphertext, &serialized[len], ENC_CIPHER_SIZE);
}
len += ENC_CIPHER_SIZE;
if (rwflag == 1) {
memcpy(&serialized[len], msg->shielded_outputs[i].out_ciphertext, OUT_CIPHER_SIZE);
}
else {
memcpy(msg->shielded_outputs[i].out_ciphertext, &serialized[len], OUT_CIPHER_SIZE);
}
len += OUT_CIPHER_SIZE;
if (rwflag == 1) {
memcpy(&serialized[len], msg->shielded_outputs[i].zkproof, GROTH_PROOF_SIZE);
}
else {
memcpy(msg->shielded_outputs[i].zkproof, &serialized[len], GROTH_PROOF_SIZE);
}
len += GROTH_PROOF_SIZE;
if (json != 0) {
cJSON *output_item = cJSON_CreateObject();
jaddbits256(output_item, "cv", msg->shielded_outputs[i].cv);
jaddbits256(output_item, "cmu", msg->shielded_outputs[i].cm);
jaddbits256(output_item, "ephemeralKey", msg->shielded_outputs[i].ephemeral_key);
char enc_cip_str[ENC_CIPHER_SIZE * 2 + 1];
init_hexbytes_noT(enc_cip_str, msg->shielded_outputs[i].enc_ciphertext, ENC_CIPHER_SIZE);
jaddstr(output_item, "encCiphertext", enc_cip_str);
char out_cip_str[OUT_CIPHER_SIZE * 2 + 1];
init_hexbytes_noT(out_cip_str, msg->shielded_outputs[i].out_ciphertext, OUT_CIPHER_SIZE);
jaddstr(output_item, "outCiphertext", out_cip_str);
jaddi(v_shielded_output, output_item);
char proof_str[GROTH_PROOF_SIZE * 2 + 1];
init_hexbytes_noT(proof_str, msg->shielded_outputs[i].zkproof, GROTH_PROOF_SIZE);
jaddstr(output_item, "proof", proof_str);
}
}
}
if (json != 0) {
cJSON_AddItemToObject(json, "vShieldedSpend", v_shielded_spend);
cJSON_AddItemToObject(json, "vShieldedOutput", v_shielded_output);
}
}
}
//printf("lock_time.%08x len.%d\n",msg->lock_time,len);
if (zcash == LP_IS_ZCASHPROTOCOL && msg->version > 1)
{
struct iguana_msgjoinsplit joinsplit; uint8_t joinsplitpubkey[33], joinsplitsig[64];
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->numjoinsplits), &msg->numjoinsplits);
if (msg->numjoinsplits > 0)
{
for (i = 0; i<msg->numjoinsplits; i++)
len += iguana_rwjoinsplit(rwflag, &serialized[len], &joinsplit, zksnark_proof_size);
if (rwflag != 0)
{
memset(joinsplitpubkey, 0, sizeof(joinsplitpubkey)); // for now
memset(joinsplitsig, 0, sizeof(joinsplitsig)); // set to actuals
memcpy(&serialized[len], joinsplitpubkey + 1, 32), len += 32;
memcpy(&serialized[len], joinsplitsig, 64), len += 64;
}
else
{
joinsplitpubkey[0] = 0x02; // need to verify its not 0x03
memcpy(joinsplitpubkey + 1, &serialized[len], 32), len += 32;
memcpy(joinsplitsig, &serialized[len], 64), len += 64;
}
}
}
if (zcash == 1 && msg->version >= 4 && !(msg->shielded_spend_num == 0 && msg->shielded_output_num == 0)) {
if (rwflag == 1) {
memcpy(&serialized[len], msg->binding_sig, 64), len += 64;
}
else {
memcpy(msg->binding_sig, &serialized[len], 64), len += 64;
}
if (json != 0) {
char binding_sig_str[64 * 2 + 1];
init_hexbytes_noT(binding_sig_str, msg->binding_sig, 64);
jaddstr(json, "bindingSig", binding_sig_str);
}
}
if ( strcmp(coin->symbol,"VPN") == 0 ) if ( strcmp(coin->symbol,"VPN") == 0 )
{ {
uint16_t ddosflag = 0; uint16_t ddosflag = 0;
@ -702,9 +895,23 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t height,int32_t rwflag,cJ
memset(sigtxid.bytes,0,sizeof(sigtxid)); memset(sigtxid.bytes,0,sizeof(sigtxid));
if ( vins != 0 && jitem(vins,i) != 0 ) if ( vins != 0 && jitem(vins,i) != 0 )
{ {
uint32_t sighash = SIGHASH_ALL; // in marketmaker we use LP_sighash(symbol,zcash) to determine sighash (depends on zcash type), but here SIGHASH_ALL is enough for now
iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript));
sigtxid = bitcoin_sigtxid(coin,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys); printf("[ Decker ] vins.(%d) = %s\n", i, jprint(vins, i));
//printf("after vini.%d vinscript.%p spendscript.%p spendlen.%d (%s)\n",i,msg->vins[i].vinscript,msg->vins[i].spendscript,msg->vins[i].spendlen,jprint(jitem(vins,i),0));
// TODO: *** how to get spendamount here from msg->vins[i] ? fix bitcoin_sigtxid (!)
//uint64_t spendamount = LP_outpoint_amount(symbol, msg->vins[i].prev_hash, msg->vins[i].prev_vout);
struct supernet_info *myinfo = SuperNET_MYINFO(0); cJSON *jtxout = 0;
jtxout = dpow_gettxout(0, coin, msg->vins[i].prev_hash, msg->vins[i].prev_vout);
spendamount = jdouble(jtxout, "value") * SATOSHIDEN;
//printf("JSON (txout): %s\n", cJSON_Print(jtxout));
//printf("spendamount = %.8f\n", dstr(spendamount));
free(jtxout);
sigtxid = bitcoin_sigtxid(coin,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,spendamount, SIGHASH_ALL,vpnstr,suppress_pubkeys, zcash);
printf("after vini.%d vinscript.%p spendscript.%p spendlen.%d (%s)\n",i,msg->vins[i].vinscript,msg->vins[i].spendscript,msg->vins[i].spendlen,jprint(jitem(vins,i),0));
if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 ) if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 )
jaddi(vinarray,iguana_vinjson(coin,&msg->vins[i],sigtxid)); jaddi(vinarray,iguana_vinjson(coin,&msg->vins[i],sigtxid));
if ( msg->vins[i].spendscript == spendscript ) if ( msg->vins[i].spendscript == spendscript )
@ -729,6 +936,7 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t height,int32_t rwflag,cJ
jaddnum(json,"size",len); jaddnum(json,"size",len);
jaddbits256(json,"txid",*txidp); jaddbits256(json,"txid",*txidp);
//printf("TX.(%s) %p\n",jprint(json,0),json); //printf("TX.(%s) %p\n",jprint(json,0),json);
printf("JSON after: %s\n", cJSON_Print(json));
} }
msg->allocsize = len; msg->allocsize = len;
return(len); return(len);
@ -745,7 +953,19 @@ bits256 iguana_parsetxobj(struct supernet_info *myinfo,struct iguana_info *coin,
vpnstr[0] = 0; vpnstr[0] = 0;
if ( (msg->version= juint(txobj,"version")) == 0 ) if ( (msg->version= juint(txobj,"version")) == 0 )
msg->version = 1; msg->version = 1;
if (is_cJSON_True(cJSON_GetObjectItem(txobj, "overwintered"))) {
msg->version = 1 << 31 | msg->version;
//msg->version_group_id = (uint32_t)strtol(jstr(txobj, "versiongroupid"), NULL, 16);
msg->version_group_id = strtoul(jstr(txobj, "versiongroupid"), NULL, 16);
msg->expiry_height = juint(txobj, "expiryheight");
if (msg->version >= 4) {
msg->value_balance = (uint64_t)(jdouble(txobj, "valueBalance") * SATOSHIDEN);
}
}
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version);
if (is_cJSON_True(cJSON_GetObjectItem(txobj, "overwintered"))) {
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->version_group_id), &msg->version_group_id);
}
if ( coin->chain->isPoS != 0 ) if ( coin->chain->isPoS != 0 )
{ {
if ( (msg->timestamp= juint(txobj,"timestamp")) == 0 ) if ( (msg->timestamp= juint(txobj,"timestamp")) == 0 )
@ -793,11 +1013,22 @@ bits256 iguana_parsetxobj(struct supernet_info *myinfo,struct iguana_info *coin,
} }
msg->lock_time = jint(txobj,"locktime"); msg->lock_time = jint(txobj,"locktime");
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time);
if (is_cJSON_True(cJSON_GetObjectItem(txobj, "overwintered"))) {
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->expiry_height), &msg->expiry_height);
if (msg->version >= 4) {
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->value_balance), &msg->value_balance);
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->shielded_spend_num), &msg->shielded_spend_num);
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->shielded_output_num), &msg->shielded_output_num);
}
len += iguana_rwnum(rwflag, &serialized[len], sizeof(msg->numjoinsplits), &msg->numjoinsplits);
}
//msg->txid = jbits256(txobj,"txid"); //msg->txid = jbits256(txobj,"txid");
*txstartp = 0; *txstartp = 0;
msg->allocsize = len; msg->allocsize = len;
msg->txid = txid = bits256_doublesha256(0,serialized,len);
return(txid); msg->txid = txid = bits256_doublesha256(0,serialized,len); // bits256_calctxid(coin->symbol, serialized, len);
return(txid);
} }
char *iguana_rawtxbytes(struct iguana_info *coin,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys) char *iguana_rawtxbytes(struct iguana_info *coin,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys)
@ -976,7 +1207,7 @@ int32_t iguana_msgtx_Vset(struct iguana_info *coin,uint8_t *serialized,int32_t m
int32_t bitcoin_verifyvins(struct iguana_info *coin,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys) int32_t bitcoin_verifyvins(struct iguana_info *coin,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys)
{ {
bits256 sigtxid; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs; bits256 sigtxid; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs; uint64_t spendamount;
numvouts = msgtx->tx_out; numvouts = msgtx->tx_out;
vpnstr[0] = 0; vpnstr[0] = 0;
*signedtx = 0; *signedtx = 0;
@ -994,7 +1225,16 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,int32_t height,bits256 *sign
script = msgtx->vins[vini].spendscript; script = msgtx->vins[vini].spendscript;
scriptlen = msgtx->vins[vini].spendlen; scriptlen = msgtx->vins[vini].spendlen;
} }
sigtxid = bitcoin_sigtxid(coin,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys);
uint32_t zcash = (strcmp(coin->symbol, "VRSC") == 0 || strcmp(coin->symbol, "VRSCTEST") == 0); // we definitely need to determine somehow zcash-based coins here instead of compare coin names
struct supernet_info *myinfo = SuperNET_MYINFO(0); cJSON *jtxout = 0;
jtxout = dpow_gettxout(0, coin, msgtx->vins[vini].prev_hash, msgtx->vins[vini].prev_vout);
spendamount = jdouble(jtxout, "value") * SATOSHIDEN;
//printf("JSON (txout): %s\n", cJSON_Print(jtxout));
//printf("spendamount = %.8f\n", dstr(spendamount));
free(jtxout);
sigtxid = bitcoin_sigtxid(coin,height,serialized,maxlen,msgtx,vini,script,scriptlen,spendamount,sighash,vpnstr,suppress_pubkeys,zcash);
if ( bits256_nonz(sigtxid) != 0 ) if ( bits256_nonz(sigtxid) != 0 )
{ {
vp = &V[vini]; vp = &V[vini];
@ -1271,18 +1511,31 @@ cJSON *bitcoin_txinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_
return(txobj); return(txobj);
} }
cJSON *bitcoin_txcreate(char *symbol,int32_t isPoS,int64_t locktime,uint32_t txversion,uint32_t timestamp) cJSON *bitcoin_txcreate(char *symbol, int32_t isPoS, int64_t locktime, uint32_t txversion, uint32_t timestamp)
{ {
cJSON *json = cJSON_CreateObject(); cJSON *json = cJSON_CreateObject();
jaddnum(json,"version",txversion); jaddnum(json, "version", txversion);
if ( locktime == 0 && strcmp(symbol,"KMD") == 0 ) if (txversion >= 3) {
locktime = (uint32_t)time(NULL) - 55; cJSON_AddBoolToObject(json, "overwintered", 1);
jaddnum(json,"locktime",locktime); jaddnum(json, "expiryheight", 0);
if ( isPoS != 0 ) if (txversion == 3) {
jaddnum(json,"timestamp",timestamp == 0 ? time(NULL) : timestamp); jaddstr(json, "versiongroupid", "03c48270");
jadd(json,"vin",cJSON_CreateArray()); }
jadd(json,"vout",cJSON_CreateArray()); else if (txversion == 4) {
return(json); jaddstr(json, "versiongroupid", "892f2085");
jaddnum(json, "valueBalance", 0.);
jadd(json, "vShieldedSpend", cJSON_CreateArray());
jadd(json, "vShieldedOutput", cJSON_CreateArray());
}
}
if (locktime == 0 && strcmp(symbol, "KMD") == 0)
locktime = (uint32_t)time(NULL) - 55;
jaddnum(json, "locktime", locktime);
if (isPoS != 0)
jaddnum(json, "timestamp", timestamp == 0 ? time(NULL) : timestamp);
jadd(json, "vin", cJSON_CreateArray());
jadd(json, "vout", cJSON_CreateArray());
return(json);
} }
cJSON *bitcoin_txoutput(cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis) cJSON *bitcoin_txoutput(cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis)

37
includes/iguana_structs.h

@ -106,7 +106,14 @@ struct iguana_msgblockhdr
uint32_t timestamp,bits,nonce; uint32_t timestamp,bits,nonce;
} PACKEDSTRUCT; } PACKEDSTRUCT;
#define LP_IS_ZCASHPROTOCOL 1
#define SIGHASH_FORKID 0x40
#define ZKSNARK_PROOF_SIZE 296 #define ZKSNARK_PROOF_SIZE 296
#define GROTH_PROOF_SIZE 192
#define SAPLING_AUTH_SIG_SIZE 64
#define ENC_CIPHER_SIZE 580
#define OUT_CIPHER_SIZE 80
#define ZCASH_SOLUTION_ELEMENTS 1344 #define ZCASH_SOLUTION_ELEMENTS 1344
struct iguana_msgzblockhdr struct iguana_msgzblockhdr
@ -161,15 +168,20 @@ struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_scrip
struct iguana_msgtx struct iguana_msgtx
{ {
uint32_t version,tx_in,tx_out,lock_time; uint32_t version, version_group_id, tx_in, tx_out, lock_time, expiry_height;
struct iguana_msgvin *vins; struct iguana_msgvin *vins;
struct iguana_msgvout *vouts; struct iguana_msgvout *vouts;
bits256 txid; struct sapling_spend_description *shielded_spends;
int32_t allocsize,timestamp,numinputs,numoutputs; struct sapling_output_description *shielded_outputs;
int64_t inputsum,outputsum,txfee; bits256 txid;
uint8_t *serialized; int32_t allocsize, timestamp, numinputs, numoutputs;
int64_t inputsum, outputsum, txfee;
uint8_t *serialized, shielded_spend_num, shielded_output_num, numjoinsplits;
uint64_t value_balance;
uint8_t binding_sig[64];
};// PACKEDSTRUCT; };// PACKEDSTRUCT;
struct iguana_msgjoinsplit struct iguana_msgjoinsplit
{ {
uint64_t vpub_old,vpub_new; uint64_t vpub_old,vpub_new;
@ -179,6 +191,17 @@ struct iguana_msgjoinsplit
uint8_t ciphertexts[2][601]; uint8_t ciphertexts[2][601];
}PACKEDSTRUCT; }PACKEDSTRUCT;
struct sapling_spend_description {
bits256 cv, anchor, nullifier, rk;
uint8_t zkproof[GROTH_PROOF_SIZE], spend_auth_sig[SAPLING_AUTH_SIG_SIZE];
};
struct sapling_output_description {
bits256 cv, cm, ephemeral_key;
uint8_t zkproof[GROTH_PROOF_SIZE], enc_ciphertext[ENC_CIPHER_SIZE], out_ciphertext[OUT_CIPHER_SIZE];
};
struct iguana_packet { struct queueitem DL; struct iguana_peer *addr; struct tai embargo; int32_t datalen,getdatablock; uint8_t serialized[]; }; struct iguana_packet { struct queueitem DL; struct iguana_peer *addr; struct tai embargo; int32_t datalen,getdatablock; uint8_t serialized[]; };
struct msgcounts { uint32_t version,verack,getaddr,addr,inv,getdata,notfound,getblocks,getheaders,headers,tx,block,mempool,ping,pong,reject,filterload,filteradd,filterclear,merkleblock,alert; }; struct msgcounts { uint32_t version,verack,getaddr,addr,inv,getdata,notfound,getblocks,getheaders,headers,tx,block,mempool,ping,pong,reject,filterload,filteradd,filterclear,merkleblock,alert; };

Loading…
Cancel
Save