Browse Source

test

release/v0.1
jl777 9 years ago
parent
commit
0585513244
  1. 4
      crypto777/iguana_utils.c
  2. 40
      iguana/SuperNET.c
  3. 41
      iguana/SuperNET_keys.c
  4. 20
      iguana/iguana777.h
  5. 2
      iguana/iguana_accept.c
  6. 81
      iguana/iguana_payments.c
  7. 21
      iguana/iguana_scripts.c
  8. 281
      iguana/iguana_sign.c
  9. 2
      iguana/iguana_spendvectors.c
  10. 12
      iguana/iguana_txidfind.c
  11. 35
      iguana/iguana_unspents.c
  12. 6
      iguana/iguana_volatiles.c
  13. 52
      iguana/iguana_wallet.c
  14. 8
      iguana/swaps/iguana_BTCswap.c
  15. 2
      iguana/tests/createrawtransaction
  16. 1
      iguana/tests/decoderawtransaction
  17. 1
      iguana/tests/decoderawtransactionB
  18. 2
      iguana/tests/getrawtransaction
  19. 2
      iguana/tests/gettransaction
  20. 2
      iguana/tests/signrawtransaction
  21. 1
      iguana/tests/txdata

4
crypto777/iguana_utils.c

@ -392,10 +392,10 @@ char *clonestr(char *str)
int32_t safecopy(char *dest,char *src,long len)
{
int32_t i = -1;
if ( src != 0 && dest != 0 && src != dest )
{
if ( dest != 0 )
memset(dest,0,len);
if ( src != 0 && dest != 0 )
{
for (i=0; i<len&&src[i]!=0; i++)
dest[i] = src[i];
if ( i == len )

40
iguana/SuperNET.c

@ -1381,25 +1381,31 @@ struct supernet_info *SuperNET_accountfind(cJSON *json)
FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase)
{
char savehandle[1024],savepassword[1024],savepermanentfile[1024],*str,*decryptstr = 0; cJSON *argjson; uint32_t expire = myinfo->expiration;
char *argstr,*str,*decryptstr = 0; cJSON *argjson; //uint32_t expire = myinfo->expiration; //savehandle[1024],savepassword[1024],savepermanentfile[1024]
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
safecopy(savehandle,myinfo->handle,sizeof(myinfo->handle));
safecopy(savepassword,myinfo->secret,sizeof(myinfo->secret));
safecopy(savepermanentfile,myinfo->permanentfile,sizeof(myinfo->permanentfile));
if ( bits256_nonz(myinfo->persistent_priv) != 0 && (str= SuperNET_logout(IGUANA_CALLARGS)) != 0 )
free(str);
myinfo->expiration = expire;
//safecopy(savehandle,myinfo->handle,sizeof(myinfo->handle));
//safecopy(savepassword,myinfo->secret,sizeof(myinfo->secret));
//safecopy(savepermanentfile,myinfo->permanentfile,sizeof(myinfo->permanentfile));
//if ( bits256_nonz(myinfo->persistent_priv) != 0 && (str= SuperNET_logout(IGUANA_CALLARGS)) != 0 )
// free(str);
//myinfo->expiration = expire;
if ( handle != 0 && handle[0] != 0 )
safecopy(myinfo->handle,handle,sizeof(myinfo->handle));
else safecopy(myinfo->handle,savehandle,sizeof(myinfo->handle));
safecopy(myinfo->secret,savepassword,sizeof(myinfo->secret));
safecopy(myinfo->permanentfile,savepermanentfile,sizeof(myinfo->permanentfile));
if ( (passphrase == 0 || passphrase[0] == 0) && (decryptstr= SuperNET_decryptjson(IGUANA_CALLARGS,password,permanentfile)) != 0 )
else memset(myinfo->handle,0,sizeof(myinfo->handle));
if ( password != 0 && password[0] != 0 )
safecopy(myinfo->secret,password,sizeof(myinfo->secret));
else if ( passphrase != 0 && passphrase[0] != 0 )
safecopy(myinfo->secret,passphrase,sizeof(myinfo->secret));
//else memset(myinfo->secret,0,sizeof(myinfo->secret));
if ( permanentfile != 0 )
safecopy(myinfo->permanentfile,permanentfile,sizeof(myinfo->permanentfile));
//else memset(myinfo->permanentfile,0,sizeof(myinfo->permanentfile));
if ( (decryptstr= SuperNET_decryptjson(IGUANA_CALLARGS,myinfo->secret,myinfo->permanentfile)) != 0 )
{
if ( (argjson= cJSON_Parse(decryptstr)) != 0 )
{
//printf("decrypted.(%s) exp.%u\n",decryptstr,myinfo->expiration);
printf("decrypted.(%s) exp.%u pass.(%s)\n",decryptstr,myinfo->expiration,password);
if ( myinfo->decryptstr != 0 )
free(myinfo->decryptstr);
myinfo->decryptstr = decryptstr;
@ -1425,8 +1431,16 @@ FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase)
if ( passphrase != 0 && passphrase[0] != 0 )
{
SuperNET_setkeys(myinfo,passphrase,(int32_t)strlen(passphrase),1);
if ( (str= SuperNET_encryptjson(IGUANA_CALLARGS,myinfo->secret,myinfo->permanentfile,passphrase)) != 0 )
if ( myinfo->decryptstr != 0 && (argjson= cJSON_Parse(myinfo->decryptstr)) != 0 )
{
if ( jobj(argjson,"passphrase") != 0 )
jdelete(argjson,"passphrase");
} else argjson = cJSON_CreateObject();
jaddstr(argjson,"passphrase",passphrase);
argstr = jprint(argjson,1);
if ( (str= SuperNET_encryptjson(IGUANA_CALLARGS,myinfo->secret,myinfo->permanentfile,argstr)) != 0 )
free(str);
free(argstr);
return(SuperNET_activehandle(IGUANA_CALLARGS));
}
else return(clonestr("{\"error\":\"need passphrase\"}"));

41
iguana/SuperNET_keys.c

@ -386,6 +386,26 @@ char *SuperNET_keysinit(struct supernet_info *myinfo,char *argjsonstr)
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
TWO_STRINGS(SuperNET,decryptjson,password,permanentfile)
{
char pass[8192],fname2[1023],destfname[1024]; cJSON *retjson; bits256 wallethash,wallet2priv;
safecopy(pass,password,sizeof(pass));
safecopy(fname2,permanentfile,sizeof(fname2));
wallethash = wallet2priv = GENESIS_PRIVKEY;
if ( strlen(pass) == sizeof(wallethash)*2 && is_hexstr(pass,(int32_t)sizeof(bits256)*2) > 0 )
wallethash = bits256_conv(pass);
if ( strlen(fname2) == sizeof(wallet2priv)*2 && is_hexstr(fname2,(int32_t)sizeof(bits256)*2) > 0 )
wallet2priv = bits256_conv(fname2);
if ( (retjson= SuperNET_decryptedjson(destfname,pass,sizeof(pass),wallethash,fname2,sizeof(fname2),wallet2priv)) != 0 )
{
printf("decrypt pass.(%s) fname2.(%s) -> destfname.(%s)\n",pass,fname2,destfname);
//obj = jduplicate(jobj(retjson,"payload"));
//jdelete(retjson,"payload");
//jadd(retjson,"result",obj);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"couldnt decrypt json file\"}"));
}
THREE_STRINGS(SuperNET,encryptjson,password,permanentfile,payload)
{
char destfname[4096],pass[8192],fname2[1023]; cJSON *argjson,*retjson = cJSON_CreateObject();
@ -407,27 +427,6 @@ THREE_STRINGS(SuperNET,encryptjson,password,permanentfile,payload)
free_json(argjson);
return(jprint(retjson,1));
}
TWO_STRINGS(SuperNET,decryptjson,password,permanentfile)
{
char pass[8192],fname2[1023],destfname[1024]; cJSON *retjson; bits256 wallethash,wallet2priv;
safecopy(pass,password,sizeof(pass));
safecopy(fname2,permanentfile,sizeof(fname2));
wallethash = wallet2priv = GENESIS_PRIVKEY;
if ( strlen(pass) == sizeof(wallethash)*2 && is_hexstr(pass,(int32_t)sizeof(bits256)*2) > 0 )
wallethash = bits256_conv(pass);
if ( strlen(fname2) == sizeof(wallet2priv)*2 && is_hexstr(fname2,(int32_t)sizeof(bits256)*2) > 0 )
wallet2priv = bits256_conv(fname2);
if ( (retjson= SuperNET_decryptedjson(destfname,pass,sizeof(pass),wallethash,fname2,sizeof(fname2),wallet2priv)) != 0 )
{
//printf("decrypt pass.(%s) fname2.(%s) -> destfname.(%s)\n",pass,fname2,destfname);
//obj = jduplicate(jobj(retjson,"payload"));
//jdelete(retjson,"payload");
//jadd(retjson,"result",obj);
return(jprint(retjson,1));
}
else return(clonestr("{\"error\":\"couldnt decrypt json file\"}"));
}
#include "../includes/iguana_apiundefs.h"

20
iguana/iguana777.h

@ -257,7 +257,7 @@ struct iguana_msgblock
uint32_t txn_count;
} __attribute__((packed));
struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*spendscript,*redeemscript; uint32_t prev_vout,scriptlen,spendlen,p2shlen,sequence; } __attribute__((packed));
struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*spendscript,*redeemscript,*pubkeys[16]; uint32_t prev_vout,scriptlen,spendlen,p2shlen,numpubkeys,sequence; } __attribute__((packed));
struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; } __attribute__((packed));
@ -359,7 +359,7 @@ struct iguana_pkhash { uint8_t rmd160[20]; uint32_t pkind; } __attribute__((pack
// dynamic
struct iguana_account { int64_t total; uint32_t lastunspentind; } __attribute__((packed));
struct iguana_utxo { uint32_t fromheight,prevunspentind:31,spentflag:1; } __attribute__((packed));
struct iguana_utxo { uint32_t fromheight:31,lockedflag:1,prevunspentind:31,spentflag:1; } __attribute__((packed));
struct iguana_hhaccount { UT_hash_handle hh; uint64_t pval; struct iguana_account a; } __attribute__((packed));
struct iguana_hhutxo { UT_hash_handle hh; uint64_t uval; struct iguana_utxo u; } __attribute__((packed));
@ -528,9 +528,10 @@ struct vin_info
char coinaddr[65];
uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE];
};
struct bitcoin_unspent
{
bits256 txid,privkeys[16]; uint64_t value; int32_t vout,spendlen,p2shlen; uint32_t sequence;
bits256 txid,privkeys[16]; uint64_t value; int32_t vout,spendlen,p2shlen,numpubkeys; uint32_t sequence;
uint8_t addrtype,rmd160[20],pubkeys[16][65],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE];
};
@ -816,12 +817,12 @@ void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen);
int32_t bitcoin_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime);
struct bitcoin_spend *iguana_spendset(struct supernet_info *myinfo,struct iguana_info *coin,int64_t satoshis,int64_t insurance,char *account);
cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes);
cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj);
cJSON *iguana_signtx(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj,cJSON *vins);
cJSON *bitcoin_createtx(struct iguana_info *coin,uint32_t locktime);
cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis);
int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee);
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys);
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V);
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V,int32_t numinputs);
char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson);
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr);
char *issue_startForging(struct supernet_info *myinfo,char *secret);
@ -897,6 +898,7 @@ int32_t iguana_balancefinished(struct iguana_info *coin);
int32_t iguana_alloctxbits(struct iguana_info *coin,struct iguana_ramchain *ramchain);
void iguana_allocvolatile(struct iguana_info *coin,struct iguana_ramchain *ramchain);
int32_t iguana_rwaddr(int32_t rwflag,uint8_t *serialized,struct iguana_msgaddress *addr,int32_t protover);
struct iguana_waddress *iguana_waddresscreate(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr,char *redeemScript);
int32_t iguana_peerhdrrequest(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_peer *addr,bits256 hash2);
int32_t iguana_peeraddrrequest(struct iguana_info *coin,struct iguana_peer *addr,uint8_t *space,int32_t max);
@ -914,7 +916,7 @@ void iguana_volatilesalloc(struct iguana_info *coin,struct iguana_ramchain *ramc
int32_t iguana_send_ping(struct iguana_info *coin,struct iguana_peer *addr);
int32_t iguana_process_msgrequestQ(struct iguana_info *coin);
uint32_t iguana_fastfindinit(struct iguana_info *coin);
int32_t iguana_unspentindfind(struct iguana_info *coin,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi);
int32_t iguana_unspentindfind(struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *scriptlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi);
int32_t iguana_addressvalidate(struct iguana_info *coin,uint8_t *addrtypep,uint8_t rmd160[20],char *address);
int32_t bitcoin_sign(uint8_t *sig,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 privkey);
bits256 iguana_str2priv(struct supernet_info *myinfo,struct iguana_info *coin,char *str);
@ -930,13 +932,17 @@ int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t
cJSON *iguana_p2shjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson,struct iguana_waddress *waddr);
char *setaccount(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waddress **waddrp,char *account,char *coinaddr,char *redeemScript);
char *iguana_APIrequest(struct iguana_info *coin,bits256 blockhash,bits256 txid,int32_t seconds);
int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t sighashsingle);
int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t numinputs,int32_t sighashsingle);
int64_t iguana_fastfindcreate(struct iguana_info *coin);
int32_t bitcoin_validaddress(struct iguana_info *coin,char *coinaddr);
int32_t iguana_volatileupdate(struct iguana_info *coin,int32_t incremental,struct iguana_ramchain *spentchain,int16_t spent_hdrsi,uint32_t spent_unspentind,uint32_t spent_pkind,uint64_t spent_value,uint32_t spendind,uint32_t fromheight);
int32_t iguana_utxoupdate(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t spent_unspentind,uint32_t spent_pkind,uint64_t spent_value,uint32_t spendind,uint32_t fromheight);
int32_t iguana_unspentslists(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waddress **waddrs,int32_t maxwaddrs,int64_t required,int32_t minconf,char *account);
int64_t iguana_unspentset(struct supernet_info *myinfo,struct iguana_info *coin);
int32_t iguana_txidfastfind(struct iguana_info *coin,int32_t *heightp,bits256 txid,int32_t lasthdrsi);
uint8_t iguana_addrtype(struct iguana_info *coin,uint8_t script_type);
struct iguana_waddress *iguana_waddressadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,struct iguana_waddress *addwaddr,char *redeemScript);
cJSON *iguana_createvins(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *txobj,cJSON *vins);
extern int32_t HDRnet,netBLOCKS;

