@ -15,9 +15,28 @@
# include "iguana777.h"
# include "iguana777.h"
# include "exchanges/bitcoin.h"
# include "exchanges/bitcoin.h"
# include <sodium/crypto_generichash_blake2b.h>
const unsigned char ZCASH_PREVOUTS_HASH_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' P ' , ' r ' , ' e ' , ' v ' , ' o ' , ' u ' , ' t ' , ' H ' , ' a ' , ' s ' , ' h ' } ;
const unsigned char ZCASH_SEQUENCE_HASH_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' S ' , ' e ' , ' q ' , ' u ' , ' e ' , ' n ' , ' c ' , ' H ' , ' a ' , ' s ' , ' h ' } ;
const unsigned char ZCASH_OUTPUTS_HASH_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' O ' , ' u ' , ' t ' , ' p ' , ' u ' , ' t ' , ' s ' , ' H ' , ' a ' , ' s ' , ' h ' } ;
const unsigned char ZCASH_JOINSPLITS_HASH_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' J ' , ' S ' , ' p ' , ' l ' , ' i ' , ' t ' , ' s ' , ' H ' , ' a ' , ' s ' , ' h ' } ;
const unsigned char ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' S ' , ' S ' , ' p ' , ' e ' , ' n ' , ' d ' , ' s ' , ' H ' , ' a ' , ' s ' , ' h ' } ;
const unsigned char ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' S ' , ' O ' , ' u ' , ' t ' , ' p ' , ' u ' , ' t ' , ' H ' , ' a ' , ' s ' , ' h ' } ;
const unsigned char ZCASH_SIG_HASH_SAPLING_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' S ' , ' i ' , ' g ' , ' H ' , ' a ' , ' s ' , ' h ' , ' \xBB ' , ' \x09 ' , ' \xB8 ' , ' \x76 ' } ;
const unsigned char ZCASH_SIG_HASH_OVERWINTER_PERSONALIZATION [ 16 ] =
{ ' Z ' , ' c ' , ' a ' , ' s ' , ' h ' , ' S ' , ' i ' , ' g ' , ' H ' , ' a ' , ' s ' , ' h ' , ' \x19 ' , ' \x1B ' , ' \xA8 ' , ' \x5B ' } ;
// make sure coinbase outputs are matured
int32_t iguana_rwjoinsplit ( int32_t rwflag , uint8_t * serialized , struct iguana_msgjoinsplit * msg , uint32_t proof_size ) ; // defined in iguana_msg.c
// make sure coinbase outputs are matured
int32_t iguana_vinparse ( struct iguana_info * coin , int32_t rwflag , uint8_t * serialized , struct iguana_msgvin * msg )
int32_t iguana_vinparse ( struct iguana_info * coin , int32_t rwflag , uint8_t * serialized , struct iguana_msgvin * msg )
{
{
int32_t p2shlen , len = 0 ; uint32_t tmp ;
int32_t p2shlen , len = 0 ; uint32_t tmp ;
@ -486,7 +505,7 @@ 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 )
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 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 +519,160 @@ 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 ;
// sapling tx sighash preimage
dest . vins [ i ] . scriptlen = spendlen ;
len = 0 ;
//int32_t j; for (j=0; j<spendlen; j++)
uint8_t for_sig_hash [ 1000 ] , sig_hash [ 32 ] ;
// printf("%02x",spendscript[j]);
len = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . version ) , & dest . version ) ;
//printf(" tmpscript.%d vini.%d\n",spendlen,vini);
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . version_group_id ) , & dest . version_group_id ) ;
}
uint8_t prev_outs [ 1000 ] , hash_prev_outs [ 32 ] ;
else
int32_t prev_outs_len = 0 ;
{
for ( i = 0 ; i < dest . tx_in ; i + + ) {
dest . vins [ i ] . vinscript = ( uint8_t * ) " " ;
prev_outs_len + = iguana_rwbignum ( 1 , & prev_outs [ prev_outs_len ] , sizeof ( dest . vins [ i ] . prev_hash ) , dest . vins [ i ] . prev_hash . bytes ) ;
dest . vins [ i ] . scriptlen = 0 ;
prev_outs_len + = iguana_rwnum ( 1 , & prev_outs [ prev_outs_len ] , sizeof ( dest . vins [ i ] . prev_vout ) , & dest . vins [ i ] . prev_vout ) ;
}
}
dest . vins [ i ] . p2shlen = 0 ;
crypto_generichash_blake2b_salt_personal (
dest . vins [ i ] . redeemscript = 0 ;
hash_prev_outs ,
dest . vins [ i ] . userdata = 0 ;
32 ,
dest . vins [ i ] . userdatalen = 0 ;
prev_outs ,
}
( uint64_t ) prev_outs_len ,
len = iguana_rwmsgtx ( coin , height , 1 , 0 , serialized , maxlen , & dest , & txid , vpnstr , 0 , 0 , 0 , suppress_pubkeys ) ;
NULL ,
//for (i=0; i<len; i++)
0 ,
// printf("%02x",serialized[i]);
NULL ,
//printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen);
ZCASH_PREVOUTS_HASH_PERSONALIZATION
if ( len > 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 &&
) ;
{
memcpy ( & for_sig_hash [ len ] , hash_prev_outs , 32 ) ;
# ifdef BTC2_VERSION
len + = 32 ;
if ( height > = BTC2_HARDFORK_HEIGHT )
hashtype | = ( 0x777 < < 20 ) ;
uint8_t sequence [ 1000 ] , sequence_hash [ 32 ] ;
# endif
int32_t sequence_len = 0 ;
len + = iguana_rwnum ( 1 , & serialized [ len ] , sizeof ( hashtype ) , & hashtype ) ;
revsigtxid = bits256_doublesha256 ( 0 , serialized , len ) ;
for ( i = 0 ; i < dest . tx_in ; i + + ) {
for ( i = 0 ; i < sizeof ( revsigtxid ) ; i + + )
sequence_len + = iguana_rwnum ( 1 , & sequence [ sequence_len ] , sizeof ( dest . vins [ i ] . sequence ) ,
sigtxid . bytes [ 31 - i ] = revsigtxid . bytes [ i ] ;
& dest . vins [ i ] . sequence ) ;
//char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out);
}
}
crypto_generichash_blake2b_salt_personal (
sequence_hash ,
32 ,
sequence ,
( uint64_t ) sequence_len ,
NULL ,
0 ,
NULL ,
ZCASH_SEQUENCE_HASH_PERSONALIZATION
) ;
memcpy ( & for_sig_hash [ len ] , sequence_hash , 32 ) ;
len + = 32 ;
uint8_t outputs [ 1000 ] , hash_outputs [ 32 ] ;
int32_t outputs_len = 0 ;
for ( i = 0 ; i < dest . tx_out ; i + + ) {
outputs_len + = iguana_rwnum ( 1 , & outputs [ outputs_len ] , sizeof ( dest . vouts [ i ] . value ) , & dest . vouts [ i ] . value ) ;
outputs [ outputs_len + + ] = ( uint8_t ) dest . vouts [ i ] . pk_scriptlen ;
memcpy ( & outputs [ outputs_len ] , dest . vouts [ i ] . pk_script , dest . vouts [ i ] . pk_scriptlen ) ;
outputs_len + = dest . vouts [ i ] . pk_scriptlen ;
}
crypto_generichash_blake2b_salt_personal (
hash_outputs ,
32 ,
outputs ,
( uint64_t ) outputs_len ,
NULL ,
0 ,
NULL ,
ZCASH_OUTPUTS_HASH_PERSONALIZATION
) ;
memcpy ( & for_sig_hash [ len ] , hash_outputs , 32 ) ;
len + = 32 ;
// no join splits, fill the hashJoinSplits with 32 zeros
memset ( & for_sig_hash [ len ] , 0 , 32 ) ;
len + = 32 ;
if ( version > 3 ) {
// no shielded spends, fill the hashShieldedSpends with 32 zeros
memset ( & for_sig_hash [ len ] , 0 , 32 ) ;
len + = 32 ;
// no shielded outputs, fill the hashShieldedOutputs with 32 zeros
memset ( & for_sig_hash [ len ] , 0 , 32 ) ;
len + = 32 ;
}
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . lock_time ) , & dest . lock_time ) ;
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . expiry_height ) , & dest . expiry_height ) ;
if ( version > 3 ) {
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . value_balance ) , & dest . value_balance ) ;
}
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( hashtype ) , & hashtype ) ;
len + = iguana_rwbignum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . vins [ vini ] . prev_hash ) , dest . vins [ vini ] . prev_hash . bytes ) ;
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . vins [ vini ] . prev_vout ) , & dest . vins [ vini ] . prev_vout ) ;
for_sig_hash [ len + + ] = ( uint8_t ) spendlen ;
memcpy ( & for_sig_hash [ len ] , spendscript , spendlen ) , len + = spendlen ;
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( spendamount ) , & spendamount ) ;
len + = iguana_rwnum ( 1 , & for_sig_hash [ len ] , sizeof ( dest . vins [ vini ] . sequence ) , & dest . vins [ vini ] . sequence ) ;
unsigned const char * sig_hash_personal = ZCASH_SIG_HASH_OVERWINTER_PERSONALIZATION ;
if ( version = = 4 ) {
sig_hash_personal = ZCASH_SIG_HASH_SAPLING_PERSONALIZATION ;
}
crypto_generichash_blake2b_salt_personal (
sig_hash ,
32 ,
for_sig_hash ,
( uint64_t ) len ,
NULL ,
0 ,
NULL ,
sig_hash_personal
) ;
for ( i = 0 ; i < 32 ; i + + )
sigtxid . bytes [ i ] = sig_hash [ i ] ;
}
else {
for ( i = 0 ; i < dest . tx_in ; i + + )
{
if ( i = = vini )
{
dest . vins [ i ] . vinscript = spendscript ;
dest . vins [ i ] . scriptlen = spendlen ;
//int32_t j; for (j=0; j<spendlen; j++)
// printf("%02x",spendscript[j]);
//printf(" tmpscript.%d vini.%d\n",spendlen,vini);
}
else
{
dest . vins [ i ] . vinscript = ( uint8_t * ) " " ;
dest . vins [ i ] . scriptlen = 0 ;
}
dest . vins [ i ] . p2shlen = 0 ;
dest . vins [ i ] . redeemscript = 0 ;
dest . vins [ i ] . userdata = 0 ;
dest . vins [ i ] . userdatalen = 0 ;
}
len = iguana_rwmsgtx ( coin , height , 1 , 0 , serialized , maxlen , & dest , & txid , vpnstr , 0 , 0 , 0 , suppress_pubkeys ) ;
//for (i=0; i<len; i++)
// printf("%02x",serialized[i]);
//printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen);
if ( len > 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 &&
{
# 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 +724,38 @@ 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 ;
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 ( coin - > sapling ! = 0 ) {
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 +838,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 ( ( coin - > sapling ! = 0 ) & & 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 ( ( coin - > sapling ! = 0 ) & & 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 ( ( coin - > sapling ! = 0 ) & & 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 +1019,19 @@ 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("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));
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 ) ;
// 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 )
@ -745,7 +1072,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 +1132,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 +1326,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 +1344,15 @@ 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 ) ;
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 ) ;
if ( bits256_nonz ( sigtxid ) ! = 0 )
if ( bits256_nonz ( sigtxid ) ! = 0 )
{
{
vp = & V [ vini ] ;
vp = & V [ vini ] ;
@ -1271,18 +1629,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 )