2
iguana/iguana_accept.c

@ -250,7 +250,7 @@ int32_t iguana_peerdatarequest(struct iguana_info *coin,struct iguana_peer *addr
int32_t iguana_peerhdrrequest(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_peer *addr,bits256 hash2)
{
int32_t len=0,i,height,hdrsi,bundlei,bundlesize,firstvout,retval=-1; struct iguana_block *block; struct iguana_msgblock msgB; bits256 checkhash2; struct iguana_bundle *bp;
if ( (firstvout= iguana_unspentindfind(coin,&height,hash2,0,coin->bundlescount-1)) != 0 )
if ( (firstvout= iguana_unspentindfind(coin,0,0,0,0,&height,hash2,0,coin->bundlescount-1)) != 0 )
{
bundlesize = coin->chain->bundlesize;
hdrsi = (height / bundlesize);

81
iguana/iguana_payments.c

@ -178,8 +178,20 @@ char *sendtoaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *
STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees)
{
cJSON *retjson = cJSON_CreateObject();
// send to 2 peers
cJSON *retjson = cJSON_CreateObject(); char txidstr[65]; bits256 txid; uint8_t *serialized; struct iguana_peer *addr; int32_t i,len = (int32_t)strlen(rawtx) >> 1;
if ( coin->peers.numranked >= 8 )
{
serialized = calloc(1,sizeof(struct iguana_msghdr) + len);
decode_hex(&serialized[sizeof(struct iguana_msghdr)],len,rawtx);
for (i=0; i<8; i++)
{
if ( (addr= coin->peers.ranked[i]) != 0 && addr->dead == 0 && addr->usock >= 0 )
iguana_queue_send(coin,addr,0,serialized,"tx",len,0,0);
}
free(serialized);
txid = bits256_doublesha256(txidstr,&serialized[sizeof(struct iguana_msghdr)],len);
jaddstr(retjson,"result",txidstr);
} else jaddstr(retjson,"error","no peers");
return(jprint(retjson,1));
}
@ -328,7 +340,7 @@ HASH_AND_TWOINTS(bitcoinrpc,gettxout,txid,vout,mempool)
if ( coin != 0 )
{
minconf = (mempool != 0) ? 0 : 1;
if ( (unspentind= iguana_unspentindfind(coin,&height,txid,vout,coin->bundlescount-1)) != 0 )
if ( (unspentind= iguana_unspentindfind(coin,0,0,0,0,&height,txid,vout,coin->bundlescount-1)) != 0 )
{
if ( height >= 0 && height < coin->longestchain && (bp= coin->bundles[height / coin->chain->bundlesize]) != 0 )
{
@ -411,7 +423,7 @@ THREE_STRINGS(bitcoinrpc,verifymessage,address,sig,message)
HASH_AND_INT(bitcoinrpc,getrawtransaction,txid,verbose)
{
struct iguana_txid *tx,T; char *txbytes; bits256 checktxid; int32_t len,height; cJSON *retjson;
struct iguana_txid *tx,T; char *txbytes; bits256 checktxid; int32_t len,height; cJSON *retjson,*txobj;
if ( (tx= iguana_txidfind(coin,&height,&T,txid,coin->bundlescount-1)) != 0 )
{
retjson = cJSON_CreateObject();
@ -419,6 +431,13 @@ HASH_AND_INT(bitcoinrpc,getrawtransaction,txid,verbose)
{
txbytes = calloc(1,len*2+1);
init_hexbytes_noT(txbytes,coin->blockspace,len);
if ( verbose != 0 )
{
txobj = bitcoin_hex2json(coin,&checktxid,0,txbytes);
free(txbytes);
if ( txobj != 0 )
return(jprint(txobj,1));
}
jaddstr(retjson,"result",txbytes);
printf("txbytes.(%s) len.%d (%s)\n",txbytes,len,jprint(retjson,0));
free(txbytes);
@ -474,35 +493,71 @@ HASH_ARG(bitcoinrpc,gettransaction,txid)
return(bitcoinrpc_getrawtransaction(IGUANA_CALLARGS,txid,1));
}
ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime)
cJSON *iguana_createvins(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *txobj,cJSON *vins)
{
bits256 txid; int32_t vout,offset,spendlen=0,p2shlen=0,i,n; uint32_t sequenceid; uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],redeemscript[IGUANA_MAXSCRIPTSIZE]; uint64_t satoshis; char *hexstr,*str,*field,*txstr; cJSON *txobj,*item,*obj,*retjson = cJSON_CreateObject();
if ( coin != 0 && (txobj= bitcoin_createtx(coin,locktime)) != 0 )
{
int32_t i,n,vout,p2shlen=0,spendlen=0,unspentind,height; uint64_t satoshis; char coinaddr[128],pubkeystr[256],scriptstr[IGUANA_MAXSCRIPTSIZE*2],*str,*hexstr; cJSON *pubkeys,*item,*obj,*newvin,*newvins; uint32_t sequenceid; bits256 txid; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE],redeemscript[IGUANA_MAXSCRIPTSIZE]; struct iguana_waccount *wacct; struct iguana_waddress *waddr;
newvins = cJSON_CreateArray();
if ( (n= cJSON_GetArraySize(vins)) > 0 )
{
for (i=0; i<n; i++)
{
pubkeys = cJSON_CreateArray();
newvin = cJSON_CreateObject();
item = jitem(vins,i);
txid = jbits256(item,"txid");
vout = jint(item,"vout");
jaddbits256(newvin,"txid",txid);
jaddnum(newvin,"vout",vout);
p2shlen = spendlen = 0;
if ( (str= jstr(item,"scriptPubKey")) != 0 || (str= jstr(item,"scriptPubkey")) != 0 )
if ( ((str= jstr(item,"scriptPub")) != 0 || (str= jstr(item,"scriptPubkey")) != 0) && is_hexstr(str,(int32_t)strlen(str)) > 0 )
{
spendlen = (int32_t)strlen(str) >> 1;
decode_hex(spendscript,spendlen,str);
}
else if ( ((obj= jobj(item,"scriptPub")) != 0 || (obj= jobj(item,"scriptPubkey")) != 0) && (hexstr= jstr(obj,"hex")) != 0 )
{
spendlen = (int32_t)strlen(hexstr) >> 1;
decode_hex(spendscript,spendlen,hexstr);
}
if ( (unspentind= iguana_unspentindfind(coin,coinaddr,spendscript,&spendlen,&satoshis,&height,txid,vout,coin->bundlescount-1)) > 0 )
{
printf("[%d] unspentind.%d (%s) spendlen.%d %.8f\n",height/coin->chain->bundlesize,unspentind,coinaddr,spendlen,dstr(satoshis));
if ( coinaddr[0] != 0 && (waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) != 0 )
{
init_hexbytes_noT(pubkeystr,waddr->pubkey,bitcoin_pubkeylen(waddr->pubkey));
jaddistr(pubkeys,pubkeystr);
}
}
if ( spendscript != 0 && spendlen > 0 )
{
init_hexbytes_noT(scriptstr,spendscript,spendlen);
jaddstr(newvin,"scriptPub",scriptstr);
}
if ( (str= jstr(item,"redeemScript")) != 0 )
{
p2shlen = (int32_t)strlen(str) >> 1;
decode_hex(redeemscript,p2shlen,str);
init_hexbytes_noT(scriptstr,redeemscript,p2shlen);
jaddstr(newvin,"redeemScript",scriptstr);
}
vout = jint(item,"vout");
if ( jobj(item,"sequenceid") != 0 )
sequenceid = juint(item,"sequenceid");
if ( jobj(item,"sequence") != 0 )
sequenceid = juint(item,"sequence");
else sequenceid = 0xffffffff;
txid = jbits256(item,"txid");
jaddnum(newvin,"sequence",sequenceid);
bitcoin_addinput(coin,txobj,txid,vout,sequenceid,spendscript,spendlen,redeemscript,p2shlen,0,0);
jadd(newvin,"pubkeys",pubkeys);
jaddi(newvins,newvin);
}
}
return(newvins);
}
ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime)
{
bits256 txid; int32_t offset,spendlen=0,n; uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; uint64_t satoshis; char *hexstr,*field,*txstr; cJSON *txobj,*item,*obj,*retjson = cJSON_CreateObject();
if ( coin != 0 && (txobj= bitcoin_createtx(coin,locktime)) != 0 )
{
iguana_createvins(myinfo,coin,txobj,vins);
if ( (n= cJSON_GetArraySize(vouts)) > 0 )
{
item = vouts->child;

21
iguana/iguana_scripts.c

@ -407,7 +407,7 @@ int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int3
int32_t bitcoin_scriptsig(struct iguana_info *coin,uint8_t *script,int32_t n,const struct vin_info *vp,struct iguana_msgtx *msgtx)
{
int32_t i,siglen;
int32_t i,siglen,plen;
if ( vp->N > 1 )
script[n++] = SCRIPT_OP_NOP;
for (i=0; i<vp->N; i++)
@ -418,6 +418,11 @@ int32_t bitcoin_scriptsig(struct iguana_info *coin,uint8_t *script,int32_t n,con
memcpy(&script[n],vp->signers[i].sig,siglen), n += siglen;
}
}
if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) > 0 && vp->type == IGUANA_SCRIPT_76A988AC )
{
script[n++] = plen;
memcpy(&script[n],vp->signers[0].pubkey,plen), n += plen;
}
if ( vp->type == IGUANA_SCRIPT_P2SH )
{
printf("add p2sh script to sig\n");
@ -448,17 +453,22 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd
return(n);
}
uint8_t iguana_addrtype(struct iguana_info *coin,uint8_t script_type)
{
if ( script_type == IGUANA_SCRIPT_76A988AC || script_type == IGUANA_SCRIPT_AC || script_type == IGUANA_SCRIPT_76AC )
return(coin->chain->pubtype);
else return(coin->chain->p2shtype);
}
int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi)
{
uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t plen,i,m,n,flag = 0,scriptlen = 0;
m = n = 0;
if ( asmstr != 0 )
asmstr[0] = 0;
addrtype = iguana_addrtype(coin,type);
if ( type == IGUANA_SCRIPT_76A988AC || type == IGUANA_SCRIPT_AC || type == IGUANA_SCRIPT_76AC || type == IGUANA_SCRIPT_P2SH )
{
if ( type == IGUANA_SCRIPT_P2SH )
addrtype = coin->chain->p2shtype;
else addrtype = coin->chain->pubtype;
init_hexbytes_noT(rmd160str,rmd160,20);
bitcoin_address(coinaddr,addrtype,rmd160,20);
}
@ -499,6 +509,7 @@ int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char
case IGUANA_SCRIPT_OPRETURN:
if ( asmstr != 0 )
strcpy(asmstr,"OP_RETURN ");
bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
flag++;
break;
case IGUANA_SCRIPT_3of3: m = 3, n = 3; break;
@ -511,11 +522,13 @@ int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char
case IGUANA_SCRIPT_DATA:
if ( asmstr != 0 )
strcpy(asmstr,"DATA ONLY");
bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
flag++;
break;
case IGUANA_SCRIPT_STRANGE:
if ( asmstr != 0 )
strcpy(asmstr,"STRANGE SCRIPT ");
bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
flag++;
break;
default: break;//printf("unexpected script type.%d\n",type); break;

281
iguana/iguana_sign.c

@ -19,6 +19,7 @@
int32_t iguana_vinparse(struct iguana_info *coin,int32_t rwflag,uint8_t *serialized,struct iguana_msgvin *msg)
{
//int32_t sighash,i,plen,len = 0; struct vin_info V; uint32_t sigsize,pubkeysize,p2shsize,suffixlen;
int32_t len = 0;
len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->prev_hash),msg->prev_hash.bytes);
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->prev_vout),&msg->prev_vout);
@ -33,13 +34,51 @@ int32_t iguana_vinparse(struct iguana_info *coin,int32_t rwflag,uint8_t *seriali
msg->vinscript = &serialized[len];
len += msg->scriptlen;
}
else
else if ( msg->vinscript != 0 && msg->scriptlen > 0 )
{
if ( msg->scriptlen > 0 )
/*if ( msg->p2shlen > 0 || msg->pubkeys != 0 )
{
memcpy(&serialized[len],msg->vinscript,msg->scriptlen);
len += msg->scriptlen;
sighash = iguana_vinscriptparse(coin,&V,&sigsize,&pubkeysize,&p2shsize,&suffixlen,msg->vinscript,msg->scriptlen);
if ( V.numsigs > 0 )
{
for (i=0; i<V.numsigs; i++)
{
serialized[len++] = V.signers[i].siglen;
memcpy(&serialized[len],V.signers[i].sig,V.signers[i].siglen);
}
}
if ( msg->pubkeys != 0 && msg->numpubkeys > 0 )
{
for (i=0; i<msg->numpubkeys; i++)
{
if ( (plen= bitcoin_pubkeylen(V.signers[i].pubkey)) > 0 )
{
serialized[len++] = plen;
memcpy(&serialized[len],V.signers[i].pubkey,plen), len += plen;
} else serialized[len++] = 0;
}
}
if ( msg->p2shlen > 0 && msg->redeemscript != 0 )
{
if ( msg->p2shlen < 76 )
serialized[len++] = msg->p2shlen;
else if ( msg->p2shlen <= 0xff )
{
serialized[len++] = 0x4c;
serialized[len++] = msg->p2shlen;
}
else if ( msg->p2shlen <= 0xffff )
{
serialized[len++] = 0x4d;
serialized[len++] = (msg->p2shlen & 0xff);
serialized[len++] = ((msg->p2shlen >> 8) & 0xff);
} else return(-1);
memcpy(&serialized[len],msg->redeemscript,msg->p2shlen), len += plen;
}
if ( suffixlen > 0 )
memcpy(&serialized[len],&msg->vinscript[msg->scriptlen - suffixlen],suffixlen), len += suffixlen;
} else */
memcpy(&serialized[len],msg->vinscript,msg->scriptlen), len += msg->scriptlen;
}
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence);
if ( 0 )
@ -119,6 +158,19 @@ void iguana_addscript(struct iguana_info *coin,cJSON *dest,uint8_t *script,int32
}
}
cJSON *iguana_pubkeysjson(uint8_t *pubkeyptrs[],int32_t numpubkeys)
{
int32_t i,plen; char pubkeystr[256]; cJSON *pubkeysjson = cJSON_CreateArray();
for (i=0; i<numpubkeys; i++)
{
if ( pubkeyptrs != 0 && (plen= bitcoin_pubkeylen(pubkeyptrs[i])) > 0 )
init_hexbytes_noT(pubkeystr,pubkeyptrs[i],plen);
else pubkeystr[0] = 0;
jaddistr(pubkeysjson,pubkeystr);
}
return(pubkeysjson);
}
cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin)
{
char str[65]; int32_t vout; cJSON *json = cJSON_CreateObject();
@ -133,16 +185,19 @@ cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin)
if ( vin->scriptlen > 0 )
iguana_addscript(coin,json,vin->vinscript,vin->scriptlen,"scriptSig");
if ( vin->spendlen > 0 )
iguana_addscript(coin,json,vin->spendscript,vin->spendlen,"scriptPub");
iguana_addscript(coin,json,vin->spendscript,vin->spendlen,"scriptPubKey");
if ( vin->p2shlen > 0 )
iguana_addscript(coin,json,vin->redeemscript,vin->p2shlen,"redeemScript");
if ( vin->pubkeys != 0 && vin->numpubkeys > 0 )
jadd(json,"pubkeys",iguana_pubkeysjson(vin->pubkeys,vin->numpubkeys));
}
return(json);
}
int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgvin *vin,cJSON *vinobj)
{
int32_t n,len = 0; char *hexstr,*redeemstr = 0,*spendstr = 0; cJSON *scriptjson,*pubkeys;
int32_t i,n,plen,len = 0; char *pubkeystr,*hexstr = 0,*redeemstr = 0,*spendstr = 0; cJSON *scriptjson = 0,*obj,*pubkeysjson = 0;
//printf("PARSEVIN.(%s)\n",jprint(vinobj,0));
memset(vin,0,sizeof(*vin));
vin->prev_vout = -1;
vin->sequence = juint(vinobj,"sequence");
@ -152,10 +207,44 @@ int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t
vin->prev_vout = jint(vinobj,"vout");
if ( (scriptjson= jobj(vinobj,"scriptSig")) != 0 )
hexstr = jstr(scriptjson,"hex");
if ( (scriptjson= jobj(vinobj,"scriptPub")) != 0 )
spendstr = jstr(scriptjson,"hex");
redeemstr = jstr(vinobj,"redeemScript");
pubkeys = jarray(&n,vinobj,"pubkeys");
if ( ((spendstr= jstr(vinobj,"scriptPub")) == 0 && (spendstr= jstr(vinobj,"scriptPubkey")) == 0) || is_hexstr(spendstr,(int32_t)strlen(spendstr)) <= 0 )
{
if ( (obj= jobj(vinobj,"scriptPub")) != 0 || (obj= jobj(vinobj,"scriptPubkey")) != 0 )
spendstr = jstr(obj,"hex");
}
if ( (redeemstr= jstr(vinobj,"redeemScript")) == 0 || is_hexstr(redeemstr,(int32_t)strlen(redeemstr)) <= 0 )
{
if ( (obj= jobj(vinobj,"redeemScript")) != 0 )
redeemstr = jstr(obj,"hex");
}
/*if ( (addrs= jarray(&n,vinobj,"addresses")) != 0 )
{
for (i=0; i<n; i++)
{
V.signers[i].coinaddr[0] = 0;
if ( (coinaddr= jstr(jitem(addrs,i),0)) != 0 )
safecopy(V.signers[i].coinaddr,coinaddr,sizeof(V.signers[i].coinaddr));
}
}*/
if ( (pubkeysjson= jarray(&n,vinobj,"pubkeys")) != 0 )
{
for (i=0; i<n; i++)
{
vin->pubkeys[i] = 0;
if ( (pubkeystr= jstr(jitem(pubkeysjson,i),0)) != 0 && (len= (int32_t)strlen(pubkeystr) >> 1) > 0 )
{
decode_hex(serialized,len,pubkeystr);
if ( (plen= bitcoin_pubkeylen(serialized)) == len )
{
vin->pubkeys[i] = serialized;
//if ( V.signers[i].coinaddr[0] == 0 )
// bitcoin_address(V.signers[i].coinaddr,coin->chain->pubtype,serialized,len);
serialized = &serialized[len];
}
}
}
vin->numpubkeys = n;
}
}
if ( hexstr != 0 )
{
@ -475,7 +564,7 @@ cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *payments
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys)
{
cJSON *item,*vins,*pubkeysjson; char p2shscriptstr[IGUANA_MAXSCRIPTSIZE*2+1],pubkeystr[136]; int32_t i,plen; uint8_t *script,len;
cJSON *item,*vins; char p2shscriptstr[IGUANA_MAXSCRIPTSIZE*2+1]; uint8_t *script,len;
vins = jduplicate(jobj(txobj,"vin"));
jdelete(txobj,"vin");
item = cJSON_CreateObject();
@ -493,23 +582,13 @@ cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32
if ( script != 0 && numpubkeys == 0 )
jadd(item,"pubkeys",iguana_scriptpubkeys(coin,script,len,txid,vout,sequenceid));
else if ( pubkeys != 0 && numpubkeys > 0 )
{
pubkeysjson = cJSON_CreateArray();
for (i=0; i<numpubkeys; i++)
{
if ( pubkeys[i] != 0 && (plen= bitcoin_pubkeylen(pubkeys[i])) > 0 )
init_hexbytes_noT(pubkeystr,pubkeys[i],plen);
else pubkeystr[0] = 0;
jaddistr(pubkeysjson,pubkeystr);
}
jadd(item,"pubkeys",pubkeysjson);
}
jadd(item,"pubkeys",iguana_pubkeysjson(pubkeys,numpubkeys));
jaddbits256(item,"txid",txid);
jaddnum(item,"vout",vout);
jaddnum(item,"sequence",sequenceid);
jaddi(vins,item);
jadd(txobj,"vin",vins);
printf("addvin -> (%s)\n",jprint(txobj,0));
//printf("addvin -> (%s)\n",jprint(txobj,0));
return(txobj);
}
@ -541,7 +620,6 @@ cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_ms
decode_hex(serialized,len,txbytes);
vpnstr[0] = 0;
memset(txidp,0,sizeof(*txidp));
printf("B bitcoin_hex2json len.%d\n",len);
if ( (n= iguana_rwmsgtx(coin,0,txobj,serialized,len + 32768,msgtx,txidp,vpnstr)) <= 0 )
{
printf("error from rwmsgtx\n");
@ -552,18 +630,17 @@ cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_ms
return(txobj);
}
int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t sighashsingle)
int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t numinputs,int32_t sighashsingle)
{
bits256 txid,sigtxid,revsigtxid; uint8_t *sig,*pubkey; struct vin_info *vp;
char txidstr[128],bigstr[2560],coinaddr[64],vpnstr[64],str[65]; uint32_t suffixlen,sigsize,pubkeysize;
int32_t n2,i,j,k,plen,vini=0,flag,numvins,hashtype,retval,siglen,asmtype,numvouts;
int32_t savelen,n2,i,j,k,plen,vini=0,flag,hashtype,retval,siglen,asmtype,numvouts;
numvouts = msgtx->tx_out;
vpnstr[0] = 0;
*signedtx = 0;
memset(signedtxidp,0,sizeof(*signedtxidp));
numvins = msgtx->tx_in;
retval = -numvins;
for (vini=0; vini<numvins; vini++)
retval = -numinputs;
for (vini=0; vini<numinputs; vini++)
{
//saveinput = msgtx->vins[vini].vinscript;
vp = &V[vini];
@ -574,11 +651,14 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
for (k=0; k<2; k++)
{
asmtype = (k == 0) ? IGUANA_SCRIPT_76A988AC : IGUANA_SCRIPT_76AC;
savelen = vp->spendlen;
if ( bitcoin_scriptget(coin,&hashtype,&sigsize,&pubkeysize,&suffixlen,vp,msgtx->vins[vini].vinscript,msgtx->vins[vini].scriptlen,asmtype) < 0 )
{
printf("cant get script for (%s).v%d\n",bits256_str(str,vp->vin.prev_hash),vp->vin.prev_vout);
continue;
}
if ( vp->spendlen == 0 )
vp->spendlen = savelen;
if ( sighashsingle != 0 && vini == 0 )
{
msgtx->tx_out = 1;
@ -587,6 +667,7 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
msgtx->vins[vini].spendscript = vp->spendscript;
msgtx->vins[vini].spendlen = vp->spendlen;
msgtx->vins[vini].sequence = vp->sequence;
printf("spendscript.[%d]\n",vp->spendlen);
for (j=0; j<vp->N; j++)
{
pubkey = vp->signers[j].pubkey;
@ -623,7 +704,8 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
msgtx->vins[vini].scriptlen = bitcoin_scriptsig(coin,msgtx->vins[vini].vinscript,0,(const struct vin_info *)vp,msgtx);
//for (i=0; i<siglen; i++)
// printf("%02x",sig[i]);
//printf(" SIGNEDTX.[%02x] plen.%d siglen.%d\n",sig[siglen-1],plen,siglen);
// s2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1;
printf(" SIGNEDTX.[%02x] plen.%d siglen.%d\n",sig[siglen-1],plen,siglen);
}
if ( bitcoin_verify(sig,siglen,sigtxid.bytes,sizeof(sigtxid),vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 )
{
@ -638,7 +720,7 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
cJSON *txobj = cJSON_CreateObject();
*signedtx = iguana_rawtxbytes(coin,txobj,msgtx);
*signedtxidp = msgtx->txid;
//printf("SIG.%d VERIFIED %s (%s)\n",vini,*signedtx,jprint(txobj,1));
printf("SIG.%d VERIFIED \n",vini);//%s (%s)\n",vini,*signedtx,jprint(txobj,1));
flag = 1;
break;
}
@ -656,9 +738,9 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
return(retval);
}
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V)
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V,int32_t numinputs)
{
int32_t len,maxsize,numvins,retval = -1; uint8_t *serialized,*serialized2;
int32_t len,maxsize,retval = -1; uint8_t *serialized,*serialized2;
struct iguana_msgtx msgtx; bits256 txid; char vpnstr[64];
len = (int32_t)strlen(rawtxstr);
maxsize = len + 32768;
@ -669,8 +751,7 @@ int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **si
memset(&msgtx,0,sizeof(msgtx));
if ( iguana_rwmsgtx(coin,0,0,serialized,maxsize,&msgtx,&txid,vpnstr) > 0 )
{
numvins = msgtx.tx_in;
if ( bitcoin_verifyvins(coin,signedtxidp,signedtx,&msgtx,serialized2,maxsize,V,0) == 0 )
if ( bitcoin_verifyvins(coin,signedtxidp,signedtx,&msgtx,serialized2,maxsize,V,numinputs,0) == 0 )
retval = 0;
else printf("bitcoin_verifytx: bitcoin_verifyvins error\n");
} else printf("bitcoin_verifytx: error iguana_rwmsgtx\n");
@ -678,40 +759,101 @@ int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **si
return(retval);
}
cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj)
cJSON *iguana_signtx(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj,cJSON *vins)
{
int32_t i,j; char *rawtxstr; struct vin_info V; bits256 txid;
for (i=0; i<spend->numinputs; i++) // N times less efficient, but for small number of inputs ok
{
int32_t i,j,m,n,plen; char *rawtxstr,*pubkeystr,*spendstr; struct vin_info *V,*vp; bits256 txid; struct iguana_waccount *wacct; struct iguana_waddress *waddr; cJSON *vitem,*vinsobj,*pubkeys;
V = calloc(spend->numinputs,sizeof(*V));
if ( *signedtxp != 0 )
{
if ( txobj != 0 )
free_json(txobj);
txobj = bitcoin_hex2json(coin,&txid,0,*signedtxp);
if ( vins != 0 )
{
if ( jobj(txobj,"vin") != 0 )
jdelete(txobj,"vin");
jadd(txobj,"vin",iguana_createvins(myinfo,coin,txobj,vins));
}
//printf("bitcoin_hex2json (%s)\n",jprint(txobj,0));
free(*signedtxp);
}
vinsobj = jarray(&n,txobj,"vin");
for (i=0; i<spend->numinputs; i++) // N times less efficient, but for small number of inputs ok
{
vp = &V[i];
if ( i < n )
{
if ( (vitem= jitem(vinsobj,i)) != 0 && ((spendstr= jstr(vitem,"scriptPub")) != 0 || (spendstr= jstr(vitem,"scriptPubKey")) != 0) )
{
vp->spendlen = (int32_t)strlen(spendstr) >> 1;
decode_hex(vp->spendscript,vp->spendlen,spendstr);
} else spendstr = 0;
}
else vitem = 0;
vp->N = vp->M = 1;
if ( (rawtxstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 )
{
memset(&V,0,sizeof(V));
for (j=0; j<sizeof(spend->inputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++)
{
if ( bits256_nonz(spend->inputs[i].privkeys[j]) != 0 )
V.signers[j].privkey = spend->inputs[i].privkeys[j];
{
vp->signers[j].privkey = spend->inputs[i].privkeys[j];
bitcoin_pubkey33(vp->signers[j].pubkey,vp->signers[j].privkey);
}
else
{
vp->signers[j].pubkey[0] = 0;
break;
}
}
if ( vitem != 0 && (pubkeys= jarray(&m,vitem,"pubkeys")) != 0 )//spend->inputs[i].numpubkeys > 0 )
{
for (j=0; j<sizeof(spend->inputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++)
{
if ( j < m && (pubkeystr= jstr(jitem(pubkeys,j),0)) != 0 && is_hexstr(pubkeystr,(int32_t)strlen(pubkeystr)) > 0 )
decode_hex(vp->signers[j].pubkey,(int32_t)strlen(pubkeystr)>>1,pubkeystr);
else if ( (plen= bitcoin_pubkeylen(spend->inputs[i].pubkeys[j])) > 0 )
memcpy(vp->signers[j].pubkey,spend->inputs[i].pubkeys[j],plen);
}
}
if ( spend->inputs[i].spendlen > 0 )
/*if ( spend->inputs[i].spendlen > 0 )
{
memcpy(V.spendscript,spend->inputs[i].spendscript,spend->inputs[i].spendlen);
V.spendlen = spend->inputs[i].spendlen;
memcpy(vp->spendscript,spend->inputs[i].spendscript,spend->inputs[i].spendlen);
vp->spendlen = spend->inputs[i].spendlen;
}*/
if ( spend->inputs[i].p2shscript != 0 && spend->inputs[i].p2shlen > 0 )
{
memcpy(vp->p2shscript,spend->inputs[i].p2shscript,spend->inputs[i].p2shlen);
vp->p2shlen = spend->inputs[i].p2shlen;
}
for (j=0; j<sizeof(spend->inputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++)
{
if ( vp->signers[j].coinaddr[0] == 0 && (plen= bitcoin_pubkeylen(spend->inputs[i].pubkeys[j])) > 0 )
{
bitcoin_address(vp->signers[j].coinaddr,coin->chain->pubtype,spend->inputs[i].pubkeys[j],plen);
}
}
if ( myinfo->expiration != 0 )
{
for (j=0; j<sizeof(spend->inputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++)
{
if ( bits256_nonz(vp->signers[j].privkey) == 0 && vp->signers[j].coinaddr[0] != 0 )
{
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,vp->signers[j].coinaddr)) != 0 )
vp->signers[j].privkey = waddr->privkey;
}
}
V.sequence = spend->inputs[i].sequence;
}
vp->sequence = spend->inputs[i].sequence;
//printf("json2hex.(%s)\n",rawtxstr);
bitcoin_verifytx(coin,txidp,signedtxp,rawtxstr,&V);
}
}
bitcoin_verifytx(coin,txidp,signedtxp,rawtxstr,V,spend->numinputs);
//printf("json2hex.(%s)\n",rawtxstr);
free(rawtxstr);
} else break;
}
if ( *signedtxp != 0 && i != spend->numinputs )
free(*signedtxp), *signedtxp = 0;
free(V);
return(txobj);
}
@ -746,6 +888,10 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount
char msigaddr[64],*retstr; cJSON *retjson,*txobj; struct iguana_info *active;
bits256 signedtxid; char *signedtx;
struct iguana_msgtx msgtx;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
if ( (active= iguana_coinfind(activecoin)) == 0 )
return(clonestr("{\"error\":\"activecoin isnt active\"}"));
if ( M > N || N > 3 )
@ -783,7 +929,7 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount
bitcoin_addinput(active,txobj,vintxid,vinvout,0xffffffff,spendscript,spendlen,V.p2shscript,V.p2shlen,pubkeyptrs,N);
bitcoin_address(msigaddr,active->chain->p2shtype,V.p2shscript,V.p2shlen);
retjson = cJSON_CreateObject();
if ( bitcoin_verifyvins(active,&signedtxid,&signedtx,&msgtx,serialized,sizeof(serialized),&V,0) == 0 )
if ( bitcoin_verifyvins(active,&signedtxid,&signedtx,&msgtx,serialized,sizeof(serialized),&V,1,0) == 0 )
{
jaddstr(retjson,"result","msigtx");
if ( signedtx != 0 )
@ -796,7 +942,11 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount
STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighash)
{
bits256 txid; char *privkeystr,*signedtx = 0; bits256 privkey; int32_t i,n,numinputs = 1; struct bitcoin_spend *spend; cJSON *txobj=0,*item,*retjson = cJSON_CreateObject();
bits256 txid; uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char *privkeystr,coinaddr[128],*signedtx = 0; bits256 privkey; int32_t i,n,numinputs = 1; struct bitcoin_spend *spend; cJSON *txobj=0,*item,*retjson = cJSON_CreateObject();
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
//printf("rawtx.(%s) vins.(%s) privkeys.(%s) sighash.(%s)\n",rawtx,jprint(vins,0),jprint(privkeys,0),sighash);
if ( sighash == 0 || sighash[0] == 0 )
sighash = "ALL";
@ -804,7 +954,6 @@ STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighas
jaddstr(retjson,"error","only sighash all supported for now");
else
{
// need to mix and match privkeys with inputs[i]
signedtx = clonestr(rawtx);
if ( (numinputs= cJSON_GetArraySize(vins)) > 0 && (n= cJSON_GetArraySize(privkeys)) > 0 )
{
@ -815,15 +964,35 @@ STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighas
item = jitem(privkeys,i);
privkeystr = jstr(item,0);
privkey = iguana_str2priv(myinfo,coin,privkeystr);
spend->inputs[i].sequence = 0xffffffff;
spend->inputs[i].privkeys[0] = privkey;
if ( bits256_nonz(privkey) != 0 )
{
spend->inputs[0].privkeys[i] = privkey;
//if ( i < numinputs )
// spend->inputs[i].privkeys[0] = privkey;
char str2[65]; printf("privkey.%s <- %s\n",bits256_str(str2,privkey),privkeystr);
bitcoin_pubkey33(pubkey33,privkey);
memcpy(spend->inputs[i].pubkeys[0],pubkey33,33);
bitcoin_address(coinaddr,coin->chain->pubtype,pubkey33,33);
if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) )
{
if ( waddr == 0 )
{
memset(&addr,0,sizeof(addr));
iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,&addr,privkey);
if ( (wacct= iguana_waccountfind(myinfo,coin,"default")) != 0 )
waddr = iguana_waddressadd(myinfo,coin,wacct,&addr,0);
}
if ( waddr != 0 )
{
waddr->privkey = privkey;
if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->chain->wiftype) > 0 )
{
waddr->wiftype = coin->chain->wiftype;
waddr->addrtype = coin->chain->pubtype;
}
}
}
}
}
txobj = iguana_signtx(coin,&txid,&signedtx,spend,txobj);
txobj = iguana_signtx(myinfo,coin,&txid,&signedtx,spend,txobj,vins);
free(spend);
free_json(txobj);
if ( signedtx != 0 )

2
iguana/iguana_spendvectors.c

@ -200,7 +200,7 @@ struct iguana_bundle *iguana_fastexternalspent(struct iguana_info *coin,bits256
char str[65]; //double duration,startmillis = OS_milliseconds();
X = (void *)(long)((long)rdata + rdata->Xoffset);
*prevhashp = prev_hash = X[ind];
if ( (unspentind= iguana_unspentindfind(coin,&height,prev_hash,prev_vout,spent_hdrsi-1)) != 0 )
if ( (unspentind= iguana_unspentindfind(coin,0,0,0,0,&height,prev_hash,prev_vout,spent_hdrsi-1)) != 0 )
//if ( (firstvout= iguana_txidfastfind(coin,&height,prev_hash,spent_hdrsi-1)) >= 0 )
{
/*duration = (OS_milliseconds() - startmillis);

12
iguana/iguana_txidfind.c

@ -391,18 +391,6 @@ int32_t iguana_txidfastfind(struct iguana_info *coin,int32_t *heightp,bits256 tx
return(-1);
}
int32_t iguana_unspentindfind(struct iguana_info *coin,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi)
{
struct iguana_txid *tp,TX; int32_t firstvout;
if ( coin->fastfind != 0 && (firstvout= iguana_txidfastfind(coin,heightp,txid,lasthdrsi)) >= 0 )
{
return(firstvout + vout);
}
if ( (tp= iguana_txidfind(coin,heightp,&TX,txid,lasthdrsi)) != 0 )
return(tp->firstvout + vout);
return(-1);
}
int32_t iguana_fastfindadd(struct iguana_info *coin,bits256 txid,int32_t height,uint32_t firstvout)
{
FILE *fp;

35
iguana/iguana_unspents.c

@ -20,6 +20,38 @@
#include "iguana777.h"
#include "exchanges/bitcoin.h"
int32_t iguana_unspentindfind(struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *spendlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi)
{
struct iguana_txid *tp,TX; struct iguana_pkhash *P; struct iguana_unspent *U; struct iguana_bundle *bp; struct iguana_ramchaindata *rdata; int64_t RTspend; int32_t pkind,hdrsi,firstvout,spentheight,unspentind = -1;
if ( valuep != 0 )
*valuep = 0;
if ( coinaddr != 0 )
coinaddr[0] = 0;
if ( coin->fastfind != 0 && (firstvout= iguana_txidfastfind(coin,heightp,txid,lasthdrsi)) >= 0 )
unspentind = (firstvout + vout);
else if ( (tp= iguana_txidfind(coin,heightp,&TX,txid,lasthdrsi)) != 0 )
unspentind = (tp->firstvout + vout);
if ( coinaddr != 0 && unspentind > 0 && (hdrsi= *heightp/coin->chain->bundlesize) >= 0 && hdrsi < coin->bundlescount && (bp= coin->bundles[hdrsi]) != 0 && (rdata= bp->ramchain.H.data) != 0 && unspentind < rdata->numunspents )
{
U = (void *)(long)((long)rdata + rdata->Uoffset);
P = (void *)(long)((long)rdata + rdata->Poffset);
pkind = U[unspentind].pkind;
if ( pkind > 0 && pkind < rdata->numpkinds )
{
RTspend = 0;
if ( iguana_spentflag(coin,&RTspend,&spentheight,bp == coin->current ? &coin->RTramchain : &bp->ramchain,bp->hdrsi,unspentind,0,1,coin->longestchain,U[unspentind].value) == 0 )
{
if ( valuep != 0 )
*valuep = U[unspentind].value;
bitcoin_address(coinaddr,iguana_addrtype(coin,U[unspentind].type),P[pkind].rmd160,sizeof(P[pkind].rmd160));
if ( spendscript != 0 && spendlenp != 0 )
*spendlenp = iguana_voutscript(coin,bp,spendscript,0,&U[unspentind],&P[pkind],1);
}
}
}
return(unspentind);
}
cJSON *ramchain_unspentjson(struct iguana_unspent *up,uint32_t unspentind)
{
cJSON *item = cJSON_CreateObject();
@ -58,7 +90,7 @@ cJSON *iguana_unspentjson(struct supernet_info *myinfo,struct iguana_info *coin,
if ( iguana_scriptget(coin,scriptstr,asmstr,sizeof(scriptstr),hdrsi,unspentind,T[up->txidind].txid,up->vout,rmd160,up->type,pubkey33) != 0 )
jaddstr(item,"scriptPubKey",scriptstr);
jaddnum(item,"amount",dstr(up->value));
if ( (checkind= iguana_unspentindfind(coin,&height,T[up->txidind].txid,up->vout,coin->bundlescount-1)) != 0 )
if ( (checkind= iguana_unspentindfind(coin,0,0,0,0,&height,T[up->txidind].txid,up->vout,coin->bundlescount-1)) != 0 )
{
jaddnum(item,"confirmations",coin->blocks.hwmchain.height - height + 1);
jaddnum(item,"checkind",checkind);
@ -343,4 +375,3 @@ int32_t iguana_unspentslists(struct supernet_info *myinfo,struct iguana_info *co
return(num);
}

6
iguana/iguana_volatiles.c

@ -149,7 +149,11 @@ int32_t iguana_spentflag(struct iguana_info *coin,int64_t *RTspendp,int32_t *spe
if ( (confs= coin->blocks.hwmchain.height - utxo.fromheight) >= minconf && confs < maxconf && (height == 0 || utxo.fromheight < height) )
{
(*RTspendp) += RTspend;
return(utxo.spentflag);
if ( utxo.spentflag != 0 )
return(1);
else if ( utxo.lockedflag != 0 )
return(-1);
else return(0);
}
return(0);
}

52
iguana/iguana_wallet.c

@ -50,9 +50,36 @@ struct iguana_waddress *iguana_waddressalloc(uint8_t addrtype,char *symbol,char
return(waddr);
}
struct iguana_waccount *iguana_waccountfind(struct supernet_info *myinfo,struct iguana_info *coin,char *account)
{
struct iguana_waccount *wacct;
HASH_FIND(hh,myinfo->wallet,account,strlen(account)+1,wacct);
//printf("waccountfind.(%s) -> wacct.%p\n",account,wacct);
return(wacct);
}
struct iguana_waccount *iguana_waccountcreate(struct supernet_info *myinfo,struct iguana_info *coin,char *account)
{
struct iguana_waccount *wacct,*ptr; int32_t len = (int32_t)strlen(account)+1;
HASH_FIND(hh,myinfo->wallet,account,len,wacct);
if ( wacct == 0 )
{
wacct = mycalloc('w',1,sizeof(*wacct));
strcpy(wacct->account,account);
HASH_ADD_KEYPTR(hh,myinfo->wallet,wacct->account,len,wacct);
//printf("waccountcreate.(%s) -> wacct.%p\n",account,wacct);
myinfo->dirty = (uint32_t)time(NULL);
if ( (ptr= iguana_waccountfind(myinfo,coin,account)) != wacct )
printf("iguana_waccountcreate verify error %p vs %p\n",ptr,wacct);
}
return(wacct);
}
struct iguana_waddress *iguana_waddresscreate(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr,char *redeemScript)
{
struct iguana_waddress *waddr,*ptr; int32_t len = (int32_t)strlen(coinaddr)+1;
if ( wacct == 0 )
wacct = iguana_waccountcreate(myinfo,coin,"");
HASH_FIND(hh,wacct->waddr,coinaddr,len,waddr);
if ( waddr == 0 )
{
@ -156,31 +183,6 @@ struct iguana_waddress *iguana_waddresssearch(struct supernet_info *myinfo,struc
return(0);
}
struct iguana_waccount *iguana_waccountfind(struct supernet_info *myinfo,struct iguana_info *coin,char *account)
{
struct iguana_waccount *wacct;
HASH_FIND(hh,myinfo->wallet,account,strlen(account)+1,wacct);
//printf("waccountfind.(%s) -> wacct.%p\n",account,wacct);
return(wacct);
}
struct iguana_waccount *iguana_waccountcreate(struct supernet_info *myinfo,struct iguana_info *coin,char *account)
{
struct iguana_waccount *wacct,*ptr; int32_t len = (int32_t)strlen(account)+1;
HASH_FIND(hh,myinfo->wallet,account,len,wacct);
if ( wacct == 0 )
{
wacct = mycalloc('w',1,sizeof(*wacct));
strcpy(wacct->account,account);
HASH_ADD_KEYPTR(hh,myinfo->wallet,wacct->account,len,wacct);
//printf("waccountcreate.(%s) -> wacct.%p\n",account,wacct);
myinfo->dirty = (uint32_t)time(NULL);
if ( (ptr= iguana_waccountfind(myinfo,coin,account)) != wacct )
printf("iguana_waccountcreate verify error %p vs %p\n",ptr,wacct);
}
return(wacct);
}
struct iguana_waddress *iguana_waddresscalc(uint8_t pubtype,uint8_t wiftype,struct iguana_waddress *addr,bits256 privkey)
{
addr->privkey = privkey;

8
iguana/swaps/iguana_BTCswap.c

@ -125,7 +125,7 @@ struct bitcoin_statetx *instantdex_feetx(struct supernet_info *myinfo,struct ins
len = bitcoin_standardspend(paymentscript,0,spend->change160);
bitcoin_addoutput(coin,txobj,paymentscript,len,spend->change);
}
txobj = iguana_signtx(coin,&txid,&feetx,spend,txobj);
txobj = iguana_signtx(myinfo,coin,&txid,&feetx,spend,txobj,0);
if ( feetx != 0 )
{
ptr = calloc(1,sizeof(*ptr) + strlen(feetx) + 1);
@ -211,7 +211,7 @@ struct bitcoin_statetx *instantdex_bobtx(struct supernet_info *myinfo,struct igu
n = instantdex_bobscript(script,0,&secretstart,locktime,pub1,secret,pub2);
bitcoin_addoutput(coin,txobj,script,n,amount + depositflag*insurance*100);
iguana_addinputs(coin,spend,txobj,0xffffffff);
txobj = iguana_signtx(coin,&txid,&signedtx,spend,txobj);
txobj = iguana_signtx(myinfo,coin,&txid,&signedtx,spend,txobj,0);
if ( signedtx != 0 )
{
ptr = calloc(1,sizeof(*ptr) + strlen(signedtx) + 1);
@ -311,7 +311,7 @@ struct bitcoin_statetx *instantdex_alicetx(struct supernet_info *myinfo,struct i
n = instantdex_alicescript(script,0,msigaddr,altcoin->chain->p2shtype,pubAm,pubBn);
bitcoin_addoutput(altcoin,txobj,script,n,amount);
iguana_addinputs(altcoin,spend,txobj,0xffffffff);
txobj = iguana_signtx(altcoin,&txid,&signedtx,spend,txobj);
txobj = iguana_signtx(myinfo,altcoin,&txid,&signedtx,spend,txobj,0);
if ( signedtx != 0 )
{
printf("alice payment.%s\n",signedtx);
@ -613,7 +613,7 @@ char *BTC_txconfirmed(struct supernet_info *myinfo,struct iguana_info *coin,stru
*numconfirmsp = -1.;
if ( coin != 0 && *numconfirmsp < 0 )
{
if ( (firstvout= iguana_unspentindfind(coin,&height,txid,0,coin->bundlescount-1)) != 0 && (confs= iguana_numconfs(coin,txid,height)) >= requiredconfs )
if ( (firstvout= iguana_unspentindfind(coin,0,0,0,0,&height,txid,0,coin->bundlescount-1)) != 0 && (confs= iguana_numconfs(coin,txid,height)) >= requiredconfs )
{
*numconfirmsp = confs;
if ( (retstr= instantdex_sendcmd(myinfo,&swap->mine.offer,newjson,virtualevent,myinfo->myaddr.persistent,0,0,0)) != 0 )

2
iguana/tests/createrawtransaction

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"createrawtransaction\",\"params\":[[{\"txid\":\"fe9ba49c411ee7b3ae16f8de6f2e32b4ea469a8ff64766be113817646100bb56\",\"vout\":24}], {\"RV37MfeBD1QTeoLHteab3j4mFVrsSaGMJx\":0.00167}] }"

1
iguana/tests/decoderawtransaction

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"decoderawtransaction\",\"params\":[\"0100000010fd23570156bb006164173811be6647f68f9a46eab4322e6fdef816aeb3e71e419ca49bfe1800000000ffffffff0168b30200000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\"]}"

1
iguana/tests/decoderawtransactionB

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"decoderawtransaction\",\"params\":[\"01000000dc4f24570156bb006164173811be6647f68f9a46eab4322e6fdef816aeb3e71e419ca49bfe180000006a473044022027e0e1983c88832e9adcad681692e905333f32905553bedc6df2fcacc250574d0220259aa91c7fb0378561c37477c2b5e7872b5c9a1daababe087945639fe79593e0012102d14a195654f536df6dfe5a38278d1b470d00f17de78eeb5ce9e9eea9edb2c212ffffffff01588c0200000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\"]}"

2
iguana/tests/getrawtransaction

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"getrawtransaction\",\"params\":[\"fe9ba49c411ee7b3ae16f8de6f2e32b4ea469a8ff64766be113817646100bb56\"]}"

2
iguana/tests/gettransaction

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"gettransaction\",\"params\":[\"fe9ba49c411ee7b3ae16f8de6f2e32b4ea469a8ff64766be113817646100bb56\"]}"

2
iguana/tests/signrawtransaction

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"signrawtransaction\",\"params\":[\"01000000dc4f24570156bb006164173811be6647f68f9a46eab4322e6fdef816aeb3e71e419ca49bfe1800000000ffffffff01588c0200000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\", [{\"txid\":\"fe9ba49c411ee7b3ae16f8de6f2e32b4ea469a8ff64766be113817646100bb56\",\"vout\":24}], [\"UqvuZXEAVXDXJkL4j4Xq6qoMdeJfPF1aNsCzmzfZaQ1ZgBTwfmWn\"], \"ALL\"] }"

1
iguana/tests/txdata

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save