Browse Source

test

release/v0.1
jl777 9 years ago
parent
commit
54d5169d24
  1. 6
      crypto777/m_unix
  2. 0
      deprecated/iguana_html.c
  3. 8
      deprecated/m_unix.crypto777
  4. 184
      deprecated/obsolete.h
  5. 2
      iguana/SuperNET.c
  6. 1020
      iguana/exchanges/bitcoin.c
  7. 5
      iguana/iguana.sources
  8. 19
      iguana/iguana777.h
  9. 29
      iguana/iguana_bundles.c
  10. 672
      iguana/iguana_payments.c
  11. 355
      iguana/iguana_realtime.c
  12. 4
      iguana/iguana_rpc.c
  13. 775
      iguana/iguana_sign.c
  14. 1101
      iguana/iguana_spendvectors.c
  15. 609
      iguana/iguana_txidfind.c
  16. 2839
      iguana/iguana_unspents.c
  17. 342
      iguana/iguana_volatiles.c
  18. 900
      iguana/iguana_wallet.c
  19. 2
      iguana/main.c
  20. 535
      iguana/ramchain_api.c
  21. 10
      iguana/swaps/iguana_BTCswap.c
  22. 1
      iguana/tests/sendmany
  23. 2
      iguana/tests/sendtoaddress
  24. 18
      includes/iguana_apideclares.h

6
crypto777/m_unix

@ -1,8 +1,2 @@
#DNN_DISABLE_GETADDRINFO_A=1 -DNN_USE_LITERAL_IFADDR=1 -DNN_HAVE_STDINT=1 -DNN_HAVE_MSG_CONTROL=1 -DNN_HAVE_SEMAPHORE=1 -DNN_HAVE_POLL=1 -DNN_HAVE_SOCKETPAIR=1 -DNN_USE_POLL=1
#nanosrc/core/global.c nanosrc/core/ep.c nanosrc/core/epbase.c nanosrc/core/pipe.c nanosrc/core/poll.c nanosrc/core/sock.c nanosrc/core/sockbase.c nanosrc/core/symbol.c nanosrc/devices/device.c nanosrc/devices/tcpmuxd.c nanosrc/aio/ctx.c nanosrc/aio/fsm.c nanosrc/aio/poller.c nanosrc/aio/pool.c nanosrc/aio/timer.c nanosrc/aio/usock.c nanosrc/aio/timerset.c nanosrc/aio/worker.c nanosrc/utils/alloc.c nanosrc/utils/atomic.c nanosrc/utils/chunk.c nanosrc/utils/chunkref.c nanosrc/utils/clock.c nanosrc/utils/closefd.c nanosrc/utils/efd.c nanosrc/utils/err.c nanosrc/utils/glock.c nanosrc/utils/hash.c nanosrc/utils/list.c nanosrc/utils/msg.c nanosrc/utils/mutex.c nanosrc/utils/queue.c nanosrc/utils/random.c nanosrc/utils/sem.c nanosrc/utils/sleep.c nanosrc/utils/stopwatch.c nanosrc/utils/thread.c nanosrc/utils/wire.c nanosrc/protocols/utils/dist.c nanosrc/protocols/utils/excl.c nanosrc/protocols/utils/fq.c nanosrc/protocols/utils/lb.c nanosrc/protocols/utils/priolist.c nanosrc/protocols/bus/bus.c nanosrc/protocols/bus/xbus.c nanosrc/protocols/pipeline/push.c nanosrc/protocols/pipeline/pull.c nanosrc/protocols/pipeline/xpull.c nanosrc/protocols/pipeline/xpush.c nanosrc/protocols/pubsub/pub.c nanosrc/protocols/pubsub/sub.c nanosrc/protocols/pubsub/trie.c nanosrc/protocols/pubsub/xpub.c nanosrc/protocols/pubsub/xsub.c nanosrc/protocols/pair/pair.c nanosrc/protocols/pair/xpair.c nanosrc/protocols/reqrep/req.c nanosrc/protocols/reqrep/rep.c nanosrc/protocols/reqrep/task.c nanosrc/protocols/reqrep/xrep.c nanosrc/protocols/reqrep/xreq.c nanosrc/protocols/survey/respondent.c nanosrc/protocols/survey/surveyor.c nanosrc/protocols/survey/xrespondent.c nanosrc/protocols/survey/xsurveyor.c nanosrc/transports/utils/backoff.c nanosrc/transports/utils/dns.c nanosrc/transports/utils/iface.c nanosrc/transports/utils/literal.c nanosrc/transports/utils/port.c nanosrc/transports/utils/streamhdr.c nanosrc/transports/utils/base64.c nanosrc/transports/ipc/aipc.c nanosrc/transports/ipc/bipc.c nanosrc/transports/ipc/cipc.c nanosrc/transports/ipc/ipc.c nanosrc/transports/ipc/sipc.c nanosrc/transports/tcp/atcp.c nanosrc/transports/tcp/btcp.c nanosrc/transports/tcp/ctcp.c nanosrc/transports/tcp/stcp.c nanosrc/transports/tcp/tcp.c nanosrc/transports/inproc/binproc.c nanosrc/transports/inproc/cinproc.c nanosrc/transports/inproc/inproc.c nanosrc/transports/inproc/ins.c nanosrc/transports/inproc/msgqueue.c nanosrc/transports/inproc/sinproc.c
#include crypto777.sources
#gcc -c -O2 $(CRYPTO777_SRCS)
gcc -c -O2 *.c jpeg/*.c jpeg/unix/*.c -I/usr/lib/x86_64-linux-gnu/curl gcc -c -O2 *.c jpeg/*.c jpeg/unix/*.c -I/usr/lib/x86_64-linux-gnu/curl
rm -f ../agents/libcrypto777.a; ar rcu ../agents/libcrypto777.a *.o rm -f ../agents/libcrypto777.a; ar rcu ../agents/libcrypto777.a *.o

0
iguana/iguana_html.c → deprecated/iguana_html.c

8
deprecated/m_unix.crypto777

@ -0,0 +1,8 @@
#DNN_DISABLE_GETADDRINFO_A=1 -DNN_USE_LITERAL_IFADDR=1 -DNN_HAVE_STDINT=1 -DNN_HAVE_MSG_CONTROL=1 -DNN_HAVE_SEMAPHORE=1 -DNN_HAVE_POLL=1 -DNN_HAVE_SOCKETPAIR=1 -DNN_USE_POLL=1
#nanosrc/core/global.c nanosrc/core/ep.c nanosrc/core/epbase.c nanosrc/core/pipe.c nanosrc/core/poll.c nanosrc/core/sock.c nanosrc/core/sockbase.c nanosrc/core/symbol.c nanosrc/devices/device.c nanosrc/devices/tcpmuxd.c nanosrc/aio/ctx.c nanosrc/aio/fsm.c nanosrc/aio/poller.c nanosrc/aio/pool.c nanosrc/aio/timer.c nanosrc/aio/usock.c nanosrc/aio/timerset.c nanosrc/aio/worker.c nanosrc/utils/alloc.c nanosrc/utils/atomic.c nanosrc/utils/chunk.c nanosrc/utils/chunkref.c nanosrc/utils/clock.c nanosrc/utils/closefd.c nanosrc/utils/efd.c nanosrc/utils/err.c nanosrc/utils/glock.c nanosrc/utils/hash.c nanosrc/utils/list.c nanosrc/utils/msg.c nanosrc/utils/mutex.c nanosrc/utils/queue.c nanosrc/utils/random.c nanosrc/utils/sem.c nanosrc/utils/sleep.c nanosrc/utils/stopwatch.c nanosrc/utils/thread.c nanosrc/utils/wire.c nanosrc/protocols/utils/dist.c nanosrc/protocols/utils/excl.c nanosrc/protocols/utils/fq.c nanosrc/protocols/utils/lb.c nanosrc/protocols/utils/priolist.c nanosrc/protocols/bus/bus.c nanosrc/protocols/bus/xbus.c nanosrc/protocols/pipeline/push.c nanosrc/protocols/pipeline/pull.c nanosrc/protocols/pipeline/xpull.c nanosrc/protocols/pipeline/xpush.c nanosrc/protocols/pubsub/pub.c nanosrc/protocols/pubsub/sub.c nanosrc/protocols/pubsub/trie.c nanosrc/protocols/pubsub/xpub.c nanosrc/protocols/pubsub/xsub.c nanosrc/protocols/pair/pair.c nanosrc/protocols/pair/xpair.c nanosrc/protocols/reqrep/req.c nanosrc/protocols/reqrep/rep.c nanosrc/protocols/reqrep/task.c nanosrc/protocols/reqrep/xrep.c nanosrc/protocols/reqrep/xreq.c nanosrc/protocols/survey/respondent.c nanosrc/protocols/survey/surveyor.c nanosrc/protocols/survey/xrespondent.c nanosrc/protocols/survey/xsurveyor.c nanosrc/transports/utils/backoff.c nanosrc/transports/utils/dns.c nanosrc/transports/utils/iface.c nanosrc/transports/utils/literal.c nanosrc/transports/utils/port.c nanosrc/transports/utils/streamhdr.c nanosrc/transports/utils/base64.c nanosrc/transports/ipc/aipc.c nanosrc/transports/ipc/bipc.c nanosrc/transports/ipc/cipc.c nanosrc/transports/ipc/ipc.c nanosrc/transports/ipc/sipc.c nanosrc/transports/tcp/atcp.c nanosrc/transports/tcp/btcp.c nanosrc/transports/tcp/ctcp.c nanosrc/transports/tcp/stcp.c nanosrc/transports/tcp/tcp.c nanosrc/transports/inproc/binproc.c nanosrc/transports/inproc/cinproc.c nanosrc/transports/inproc/inproc.c nanosrc/transports/inproc/ins.c nanosrc/transports/inproc/msgqueue.c nanosrc/transports/inproc/sinproc.c
#include crypto777.sources
#gcc -c -O2 $(CRYPTO777_SRCS)
gcc -c -O2 *.c jpeg/*.c jpeg/unix/*.c -I/usr/lib/x86_64-linux-gnu/curl
rm -f ../agents/libcrypto777.a; ar rcu ../agents/libcrypto777.a *.o

184
deprecated/obsolete.h

@ -16260,6 +16260,190 @@ len = 0;
} else return(clonestr("{\"error\":\"couldnt save wallet backup\"}")); } else return(clonestr("{\"error\":\"couldnt save wallet backup\"}"));
} }
/*struct iguana_waddress *iguana_waccountadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount **wacctp,char *walletaccount,char *coinaddr,char *redeemScript)
{
struct iguana_waccount *wacct; struct iguana_waddress *waddr = 0;
if ( (wacct= iguana_waccountfind(myinfo,coin,walletaccount)) == 0 )
wacct = iguana_waccountcreate(myinfo,coin,walletaccount);
if ( wacct != 0 )
waddr = iguana_waddresscreate(myinfo,coin,wacct,coinaddr,redeemScript);
return(waddr);
}*/
#ifdef testing
char *bitcoin_cltvtx(struct iguana_info *coin,char *changeaddr,char *senderaddr,char *senders_otheraddr,char *otheraddr,uint32_t locktime,uint64_t satoshis,bits256 txid,int32_t vout,uint64_t inputsatoshis,bits256 privkey)
{
uint64_t change; char *rawtxstr,*signedtx; struct vin_info V; bits256 cltxid,signedtxid;
int32_t cltvlen,len; uint32_t timestamp; char ps2h_coinaddr[65]; cJSON *txobj;
uint8_t p2sh_rmd160[20],cltvscript[1024],paymentscript[64],rmd160[20],secret160[20],addrtype;
timestamp = (uint32_t)time(NULL);
bitcoin_addr2rmd160(&addrtype,secret160,senders_otheraddr);
cltvlen = bitcoin_cltvscript(coin->chain->p2shtype,ps2h_coinaddr,p2sh_rmd160,cltvscript,0,senderaddr,otheraddr,secret160,locktime);
txobj = bitcoin_createtx(coin,locktime);
len = bitcoin_p2shspend(paymentscript,0,p2sh_rmd160);
bitcoin_addoutput(coin,txobj,paymentscript,len,satoshis);
bitcoin_addinput(coin,txobj,txid,vout,locktime);
if ( inputsatoshis > (satoshis + 10000) )
{
change = inputsatoshis - (satoshis + 10000);
if ( changeaddr != 0 && changeaddr[0] != 0 )
{
bitcoin_addr2rmd160(&addrtype,rmd160,changeaddr);
if ( addrtype == coin->chain->pubtype )
len = bitcoin_standardspend(paymentscript,0,rmd160);
else if ( addrtype == coin->chain->p2shtype )
len = bitcoin_standardspend(paymentscript,0,rmd160);
else
{
printf("error with mismatched addrtype.%02x vs (%02x %02x)\n",addrtype,coin->chain->pubtype,coin->chain->p2shtype);
return(0);
}
bitcoin_addoutput(coin,txobj,paymentscript,len,change);
}
else
{
printf("error no change address when there is change\n");
return(0);
}
}
rawtxstr = bitcoin_json2hex(coin,&cltxid,txobj);
char str[65]; printf("CLTV.%s (%s)\n",bits256_str(str,cltxid),rawtxstr);
memset(&V,0,sizeof(V));
V.signers[0].privkey = privkey;
bitcoin_verifytx(coin,&signedtxid,&signedtx,rawtxstr,&V);
free(rawtxstr);
if ( signedtx != 0 )
printf("signed CLTV.%s (%s)\n",bits256_str(str,signedtxid),signedtx);
else printf("error generating signedtx\n");
free_json(txobj);
return(signedtx);
}
#endif
char *refstr = "01000000\
01\
eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2\
01000000\
8c\
4930460221009e0339f72c793a89e664a8a932df073962a3f84eda0bd9e02084a6a9567f75aa022100bd9cbaca2e5ec195751efdfac164b76250b1e21302e51ca86dd7ebd7020cdc0601410450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6\
ffffffff\
01\
605af40500000000\
19\
76a914097072524438d003d23a2f23edb65aae1bb3e46988ac\
00000000";
cJSON *bitcoin_txtest(struct iguana_info *coin,char *rawtxstr,bits256 txid)
{
struct iguana_msgtx msgtx; char str[65],str2[65]; bits256 checktxid,blockhash,signedtxid;
cJSON *retjson,*txjson; uint8_t *serialized,*serialized2; uint32_t firstvout;
struct vin_info *V; char vpnstr[64],*txbytes,*signedtx; int32_t n,txstart,height,n2,maxsize,len;
rawtxstr = refstr;
len = (int32_t)strlen(rawtxstr);
maxsize = len + 32768;
serialized = calloc(1,maxsize);
serialized2 = calloc(1,maxsize);
len >>= 1;
V = 0;
vpnstr[0] = 0;
memset(&msgtx,0,sizeof(msgtx));
if ( len < maxsize )
{
decode_hex(serialized,len,rawtxstr);
txjson = cJSON_CreateObject();
retjson = cJSON_CreateObject();
if ( (n= iguana_rwmsgtx(coin,0,txjson,serialized,maxsize,&msgtx,&txid,vpnstr)) < 0 )
{
printf("bitcoin_txtest len.%d: n.%d from (%s)\n",len,n,rawtxstr);
free(serialized), free(serialized2);
return(cJSON_Parse("{\"error\":\"cant parse txbytes\"}"));
}
V = calloc(msgtx.tx_in,sizeof(*V));
{
//char *pstr; int32_t plen;
decode_hex(V[0].signers[0].privkey.bytes,sizeof(V[0].signers[0].privkey),"18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725");
//pstr = "0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6";
//plen = (int32_t)strlen(pstr);
//decode_hex(V[0].signers[0].pubkey,plen,pstr);
}
if ( bitcoin_verifytx(coin,&signedtxid,&signedtx,rawtxstr,V) != 0 )
printf("bitcoin_verifytx error\n");
jadd(retjson,"result",txjson);
if ( (firstvout= iguana_unspentindfind(coin,&height,txid,0,coin->bundlescount-1)) != 0 )
{
if ( height >= 0 )
{
blockhash = iguana_blockhash(coin,height);
jaddnum(retjson,"height",height);
jaddnum(retjson,"confirmations",coin->longestchain - height);
jaddbits256(retjson,"blockhash",blockhash);
}
}
//printf("retjson.(%s) %p\n",jprint(retjson,0),retjson);
memset(checktxid.bytes,0,sizeof(checktxid));
if ( (n2= iguana_rwmsgtx(coin,1,0,serialized2,maxsize,&msgtx,&checktxid,vpnstr)) < 0 || n != n2 )
{
printf("bitcoin_txtest: n.%d vs n2.%d\n",n,n2);
free(serialized), free(serialized2), free(V);
return(retjson);
}
if ( bits256_cmp(checktxid,txid) != 0 )
{
printf("bitcoin_txtest: txid.%s vs check.%s\n",bits256_str(str,txid),bits256_str(str2,checktxid));
}
checktxid = iguana_parsetxobj(coin,&txstart,serialized,maxsize,&msgtx,jobj(retjson,"result"));
if ( bits256_cmp(checktxid,txid) != 0 )
{
printf("bitcoin_txtest: txid.%s vs check2.%s\n",bits256_str(str,txid),bits256_str(str2,checktxid));
}
if ( msgtx.allocsize != 0 )
{
txbytes = malloc(msgtx.allocsize*2 + 1);
init_hexbytes_noT(txbytes,&serialized[txstart],msgtx.allocsize);
if ( strcmp(txbytes,rawtxstr) != 0 )
printf("bitcoin_txtest: reconstruction error: %s != %s\n",rawtxstr,txbytes);
else printf("reconstruction PASSED\n");
free(txbytes);
} else printf("bitcoin_txtest: zero msgtx allocsize\n");
free(serialized), free(serialized2), free(V);
return(retjson);
}
free(serialized), free(serialized2);
return(cJSON_Parse("{\"error\":\"testing bitcoin txbytes\"}"));
}
/*int32_t btc_priv2wif(char *wifstr,uint8_t privkey[32],uint8_t addrtype)
{
uint8_t tmp[128]; char hexstr[67]; cstring *btc_addr;
memcpy(tmp,privkey,32);
tmp[32] = 1;
init_hexbytes_noT(hexstr,tmp,32);
if ( (btc_addr= base58_encode_check(addrtype,true,tmp,33)) != 0 )
{
strcpy(wifstr,btc_addr->str);
cstr_free(btc_addr,true);
}
//printf("-> (%s) -> wif.(%s) addrtype.%02x\n",hexstr,wifstr,addrtype);
return(0);
}
cstring *base58_encode_check(uint8_t addrtype,bool have_addrtype,const void *data,size_t data_len)
{
uint8_t i,buf[64]; bits256 hash; cstring *s_enc;//,*s = cstr_new_sz(data_len + 1 + 4);
buf[0] = addrtype;
memcpy(buf+1,data,data_len);
hash = bits256_doublesha256(0,buf,(int32_t)data_len+1);
//bu_Hash4(md32,buf,(int32_t)data_len+1);
for (i=0; i<4; i++)
{
buf[data_len+i+1] = hash.bytes[31-i];
//printf("(%02x %02x) ",hash.bytes[31-i],md32[i]);
}
//printf("hash4 cmp\n");
s_enc = base58_encode(buf,data_len+5);
return s_enc;
}
*/
#endif #endif
#endif #endif

2
iguana/SuperNET.c

@ -1407,7 +1407,7 @@ FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase)
{ {
SuperNET_setkeys(myinfo,passphrase,(int32_t)strlen(passphrase),1); SuperNET_setkeys(myinfo,passphrase,(int32_t)strlen(passphrase),1);
free_json(argjson); free_json(argjson);
myinfo->expiration = (uint32_t)(time(NULL) + 3600*24); myinfo->expiration = (uint32_t)(time(NULL) + 3600);
return(SuperNET_activehandle(IGUANA_CALLARGS)); return(SuperNET_activehandle(IGUANA_CALLARGS));
} }
else else

1020
iguana/exchanges/bitcoin.c

File diff suppressed because it is too large

5
iguana/iguana.sources

@ -1,5 +1,2 @@
#iguana_html.c
#SOURCES := iguana_rpc.c SuperNET.c SuperNET_keys.c SuperNET_category.c SuperNET_hexmsg.c iguana_exchanges.c iguana_tradebots.c iguana_instantdex.c pangea_api.c pangea_bets.c cards777.c pangea_summary.c pangea_json.c pangea_hand.c poker.c ramchain_api.c iguana_tx.c iguana_wallet.c iguana_scripts.c iguana_pubkeys.c iguana_unspents.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c main.c peggy.c peggy_consensus.c peggy_price.c peggy_update.c peggy_accts.c peggy_tx.c peggy_txind.c peggy_ramkv.c peggy_serdes.c SOURCES := SuperNET.c iguana_bundles.c main.c igana_payment.c iguana_spendvectors.c iguana_sign.c iguana_txidfind.c iguana_realtime.c iguana_volatiles.c peggy_price.c SuperNET_category.c iguana_chains.c iguana_ramchain.c pangea_api.c peggy_ramkv.c SuperNET_hexmsg.c iguana_exchanges.c iguana_recv.c pangea_bets.c peggy_serdes.c SuperNET_keys.c iguana_rpc.c pangea_hand.c peggy_tx.c cards777.c iguana_init.c iguana_scripts.c pangea_json.c peggy_txind.c iguana777.c iguana_instantdex.c iguana_tradebots.c pangea_summary.c peggy_update.c iguana_accept.c iguana_json.c iguana_tx.c peggy.c poker.c iguana_bitmap.c iguana_msg.c iguana_unspents.c peggy_accts.c ramchain_api.c iguana_blocks.c iguana_peers.c iguana_wallet.c peggy_consensus.c databases/iguana_DB.c
SOURCES := SuperNET.c iguana_bundles.c main.c peggy_price.c SuperNET_category.c iguana_chains.c iguana_ramchain.c pangea_api.c peggy_ramkv.c SuperNET_hexmsg.c iguana_exchanges.c iguana_recv.c pangea_bets.c peggy_serdes.c SuperNET_keys.c iguana_html.c iguana_rpc.c pangea_hand.c peggy_tx.c cards777.c iguana_init.c iguana_scripts.c pangea_json.c peggy_txind.c iguana777.c iguana_instantdex.c iguana_tradebots.c pangea_summary.c peggy_update.c iguana_accept.c iguana_json.c iguana_tx.c peggy.c poker.c iguana_bitmap.c iguana_msg.c iguana_unspents.c peggy_accts.c ramchain_api.c iguana_blocks.c iguana_peers.c iguana_wallet.c peggy_consensus.c databases/iguana_DB.c

19
iguana/iguana777.h

@ -474,7 +474,7 @@ struct iguana_bundlereq
struct iguana_bitmap { int32_t width,height,amplitude; char name[52]; uint8_t data[IGUANA_WIDTH*IGUANA_HEIGHT*3]; }; struct iguana_bitmap { int32_t width,height,amplitude; char name[52]; uint8_t data[IGUANA_WIDTH*IGUANA_HEIGHT*3]; };
struct iguana_waddress { UT_hash_handle hh; uint16_t scriptlen; uint8_t rmd160[20],type,pubkey[33],wiftype; bits256 privkey; char symbol[8],coinaddr[36],wifstr[54]; uint8_t redeemScript[]; }; struct iguana_waddress { UT_hash_handle hh; uint64_t balance,*unspents; uint32_t maxunspents,numunspents; uint16_t scriptlen; uint8_t rmd160[20],pubkey[33],wiftype,addrtype; bits256 privkey; char symbol[8],coinaddr[36],wifstr[54]; uint8_t redeemScript[]; };
struct iguana_waccount { UT_hash_handle hh; char account[128]; struct iguana_waddress *waddr,*current; }; struct iguana_waccount { UT_hash_handle hh; char account[128]; struct iguana_waddress *waddr,*current; };
struct iguana_wallet { UT_hash_handle hh; struct iguana_waccount *wacct; }; struct iguana_wallet { UT_hash_handle hh; struct iguana_waccount *wacct; };
@ -531,7 +531,7 @@ struct vin_info
struct bitcoin_unspent 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; uint32_t sequence;
uint8_t addrtype,rmd160[20],pubkey[65],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE]; uint8_t addrtype,rmd160[20],pubkeys[16][65],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE];
}; };
struct bitcoin_spend struct bitcoin_spend
@ -827,11 +827,10 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr
char *issue_startForging(struct supernet_info *myinfo,char *secret); char *issue_startForging(struct supernet_info *myinfo,char *secret);
struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,char **retstrp,double *balancep,int32_t *numunspentsp,double minconfirms,char *account); struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,char **retstrp,double *balancep,int32_t *numunspentsp,double minconfirms,char *account);
void iguana_chainparms(struct iguana_chain *chain,cJSON *argjson); void iguana_chainparms(struct iguana_chain *chain,cJSON *argjson);
void iguana_addinputs(struct iguana_info *coin,struct bitcoin_spend *spend,cJSON *txobj,uint32_t sequence); int32_t iguana_pkhasharray(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,int64_t *totalp,struct iguana_pkhash *P,int32_t max,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t lastheight,uint64_t *unspents,int32_t *numunspentsp);
int32_t iguana_pkhasharray(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,int64_t *totalp,struct iguana_pkhash *P,int32_t max,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t lastheight);
long iguana_spentsfile(struct iguana_info *coin,int32_t n); long iguana_spentsfile(struct iguana_info *coin,int32_t n);
uint8_t *iguana_rmdarray(struct iguana_info *coin,int32_t *numrmdsp,cJSON *array,int32_t firsti); uint8_t *iguana_rmdarray(struct iguana_info *coin,int32_t *numrmdsp,cJSON *array,int32_t firsti);
int64_t iguana_unspents(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,uint8_t *rmdarray,int32_t numrmds,int32_t lastheight); int64_t iguana_unspents(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,uint8_t *rmdarray,int32_t numrmds,int32_t lastheight,uint64_t *unspents,int32_t *numunspentsp);
uint8_t *iguana_walletrmds(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *numrmdsp); uint8_t *iguana_walletrmds(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *numrmdsp);
char *iguana_bundleaddrs(struct iguana_info *coin,int32_t hdrsi); char *iguana_bundleaddrs(struct iguana_info *coin,int32_t hdrsi);
uint32_t iguana_sparseaddpk(uint8_t *bits,int32_t width,uint32_t tablesize,uint8_t rmd160[20],struct iguana_pkhash *P,uint32_t pkind,struct iguana_ramchain *ramchain); uint32_t iguana_sparseaddpk(uint8_t *bits,int32_t width,uint32_t tablesize,uint8_t rmd160[20],struct iguana_pkhash *P,uint32_t pkind,struct iguana_ramchain *ramchain);
@ -928,6 +927,16 @@ int64_t iguana_addressreceived(struct supernet_info *myinfo,struct iguana_info *
cJSON *iguana_walletjson(struct supernet_info *myinfo); cJSON *iguana_walletjson(struct supernet_info *myinfo);
int32_t iguana_payloadupdate(struct supernet_info *myinfo,struct iguana_info *coin,char *retstr,struct iguana_waddress *waddr,char *account); int32_t iguana_payloadupdate(struct supernet_info *myinfo,struct iguana_info *coin,char *retstr,struct iguana_waddress *waddr,char *account);
int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp); int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp);
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);
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);
extern int32_t HDRnet,netBLOCKS; extern int32_t HDRnet,netBLOCKS;

29
iguana/iguana_bundles.c

@ -416,6 +416,35 @@ struct iguana_txid *iguana_bundletx(struct iguana_info *coin,struct iguana_bundl
return(0); return(0);
} }
char *iguana_bundleaddrs(struct iguana_info *coin,int32_t hdrsi)
{
uint8_t *PKbits; struct iguana_pkhash *P; uint32_t pkind,numpkinds; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; cJSON *retjson; char rmdstr[41];
if ( (bp= coin->bundles[hdrsi]) != 0 )
{
if ( 0 && coin->RTramchain_busy != 0 )
{
printf("iguana_bundleaddrs: unexpected access when RTramchain_busy\n");
return(0);
}
ramchain = &bp->ramchain;//(bp->isRT != 0) ? &bp->ramchain : &coin->RTramchain;
if ( ramchain->H.data != 0 )
{
numpkinds = ramchain->H.data->numpkinds;//(bp->isRT != 0) ? ramchain->H.data->numpkinds : ramchain->pkind;
retjson = cJSON_CreateArray();
PKbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->PKoffset);
P = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Poffset);
for (pkind=0; pkind<numpkinds; pkind++,P++)
{
init_hexbytes_noT(rmdstr,P->rmd160,20);
jaddistr(retjson,rmdstr);
}
return(jprint(retjson,1));
}
//iguana_bundleQ(coin,bp,bp->n);
return(clonestr("{\"error\":\"no bundle data\"}"));
} return(clonestr("{\"error\":\"no bundle\"}"));
}
void iguana_bundlepurgefiles(struct iguana_info *coin,struct iguana_bundle *bp) void iguana_bundlepurgefiles(struct iguana_info *coin,struct iguana_bundle *bp)
{ {
static const bits256 zero; static const bits256 zero;

672
iguana/iguana_payments.c

@ -0,0 +1,672 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "iguana777.h"
char *iguana_APIrequest(struct iguana_info *coin,bits256 blockhash,bits256 txid,int32_t seconds)
{
int32_t i,len; char *retstr = 0; uint8_t serialized[1024]; char str[65];
coin->APIblockhash = blockhash;
coin->APItxid = txid;
printf("request block.(%s) txid.%llx\n",bits256_str(str,blockhash),(long long)txid.txid);
if ( (len= iguana_getdata(coin,serialized,MSG_BLOCK,&blockhash,1)) > 0 )
{
for (i=0; i<seconds; i++)
{
if ( i == 0 )
iguana_send(coin,0,serialized,len);
if ( coin->APIblockstr != 0 )
{
retstr = coin->APIblockstr;
coin->APIblockstr = 0;
memset(&coin->APIblockhash,0,sizeof(coin->APIblockhash));
memset(&coin->APItxid,0,sizeof(coin->APItxid));
return(retstr);
}
sleep(1);
}
}
return(0);
}
bits256 iguana_str2priv(struct supernet_info *myinfo,struct iguana_info *coin,char *str)
{
bits256 privkey; int32_t n; uint8_t addrtype; struct iguana_waccount *wacct=0; struct iguana_waddress *waddr;
memset(&privkey,0,sizeof(privkey));
if ( str != 0 )
{
n = (int32_t)strlen(str) >> 1;
if ( n == sizeof(bits256) && is_hexstr(str,sizeof(bits256)) > 0 )
decode_hex(privkey.bytes,sizeof(privkey),str);
else if ( bitcoin_wif2priv(&addrtype,&privkey,str) != sizeof(bits256) )
{
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,str)) != 0 )
privkey = waddr->privkey;
else memset(privkey.bytes,0,sizeof(privkey));
}
}
return(privkey);
}
int32_t iguana_pubkeyget(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *pubkey33,char *str)
{
bits256 privkey,pubkey; uint8_t pubkeydata[128]; int32_t len,plen= -1; struct iguana_waccount *wacct; struct iguana_waddress *waddr;
len = (int32_t)strlen(str);
if ( is_hexstr(str,len) == 0 )
{
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,str)) != 0 )
{
if ( (plen= bitcoin_pubkeylen(waddr->pubkey)) > 0 )
memcpy(pubkeydata,waddr->pubkey,plen);
}
}
else
{
decode_hex(pubkeydata,len,str);
plen = bitcoin_pubkeylen(pubkeydata);
}
if ( plen <= 0 )
{
privkey = iguana_str2priv(myinfo,coin,str);
if ( bits256_nonz(privkey) == 0 )
return(-1);
else
{
pubkey = bitcoin_pubkey33(pubkeydata,privkey);
if ( bits256_nonz(pubkey) == 0 )
return(-1);
}
}
if ( (plen= bitcoin_pubkeylen(pubkeydata)) > 0 )
memcpy(pubkey33,pubkeydata,plen);
return(0);
}
cJSON *iguana_p2shjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson,struct iguana_waddress *waddr)
{
char str[4096]; uint8_t type; struct iguana_waccount *wacct; bits256 debugtxid; struct vin_info V; cJSON *privkeys,*pubkeys,*addresses; int32_t i,plen;
if ( retjson == 0 )
retjson = cJSON_CreateObject();
init_hexbytes_noT(str,waddr->redeemScript,waddr->scriptlen);
jaddstr(retjson,"redeemScript",str);
memset(debugtxid.bytes,0,sizeof(debugtxid));
if ( (type= iguana_calcrmd160(coin,0,&V,waddr->redeemScript,waddr->scriptlen, debugtxid,-1,0xffffffff)) >= 0 )
{
privkeys = cJSON_CreateArray();
pubkeys = cJSON_CreateArray();
addresses = cJSON_CreateArray();
for (i=0; i<V.N; i++)
{
if ( V.signers[i].coinaddr[0] != 0 && (waddr= iguana_waddresssearch(myinfo,coin,&wacct,V.signers[i].coinaddr)) != 0 && waddr->wifstr[0] != 0 )
jaddistr(privkeys,waddr->wifstr);
else jaddistr(privkeys,"");
if ( (plen= bitcoin_pubkeylen(V.signers[i].pubkey)) > 0 )
{
init_hexbytes_noT(str,V.signers[i].pubkey,plen);
jaddistr(pubkeys,str);
} else jaddistr(pubkeys,"");
jaddistr(addresses,V.signers[i].coinaddr);
}
jaddstr(retjson,"result",V.coinaddr);
jaddnum(retjson,"M",V.M);
jaddnum(retjson,"N",V.N);
jadd(retjson,"pubkeys",pubkeys);
jadd(retjson,"privkeys",privkeys);
jadd(retjson,"addresses",addresses);
}
return(retjson);
}
cJSON *iguana_scriptobj(struct iguana_info *coin,uint8_t rmd160[20],char *coinaddr,char *asmstr,uint8_t *script,int32_t scriptlen)
{
struct vin_info V; int32_t i,plen,asmtype; char pubkeystr[130],rmdstr[41]; cJSON *addrobj,*scriptobj=0;
if ( (asmtype= iguana_calcrmd160(coin,asmstr,&V,script,scriptlen,rand256(1),1,0xffffffff)) >= 0 )
{
if ( asmstr != 0 && asmstr[0] != 0 )
jaddstr(scriptobj,"asm",asmstr);
jaddnum(scriptobj,"iguanatype",asmtype);
jaddnum(scriptobj,"scriptlen",scriptlen);
jaddnum(scriptobj,"reqSigs",V.M);
if ( (plen= bitcoin_pubkeylen(V.signers[0].pubkey)) > 0 )
{
init_hexbytes_noT(pubkeystr,V.signers[0].pubkey,plen);
jaddstr(scriptobj,"pubkey",pubkeystr);
init_hexbytes_noT(rmdstr,V.signers[0].rmd160,20);
jaddstr(scriptobj,"rmd160",rmdstr);
}
addrobj = cJSON_CreateArray();
for (i=0; i<V.N; i++)
jaddistr(addrobj,V.signers[i].coinaddr);
jadd(scriptobj,"addresses",addrobj);
if ( V.p2shlen != 0 )
jaddstr(scriptobj,"p2sh",V.coinaddr);
strcpy(coinaddr,V.coinaddr);
memcpy(rmd160,V.rmd160,20);
}
return(scriptobj);
}
char *sendtoaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,double amount,char *comment,char *comment2,int32_t minconf,char *account)
{
uint8_t addrtype,rmd160[20]; int32_t numwaddrs; struct iguana_waddress **waddrs;
//sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to] <amount> is a real and is rounded to 8 decimal places. Returns the transaction ID <txid> if successful. Y
if ( coinaddr != 0 && coinaddr[0] != 0 && amount > 0. )
{
if ( iguana_addressvalidate(coin,&addrtype,rmd160,coinaddr) < 0 )
return(clonestr("{\"error\":\"invalid coin address\"}"));
numwaddrs = iguana_unspentslists(myinfo,coin,(struct iguana_waddress **)coin->blockspace,(int32_t)(sizeof(coin->blockspace)/sizeof(*waddrs)),amount,minconf,0);
printf("need to generate send %.8f to %s [%s] [%s] using numaddrs.%d\n",dstr(amount),coinaddr,comment!=0?comment:"",comment2!=0?comment2:"",numwaddrs);
}
return(clonestr("{\"error\":\"need address and amount\"}"));
}
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees)
{
cJSON *retjson = cJSON_CreateObject();
// send to 2 peers
return(jprint(retjson,1));
}
STRING_ARG(bitcoinrpc,submitblock,rawbytes)
{
cJSON *retjson = cJSON_CreateObject();
// send to all peers
return(jprint(retjson,1));
}
ZERO_ARGS(bitcoinrpc,makekeypair)
{
bits256 privkey; char str[67]; cJSON *retjson = cJSON_CreateObject();
privkey = rand256(1);
jaddstr(retjson,"result","success");
jaddstr(retjson,"privkey",bits256_str(str,privkey));
jadd(retjson,"rosetta",SuperNET_rosettajson(privkey,1));
return(jprint(retjson,1));
}
STRING_ARG(bitcoinrpc,validatepubkey,pubkeystr)
{
uint8_t rmd160[20],pubkey[65],addrtype = 0; int32_t plen; char coinaddr[128],*str; cJSON *retjson;
plen = (int32_t)strlen(pubkeystr) >> 1;
if ( plen <= 65 && coin != 0 && coin->chain != 0 )
{
addrtype = coin->chain->pubtype;
decode_hex(pubkey,plen,pubkeystr);
if ( (str= bitcoin_address(coinaddr,addrtype,pubkey,plen)) != 0 )
{
if ( iguana_addressvalidate(coin,&addrtype,rmd160,coinaddr) < 0 )
return(clonestr("{\"error\":\"invalid coin address\"}"));
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"pubkey",pubkeystr);
jaddstr(retjson,"address",coinaddr);
jaddstr(retjson,"coin",coin->symbol);
return(jprint(retjson,1));
}
}
return(clonestr("{\"error\":\"invalid pubkey\"}"));
}
STRING_ARG(bitcoinrpc,decodescript,scriptstr)
{
int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE],rmd160[20]; char coinaddr[128],asmstr[IGUANA_MAXSCRIPTSIZE*2+1]; cJSON *scriptobj,*retjson = cJSON_CreateObject();
if ( coin != 0 && (scriptlen= (int32_t)strlen(scriptstr)>>1) < sizeof(script) )
{
decode_hex(script,scriptlen,scriptstr);
if ( (scriptobj= iguana_scriptobj(coin,rmd160,coinaddr,asmstr,script,scriptlen)) != 0 )
jadd(retjson,"result",scriptobj);
}
return(jprint(retjson,1));
}
INT_ARRAY_STRING(bitcoinrpc,createmultisig,M,pubkeys,ignore)
{
cJSON *retjson,*pkjson,*addresses; uint8_t script[2048],p2sh_rmd160[20]; char pubkeystr[256],msigaddr[64],*pkstr,scriptstr[sizeof(script)*2+1]; struct vin_info V; int32_t i,plen,len,n = cJSON_GetArraySize(pubkeys);
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( n < 0 || n > 16 || M < 0 || M > n )
return(clonestr("{\"error\":\"illegal number of pubkeys\"}"));
memset(&V,0,sizeof(V));
V.M = M, V.N = n;
pkjson = cJSON_CreateArray();
addresses = cJSON_CreateArray();
for (i=0; i<n; i++)
{
if ( (pkstr= jstr(jitem(pubkeys,i),0)) != 0 )
{
if ( iguana_pubkeyget(myinfo,coin,V.signers[i].pubkey,pkstr) < 0 )
break;
if ( (plen= bitcoin_pubkeylen(V.signers[i].pubkey)) <= 0 )
break;
bitcoin_address(V.signers[i].coinaddr,coin->chain->pubtype,V.signers[i].pubkey,plen);
jaddistr(addresses,V.signers[i].coinaddr);
init_hexbytes_noT(pubkeystr,V.signers[i].pubkey,plen);
jaddistr(pkjson,pubkeystr);
} else break;
}
retjson = cJSON_CreateObject();
if ( i == n )
{
len = bitcoin_MofNspendscript(p2sh_rmd160,script,0,&V);
bitcoin_address(msigaddr,coin->chain->p2shtype,p2sh_rmd160,sizeof(p2sh_rmd160));
jaddstr(retjson,"result","success");
jaddstr(retjson,"address",msigaddr);
init_hexbytes_noT(scriptstr,script,len);
jaddstr(retjson,"redeemScript",scriptstr);
jaddnum(retjson,"M",M);
jaddnum(retjson,"N",n);
jadd(retjson,"pubkeys",pkjson);
jadd(retjson,"addresses",addresses);
}
else
{
jaddstr(retjson,"error","couldnt get all pubkeys");
free_json(pkjson);
}
return(jprint(retjson,1));
}
INT_ARRAY_STRING(bitcoinrpc,addmultisigaddress,M,pubkeys,account) //
{
cJSON *retjson,*tmpjson,*setjson=0; char *retstr,*str=0,*msigaddr,*redeemScript;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( (retstr= bitcoinrpc_createmultisig(IGUANA_CALLARGS,M,pubkeys,account)) != 0 )
{
//printf("CREATEMULTISIG.(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (msigaddr= jstr(retjson,"address")) != 0 )
{
if ( (redeemScript= jstr(retjson,"redeemScript")) == 0 || (str= setaccount(myinfo,coin,0,account,msigaddr,redeemScript)) == 0 || (setjson= cJSON_Parse(str)) == 0 || jobj(setjson,"error") != 0 )
{
if ( jobj(retjson,"result") != 0 )
jdelete(retjson,"result");
if ( jobj(retjson,"error") == 0 )
jaddstr(retjson,"error","couldnt add multisig address to account");
}
else
{
tmpjson = cJSON_CreateObject();
jaddstr(tmpjson,"result",msigaddr);
free_json(retjson);
free(retstr);
retjson = tmpjson;
}
}
if ( setjson != 0 )
free_json(setjson);
if ( str != 0 )
free(str);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"couldnt parse retstr from createmultisig\"}"));
} else return(clonestr("{\"error\":\"no retstr from createmultisig\"}"));
}
HASH_AND_TWOINTS(bitcoinrpc,gettxout,txid,vout,mempool)
{
uint8_t script[IGUANA_MAXSCRIPTSIZE],rmd160[20],pubkey33[33]; char coinaddr[128],asmstr[IGUANA_MAXSCRIPTSIZE*2+1]; struct iguana_bundle *bp; int32_t minconf,scriptlen,unspentind,height,spentheight; int64_t RTspend; struct iguana_ramchaindata *rdata; struct iguana_pkhash *P; struct iguana_txid *T; struct iguana_unspent *U; struct iguana_ramchain *ramchain; cJSON *scriptobj,*retjson = cJSON_CreateObject();
if ( coin != 0 )
{
minconf = (mempool != 0) ? 0 : 1;
if ( (unspentind= iguana_unspentindfind(coin,&height,txid,vout,coin->bundlescount-1)) != 0 )
{
if ( height >= 0 && height < coin->longestchain && (bp= coin->bundles[height / coin->chain->bundlesize]) != 0 )
{
ramchain = (bp == coin->current) ? &coin->RTramchain : &bp->ramchain;
if ( (rdata= ramchain->H.data) != 0 )
{
U = (void *)(long)((long)rdata + rdata->Uoffset);
P = (void *)(long)((long)rdata + rdata->Poffset);
T = (void *)(long)((long)rdata + rdata->Toffset);
RTspend = 0;
if ( iguana_spentflag(coin,&RTspend,&spentheight,ramchain,bp->hdrsi,unspentind,height,minconf,coin->longestchain,U[unspentind].value) == 0 )
{
jaddbits256(retjson,"bestblock",coin->blocks.hwmchain.RO.hash2);
jaddnum(retjson,"bestheight",coin->blocks.hwmchain.height);
jaddnum(retjson,"height",height);
jaddnum(retjson,"confirmations",coin->blocks.hwmchain.height - height + 1);
jaddnum(retjson,"value",dstr(U[unspentind].value));
memset(rmd160,0,sizeof(rmd160));
memset(pubkey33,0,sizeof(pubkey33));
memset(coinaddr,0,sizeof(coinaddr));
if ( (scriptlen= iguana_voutscript(coin,bp,script,0,&U[unspentind],&P[U[unspentind].pkind],vout)) > 0 )
{
if ( (scriptobj= iguana_scriptobj(coin,rmd160,coinaddr,asmstr,script,scriptlen)) != 0 )
jadd(retjson,"scriptPubKey",scriptobj);
}
jadd(retjson,"iguana",iguana_unspentjson(myinfo,coin,bp->hdrsi,unspentind,T,&U[unspentind],rmd160,coinaddr,pubkey33));
if ( (height % coin->chain->bundlesize) == 0 && vout == 0 )
jadd(retjson,"coinbase",jtrue());
else jadd(retjson,"coinbase",jfalse());
}
else
{
jaddstr(retjson,"error","already spent");
jaddnum(retjson,"spentheight",spentheight);
jaddnum(retjson,"unspentind",unspentind);
}
}
}
}
}
return(jprint(retjson,1));
}
TWO_STRINGS(bitcoinrpc,signmessage,address,messagestr)
{
bits256 privkey; int32_t n,len,siglen; char sigstr[256],sig64str[256]; uint8_t sig[128],*message=0; cJSON *retjson = cJSON_CreateObject();
if ( coin != 0 )
{
privkey = iguana_str2priv(myinfo,coin,address);
if ( bits256_nonz(privkey) != 0 )
{
n = (int32_t)strlen(messagestr) >> 1;
if ( messagestr[0] == '0' && messagestr[1] == 'x' && is_hexstr(messagestr+2,n-2) > 0 )
{
message = malloc(n-2);
decode_hex(message,n-2,messagestr+2);
n -= 2;
} else message = (uint8_t *)messagestr, n <<= 1;
if ( (siglen= bitcoin_sign(sig,sizeof(sig),message,n,privkey)) > 0 )
{
sigstr[0] = sig64str[0] = 0;
//init_hexbytes_noT(sigstr,sig,siglen);
len = nn_base64_encode(sig,siglen,sig64str,sizeof(sig64str));
sig64str[len++] = '=';
sig64str[len++] = 0;
jaddstr(retjson,"result",sig64str);
}
if ( message != (void *)messagestr )
free(message);
} else jaddstr(retjson,"error","invalid address (can be wif, wallet address or privkey hex)");
}
return(jprint(retjson,1));
}
THREE_STRINGS(bitcoinrpc,verifymessage,address,sig,message)
{
cJSON *retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
HASH_AND_INT(bitcoinrpc,getrawtransaction,txid,verbose)
{
struct iguana_txid *tx,T; char *txbytes; bits256 checktxid; int32_t len,height; cJSON *retjson;
if ( (tx= iguana_txidfind(coin,&height,&T,txid,coin->bundlescount-1)) != 0 )
{
retjson = cJSON_CreateObject();
if ( (len= iguana_ramtxbytes(coin,coin->blockspace,sizeof(coin->blockspace),&checktxid,tx,height,0,0,0)) > 0 )
{
txbytes = calloc(1,len*2+1);
init_hexbytes_noT(txbytes,coin->blockspace,len);
jaddstr(retjson,"result",txbytes);
printf("txbytes.(%s) len.%d (%s)\n",txbytes,len,jprint(retjson,0));
free(txbytes);
return(jprint(retjson,1));
}
else if ( height >= 0 )
{
if ( coin->APIblockstr != 0 )
jaddstr(retjson,"error","already have pending request");
else
{
int32_t datalen; uint8_t *data; char *blockstr; bits256 blockhash;
blockhash = iguana_blockhash(coin,height);
if ( (blockstr= iguana_APIrequest(coin,blockhash,txid,2)) != 0 )
{
datalen = (int32_t)(strlen(blockstr) >> 1);
data = malloc(datalen);
decode_hex(data,datalen,blockstr);
if ( (txbytes= iguana_txscan(coin,verbose != 0 ? retjson : 0,data,datalen,txid)) != 0 )
{
jaddstr(retjson,"result",txbytes);
jaddbits256(retjson,"blockhash",blockhash);
jaddnum(retjson,"height",height);
free(txbytes);
} else jaddstr(retjson,"error","cant find txid in block");
free(blockstr);
free(data);
} else jaddstr(retjson,"error","cant find blockhash");
return(jprint(retjson,1));
}
} else printf("height.%d\n",height);
}
return(clonestr("{\"error\":\"cant find txid\"}"));
}
STRING_ARG(bitcoinrpc,decoderawtransaction,rawtx)
{
cJSON *txobj = 0; bits256 txid;
if ( rawtx != 0 && rawtx[0] != 0 )
{
if ( (strlen(rawtx) & 1) != 0 )
return(clonestr("{\"error\":\"rawtx hex has odd length\"}"));
txobj = bitcoin_hex2json(coin,&txid,0,rawtx);
//char str[65]; printf("got txid.(%s)\n",bits256_str(str,txid));
}
if ( txobj == 0 )
txobj = cJSON_CreateObject();
return(jprint(txobj,1));
}
HASH_ARG(bitcoinrpc,gettransaction,txid)
{
return(bitcoinrpc_getrawtransaction(IGUANA_CALLARGS,txid,1));
}
ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime)
{
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 )
{
if ( (n= cJSON_GetArraySize(vins)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(vins,i);
p2shlen = spendlen = 0;
if ( (str= jstr(item,"scriptPubKey")) != 0 || (str= jstr(item,"scriptPubkey")) != 0 )
{
spendlen = (int32_t)strlen(str) >> 1;
decode_hex(spendscript,spendlen,str);
}
if ( (str= jstr(item,"redeemScript")) != 0 )
{
p2shlen = (int32_t)strlen(str) >> 1;
decode_hex(redeemscript,p2shlen,str);
}
vout = jint(item,"vout");
if ( jobj(item,"sequenceid") != 0 )
sequenceid = juint(item,"sequenceid");
else sequenceid = 0xffffffff;
txid = jbits256(item,"txid");
bitcoin_addinput(coin,txobj,txid,vout,sequenceid,spendscript,spendlen,redeemscript,p2shlen);
}
}
if ( (n= cJSON_GetArraySize(vouts)) > 0 )
{
item = vouts->child;
while ( item != 0 )
{
if ( (field= jfieldname(item)) != 0 )
{
if ( strcmp(field,"data") == 0 )
{
if ( (hexstr= jstr(item,"data")) != 0 )
{
spendlen = (int32_t)strlen(hexstr) >> 1;
offset = 0;
if ( is_hexstr(hexstr,spendlen) > 0 )
{
decode_hex(spendscript+4,spendlen,hexstr);
spendscript[3] = SCRIPT_OPRETURN;
spendlen++;
/* 1-75 0x01-0x4b (special) data The next opcode bytes is data to be pushed onto the stack
OP_PUSHDATA1 76 0x4c (special) data The next byte contains the number of bytes to be pushed onto the stack.
OP_PUSHDATA2 77 0x4d*/
if ( spendlen < 76 )
{
spendscript[2] = spendlen;
offset = 2;
spendlen++;
}
else if ( spendlen <= 0xff )
{
spendscript[2] = spendlen;
spendscript[1] = 0x4c;
offset = 1;
spendlen += 2;
}
else if ( spendlen <= 0xffff )
{
spendscript[2] = ((spendlen >> 8) & 0xff);
spendscript[1] = (spendlen & 0xff);
spendscript[0] = 0x4d;
offset = 0;
spendlen += 3;
}
else continue;
if ( (obj= jobj(item,"amount")) != 0 )
satoshis = get_API_float(obj) * SATOSHIDEN;
else satoshis = 0;
bitcoin_addoutput(coin,txobj,spendscript+offset,spendlen,satoshis);
}
}
break;
}
else
{
if ( bitcoin_addr2rmd160(&addrtype,rmd160,field) == sizeof(rmd160) )
{
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
satoshis = get_API_float(item) * SATOSHIDEN;
bitcoin_addoutput(coin,txobj,spendscript,spendlen,satoshis);
}
}
}
item = item->next;
}
}
if ( (txstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 )
{
jaddstr(retjson,"result",txstr);
free(txstr);
}
}
return(jprint(retjson,1));
}
TWOINTS_AND_ARRAY(bitcoinrpc,listunspent,minconf,maxconf,array)
{
int32_t numrmds; uint8_t *rmdarray; cJSON *retjson = cJSON_CreateArray();
if ( minconf == 0 )
minconf = 1;
if ( maxconf == 0 )
maxconf = 9999999;
rmdarray = iguana_rmdarray(coin,&numrmds,array,0);
iguana_unspents(myinfo,coin,retjson,minconf,maxconf,rmdarray,numrmds,0,0,0);
if ( rmdarray != 0 )
free(rmdarray);
return(jprint(retjson,1));
}
INT_AND_ARRAY(bitcoinrpc,lockunspent,flag,array)
{
cJSON *retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
ZERO_ARGS(bitcoinrpc,listlockunspent)
{
cJSON *retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
DOUBLE_ARG(bitcoinrpc,settxfee,amount)
{
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
coin->txfee_perkb = amount * SATOSHIDEN;
retjson = cJSON_CreateObject();
jadd(retjson,"result",jtrue());
return(jprint(retjson,1));
}
S_D_SS(bitcoinrpc,sendtoaddress,address,amount,comment,comment2)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
iguana_unspentset(myinfo,coin);
return(sendtoaddress(myinfo,coin,address,amount,comment,comment2,coin->minconfirms,0));
}
SS_D_I_SS(bitcoinrpc,sendfrom,fromaccount,toaddress,amount,minconf,comment,comment2)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
iguana_unspentset(myinfo,coin);
return(sendtoaddress(myinfo,coin,toaddress,amount,comment,comment2,minconf,fromaccount));
}
S_A_I_S(bitcoinrpc,sendmany,fromaccount,payments,minconf,comment)
{
cJSON *retjson,*item; int32_t i,n; char *coinaddr,*str; int64_t required,val; double amount;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
iguana_unspentset(myinfo,coin);
n = cJSON_GetArraySize(payments);
item = payments->child;
for (required=i=0; i<n; i++)
{
if ( item != 0 && (coinaddr= item->string) != 0 )
{
amount = jdouble(item,0);
val = amount * SATOSHIDEN;
printf("(%s %.8f) ",coinaddr,dstr(val));
if ( (str= sendtoaddress(myinfo,coin,coinaddr,amount,comment,"",minconf,fromaccount)) != 0 )
{
free(str);
}
required += val;
}
item = item->next;
}
printf("required %.8f\n",dstr(required));
retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
#include "../includes/iguana_apiundefs.h"

355
iguana/iguana_realtime.c

@ -0,0 +1,355 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "iguana777.h"
void iguana_RTramchainfree(struct iguana_info *coin,struct iguana_bundle *bp)
{
int32_t hdrsi;
if ( coin->utxotable != 0 )
{
printf("free RTramchain\n");
iguana_utxoupdate(coin,-1,0,0,0,0,-1); // free hashtables
coin->RTheight = coin->balanceswritten * coin->chain->bundlesize;
coin->RTgenesis = 0;
iguana_ramchain_free(coin,&coin->RTramchain,1);
if ( bp != 0 )
bp->ramchain = coin->RTramchain;
iguana_mempurge(&coin->RTmem);
iguana_mempurge(&coin->RThashmem);
coin->RTdatabad = 0;
for (hdrsi=coin->bundlescount-1; hdrsi>0; hdrsi--)
if ( (bp= coin->bundles[hdrsi]) == 0 && bp != coin->current )
{
iguana_volatilespurge(coin,&bp->ramchain);
if ( iguana_volatilesmap(coin,&bp->ramchain) != 0 )
printf("error mapping bundle.[%d]\n",hdrsi);
}
printf("done RTramchain\n");
}
}
void *iguana_ramchainfile(struct iguana_info *coin,struct iguana_ramchain *dest,struct iguana_ramchain *R,struct iguana_bundle *bp,int32_t bundlei,struct iguana_block *block)
{
char fname[1024]; long filesize; int32_t err; void *ptr=0;
if ( block == bp->blocks[bundlei] && (ptr= iguana_bundlefile(coin,fname,&filesize,bp,bundlei)) != 0 )
{
if ( iguana_mapchaininit(fname,coin,R,bp,bundlei,block,ptr,filesize) >= 0 )
{
if ( dest != 0 && dest->H.data != 0 )
err = iguana_ramchain_iterate(coin,dest,R,bp,bundlei);
else err = 0;
if ( err != 0 || dest->H.data == 0 || bits256_cmp(R->H.data->firsthash2,block->RO.hash2) != 0 )
{
char str[65];
printf("ERROR [%d:%d] %s vs ",bp->hdrsi,bundlei,bits256_str(str,block->RO.hash2));
printf("mapped.%s\n",bits256_str(str,R->H.data->firsthash2));
} else return(ptr);
}
iguana_blockunmark(coin,block,bp,bundlei,1);
iguana_ramchain_free(coin,R,1);
} //else printf("ramchainfile ptr.%p block.%p\n",ptr,block);
return(0);
}
void iguana_RTramchainalloc(char *fname,struct iguana_info *coin,struct iguana_bundle *bp)
{
uint32_t i,changed = 0; struct iguana_ramchaindata *rdata; struct iguana_ramchain *dest = &coin->RTramchain; struct iguana_blockRO *B; struct iguana_bundle *tmpbp;
if ( (rdata= dest->H.data) != 0 )
{
i = 0;
if ( coin->RTheight != bp->bundleheight + rdata->numblocks )
changed++;
else
{
B = (void *)(long)((long)rdata + rdata->Boffset);
for (i=0; i<rdata->numblocks; i++)
if ( bits256_cmp(B[i].hash2,bp->hashes[i]) != 0 )
{
char str[65],str2[65]; printf("mismatched hash2 at %d %s vs %s\n",bp->bundleheight+i,bits256_str(str,B[i].hash2),bits256_str(str2,bp->hashes[i]));
changed++;
break;
}
}
if ( changed != 0 )
{
printf("RTramchain changed %d bundlei.%d | coin->RTheight %d != %d bp->bundleheight + %d coin->RTramchain.H.data->numblocks\n",coin->RTheight,i,coin->RTheight,bp->bundleheight,rdata->numblocks);
//coin->RTheight = coin->balanceswritten * coin->chain->bundlesize;
iguana_RTramchainfree(coin,bp);
}
}
if ( coin->RTramchain.H.data == 0 )
{
printf("ALLOC RTramchain\n");
iguana_ramchainopen(fname,coin,dest,&coin->RTmem,&coin->RThashmem,bp->bundleheight,bp->hashes[0]);
dest->H.txidind = dest->H.unspentind = dest->H.spendind = dest->pkind = dest->H.data->firsti;
dest->externalind = dest->H.stacksize = 0;
dest->H.scriptoffset = 1;
if ( 1 )
{
for (i=0; i<bp->hdrsi; i++)
if ( (tmpbp= coin->bundles[i]) != 0 )
{
//iguana_volatilespurge(coin,&tmpbp->ramchain);
iguana_volatilesmap(coin,&tmpbp->ramchain);
}
sleep(1);
}
}
}
void iguana_rdataset(struct iguana_ramchain *dest,struct iguana_ramchaindata *rdest,struct iguana_ramchain *src)
{
*dest = *src;
dest->H.data = rdest;
*rdest = *src->H.data;
rdest->numpkinds = src->pkind;
rdest->numexternaltxids = src->externalind;
rdest->numtxids = src->H.txidind;
rdest->numunspents = src->H.unspentind;
rdest->numspends = src->H.spendind;
//printf("RT set numtxids.%u numspends.%u\n",rdest->numtxids,rdest->numspends);
}
void iguana_rdatarestore(struct iguana_ramchain *dest,struct iguana_ramchaindata *rdest,struct iguana_ramchain *src)
{
*src = *dest;
*src->H.data = *rdest;
src->pkind = rdest->numpkinds;
src->externalind = rdest->numexternaltxids;
src->H.txidind = rdest->numtxids;
src->H.unspentind = rdest->numunspents;
src->H.spendind = rdest->numspends;
printf("RT restore numtxids.%u numspends.%u\n",rdest->numtxids,rdest->numspends);
}
void iguana_RThdrs(struct iguana_info *coin,struct iguana_bundle *bp,int32_t numaddrs)
{
int32_t datalen,i; uint8_t serialized[512]; char str[65]; struct iguana_peer *addr;
for (i=0; i<numaddrs && i<coin->peers.numranked; i++)
{
queue_enqueue("hdrsQ",&coin->hdrsQ,queueitem(bits256_str(str,bp->hashes[0])),1);
if ( (addr= coin->peers.ranked[i]) != 0 && addr->usock >= 0 && addr->dead == 0 && (datalen= iguana_gethdrs(coin,serialized,coin->chain->gethdrsmsg,bits256_str(str,bp->hashes[0]))) > 0 )
{
iguana_send(coin,addr,serialized,datalen);
addr->pendhdrs++;
}
}
}
void iguana_RTspendvectors(struct iguana_info *coin,struct iguana_bundle *bp)
{
int32_t iterate,lasti,num,hdrsi,orignumemit; struct iguana_ramchain R; struct iguana_ramchaindata RDATA;
if ( bp->hdrsi <= 0 )
return;
bp->ramchain = coin->RTramchain;
iguana_rdataset(&R,&RDATA,&coin->RTramchain);
if ( (lasti= (coin->RTheight - ((coin->RTheight/bp->n)*bp->n))) >= bp->n-1 )
lasti = bp->n - 1;
orignumemit = bp->numtmpspends;
#ifdef __APPLE__
iterate = 0*(coin->bundlescount-1);
#else
iterate = 0;
#endif
if ( iguana_spendvectors(coin,bp,&coin->RTramchain,coin->RTstarti,lasti,0,iterate) < 0 )
{
printf("RTutxo error -> RTramchainfree\n");
coin->RTdatabad = 1;
return;
}
else
{
printf("RTspendvectors calculated to %d [%d]\n",coin->RTheight,bp->hdrsi);
bp->converted = 1;
for (hdrsi=num=0; hdrsi<bp->hdrsi; hdrsi++)
{
#ifdef __APPLE__
if ( coin->bundles[hdrsi]->lastprefetch == 0 )
{
iguana_ramchain_prefetch(coin,&coin->bundles[hdrsi]->ramchain,2);
coin->bundles[hdrsi]->lastprefetch = (uint32_t)time(NULL);
}
#endif
num += iguana_convert(coin,IGUANA_NUMHELPERS,coin->bundles[hdrsi],1,orignumemit);
}
printf("RTspendvectors converted.%d to %d\n",num,coin->RTheight);
bp->converted = (uint32_t)time(NULL);
if ( iguana_balancegen(coin,1,bp,coin->RTstarti,coin->RTheight > 0 ? coin->RTheight-1 : bp->n-1,orignumemit) < 0 )
coin->RTdatabad = 1;
else if ( coin->RTgenesis == 0 )
printf(">>>>>> IGUANA BTC INITIALIZATION COMPLETE <<<<<<\n");
//printf("iguana_balancegen [%d] (%d to %d)\n",bp->hdrsi,coin->RTstarti,(coin->RTheight-1)%bp->n);
coin->RTstarti = (coin->RTheight % bp->n);
}
}
int32_t iguana_realtime_update(struct iguana_info *coin)
{
double startmillis0; static double totalmillis0; static int32_t num0;
struct iguana_bundle *bp; struct iguana_ramchaindata *rdata; int32_t bundlei,i,n,flag=0; bits256 hash2,*ptr; struct iguana_peer *addr;
struct iguana_block *block=0; struct iguana_blockRO *B; struct iguana_ramchain *dest=0,blockR;
if ( coin->current != 0 && (coin->blocks.hwmchain.height % coin->chain->bundlesize) == coin->chain->bundlesize-1 )
{
block = coin->current->blocks[coin->current->n - 1];
if ( _iguana_chainlink(coin,block) <= 0 )
{
//printf("RT edge case couldnt link\n");
}
else printf("RT edge case.%d\n",block->height);
}
if ( coin->spendvectorsaved <= 1 )
return(0);
for (i=0; i<coin->bundlescount-1; i++)
{
if ( (bp= coin->bundles[i]) != 0 && (i > 0 && bp->utxofinish == 0) )
{
if ( iguana_spendvectors(coin,bp,&bp->ramchain,0,bp->n,0,0) < 0 )
{
printf("error generating spendvectors.[%d], exiting. just restart iguana\n",i);
exit(-1);
} // else printf("generated UTXO.[%d]\n",i);
coin->spendvectorsaved = 1;
}
}
bp = coin->current;
if ( bp == 0 || iguana_validated(coin) < bp->hdrsi )
return(0);
if ( 1 && coin->RTheight > 0 && coin->spendvectorsaved != 1 && coin->bundlescount-1 != coin->balanceswritten )
{
printf("RT mismatch %d != %d\n",coin->bundlescount-1,coin->balanceswritten);
coin->spendvectorsaved = 0;
iguana_RTramchainfree(coin,coin->current);
return(0);
}
if ( coin->RTdatabad == 0 && bp->hdrsi == coin->longestchain/coin->chain->bundlesize && bp->hdrsi >= coin->balanceswritten && coin->RTheight >= bp->bundleheight && coin->RTheight < bp->bundleheight+bp->n && ((coin->RTheight <= coin->blocks.hwmchain.height && time(NULL) > bp->lastRT) || time(NULL) > bp->lastRT+10) )
{
if ( (block= bp->blocks[0]) == 0 || block->txvalid == 0 || block->mainchain == 0 )
{
if ( block != 0 )
{
if ( _iguana_chainlink(coin,block) <= 0 )
{
iguana_blockunmark(coin,block,bp,0,0);
bp->issued[0] = 0;
hash2 = bp->hashes[0];
//char str[65]; printf("RT[0] [%d:%d] %s %p\n",bp->hdrsi,0,bits256_str(str,hash2),block);
addr = coin->peers.ranked[rand() % 8];
if ( addr != 0 && addr->usock >= 0 && addr->dead == 0 )
iguana_sendblockreqPT(coin,addr,bp,0,hash2,0);
}
}
}
//char str[65]; printf("check longest.%d RTheight.%d hwm.%d %s %p\n",coin->longestchain,coin->RTheight,coin->blocks.hwmchain.height,bits256_str(str,bp->hashes[0]),block);
if ( bits256_cmp(coin->RThash1,bp->hashes[1]) != 0 )
coin->RThash1 = bp->hashes[1];
bp->lastRT = (uint32_t)time(NULL);
if ( coin->RTheight < coin->longestchain && coin->peers.numranked > 0 && time(NULL) > coin->RThdrstime+10 )
{
iguana_RThdrs(coin,bp,coin->peers.numranked);
coin->RThdrstime = bp->lastRT;
for (i=0; i<coin->peers.numranked; i++)
{
if ( (addr= coin->peers.ranked[i]) != 0 && addr->usock >= 0 && addr->dead == 0 )
{
//printf("%d ",addr->numRThashes);
}
}
//printf("RTheaders %s\n",coin->symbol);
}
bp->lastRT = (uint32_t)time(NULL);
iguana_RTramchainalloc("RTbundle",coin,bp);
bp->isRT = 1;
while ( (rdata= coin->RTramchain.H.data) != 0 && coin->RTheight <= coin->blocks.hwmchain.height )
{
if ( coin->RTdatabad != 0 )
break;
dest = &coin->RTramchain;
B = (void *)(long)((long)rdata + rdata->Boffset);
bundlei = (coin->RTheight % coin->chain->bundlesize);
if ( (block= iguana_bundleblock(coin,&hash2,bp,bundlei)) != 0 )
iguana_bundlehashadd(coin,bp,bundlei,block);
//printf("RT.%d vs hwm.%d starti.%d bp->n %d block.%p/%p ramchain.%p\n",coin->RTheight,coin->blocks.hwmchain.height,coin->RTstarti,bp->n,block,bp->blocks[bundlei],dest->H.data);
if ( coin->RTdatabad == 0 && block != 0 && bits256_nonz(block->RO.prev_block) != 0 )
{
iguana_blocksetcounters(coin,block,dest);
startmillis0 = OS_milliseconds();
if ( coin->RTdatabad == 0 && iguana_ramchainfile(coin,dest,&blockR,bp,bundlei,block) == 0 )
{
for (i=0; i<bp->n; i++)
if ( GETBIT(bp->haveblock,i) == 0 )
bp->issued[i] = 0;
if ( (n= iguana_bundleissuemissing(coin,bp,3,1.)) > 0 )
printf("RT issued %d priority requests [%d] to unstick stuckiters.%d\n",n,bp->hdrsi,coin->stuckiters);
for (i=bundlei; i<bp->n; i++)
{
block = iguana_bundleblock(coin,&hash2,bp,i);
if ( bits256_nonz(hash2) != 0 && (block == 0 || block->txvalid == 0) )
{
uint8_t serialized[512]; int32_t len; struct iguana_peer *addr;
//char str[65]; printf("RT error [%d:%d] %s %p\n",bp->hdrsi,i,bits256_str(str,hash2),block);
addr = coin->peers.ranked[rand() % 8];
if ( addr != 0 && addr->usock >= 0 && addr->dead == 0 && (len= iguana_getdata(coin,serialized,MSG_BLOCK,&hash2,1)) > 0 )
iguana_send(coin,addr,serialized,len);
coin->RTgenesis = 0;
}
if ( bits256_nonz(hash2) != 0 )
iguana_blockQ("RTerr",coin,bp,i,hash2,1);
break;
}
return(-1);
} else iguana_ramchain_free(coin,&blockR,1);
B[bundlei] = block->RO;
totalmillis0 += (OS_milliseconds() - startmillis0);
num0++;
flag++;
coin->blocks.RO[bp->bundleheight+bundlei] = block->RO;
coin->RTheight++;
printf(">>>> RT.%d hwm.%d L.%d T.%d U.%d S.%d P.%d X.%d -> size.%ld\n",coin->RTheight,coin->blocks.hwmchain.height,coin->longestchain,dest->H.txidind,dest->H.unspentind,dest->H.spendind,dest->pkind,dest->externalind,(long)dest->H.data->allocsize);
if ( coin->RTramchain.H.data != 0 )
coin->RTramchain.H.data->numblocks = bundlei + 1;
else break;
} else break;
}
}
n = 0;
if ( coin->RTdatabad == 0 && dest != 0 && flag != 0 && coin->RTheight >= coin->longestchain )
{
//printf("ramchainiterate.[%d] ave %.2f micros, total %.2f seconds starti.%d num.%d\n",num0,(totalmillis0*1000.)/num0,totalmillis0/1000.,coin->RTstarti,coin->RTheight%bp->n);
if ( (n= iguana_walkchain(coin,1)) == coin->RTheight-1 )
{
//printf("RTgenesis verified\n");
iguana_RTspendvectors(coin,bp);
coin->RTgenesis = (uint32_t)time(NULL);
} else coin->RTdatabad = 1;
}
if ( dest != 0 && flag != 0 )
printf("<<<< flag.%d RT.%d:%d hwm.%d L.%d T.%d U.%d S.%d P.%d X.%d -> size.%ld\n",flag,coin->RTheight,n,coin->blocks.hwmchain.height,coin->longestchain,dest->H.txidind,dest->H.unspentind,dest->H.spendind,dest->pkind,dest->externalind,dest->H.data!=0?(long)dest->H.data->allocsize:-1);
if ( coin->RTdatabad != 0 )
{
iguana_RTramchainfree(coin,bp);
//memset(bp->hashes,0,sizeof(bp->hashes));
memset(bp->blocks,0,sizeof(bp->blocks));
if ( 0 && bp->speculative != 0 )
{
ptr = bp->speculative;
bp->speculative = 0;
memset(ptr,0,sizeof(*bp->speculative)*bp->n);
myfree(ptr,(bp->n+1)*sizeof(*bp->speculative));
}
iguana_RTramchainalloc("RTbundle",coin,bp);
}
return(flag);
}

4
iguana/iguana_rpc.c

@ -330,7 +330,7 @@ static char *getaccountaddress(RPCARGS)
return(sglue1(0,CALLGLUE,"bitcoinrpc","getaccountaddress","account",params[0])); return(sglue1(0,CALLGLUE,"bitcoinrpc","getaccountaddress","account",params[0]));
} }
static char *setaccount(RPCARGS) static char *setaccountrpc(RPCARGS)
{ {
return(sglue2(0,CALLGLUE,"bitcoinrpc","setaccount","address",params[0],"account",params[1])); return(sglue2(0,CALLGLUE,"bitcoinrpc","setaccount","address",params[0],"account",params[1]));
} }
@ -536,7 +536,7 @@ struct RPC_info { char *name; char *(*rpcfunc)(RPCARGS); int32_t flag0,remotefla
{ "getnewaddress", &getnewaddress, true, false }, { "getnewaddress", &getnewaddress, true, false },
{ "getnewpubkey", &makekeypair, true, false }, { "getnewpubkey", &makekeypair, true, false },
{ "getaccountaddress", &getaccountaddress, true, false }, { "getaccountaddress", &getaccountaddress, true, false },
{ "setaccount", &setaccount, true, false }, { "setaccount", &setaccountrpc, true, false },
{ "getaccount", &getaccount, false, false }, { "getaccount", &getaccount, false, false },
{ "getaddressesbyaccount", &getaddressesbyaccount, true, false }, { "getaddressesbyaccount", &getaddressesbyaccount, true, false },
{ "sendtoaddress", &sendtoaddress, false, false }, { "sendtoaddress", &sendtoaddress, false, false },

775
iguana/iguana_sign.c

@ -0,0 +1,775 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "iguana777.h"
#include "exchanges/bitcoin.h"
void iguana_addscript(struct iguana_info *coin,cJSON *dest,uint8_t *script,int32_t scriptlen,char *fieldname)
{
char *scriptstr,scriptbuf[8192+256]; int32_t len; cJSON *scriptobj;
if ( scriptlen < 0 )
return;
if ( scriptlen > sizeof(scriptbuf) )
len = (scriptlen << 1) + 256, scriptstr = malloc(len);
else scriptstr = scriptbuf, len = sizeof(scriptbuf);
init_hexbytes_noT(scriptstr,script,scriptlen);
if ( strcmp(fieldname,"coinbase") == 0 )
jaddstr(dest,"coinbase",scriptstr);
else
{
scriptobj = cJSON_CreateObject();
jaddstr(scriptobj,"hex",scriptstr);
iguana_expandscript(coin,scriptstr,len,script,scriptlen);
if ( scriptstr[0] != 0 )
jaddstr(scriptobj,"asm",scriptstr);
if ( scriptstr != scriptbuf )
free(scriptstr);
jadd(dest,fieldname,scriptobj);
}
}
cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin)
{
char str[65]; int32_t vout; cJSON *json = cJSON_CreateObject();
vout = vin->prev_vout;
jaddnum(json,"sequence",vin->sequence);
if ( vout < 0 && bits256_nonz(vin->prev_hash) == 0 )
iguana_addscript(coin,json,vin->vinscript,vin->scriptlen,"coinbase");
else
{
jaddstr(json,"txid",bits256_str(str,vin->prev_hash));
jaddnum(json,"vout",vout);
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");
}
return(json);
}
int32_t iguana_vinparse(struct iguana_info *coin,int32_t rwflag,uint8_t *serialized,struct iguana_msgvin *msg)
{
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);
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->scriptlen);
if ( msg->scriptlen > IGUANA_MAXSCRIPTSIZE )
{
printf("iguana_vinparse illegal scriptlen.%d\n",msg->scriptlen);
return(-1);
}
if ( rwflag == 0 )
{
msg->vinscript = &serialized[len];
len += msg->scriptlen;
}
else
{
if ( msg->scriptlen > 0 )
{
memcpy(&serialized[len],msg->vinscript,msg->scriptlen);
len += msg->scriptlen;
}
}
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence);
if ( 0 )
{
int32_t i; char str[65];
for (i=0; i<msg->scriptlen; i++)
printf("%02x",msg->vinscript[i]);
printf(" prev_hash.(%s) vout.%d [%p] scriptlen.%d rwflag.%d\n",bits256_str(str,msg->prev_hash),msg->prev_vout,msg->vinscript,msg->scriptlen,rwflag);
}
return(len);
}
int32_t iguana_voutparse(int32_t rwflag,uint8_t *serialized,struct iguana_msgvout *msg)
{
int32_t len = 0;
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->value),&msg->value);
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->pk_scriptlen);
if ( msg->pk_scriptlen > IGUANA_MAXSCRIPTSIZE )
{
printf("iguana_voutparse illegal scriptlen.%d\n",msg->pk_scriptlen);
return(-1);
}
if ( rwflag == 0 )
msg->pk_script = &serialized[len];
else memcpy(&serialized[len],msg->pk_script,msg->pk_scriptlen);
if ( 0 )
{
int32_t i;
for (i=0; i<msg->pk_scriptlen; i++)
printf("%02x",msg->pk_script[i]);
printf(" [%p] scriptlen.%d rwflag.%d %.8f\n",msg->pk_script,msg->pk_scriptlen,rwflag,dstr(msg->value));
}
len += msg->pk_scriptlen;
return(len);
}
int32_t iguana_parsevoutobj(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgvout *vout,cJSON *voutobj)
{
int32_t len = 0; cJSON *skey; char *hexstr;
memset(vout,0,sizeof(*vout));
vout->value = jdouble(voutobj,"value") * SATOSHIDEN;
if ( (skey= jobj(voutobj,"scriptPubKey")) != 0 )
{
if ( (hexstr= jstr(skey,"hex")) != 0 )
{
len = (int32_t)strlen(hexstr) >> 1;
decode_hex(serialized,len,hexstr);
vout->pk_script = serialized;
vout->pk_scriptlen = len;
}
}
return(len);
}
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,*spendstr = 0; cJSON *scriptjson;
memset(vin,0,sizeof(*vin));
vin->prev_vout = -1;
vin->sequence = juint(vinobj,"sequence");
if ( (hexstr= jstr(vinobj,"coinbase")) == 0 )
{
vin->prev_hash = jbits256(vinobj,"txid");
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");
}
if ( hexstr != 0 )
{
len = (int32_t)strlen(hexstr) >> 1;
decode_hex(serialized,len,hexstr);
vin->vinscript = serialized;
vin->scriptlen = len;
serialized = &serialized[len];
} //else printf("iguana_parsevinobj: hex script missing (%s)\n",jprint(vinobj,0));
if ( spendstr != 0 )
{
n = (int32_t)strlen(spendstr) >> 1;
decode_hex(serialized,n,spendstr);
vin->spendscript = serialized;
vin->spendlen = n;
len += n;
}
return(len);
}
cJSON *iguana_voutjson(struct iguana_info *coin,struct iguana_msgvout *vout,int32_t txi,bits256 txid)
{
// 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG
char scriptstr[IGUANA_MAXSCRIPTSIZE+1],asmstr[2*IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp;
uint8_t space[8192]; cJSON *addrs,*skey,*json = cJSON_CreateObject();
vp = calloc(1,sizeof(*vp));
jaddnum(json,"value",dstr(vout->value));
jaddnum(json,"n",txi);
//"scriptPubKey":{"asm":"OP_DUP OP_HASH160 5f69cb73016264270dae9f65c51f60d0e4d6fd44 OP_EQUALVERIFY OP_CHECKSIG","reqSigs":1,"type":"pubkeyhash","addresses":["RHyh1V9syARTf2pyxibz7v27D5paBeWza5"]}
if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) )
{
memset(vp,0,sizeof(*vp));
if ( (asmtype= iguana_calcrmd160(coin,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 )
{
skey = cJSON_CreateObject();
scriptlen = iguana_scriptgen(coin,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi);
if ( asmstr[0] != 0 )
jaddstr(skey,"asm",asmstr);
addrs = cJSON_CreateArray();
if ( vp->N == 1 )
{
if ( asmtype == 2 )
{
jaddnum(skey,"reqSigs",1);
jaddstr(skey,"type","pubkeyhash");
}
if ( vp->coinaddr[0] != 0 )
jaddistr(addrs,vp->coinaddr);
}
else
{
jaddnum(skey,"reqSigs",vp->M);
for (i=0; i<vp->N; i++)
{
//btc_convrmd160(coinaddr,coin->chain->pubtype,V.signers[i].pubkey);
jaddistr(addrs,vp->signers[i].coinaddr);
}
}
jadd(skey,"addresses",addrs);
init_hexbytes_noT(scriptstr,vout->pk_script,vout->pk_scriptlen);
if ( scriptstr[0] != 0 )
jaddstr(skey,"hex",scriptstr);
jadd(json,"scriptPubKey",skey);
}
}
return(json);
}
int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr)
{
int32_t i,n,len = 0; uint8_t *txstart = serialized; char txidstr[65]; cJSON *array=0;
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version);
if ( json != 0 )
{
jaddnum(json,"version",msg->version);
array = cJSON_CreateArray();
}
//printf("version.%d\n",msg->version);
if ( coin->chain->hastimestamp != 0 )
{
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->timestamp),&msg->timestamp);
//char str[65]; printf("version.%d timestamp.%08x %u %s\n",msg->version,msg->timestamp,msg->timestamp,utc_str(str,msg->timestamp));
if ( json != 0 )
jaddnum(json,"timestamp",msg->timestamp);
}
//for (i=len; i<len+16; i++)
// printf("%02x",serialized[i]);
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_in);
//printf(" tx_in.%08x\n",msg->tx_in);
if ( rwflag == 0 )
{
if ( len + sizeof(struct iguana_msgvin)*msg->tx_in > maxsize )
{
printf("len.%d + tx_in.%d > maxsize.%d\n",len,msg->tx_in,maxsize);
return(-1);
}
maxsize -= (sizeof(struct iguana_msgvin) * msg->tx_in);
msg->vins = (struct iguana_msgvin *)&serialized[maxsize];
memset(msg->vins,0,sizeof(struct iguana_msgvin) * msg->tx_in);
}
for (i=0; i<msg->tx_in; i++)
{
if ( (n= iguana_vinparse(coin,rwflag,&serialized[len],&msg->vins[i])) < 0 )
return(-1);
//printf("vin.%d n.%d len.%d\n",i,n,len);
len += n;
if ( len > maxsize )
{
printf("invalid tx_in.%d len.%d vs maxsize.%d\n",msg->tx_in,len,maxsize);
return(-1);
}
if ( array != 0 )
jaddi(array,iguana_vinjson(coin,&msg->vins[i]));
}
if ( array != 0 )
{
jadd(json,"vin",array);
jaddnum(json,"numvins",msg->tx_in);
array = cJSON_CreateArray();
}
//for (i=len; i<len+16; i++)
// printf("%02x",serialized[i]);
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_out);
//printf(" txout.%d\n",msg->tx_out);
if ( rwflag == 0 )
{
if ( len + sizeof(struct iguana_msgvout)*msg->tx_out > maxsize )
{
printf("len.%d + tx_in.%d > maxsize.%d\n",len,msg->tx_in,maxsize);
return(-1);
}
maxsize -= (sizeof(struct iguana_msgvout) * msg->tx_out);
msg->vouts = (struct iguana_msgvout *)&serialized[maxsize];
memset(msg->vouts,0,sizeof(struct iguana_msgvout) * msg->tx_out);
}
for (i=0; i<msg->tx_out; i++)
{
if ( (n= iguana_voutparse(rwflag,&serialized[len],&msg->vouts[i])) < 0 )
return(-1);
len += n;
if ( len > maxsize )
{
printf("invalid tx_out.%d len.%d vs maxsize.%d\n",msg->tx_out,len,maxsize);
return(-1);
}
if ( array != 0 )
jaddi(array,iguana_voutjson(coin,&msg->vouts[i],i,*txidp));
}
if ( array != 0 )
{
jadd(json,"vout",array);
jaddnum(json,"numvouts",msg->tx_out);
}
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time);
//printf("lock_time.%08x\n",msg->lock_time);
if ( strcmp(coin->symbol,"VPN") == 0 )
{
uint16_t ddosflag = 0;
len += iguana_rwnum(rwflag,&serialized[len],sizeof(ddosflag),&ddosflag);
for (i=0; serialized[len]!=0&&len<maxsize; len++,i++) // eat null terminated string
{
if ( rwflag == 0 )
serialized[len] = vpnstr[i];
else vpnstr[i] = serialized[len];
}
if ( rwflag == 0 )
serialized[len] = 0;
else vpnstr[i] = 0;
len++;
if ( json != 0 )
{
jaddnum(json,"ddosflag",ddosflag);
jaddstr(json,"vpnstr",vpnstr);
}
}
*txidp = bits256_doublesha256(txidstr,txstart,len);
if ( json != 0 )
{
jaddnum(json,"locktime",msg->lock_time);
jaddnum(json,"size",len);
jaddbits256(json,"txid",*txidp);
//printf("TX.(%s) %p\n",jprint(json,0),json);
}
msg->allocsize = len;
return(len);
}
bits256 iguana_parsetxobj(struct iguana_info *coin,int32_t *txstartp,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,cJSON *txobj) // json -> serialized + (msg,V)
{
int32_t i,numvins,numvouts,len = 0; cJSON *array=0; bits256 txid; char vpnstr[64];
memset(msg,0,sizeof(*msg));
vpnstr[0] = 0;
if ( (msg->version= juint(txobj,"version")) == 0 )
msg->version = 1;
if ( coin->chain->hastimestamp != 0 )
{
if ( (msg->timestamp= juint(txobj,"timestamp")) == 0 )
msg->timestamp = (uint32_t)time(NULL);
}
if ( (array= jarray(&numvins,txobj,"vin")) != 0 )
{
msg->tx_in = numvins;
if ( len + sizeof(struct iguana_msgvin)*msg->tx_in > maxsize )
return(msg->txid);
maxsize -= (sizeof(struct iguana_msgvin) * msg->tx_in);
msg->vins = (struct iguana_msgvin *)&serialized[maxsize];
if ( msg->tx_in > 0 && msg->tx_in*sizeof(struct iguana_msgvin) < maxsize )
{
for (i=0; i<msg->tx_in; i++)
len += iguana_parsevinobj(coin,&serialized[len],maxsize,&msg->vins[i],jitem(array,i));
}
}
if ( (array= jarray(&numvouts,txobj,"vout")) != 0 )
{
msg->tx_out = numvouts;
if ( len + sizeof(struct iguana_msgvout)*msg->tx_out > maxsize )
return(msg->txid);
maxsize -= (sizeof(struct iguana_msgvout) * msg->tx_out);
msg->vouts = (struct iguana_msgvout *)&serialized[maxsize];
if ( msg->tx_out > 0 && msg->tx_out*sizeof(struct iguana_msgvout) < maxsize )
{
for (i=0; i<msg->tx_out; i++)
len += iguana_parsevoutobj(coin,&serialized[len],maxsize,&msg->vouts[i],jitem(array,i));
}
}
msg->lock_time = juint(txobj,"locktime");
msg->txid = jbits256(txobj,"txid");
*txstartp = len;
if ( (msg->allocsize= iguana_rwmsgtx(coin,1,0,&serialized[len],maxsize-len,msg,&txid,vpnstr)) < 0 )
{
memset(txid.bytes,0,sizeof(txid));
printf("error parsing txobj\n");
msg->allocsize = 0;
}
//char str[65]; printf("json -> %s\n",bits256_str(str,txid));
return(txid);
}
char *iguana_rawtxbytes(struct iguana_info *coin,cJSON *json,struct iguana_msgtx *msgtx)
{
int32_t n; char *txbytes = 0,vpnstr[64]; uint8_t *serialized;
serialized = malloc(IGUANA_MAXPACKETSIZE);
vpnstr[0] = 0;
//char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid));
if ( (n= iguana_rwmsgtx(coin,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr)) > 0 )
{
txbytes = malloc(n*2+1);
init_hexbytes_noT(txbytes,serialized,n);
}
free(serialized);
return(txbytes);
}
cJSON *bitcoin_createtx(struct iguana_info *coin,uint32_t locktime)
{
cJSON *json = cJSON_CreateObject();
if ( locktime == 0 )
{
jaddnum(json,"version",1);
jaddnum(json,"locktime",0);
}
else
{
jaddnum(json,"version",4);
jaddnum(json,"locktime",locktime);
}
if ( coin->chain->hastimestamp != 0 )
jaddnum(json,"timestamp",time(NULL));
jadd(json,"vin",cJSON_CreateArray());
jadd(json,"vout",cJSON_CreateArray());
return(json);
}
cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis)
{
char *hexstr; cJSON *item,*skey,*vouts = jduplicate(jobj(txobj,"vout"));
jdelete(txobj,"vout");
item = cJSON_CreateObject();
jaddnum(item,"value",dstr(satoshis));
skey = cJSON_CreateObject();
hexstr = malloc(len*2 + 1);
init_hexbytes_noT(hexstr,paymentscript,len);
jaddstr(skey,"hex",hexstr);
//printf("addoutput.(%s %s)\n",hexstr,jprint(skey,0));
free(hexstr);
jadd(item,"scriptPubkey",skey);
jaddi(vouts,item);
jadd(txobj,"vout",vouts);
return(txobj);
}
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)
{
cJSON *item,*vins; char p2shscriptstr[IGUANA_MAXSCRIPTSIZE*2+1];
vins = jduplicate(jobj(txobj,"vin"));
jdelete(txobj,"vin");
item = cJSON_CreateObject();
if ( spendscript != 0 && spendscript > 0 )
iguana_addscript(coin,item,spendscript,spendlen,"scriptPubKey");
if ( redeemscript != 0 && p2shlen > 0 )
{
init_hexbytes_noT(p2shscriptstr,redeemscript,p2shlen);
jaddstr(item,"redeemScript",p2shscriptstr);
}
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));
return(txobj);
}
char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson)
{
int32_t txstart; uint8_t *serialized; struct iguana_msgtx msgtx; char *txbytes = 0;
serialized = malloc(IGUANA_MAXPACKETSIZE*1.5);
*txidp = iguana_parsetxobj(coin,&txstart,serialized,IGUANA_MAXPACKETSIZE*1.5,&msgtx,txjson);
if ( msgtx.allocsize > 0 )
{
txbytes = malloc(msgtx.allocsize*2 + 1);
init_hexbytes_noT(txbytes,&serialized[txstart],msgtx.allocsize);
} else printf("bitcoin_txtest: zero msgtx allocsize.(%s)\n",jprint(txjson,0));
free(serialized);
return(txbytes);
}
cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes)
{
int32_t n,len; char vpnstr[64]; struct iguana_msgtx M; uint8_t *serialized; cJSON *txobj;
txobj = cJSON_CreateObject();
if ( msgtx == 0 )
{
msgtx = &M;
memset(msgtx,0,sizeof(M));
}
len = (int32_t)strlen(txbytes) >> 1;
serialized = malloc(len + 32768);
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");
free_json(txobj);
txobj = 0;
}
free(serialized);
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)
{
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;
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++)
{
//saveinput = msgtx->vins[vini].vinscript;
vp = &V[vini];
sig = &msgtx->vins[vini].vinscript[1];
siglen = msgtx->vins[vini].vinscript[0];
vp->vin = msgtx->vins[vini];
flag = 0;
for (k=0; k<2; k++)
{
asmtype = (k == 0) ? IGUANA_SCRIPT_76A988AC : IGUANA_SCRIPT_76AC;
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 ( sighashsingle != 0 && vini == 0 )
{
msgtx->tx_out = 1;
hashtype = SIGHASH_SINGLE;
} else msgtx->tx_out = numvouts;
msgtx->vins[vini].spendscript = vp->spendscript;
msgtx->vins[vini].spendlen = vp->spendlen;
msgtx->vins[vini].sequence = vp->sequence;
for (j=0; j<vp->N; j++)
{
pubkey = vp->signers[j].pubkey;
if ( (plen= bitcoin_pubkeylen(pubkey)) < 0 )
{
if ( bits256_nonz(vp->signers[j].privkey) > 0 )
{
pubkey = vp->signers[j].pubkey;
bitcoin_pubkey33(pubkey,vp->signers[j].privkey);
plen = bitcoin_pubkeylen(pubkey);
}
if ( plen < 0 )
{
printf("nopubkey for j.%d vini.%d plen.%d [%02x]\n",j,vini,plen,pubkey[0]);
continue;
}
}
bitcoin_address(coinaddr,coin->chain->pubtype,pubkey,plen);
n2 = iguana_rwmsgtx(coin,1,0,serialized,maxsize,msgtx,&txid,vpnstr);
if ( n2 > 0 )
{
n2 += iguana_rwnum(1,&serialized[n2],sizeof(hashtype),&hashtype);
//printf("hashtype.%d [%02x]\n",hashtype,sig[siglen-1]);
revsigtxid = bits256_doublesha256(txidstr,serialized,n2);
for (i=0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31-i] = revsigtxid.bytes[i];
if ( 1 && bits256_nonz(vp->signers[j].privkey) != 0 )
{
siglen = bitcoin_sign(vp->signers[j].sig,sizeof(vp->signers[j].sig),sigtxid.bytes,sizeof(sigtxid),vp->signers[j].privkey);
sig = vp->signers[j].sig;
sig[siglen++] = hashtype;
vp->signers[j].siglen = siglen;
msgtx->vins[vini].vinscript = calloc(1,siglen*2+256); // fix this memleak!
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);
}
if ( bitcoin_verify(sig,siglen,sigtxid.bytes,sizeof(sigtxid),vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 )
{
init_hexbytes_noT(bigstr,serialized,n2);
printf("(%s) doesnt verify hash2.%s\n",bigstr,bits256_str(str,sigtxid));
*signedtx = iguana_rawtxbytes(coin,0,msgtx);
*signedtxidp = msgtx->txid;
printf("SIG.%d ERROR %s\n",vini,*signedtx);
}
else
{
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));
flag = 1;
break;
}
} else printf("bitcoin_verifyvins: vini.%d n2.%d\n",vini,n2);
}
if ( flag > 0 )
{
retval++;
break;
}
if ( vp->type != IGUANA_SCRIPT_76A988AC && vp->type != IGUANA_SCRIPT_76AC )
break;
}
}
return(retval);
}
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V)
{
int32_t len,maxsize,numvins,retval = -1; uint8_t *serialized,*serialized2;
struct iguana_msgtx msgtx; bits256 txid; char vpnstr[64];
len = (int32_t)strlen(rawtxstr);
maxsize = len + 32768;
serialized = calloc(1,maxsize), serialized2 = calloc(1,maxsize);
len >>= 1;
vpnstr[0] = 0;
decode_hex(serialized,len,rawtxstr);
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 )
retval = 0;
else printf("bitcoin_verifytx: bitcoin_verifyvins error\n");
} else printf("bitcoin_verifytx: error iguana_rwmsgtx\n");
free(serialized), free(serialized2);
return(retval);
}
cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj)
{
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
{
if ( *signedtxp != 0 )
{
if ( txobj != 0 )
free_json(txobj);
txobj = bitcoin_hex2json(coin,&txid,0,*signedtxp);
free(*signedtxp);
}
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];
}
if ( spend->inputs[i].spendlen > 0 )
{
memcpy(V.spendscript,spend->inputs[i].spendscript,spend->inputs[i].spendlen);
V.spendlen = spend->inputs[i].spendlen;
}
V.sequence = spend->inputs[i].sequence;
//printf("json2hex.(%s)\n",rawtxstr);
bitcoin_verifytx(coin,txidp,signedtxp,rawtxstr,&V);
//printf("json2hex.(%s)\n",rawtxstr);
free(rawtxstr);
} else break;
}
if ( *signedtxp != 0 && i != spend->numinputs )
free(*signedtxp), *signedtxp = 0;
return(txobj);
}
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
char *_setVsigner(struct iguana_info *coin,struct vin_info *V,int32_t ind,char *pubstr,char *wifstr)
{
uint8_t addrtype;
decode_hex(V->signers[ind].pubkey,(int32_t)strlen(pubstr)/2,pubstr);
bitcoin_wif2priv(&addrtype,&V->signers[ind].privkey,wifstr);
if ( addrtype != coin->chain->pubtype )
return(clonestr("{\"error\":\"invalid wifA\"}"));
else return(0);
}
int32_t bitcoin_txaddspend(struct iguana_info *coin,cJSON *txobj,char *destaddress,double destamount)
{
uint8_t outputscript[128],addrtype,rmd160[20]; int32_t scriptlen;
if ( bitcoin_validaddress(coin,destaddress) == 0 && destamount > 0. )
{
bitcoin_addr2rmd160(&addrtype,rmd160,destaddress);
scriptlen = bitcoin_standardspend(outputscript,0,rmd160);
bitcoin_addoutput(coin,txobj,outputscript,scriptlen,destamount * SATOSHIDEN);
return(0);
} else return(-1);
}
P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount,destaddress2,destamount2,M,N,pubA,wifA,pubB,wifB,pubC,wifC)
{
struct vin_info V; uint8_t p2sh_rmd160[20],serialized[2096],spendscript[32]; int32_t spendlen;
char msigaddr[64],*retstr; cJSON *retjson,*txobj; struct iguana_info *active;
bits256 signedtxid; char *signedtx;
struct iguana_msgtx msgtx;
if ( (active= iguana_coinfind(activecoin)) == 0 )
return(clonestr("{\"error\":\"activecoin isnt active\"}"));
if ( M > N || N > 3 )
return(clonestr("{\"error\":\"illegal M or N\"}"));
memset(&V,0,sizeof(V));
txobj = bitcoin_createtx(active,0);
if ( destaddress[0] != 0 && destamount > 0. )
bitcoin_txaddspend(active,txobj,destaddress,destamount);
if ( destaddress2[0] != 0 && destamount2 > 0. )
bitcoin_txaddspend(active,txobj,destaddress2,destamount2);
if ( pubA[0] != 0 && (retstr= _setVsigner(active,&V,0,pubA,wifA)) != 0 )
return(retstr);
if ( N >= 2 && pubB[0] != 0 && (retstr= _setVsigner(active,&V,1,pubB,wifB)) != 0 )
return(retstr);
if ( N == 3 && pubC[0] != 0 && (retstr= _setVsigner(active,&V,2,pubC,wifC)) != 0 )
return(retstr);
V.M = M, V.N = N, V.type = IGUANA_SCRIPT_P2SH;
V.p2shlen = bitcoin_MofNspendscript(p2sh_rmd160,V.p2shscript,0,&V);
spendlen = bitcoin_p2shspend(spendscript,0,p2sh_rmd160);
bitcoin_addinput(active,txobj,vintxid,vinvout,0xffffffff,spendscript,spendlen,V.p2shscript,V.p2shlen);
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 )
{
jaddstr(retjson,"result","msigtx");
if ( signedtx != 0 )
jaddstr(retjson,"signedtx",signedtx), free(signedtx);
jaddbits256(retjson,"txid",signedtxid);
} else jaddstr(retjson,"error","couldnt sign tx");
jaddstr(retjson,"msigaddr",msigaddr);
return(jprint(retjson,1));
}
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();
//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";
if ( strcmp(sighash,"ALL") != 0 )
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 )
{
spend = calloc(1,sizeof(*spend) + (sizeof(*spend->inputs) * numinputs));
spend->numinputs = numinputs;
for (i=0; i<n; i++)
{
item = jitem(privkeys,i);
privkeystr = jstr(item,0);
privkey = iguana_str2priv(myinfo,coin,privkeystr);
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);
}
}
txobj = iguana_signtx(coin,&txid,&signedtx,spend,txobj);
free(spend);
free_json(txobj);
if ( signedtx != 0 )
{
jaddstr(retjson,"result",signedtx);
free(signedtx);
}
}
}
return(jprint(retjson,1));
}
#include "../includes/iguana_apiundefs.h"

1101
iguana/iguana_spendvectors.c

File diff suppressed because it is too large

609
iguana/iguana_txidfind.c

@ -0,0 +1,609 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "iguana777.h"
int32_t iguana_alloctxbits(struct iguana_info *coin,struct iguana_ramchain *ramchain)
{
static int64_t total;
if ( ramchain->txbits == 0 )
{
int32_t tlen; uint8_t *TXbits = (uint8_t *)((long)ramchain->H.data + ramchain->H.data->TXoffset);
tlen = (int32_t)hconv_bitlen(ramchain->H.data->numtxsparse * ramchain->H.data->txsparsebits);
ramchain->txbits = calloc(1,tlen);
memcpy(ramchain->txbits,TXbits,tlen);
total += tlen;
char str[65]; printf("alloc.[%d] txbits.%p[%d] total %s\n",ramchain->H.data->height/coin->chain->bundlesize,ramchain->txbits,tlen,mbstr(str,total));
return(tlen);
}
return(-1);
}
int32_t iguana_alloccacheT(struct iguana_info *coin,struct iguana_ramchain *ramchain)
{
static int64_t total;
if ( ramchain->cacheT == 0 )
{
int32_t i,tlen; struct iguana_txid *T = (void *)((long)ramchain->H.data + ramchain->H.data->Toffset);
tlen = sizeof(*T) * ramchain->H.data->numtxids;
if ( (ramchain->cacheT= calloc(1,tlen)) != 0 )
{
//memcpy(ramchain->cacheT,T,tlen);
for (i=0; i<ramchain->H.data->numtxids; i++)
ramchain->cacheT[i] = T[i];
} else ramchain->cacheT = T;
total += tlen;
char str[65]; printf("alloc.[%d] cacheT.%p[%d] total %s\n",ramchain->H.data->height/coin->chain->bundlesize,ramchain->cacheT,tlen,mbstr(str,total));
return(tlen);
}
return(-1);
}
uint32_t iguana_sparseadd(uint8_t *bits,uint32_t ind,int32_t width,uint32_t tablesize,uint8_t *key,int32_t keylen,uint32_t setind,void *refdata,int32_t refsize,struct iguana_ramchain *ramchain,uint32_t maxitems)
{
static uint8_t masks[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
int32_t i,j,x,n,modval; int64_t bitoffset; uint8_t *ptr; uint32_t *table,retval = 0;
if ( tablesize == 0 )
{
printf("iguana_sparseadd tablesize zero illegal\n");
return(0);
}
if ( 0 && setind == 0 )
{
char str[65];
for (i=n=0; i<tablesize; i++)
{
bitoffset = (i * width);
ptr = &bits[bitoffset >> 3];
modval = (bitoffset & 7);
for (x=j=0; j<width; j++,modval++)
{
if ( modval >= 8 )
ptr++, modval = 0;
x <<= 1;
x |= (*ptr & masks[modval]) >> modval;
}
if ( x != 0 )
printf("%s ",bits256_str(str,*(bits256 *)(refdata + x*refsize))), n++;
}
printf("tableentries.%d\n",n);
}
//if ( setind == 0 )
// ramchain->sparsesearches++;
//else ramchain->sparseadds++;
if ( 0 && (ramchain->sparsesearches % 1000000) == 0 )
printf("[%3d] %7d.[%-2d %8d] %5.3f adds.(%-10ld %10ld) search.(hits.%-10ld %10ld) %5.2f%% max.%ld\n",ramchain->height/ramchain->H.data->numblocks,ramchain->height,width,tablesize,(double)(ramchain->sparseadditers + ramchain->sparsesearchiters)/(1+ramchain->sparsesearches+ramchain->sparseadds),ramchain->sparseadds,ramchain->sparseadditers,ramchain->sparsehits,ramchain->sparsesearches,100.*(double)ramchain->sparsehits/(1+ramchain->sparsesearches),ramchain->sparsemax+1);
if ( width == 32 )
{
table = (uint32_t *)bits;
for (i=0; i<tablesize; i++,ind++)
{
if ( ind >= tablesize )
ind = 0;
if ( (x= table[ind]) == 0 )
{
//if ( ++i > ramchain->sparsemax )
// ramchain->sparsemax = i;
if ( (retval= setind) != 0 )
{
//ramchain->sparseadditers += i;
table[ind] = setind;
} //else ramchain->sparsesearchiters += i;
return(setind);
}
else if ( x < maxitems && memcmp((void *)(long)((long)refdata + x*refsize),key,keylen) == 0 )
{
if ( setind != 0 && setind != x )
printf("sparseadd index collision setind.%d != x.%d refsize.%d keylen.%d\n",setind,x,refsize,keylen);
//ramchain->sparsehits++;
//if ( ++i > ramchain->sparsemax )
// ramchain->sparsemax = i;
//ramchain->sparseadditers += i;
return(x);
}
}
}
else
{
bitoffset = (ind * width);
if ( 0 && setind == 0 )
printf("tablesize.%d width.%d bitoffset.%d\n",tablesize,width,(int32_t)bitoffset);
for (i=0; i<tablesize; i++,ind++,bitoffset+=width)
{
if ( ind >= tablesize )
{
ind = 0;
bitoffset = 0;
}
x = 0;
if ( width == 32 )
memcpy(&x,&bits[bitoffset >> 3],4);
else if ( width == 16 )
memcpy(&x,&bits[bitoffset >> 3],2);
else if ( width != 8 )
{
ptr = &bits[bitoffset >> 3];
modval = (bitoffset & 7);
if ( 0 && setind == 0 )
printf("tablesize.%d width.%d bitoffset.%d modval.%d i.%d\n",tablesize,width,(int32_t)bitoffset,modval,i);
for (x=j=0; j<width; j++,modval++)
{
if ( modval >= 8 )
ptr++, modval = 0;
x <<= 1;
x |= (*ptr & masks[modval]) >> modval;
}
}
else x = bits[bitoffset >> 3];
if ( 0 && setind == 0 )
printf("x.%d\n",x);
if ( x == 0 )
{
if ( (x= setind) == 0 )
{
//ramchain->sparsesearchiters += (i+1);
return(0);
}
//else ramchain->sparseadditers += (i+1);
if ( width == 32 )
memcpy(&bits[bitoffset >> 3],&setind,4);
else if ( width == 16 )
memcpy(&bits[bitoffset >> 3],&setind,2);
else if ( width != 8 )
{
ptr = &bits[(bitoffset+width-1) >> 3];
modval = ((bitoffset+width-1) & 7);
for (j=0; j<width; j++,x>>=1,modval--)
{
if ( modval < 0 )
ptr--, modval = 7;
if ( (x & 1) != 0 )
*ptr |= masks[modval];
}
}
else bits[bitoffset >> 3] = setind;
if ( 0 )
{
for (x=j=0; j<width; j++)
{
x <<= 1;
x |= GETBIT(bits,bitoffset+width-1-j) != 0;
}
//if ( x != setind )
printf("x.%u vs setind.%d ind.%d bitoffset.%d, width.%d\n",x,setind,ind,(int32_t)bitoffset,width);
}
//if ( i > ramchain->sparsemax )
// ramchain->sparsemax = i;
return(setind);
}
else if ( x < maxitems && memcmp((void *)(long)((long)refdata + x*refsize),key,keylen) == 0 )
{
if ( setind == 0 )
ramchain->sparsehits++;
else if ( setind != x )
printf("sparseadd index collision setind.%d != x.%d refsize.%d keylen.%d\n",setind,x,refsize,keylen);
if ( i > ramchain->sparsemax )
ramchain->sparsemax = i;
return(x);
}
}
}
return(0);
}
uint32_t iguana_sparseaddtx(uint8_t *bits,int32_t width,uint32_t tablesize,bits256 txid,struct iguana_txid *T,uint32_t txidind,struct iguana_ramchain *ramchain)
{
uint32_t ind,retval;
//char str[65]; printf("sparseaddtx %s txidind.%d bits.%p\n",bits256_str(str,txid),txidind,bits);
ind = (txid.ulongs[0] ^ txid.ulongs[1] ^ txid.ulongs[2] ^ txid.ulongs[3]) % tablesize;
if ( (retval= iguana_sparseadd(bits,ind,width,tablesize,txid.bytes,sizeof(txid),txidind,T,sizeof(*T),ramchain,ramchain->H.data->numtxids)) != 0 )
{
char str[65];
if ( txidind != 0 && retval != txidind )
printf("sparse tx collision %s %u vs %u\n",bits256_str(str,txid),retval,txidind);
return(retval);
}
return(retval);
}
uint32_t iguana_sparseaddpk(uint8_t *bits,int32_t width,uint32_t tablesize,uint8_t rmd160[20],struct iguana_pkhash *P,uint32_t pkind,struct iguana_ramchain *ramchain)
{
uint32_t ind,key2; uint64_t key0,key1;
//int32_t i; for (i=0; i<20; i++)
// printf("%02x",rmd160[i]);
//char str[65]; printf(" sparseaddpk pkind.%d bits.%p\n",pkind,bits);
memcpy(&key0,rmd160,sizeof(key0));
memcpy(&key1,&rmd160[sizeof(key0)],sizeof(key1));
memcpy(&key2,&rmd160[sizeof(key0) + sizeof(key1)],sizeof(key2));
ind = (key0 ^ key1 ^ key2) % tablesize;
return(iguana_sparseadd(bits,ind,width,tablesize,rmd160,20,pkind,P,sizeof(*P),ramchain,ramchain->H.data->numpkinds));
}
int32_t iguana_ramchain_spendtxid(struct iguana_info *coin,uint32_t *unspentindp,bits256 *txidp,struct iguana_txid *T,int32_t numtxids,bits256 *X,int32_t numexternaltxids,struct iguana_spend *s)
{
uint32_t ind,external;
*unspentindp = 0;
memset(txidp,0,sizeof(*txidp));
ind = s->spendtxidind;
external = (ind >> 31) & 1;
ind &= ~(1 << 31);
//printf("s.%p ramchaintxid vout.%x spendtxidind.%d isext.%d ext.%d ind.%d\n",s,s->prevout,ind,s->external,external,ind);
if ( s->prevout < 0 )
return(-1);
if ( s->external != 0 && s->external == external && ind < numexternaltxids )
{
//printf("ind.%d X.%p[%d]\n",ind,X,numexternaltxids);
*txidp = X[ind];
return(s->prevout);
}
else if ( s->external == 0 && s->external == external && ind < numtxids )
{
*txidp = T[ind].txid;
*unspentindp = T[ind].firstvout + s->prevout;
return(s->prevout);
}
return(-2);
}
struct iguana_txid *iguana_txidfind(struct iguana_info *coin,int32_t *heightp,struct iguana_txid *tx,bits256 txid,int32_t lasthdrsi)
{
uint8_t *TXbits; struct iguana_txid *T; uint32_t txidind; int32_t i;
struct iguana_bundle *bp; struct iguana_ramchain *ramchain; //struct iguana_block *block;
*heightp = -1;
if ( lasthdrsi < 0 )
return(0);
for (i=lasthdrsi; i>=0; i--)
{
if ( (bp= coin->bundles[i]) != 0 && (bp == coin->current || bp->emitfinish > 1) )
{
ramchain = (bp == coin->current) ? &coin->RTramchain : &bp->ramchain;
if ( ramchain->H.data != 0 )
{
if ( (TXbits= ramchain->txbits) == 0 )
{
if ( coin->fastfind == 0 && bp != coin->current )
iguana_alloctxbits(coin,ramchain);
if ( (TXbits= ramchain->txbits) == 0 )
{
//printf("use memory mapped.[%d]\n",ramchain->H.data->height/coin->chain->bundlesize);
TXbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->TXoffset);
}
}
if ( (T= ramchain->cacheT) == 0 )
{
//if ( coin->fastfind == 0 )
// iguana_alloccacheT(coin,ramchain);
//if ( (T= ramchain->cacheT) == 0 )
T = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Toffset);
}
if ( (txidind= iguana_sparseaddtx(TXbits,ramchain->H.data->txsparsebits,ramchain->H.data->numtxsparse,txid,T,0,ramchain)) > 0 )
{
//printf("found txidind.%d\n",txidind);
if ( bits256_cmp(txid,T[txidind].txid) == 0 )
{
if ( 0 )
{
int32_t j; struct iguana_block *block;
for (j=0; j<bp->n; j++)
if ( (block= bp->blocks[j]) != 0 && txidind >= block->RO.firsttxidind && txidind < block->RO.firsttxidind+block->RO.txn_count )
break;
if ( j < bp->n )
{
if ( j != T[txidind].bundlei )
printf("bundlei mismatch j.%d != %d\n",j,T[txidind].bundlei);
else
{
*heightp = bp->bundleheight + T[txidind].bundlei;
//printf("found height.%d\n",*heightp);
*tx = T[txidind];
return(tx);
}
}
}
else
{
*heightp = bp->bundleheight + T[txidind].bundlei;
//printf("found height.%d\n",*heightp);
*tx = T[txidind];
return(tx);
}
}
char str[65],str2[65]; printf("iguana_txidfind mismatch.[%d:%d] %d %s vs %s\n",bp->hdrsi,T[txidind].extraoffset,txidind,bits256_str(str,txid),bits256_str(str2,T[txidind].txid));
return(0);
}
}
}
}
return(0);
}
int32_t iguana_txidfastfind(struct iguana_info *coin,int32_t *heightp,bits256 txid,int32_t lasthdrsi)
{
uint8_t *sorted,*item; int32_t i,j,val,num,tablesize,*hashtable; uint32_t firstvout;
if ( (sorted= coin->fast[txid.bytes[31]]) != 0 )
{
memcpy(&num,sorted,sizeof(num));
memcpy(&tablesize,&sorted[sizeof(num)],sizeof(tablesize));
if ( (hashtable= coin->fasttables[txid.bytes[31]]) == 0 )
{
hashtable = (int32_t *)((long)sorted + (1 + num)*16);
//printf("backup hashtable\n");
}
val = (txid.uints[4] % tablesize);
for (j=0; j<tablesize; j++,val++)
{
if ( val >= tablesize )
val = 0;
if ( (i= hashtable[val]) == 0 )
return(-1);
else
{
if ( i > num )
{
printf("illegal val.%d vs num.%d tablesize.%d fastfind.%02x\n",i,num,tablesize,txid.bytes[31]);
return(-1);
}
else
{
item = (void *)((long)sorted + i*16);
if ( memcmp(&txid.txid,item,sizeof(uint64_t)) == 0 )
{
memcpy(&firstvout,&item[sizeof(uint64_t)],sizeof(firstvout));
memcpy(heightp,&item[sizeof(uint64_t) + sizeof(firstvout)],sizeof(*heightp));
//printf("i.%d val.%d height.%d firstvout.%d j.%d\n",i,val,*heightp,firstvout,j);
if ( *heightp >= (lasthdrsi+1)*coin->chain->bundlesize )
{
printf("txidfastfind: unexpected height.%d with lasthdrsi.%d\n",*heightp,lasthdrsi);
return(-1);
}
return(firstvout);
}
else if ( 0 )
{
int32_t k;
for (k=-16; k<0; k++)
printf("%02x ",item[k]);
printf("<");
for (k=0; k<16; k++)
printf("%02x ",item[k]);
printf(">");
for (k=16; k<32; k++)
printf("%02x ",item[k]);
printf("\n");
printf("txid.%llx vs item.%llx ht.%d 1st.%d\n",(long long)txid.txid,*(long long *)item,*(int32_t *)&item[sizeof(uint64_t)],*(int32_t *)&item[sizeof(uint64_t)+sizeof(uint32_t)]);
}
}
}
}
}
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;
if ( bits256_nonz(txid) != 0 && (fp= coin->fastfps[txid.bytes[31]]) != 0 )
{
txid.uints[6] = firstvout;
txid.uints[7] = height;
if ( fwrite(&txid,1,sizeof(txid),fp) == sizeof(txid) )
return(1);
}
return(0);
}
int64_t iguana_fastfindinitbundle(struct iguana_info *coin,struct iguana_bundle *bp,int32_t iter)
{
int32_t i; struct iguana_txid *T; struct iguana_ramchaindata *rdata; int64_t n = 0;
if ( (rdata= bp->ramchain.H.data) != 0 )
{
T = (void *)(long)((long)rdata + rdata->Toffset);
n = rdata->numtxids;
if ( iter == 1 )
{
for (i=0; i<n; i++)
iguana_fastfindadd(coin,T[i].txid,bp->bundleheight + T[i].bundlei,T[i].firstvout);
fprintf(stderr,"[%d:%u] ",bp->hdrsi,(int32_t)n);
}
}
return(n);
}
static int _bignum_cmp(const void *a,const void *b)
{
uint8_t *biga,*bigb; int32_t i,diff;
biga = (uint8_t *)a;
bigb = (uint8_t *)b;
for (i=0; i<32; i++)
{
if ( (diff= (biga[i] - bigb[i])) > 0 )
return(1);
else if ( diff < 0 )
return(-1);
}
return(0);
}
uint32_t iguana_fastfindinit(struct iguana_info *coin)
{
int32_t i,j,iter,num,tablesize,*hashtable; uint8_t *sorted; char fname[1024];
//if ( strcmp("BTC",coin->symbol) != 0 )
// return(0);
if ( coin->fastfind != 0 )
return(coin->fastfind);
for (iter=0; iter<2; iter++)
{
for (i=0; i<0x100; i++)
{
sprintf(fname,"DB/%s%s/fastfind/%02x.all",iter!=0?"ro/":"",coin->symbol,i), OS_compatible_path(fname);
if ( (coin->fast[i]= OS_mapfile(fname,&coin->fastsizes[i],0)) == 0 )
break;
else
{
fprintf(stderr,".");
sorted = coin->fast[i];
if ( 0 )
{
coin->fast[i] = calloc(1,coin->fastsizes[i]);
memcpy(coin->fast[i],sorted,coin->fastsizes[i]);
munmap(sorted,coin->fastsizes[i]);
}
sorted = coin->fast[i];
memcpy(&num,sorted,sizeof(num));
memcpy(&tablesize,&sorted[sizeof(num)],sizeof(tablesize));
if ( (num+1)*16 + tablesize*sizeof(*hashtable) == coin->fastsizes[i] )
{
hashtable = (int32_t *)((long)sorted + (1 + num)*16);
if ( 0 )
{
coin->fasttables[i] = calloc(tablesize,sizeof(*hashtable));
memcpy(coin->fasttables[i],hashtable,tablesize * sizeof(*hashtable));
}
}
else
{
printf("size error num.%d tablesize.%d -> %lu vs %ld\n",num,tablesize,(num+1)*16 + tablesize*sizeof(*hashtable),coin->fastsizes[i]);
break;
}
}
}
if ( i == 0x100 )
{
coin->fastfind = (uint32_t)time(NULL);
printf("initialized fastfind.%s iter.%d\n",coin->symbol,iter);
return(coin->fastfind);
}
else
{
for (j=0; j<i; j++)
{
munmap(coin->fast[i],coin->fastsizes[i]);
free(coin->fasttables[i]);
coin->fast[i] = 0;
coin->fastsizes[i] = 0;
}
}
}
return(0);
}
int64_t iguana_fastfindcreate(struct iguana_info *coin)
{
int32_t i,j,val,iter,errs,num,ind,tablesize,*hashtable; bits256 *sortbuf,hash2; long allocsize; struct iguana_bundle *bp; char fname[512]; uint8_t buf[16]; int64_t total = 0;
if ( coin->current != 0 && coin->bundlescount == coin->current->hdrsi+1 )
{
sprintf(fname,"DB/%s/fastfind",coin->symbol), OS_ensure_directory(fname);
for (i=0; i<0x100; i++)
{
sprintf(fname,"DB/%s/fastfind/%02x",coin->symbol,i), OS_compatible_path(fname);
if ( (coin->fastfps[i]= fopen(fname,"wb")) == 0 )
break;
}
if ( i == 0x100 )
{
for (iter=0; iter<2; iter++)
{
total = 0;
for (i=0; i<coin->bundlescount-1; i++)
if ( (bp= coin->bundles[i]) != 0 )
total += iguana_fastfindinitbundle(coin,bp,iter);
printf("iguana_fastfindinit iter.%d total.%lld\n",iter,(long long)total);
}
for (i=errs=0; i<0x100; i++)
{
fclose(coin->fastfps[i]);
sprintf(fname,"DB/%s/fastfind/%02x",coin->symbol,i), OS_compatible_path(fname);
//printf("%s\n",fname);
if ( (sortbuf= OS_filestr(&allocsize,fname)) != 0 )
{
OS_removefile(fname,0);
num = (int32_t)allocsize/sizeof(bits256);
qsort(sortbuf,num,sizeof(bits256),_bignum_cmp);
strcat(fname,".all");
if ( (coin->fastfps[i]= fopen(fname,"wb")) != 0 )
{
tablesize = (num << 1);
hashtable = calloc(sizeof(*hashtable),tablesize);
for (ind=1; ind<=num; ind++)
{
hash2 = sortbuf[ind-1];
val = (hash2.uints[4] % tablesize);
for (j=0; j<tablesize; j++,val++)
{
if ( val >= tablesize )
val = 0;
if ( hashtable[val] == 0 )
{
hashtable[val] = ind;
break;
}
}
}
memset(&hash2,0,sizeof(hash2));
hash2.uints[0] = num;
hash2.uints[1] = tablesize;
for (j=0; j<=num; j++)
{
memcpy(buf,&hash2.txid,sizeof(hash2.txid));
memcpy(&buf[sizeof(hash2.txid)],&hash2.uints[6],sizeof(hash2.uints[6]));
memcpy(&buf[sizeof(hash2.txid) + sizeof(hash2.uints[6])],&hash2.uints[7],sizeof(hash2.uints[7]));
fwrite(buf,1,sizeof(buf),coin->fastfps[i]);
//fwrite(hash2,1,sizeof(hash2),coin->fastfps[i]);
if ( j < num )
{
hash2 = sortbuf[j];
//char str[65]; printf("%d %s\n",j,bits256_str(str,hash2));
}
}
if ( fwrite(hashtable,sizeof(*hashtable),tablesize,coin->fastfps[i]) == tablesize )
{
fclose(coin->fastfps[i]);
coin->fastfps[i] = 0;
if ( (coin->fast[i]= OS_mapfile(fname,&coin->fastsizes[i],0)) != 0 )
{
} else errs++;
printf("%s fastfind.[%02x] num.%d tablesize.%d errs.%d %p[%ld]\n",fname,i,num,tablesize,errs,coin->fast[i],coin->fastsizes[i]);
}
else
{
printf("error saving (%s)\n",fname);
OS_removefile(fname,0);
fclose(coin->fastfps[i]);
coin->fastfps[i] = 0;
}
free(hashtable);
} else printf("couldnt overwrite (%s)\n",fname);
free(sortbuf);
} else printf("couldnt load sortbuf (%s)\n",fname);
}
printf("initialized with errs.%d\n",errs);
if ( errs == 0 )
coin->fastfind = (uint32_t)time(NULL);
}
}
return(total);
}

2839
iguana/iguana_unspents.c

File diff suppressed because it is too large

342
iguana/iguana_volatiles.c

@ -0,0 +1,342 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "iguana777.h"
struct iguana_hhutxo *iguana_hhutxofind(struct iguana_info *coin,uint64_t uval)
{
struct iguana_hhutxo *hhutxo;
HASH_FIND(hh,coin->utxotable,&uval,sizeof(uval),hhutxo);
return(hhutxo);
}
struct iguana_hhaccount *iguana_hhaccountfind(struct iguana_info *coin,uint64_t pval)
{
struct iguana_hhaccount *hhacct;
HASH_FIND(hh,coin->accountstable,&pval,sizeof(pval),hhacct);
return(hhacct);
}
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)
{
//static struct iguana_hhutxo *HHUTXO; static struct iguana_hhaccount *HHACCT; static uint32_t numHHUTXO,maxHHUTXO,numHHACCT,maxHHACCT;
struct iguana_hhutxo *hhutxo,*tmputxo; struct iguana_hhaccount *hhacct,*tmpacct; uint64_t uval,pval;
if ( spent_hdrsi < 0 )
{
printf(">>>>>>>>>>> RESET UTXO HASH <<<<<<<<<\n");
if ( coin->utxotable != 0 )
{
HASH_ITER(hh,coin->utxotable,hhutxo,tmputxo)
{
//HASH_DEL(coin->utxotable,hhutxo);
hhutxo->u.spentflag = 0;
hhutxo->u.fromheight = 0;
hhutxo->u.prevunspentind = 0;
//free(hhutxo);
}
//coin->utxotable = 0;
}
if ( coin->accountstable != 0 )
{
HASH_ITER(hh,coin->accountstable,hhacct,tmpacct)
{
//HASH_DEL(coin->accountstable,hhacct);
hhacct->a.lastunspentind = 0;
hhacct->a.total = 0;
//free(hhacct);
}
//coin->accountstable = 0;
}
/*if ( HHUTXO != 0 )
{
free(HHUTXO);
maxHHUTXO = numHHUTXO = 0;
HHUTXO = 0;
}
if ( HHACCT != 0 )
{
free(HHACCT);
maxHHACCT = numHHACCT = 0;
HHACCT = 0;
}*/
return(0);
}
uval = ((uint64_t)spent_hdrsi << 32) | spent_unspentind;
pval = ((uint64_t)spent_hdrsi << 32) | spent_pkind;
if ( (hhutxo= iguana_hhutxofind(coin,uval)) != 0 && hhutxo->u.spentflag != 0 )
{
printf("hhutxo.%p spentflag.%d\n",hhutxo,hhutxo->u.spentflag);
return(-1);
}
/*if ( 0 && numHHUTXO+1 >= maxHHUTXO )
{
maxHHUTXO += 1;
HHUTXO = realloc(HHUTXO,sizeof(*HHUTXO) * maxHHUTXO);
}*/
hhutxo = calloc(1,sizeof(*hhutxo));//&HHUTXO[numHHUTXO++], memset(hhutxo,0,sizeof(*hhutxo));
hhutxo->uval = uval;
HASH_ADD_KEYPTR(hh,coin->utxotable,&hhutxo->uval,sizeof(hhutxo->uval),hhutxo);
if ( (hhacct= iguana_hhaccountfind(coin,pval)) == 0 )
{
/*if ( 0 && numHHACCT+1 >= maxHHACCT )
{
maxHHACCT += 1;
HHACCT = realloc(HHACCT,sizeof(*HHACCT) * maxHHACCT);
}*/
hhacct = calloc(1,sizeof(*hhacct)); // &HHACCT[numHHACCT++], memset(hhacct,0,sizeof(*hhacct));
hhacct->pval = pval;
HASH_ADD_KEYPTR(hh,coin->accountstable,&hhacct->pval,sizeof(hhacct->pval),hhacct);
}
//printf("create hhutxo.%p hhacct.%p from.%d\n",hhutxo,hhacct,fromheight);
hhutxo->u.spentflag = 1;
hhutxo->u.fromheight = fromheight;
hhutxo->u.prevunspentind = hhacct->a.lastunspentind;
hhacct->a.lastunspentind = spent_unspentind;
hhacct->a.total += spent_value;
/*if ( iguana_hhutxofind(coin,uval) == 0 || iguana_hhaccountfind(coin,pval) == 0 )
{
printf("null hh find.(%ld %ld) %p %p\n",(long)uval,(long)pval,iguana_hhutxofind(coin,uval),iguana_hhaccountfind(coin,pval));
}*/
return(0);
}
int32_t iguana_spentflag(struct iguana_info *coin,int64_t *RTspendp,int32_t *spentheightp,struct iguana_ramchain *ramchain,int16_t spent_hdrsi,uint32_t spent_unspentind,int32_t height,int32_t minconf,int32_t maxconf,uint64_t amount)
{
uint32_t numunspents; struct iguana_hhutxo *hhutxo; struct iguana_utxo utxo; uint64_t confs,val,RTspend = 0;
*spentheightp = 0;
numunspents = ramchain->H.data->numunspents;
memset(&utxo,0,sizeof(utxo));
val = ((uint64_t)spent_hdrsi << 32) | spent_unspentind;
if ( spent_unspentind != 0 && spent_unspentind < numunspents )
{
if ( ramchain->Uextras != 0 )
utxo = ramchain->Uextras[spent_unspentind];
if ( ramchain->Uextras == 0 || utxo.spentflag == 0 )
{
//printf("check hhutxo [%d] u%u %p\n",spent_hdrsi,spent_unspentind,iguana_hhutxofind(coin,((uint64_t)202<<32)|3909240));
if ( (hhutxo= iguana_hhutxofind(coin,val)) != 0 )
{
utxo = hhutxo->u;
if ( utxo.spentflag != 0 )
RTspend = amount;
}
}
}
else
{
printf("illegal unspentind.%u vs %u hdrs.%d\n",spent_unspentind,numunspents,spent_hdrsi);
return(-1);
}
if ( utxo.spentflag != 0 && utxo.fromheight == 0 )
{
printf("illegal unspentind.%u vs %u hdrs.%d zero fromheight?\n",spent_unspentind,numunspents,spent_hdrsi);
return(-1);
}
//printf("[%d] u%u %.8f, spentheight.%d vs height.%d spentflag.%d\n",spent_hdrsi,spent_unspentind,dstr(amount),utxo.fromheight,height,utxo.spentflag);
*spentheightp = utxo.fromheight;
if ( (confs= coin->blocks.hwmchain.height - utxo.fromheight) >= minconf && confs < maxconf && (height == 0 || utxo.fromheight < height) )
{
(*RTspendp) += RTspend;
return(utxo.spentflag);
}
return(0);
}
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)
{
struct iguana_account *A2; struct iguana_ramchaindata *rdata; struct iguana_utxo *utxo;
if ( (rdata= spentchain->H.data) != 0 )
{
if ( incremental == 0 )
{
if ( spentchain->Uextras == 0 || spentchain->A2 == 0 )
iguana_volatilesmap(coin,spentchain);
if ( spentchain->Uextras != 0 && (A2= spentchain->A2) != 0 )
{
utxo = &spentchain->Uextras[spent_unspentind];
if ( utxo->spentflag == 0 )
{
if ( 0 && fromheight/coin->chain->bundlesize >= coin->current->hdrsi )
printf("iguana_volatileupdate.%d: [%d] spent.(u%u %.8f pkind.%d) fromht.%d [%d] spendind.%d\n",incremental,spent_hdrsi,spent_unspentind,dstr(spent_value),spent_pkind,fromheight,fromheight/coin->chain->bundlesize,spendind);
utxo->prevunspentind = A2[spent_pkind].lastunspentind;
utxo->spentflag = 1;
utxo->fromheight = fromheight;
A2[spent_pkind].total += spent_value;
A2[spent_pkind].lastunspentind = spent_unspentind;
return(0);
}
else
{
printf("from.%d spent_unspentind[%d] in hdrs.[%d] is spent fromht.%d %.8f\n",fromheight,spent_unspentind,spent_hdrsi,utxo->fromheight,dstr(spent_value));
}
} else printf("null ptrs.[%d] u.%u p.%u %.8f from ht.%d s.%u\n",spent_hdrsi,spent_unspentind,spent_pkind,dstr(spent_value),fromheight,spendind);
}
else // do the equivalent of historical, ie mark as spent, linked list, balance
{
//double startmillis = OS_milliseconds(); static double totalmillis; static int32_t utxon;
if ( iguana_utxoupdate(coin,spent_hdrsi,spent_unspentind,spent_pkind,spent_value,spendind,fromheight) == 0 )
{
/*totalmillis += (OS_milliseconds() - startmillis);
if ( (++utxon % 100000) == 0 )
printf("ave utxo[%d] %.2f micros total %.2f seconds\n",utxon,(1000. * totalmillis)/utxon,totalmillis/1000.);*/
return(0);
}
}
printf("iguana_volatileupdate.%d: [%d] spent.(u%u %.8f pkind.%d) double spend? at ht.%d [%d] spendind.%d (%p %p)\n",incremental,spent_hdrsi,spent_unspentind,dstr(spent_value),spent_pkind,fromheight,fromheight/coin->chain->bundlesize,spendind,spentchain->Uextras,spentchain->A2);
if ( coin->current != 0 && fromheight >= coin->current->bundleheight )
coin->RTdatabad = 1;
else
{
printf("from.%d vs current.%d\n",fromheight,coin->current->bundleheight);
iguana_bundleremove(coin,spent_hdrsi,0);
iguana_bundleremove(coin,fromheight/coin->chain->bundlesize,0);
}
exit(-1);
} else printf("volatileupdate error null rdata [%d]\n",spentchain->height/coin->current->bundleheight);
return(-1);
}
void iguana_volatilesalloc(struct iguana_info *coin,struct iguana_ramchain *ramchain,int32_t copyflag)
{
int32_t i; struct iguana_utxo *U2; struct iguana_account *A2; struct iguana_ramchaindata *rdata = 0;
if ( ramchain != 0 && (rdata= ramchain->H.data) != 0 && (coin->current == 0 || coin->current->bundleheight > ramchain->height) )
{
//printf("volatilesalloc.[%d] %p %p\n",ramchain->height/coin->chain->bundlesize,ramchain->debitsfileptr,ramchain->lastspendsfileptr);
if ( ramchain->allocatedA2 == 0 )
{
ramchain->A2 = calloc(sizeof(*ramchain->A2),rdata->numpkinds + 16);
ramchain->allocatedA2 = sizeof(*ramchain->A2) * rdata->numpkinds;
}
if ( ramchain->allocatedU2 == 0 )
{
ramchain->Uextras = calloc(sizeof(*ramchain->Uextras),rdata->numunspents + 16);
ramchain->allocatedU2 = sizeof(*ramchain->Uextras) * rdata->numunspents;
}
if ( ramchain->debitsfileptr != 0 )
{
if ( copyflag != 0 )
{
A2 = (void *)((long)ramchain->debitsfileptr + sizeof(int32_t) + 2*sizeof(bits256));
if ( ramchain->debitsfilesize != sizeof(int32_t) + 2*sizeof(bits256) + sizeof(*A2)*rdata->numpkinds )
printf("A2 size mismatch %ld != %ld\n",ramchain->debitsfilesize,sizeof(int32_t) + 2*sizeof(bits256) + sizeof(*A2)*rdata->numpkinds);
for (i=0; i<rdata->numpkinds; i++)
ramchain->A2[i] = A2[i];
}
munmap(ramchain->debitsfileptr,ramchain->debitsfilesize);
ramchain->debitsfileptr = 0;
ramchain->debitsfilesize = 0;
}
if ( ramchain->lastspendsfileptr != 0 )
{
if ( copyflag != 0 )
{
U2 = (void *)((long)ramchain->lastspendsfileptr + sizeof(int32_t) + 2*sizeof(bits256));
if ( ramchain->lastspendsfilesize != sizeof(int32_t) + 2*sizeof(bits256) + sizeof(*U2)*rdata->numunspents )
printf("U2 size mismatch %ld != %ld\n",ramchain->lastspendsfilesize,sizeof(int32_t) + 2*sizeof(bits256) + sizeof(*U2)*rdata->numunspents);
for (i=0; i<rdata->numunspents; i++)
ramchain->Uextras[i] = U2[i];
}
munmap(ramchain->lastspendsfileptr,ramchain->lastspendsfilesize);
ramchain->lastspendsfileptr = 0;
ramchain->lastspendsfilesize = 0;
}
} else printf("illegal ramchain.%p rdata.%p\n",ramchain,rdata);
}
void iguana_volatilespurge(struct iguana_info *coin,struct iguana_ramchain *ramchain)
{
if ( ramchain != 0 )
{
//printf("volatilespurge.[%d] (%p %p) %p %p\n",ramchain->height/coin->chain->bundlesize,ramchain->A2,ramchain->Uextras,ramchain->debitsfileptr,ramchain->lastspendsfileptr);
if ( ramchain->allocatedA2 != 0 && ramchain->A2 != 0 && ramchain->A2 != ramchain->debitsfileptr+sizeof(bits256)*2+sizeof(int32_t) )
free(ramchain->A2);
if ( ramchain->allocatedU2 != 0 && ramchain->Uextras != 0 && ramchain->Uextras != ramchain->lastspendsfileptr+sizeof(bits256)*2+sizeof(int32_t) )
free(ramchain->Uextras);
ramchain->A2 = 0;
ramchain->Uextras = 0;
ramchain->allocatedA2 = ramchain->allocatedU2 = 0;
if ( ramchain->debitsfileptr != 0 )
{
munmap(ramchain->debitsfileptr,ramchain->debitsfilesize);
ramchain->debitsfileptr = 0;
ramchain->debitsfilesize = 0;
}
if ( ramchain->lastspendsfileptr != 0 )
{
munmap(ramchain->lastspendsfileptr,ramchain->lastspendsfilesize);
ramchain->lastspendsfileptr = 0;
ramchain->lastspendsfilesize = 0;
}
}
}
int32_t iguana_volatilesmap(struct iguana_info *coin,struct iguana_ramchain *ramchain)
{
int32_t iter,numhdrsi,err = -1; char fname[1024]; bits256 balancehash,allbundles; struct iguana_ramchaindata *rdata;
if ( (rdata= ramchain->H.data) == 0 )
{
if ( ramchain->height > 0 )
printf("volatilesmap.[%d] no rdata\n",ramchain->height/coin->chain->bundlesize);
return(-1);
}
if ( ramchain->debitsfileptr != 0 && ramchain->lastspendsfileptr != 0 )
return(0);
for (iter=0; iter<2; iter++)
{
sprintf(fname,"%s/%s%s/accounts/debits.%d",GLOBAL_DBDIR,iter==0?"ro/":"",coin->symbol,ramchain->height);
if ( (ramchain->debitsfileptr= OS_mapfile(fname,&ramchain->debitsfilesize,0)) != 0 && ramchain->debitsfilesize == sizeof(int32_t) + 2*sizeof(bits256) + sizeof(*ramchain->A2) * ramchain->H.data->numpkinds )
{
ramchain->from_roA = (iter == 0);
numhdrsi = *(int32_t *)ramchain->debitsfileptr;
memcpy(balancehash.bytes,(void *)((long)ramchain->debitsfileptr + sizeof(numhdrsi)),sizeof(balancehash));
memcpy(allbundles.bytes,(void *)((long)ramchain->debitsfileptr + sizeof(numhdrsi) + sizeof(balancehash)),sizeof(allbundles));
if ( coin->balanceswritten == 0 )
{
coin->balanceswritten = numhdrsi;
coin->balancehash = balancehash;
coin->allbundles = allbundles;
}
if ( numhdrsi == coin->balanceswritten && memcmp(balancehash.bytes,coin->balancehash.bytes,sizeof(balancehash)) == 0 && memcmp(allbundles.bytes,coin->allbundles.bytes,sizeof(allbundles)) == 0 )
{
ramchain->A2 = (void *)((long)ramchain->debitsfileptr + sizeof(numhdrsi) + 2*sizeof(bits256));
sprintf(fname,"%s/%s%s/accounts/lastspends.%d",GLOBAL_DBDIR,iter==0?"ro/":"",coin->symbol,ramchain->height);
if ( (ramchain->lastspendsfileptr= OS_mapfile(fname,&ramchain->lastspendsfilesize,0)) != 0 && ramchain->lastspendsfilesize == sizeof(int32_t) + 2*sizeof(bits256) + sizeof(*ramchain->Uextras) * ramchain->H.data->numunspents )
{
numhdrsi = *(int32_t *)ramchain->lastspendsfileptr;
memcpy(balancehash.bytes,(void *)((long)ramchain->lastspendsfileptr + sizeof(numhdrsi)),sizeof(balancehash));
memcpy(allbundles.bytes,(void *)((long)ramchain->lastspendsfileptr + sizeof(numhdrsi) + sizeof(balancehash)),sizeof(allbundles));
if ( numhdrsi == coin->balanceswritten && memcmp(balancehash.bytes,coin->balancehash.bytes,sizeof(balancehash)) == 0 && memcmp(allbundles.bytes,coin->allbundles.bytes,sizeof(allbundles)) == 0 )
{
ramchain->Uextras = (void *)((long)ramchain->lastspendsfileptr + sizeof(numhdrsi) + 2*sizeof(bits256));
ramchain->from_roU = (iter == 0);
//printf("volatilesmap.[%d] %p %p\n",ramchain->height/coin->chain->bundlesize,ramchain->debitsfileptr,ramchain->lastspendsfileptr);
err = 0;
} else printf("ramchain map error2 balanceswritten %d vs %d hashes %x %x\n",coin->balanceswritten,numhdrsi,coin->balancehash.uints[0],balancehash.uints[0]);
} else printf("ramchain map error3 %s\n",fname);
}
else
{
printf("ramchain.[%d] map error balanceswritten %d vs %d hashes %x %x\n",ramchain->H.data->height,coin->balanceswritten,numhdrsi,coin->balancehash.uints[0],balancehash.uints[0]);
err++;
OS_removefile(fname,0);
}
}
if ( err == 0 )
return(0);
}
//printf("couldnt map [%d]\n",ramchain->height/coin->chain->bundlesize);
iguana_volatilespurge(coin,ramchain);
return(err);
}

900
iguana/iguana_wallet.c

File diff suppressed because it is too large

2
iguana/main.c

@ -1146,7 +1146,7 @@ void iguana_appletests(struct supernet_info *myinfo)
exit(-1); exit(-1);
} }
sleep(1);*/ sleep(1);*/
if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":500,\"endpend\":500,\"services\":128,\"maxpeers\":64,\"newcoin\":\"BTC\",\"active\":1,\"numhelpers\":4,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":500,\"endpend\":500,\"services\":128,\"maxpeers\":64,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":4,\"poll\":100}"),0,myinfo->rpcport)) != 0 )
{ {
free(str); free(str);
if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"userhome\":\"/Users/jimbolaptop/Library/Application Support\",\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":1024,\"maxpeers\":256,\"newcoin\":\"BTCD\",\"active\":1}"),0,myinfo->rpcport)) != 0 ) if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"userhome\":\"/Users/jimbolaptop/Library/Application Support\",\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":1024,\"maxpeers\":256,\"newcoin\":\"BTCD\",\"active\":1}"),0,myinfo->rpcport)) != 0 )

535
iguana/ramchain_api.c

@ -16,6 +16,53 @@
#include "iguana777.h" #include "iguana777.h"
#include "../includes/iguana_apidefs.h" #include "../includes/iguana_apidefs.h"
STRING_ARG(iguana,initfastfind,activecoin)
{
if ( (coin= iguana_coinfind(activecoin)) != 0 )
{
iguana_fastfindcreate(coin);
return(clonestr("{\"result\":\"fast find initialized\"}"));
} else return(clonestr("{\"error\":\"no coin to initialize\"}"));
}
TWO_STRINGS_AND_TWO_DOUBLES(iguana,balance,activecoin,address,lastheightd,minconfd)
{
int32_t lastheight,minconf,maxconf=SATOSHIDEN; int64_t total=0; uint8_t rmd160[20],pubkey33[33],addrtype;
struct iguana_pkhash *P; cJSON *array,*retjson = cJSON_CreateObject();
if ( activecoin != 0 && activecoin[0] != 0 )
coin = iguana_coinfind(activecoin);
if ( coin != 0 )
{
if ( (minconf= minconfd) <= 0 )
minconf = 1;
lastheight = lastheightd;
jaddstr(retjson,"address",address);
if ( bitcoin_validaddress(coin,address) < 0 )
{
jaddstr(retjson,"error","illegal address");
return(jprint(retjson,1));
}
if ( bitcoin_addr2rmd160(&addrtype,rmd160,address) < 0 )
{
jaddstr(retjson,"error","cant convert address");
return(jprint(retjson,1));
}
memset(pubkey33,0,sizeof(pubkey33));
P = calloc(coin->bundlescount,sizeof(*P));
array = cJSON_CreateArray();
printf("Start %s balance.(%s) height.%d\n",coin->symbol,address,lastheight);
if ( lastheight == 0 )
lastheight = IGUANA_MAXHEIGHT;
iguana_pkhasharray(myinfo,coin,array,minconf,maxconf,&total,P,coin->bundlescount,rmd160,address,pubkey33,lastheight,0,0);
free(P);
jadd(retjson,"unspents",array);
jaddnum(retjson,"balance",dstr(total));
if ( lastheight > 0 )
jaddnum(retjson,"lastheight",lastheight);
}
return(jprint(retjson,1));
}
STRING_ARG(iguana,validate,activecoin) STRING_ARG(iguana,validate,activecoin)
{ {
int32_t i,total,validated; struct iguana_bundle *bp; cJSON *retjson; int32_t i,total,validated; struct iguana_bundle *bp; cJSON *retjson;
@ -71,32 +118,6 @@ STRING_ARG(iguana,removecoin,activecoin)
return(clonestr("{\"error\":\"no active coin\"}")); return(clonestr("{\"error\":\"no active coin\"}"));
} }
char *iguana_APIrequest(struct iguana_info *coin,bits256 blockhash,bits256 txid,int32_t seconds)
{
int32_t i,len; char *retstr = 0; uint8_t serialized[1024]; char str[65];
coin->APIblockhash = blockhash;
coin->APItxid = txid;
printf("request block.(%s) txid.%llx\n",bits256_str(str,blockhash),(long long)txid.txid);
if ( (len= iguana_getdata(coin,serialized,MSG_BLOCK,&blockhash,1)) > 0 )
{
for (i=0; i<seconds; i++)
{
if ( i == 0 )
iguana_send(coin,0,serialized,len);
if ( coin->APIblockstr != 0 )
{
retstr = coin->APIblockstr;
coin->APIblockstr = 0;
memset(&coin->APIblockhash,0,sizeof(coin->APIblockhash));
memset(&coin->APItxid,0,sizeof(coin->APItxid));
return(retstr);
}
sleep(1);
}
}
return(0);
}
INT_ARG(bitcoinrpc,getblockhash,height) INT_ARG(bitcoinrpc,getblockhash,height)
{ {
cJSON *retjson = cJSON_CreateObject(); cJSON *retjson = cJSON_CreateObject();
@ -140,71 +161,6 @@ HASH_AND_TWOINTS(bitcoinrpc,getblock,blockhash,verbose,remoteonly)
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
HASH_AND_INT(bitcoinrpc,getrawtransaction,txid,verbose)
{
struct iguana_txid *tx,T; char *txbytes; bits256 checktxid; int32_t len,height; cJSON *retjson;
if ( (tx= iguana_txidfind(coin,&height,&T,txid,coin->bundlescount-1)) != 0 )
{
retjson = cJSON_CreateObject();
if ( (len= iguana_ramtxbytes(coin,coin->blockspace,sizeof(coin->blockspace),&checktxid,tx,height,0,0,0)) > 0 )
{
txbytes = calloc(1,len*2+1);
init_hexbytes_noT(txbytes,coin->blockspace,len);
jaddstr(retjson,"result",txbytes);
printf("txbytes.(%s) len.%d (%s)\n",txbytes,len,jprint(retjson,0));
free(txbytes);
return(jprint(retjson,1));
}
else if ( height >= 0 )
{
if ( coin->APIblockstr != 0 )
jaddstr(retjson,"error","already have pending request");
else
{
int32_t datalen; uint8_t *data; char *blockstr; bits256 blockhash;
blockhash = iguana_blockhash(coin,height);
if ( (blockstr= iguana_APIrequest(coin,blockhash,txid,2)) != 0 )
{
datalen = (int32_t)(strlen(blockstr) >> 1);
data = malloc(datalen);
decode_hex(data,datalen,blockstr);
if ( (txbytes= iguana_txscan(coin,verbose != 0 ? retjson : 0,data,datalen,txid)) != 0 )
{
jaddstr(retjson,"result",txbytes);
jaddbits256(retjson,"blockhash",blockhash);
jaddnum(retjson,"height",height);
free(txbytes);
} else jaddstr(retjson,"error","cant find txid in block");
free(blockstr);
free(data);
} else jaddstr(retjson,"error","cant find blockhash");
return(jprint(retjson,1));
}
} else printf("height.%d\n",height);
}
return(clonestr("{\"error\":\"cant find txid\"}"));
}
STRING_ARG(bitcoinrpc,decoderawtransaction,rawtx)
{
cJSON *txobj = 0; bits256 txid;
if ( rawtx != 0 && rawtx[0] != 0 )
{
if ( (strlen(rawtx) & 1) != 0 )
return(clonestr("{\"error\":\"rawtx hex has odd length\"}"));
txobj = bitcoin_hex2json(coin,&txid,0,rawtx);
//char str[65]; printf("got txid.(%s)\n",bits256_str(str,txid));
}
if ( txobj == 0 )
txobj = cJSON_CreateObject();
return(jprint(txobj,1));
}
HASH_ARG(bitcoinrpc,gettransaction,txid)
{
return(bitcoinrpc_getrawtransaction(IGUANA_CALLARGS,txid,1));
}
ZERO_ARGS(bitcoinrpc,getbestblockhash) ZERO_ARGS(bitcoinrpc,getbestblockhash)
{ {
cJSON *retjson = cJSON_CreateObject(); cJSON *retjson = cJSON_CreateObject();
@ -219,340 +175,6 @@ ZERO_ARGS(bitcoinrpc,getblockcount)
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
ZERO_ARGS(bitcoinrpc,makekeypair)
{
bits256 privkey; char str[67]; cJSON *retjson = cJSON_CreateObject();
privkey = rand256(1);
jaddstr(retjson,"result","success");
jaddstr(retjson,"privkey",bits256_str(str,privkey));
jadd(retjson,"rosetta",SuperNET_rosettajson(privkey,1));
return(jprint(retjson,1));
}
STRING_ARG(bitcoinrpc,validatepubkey,pubkeystr)
{
uint8_t rmd160[20],pubkey[65],addrtype = 0; int32_t plen; char coinaddr[128],*str; cJSON *retjson;
plen = (int32_t)strlen(pubkeystr) >> 1;
if ( plen <= 65 && coin != 0 && coin->chain != 0 )
{
addrtype = coin->chain->pubtype;
decode_hex(pubkey,plen,pubkeystr);
if ( (str= bitcoin_address(coinaddr,addrtype,pubkey,plen)) != 0 )
{
if ( iguana_addressvalidate(coin,&addrtype,rmd160,coinaddr) < 0 )
return(clonestr("{\"error\":\"invalid coin address\"}"));
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"pubkey",pubkeystr);
jaddstr(retjson,"address",coinaddr);
jaddstr(retjson,"coin",coin->symbol);
return(jprint(retjson,1));
}
}
return(clonestr("{\"error\":\"invalid pubkey\"}"));
}
cJSON *iguana_scriptobj(struct iguana_info *coin,uint8_t rmd160[20],char *coinaddr,char *asmstr,uint8_t *script,int32_t scriptlen)
{
struct vin_info V; int32_t i,plen,asmtype; char pubkeystr[130],rmdstr[41]; cJSON *addrobj,*scriptobj=0;
if ( (asmtype= iguana_calcrmd160(coin,asmstr,&V,script,scriptlen,rand256(1),1,0xffffffff)) >= 0 )
{
if ( asmstr != 0 && asmstr[0] != 0 )
jaddstr(scriptobj,"asm",asmstr);
jaddnum(scriptobj,"iguanatype",asmtype);
jaddnum(scriptobj,"scriptlen",scriptlen);
jaddnum(scriptobj,"reqSigs",V.M);
if ( (plen= bitcoin_pubkeylen(V.signers[0].pubkey)) > 0 )
{
init_hexbytes_noT(pubkeystr,V.signers[0].pubkey,plen);
jaddstr(scriptobj,"pubkey",pubkeystr);
init_hexbytes_noT(rmdstr,V.signers[0].rmd160,20);
jaddstr(scriptobj,"rmd160",rmdstr);
}
addrobj = cJSON_CreateArray();
for (i=0; i<V.N; i++)
jaddistr(addrobj,V.signers[i].coinaddr);
jadd(scriptobj,"addresses",addrobj);
if ( V.p2shlen != 0 )
jaddstr(scriptobj,"p2sh",V.coinaddr);
strcpy(coinaddr,V.coinaddr);
memcpy(rmd160,V.rmd160,20);
}
return(scriptobj);
}
STRING_ARG(bitcoinrpc,decodescript,scriptstr)
{
int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE],rmd160[20]; char coinaddr[128],asmstr[IGUANA_MAXSCRIPTSIZE*2+1]; cJSON *scriptobj,*retjson = cJSON_CreateObject();
if ( coin != 0 && (scriptlen= (int32_t)strlen(scriptstr)>>1) < sizeof(script) )
{
decode_hex(script,scriptlen,scriptstr);
if ( (scriptobj= iguana_scriptobj(coin,rmd160,coinaddr,asmstr,script,scriptlen)) != 0 )
jadd(retjson,"result",scriptobj);
}
return(jprint(retjson,1));
}
HASH_AND_TWOINTS(bitcoinrpc,gettxout,txid,vout,mempool)
{
uint8_t script[IGUANA_MAXSCRIPTSIZE],rmd160[20],pubkey33[33]; char coinaddr[128],asmstr[IGUANA_MAXSCRIPTSIZE*2+1]; struct iguana_bundle *bp; int32_t minconf,scriptlen,unspentind,height,spentheight; int64_t RTspend; struct iguana_ramchaindata *rdata; struct iguana_pkhash *P; struct iguana_txid *T; struct iguana_unspent *U; struct iguana_ramchain *ramchain; cJSON *scriptobj,*retjson = cJSON_CreateObject();
if ( coin != 0 )
{
minconf = (mempool != 0) ? 0 : 1;
if ( (unspentind= iguana_unspentindfind(coin,&height,txid,vout,coin->bundlescount-1)) != 0 )
{
if ( height >= 0 && height < coin->longestchain && (bp= coin->bundles[height / coin->chain->bundlesize]) != 0 )
{
ramchain = (bp == coin->current) ? &coin->RTramchain : &bp->ramchain;
if ( (rdata= ramchain->H.data) != 0 )
{
U = (void *)(long)((long)rdata + rdata->Uoffset);
P = (void *)(long)((long)rdata + rdata->Poffset);
T = (void *)(long)((long)rdata + rdata->Toffset);
RTspend = 0;
if ( iguana_spentflag(coin,&RTspend,&spentheight,ramchain,bp->hdrsi,unspentind,height,minconf,coin->longestchain,U[unspentind].value) == 0 )
{
jaddbits256(retjson,"bestblock",coin->blocks.hwmchain.RO.hash2);
jaddnum(retjson,"bestheight",coin->blocks.hwmchain.height);
jaddnum(retjson,"height",height);
jaddnum(retjson,"confirmations",coin->blocks.hwmchain.height - height + 1);
jaddnum(retjson,"value",dstr(U[unspentind].value));
memset(rmd160,0,sizeof(rmd160));
memset(pubkey33,0,sizeof(pubkey33));
memset(coinaddr,0,sizeof(coinaddr));
if ( (scriptlen= iguana_voutscript(coin,bp,script,0,&U[unspentind],&P[U[unspentind].pkind],vout)) > 0 )
{
if ( (scriptobj= iguana_scriptobj(coin,rmd160,coinaddr,asmstr,script,scriptlen)) != 0 )
jadd(retjson,"scriptPubKey",scriptobj);
}
jadd(retjson,"iguana",iguana_unspentjson(myinfo,coin,bp->hdrsi,unspentind,T,&U[unspentind],rmd160,coinaddr,pubkey33));
if ( (height % coin->chain->bundlesize) == 0 && vout == 0 )
jadd(retjson,"coinbase",jtrue());
else jadd(retjson,"coinbase",jfalse());
}
else
{
jaddstr(retjson,"error","already spent");
jaddnum(retjson,"spentheight",spentheight);
jaddnum(retjson,"unspentind",unspentind);
}
}
}
}
}
return(jprint(retjson,1));
}
TWO_STRINGS(bitcoinrpc,signmessage,address,messagestr)
{
bits256 privkey; int32_t n,len,siglen; char sigstr[256],sig64str[256]; uint8_t sig[128],*message=0; cJSON *retjson = cJSON_CreateObject();
if ( coin != 0 )
{
privkey = iguana_str2priv(myinfo,coin,address);
if ( bits256_nonz(privkey) != 0 )
{
n = (int32_t)strlen(messagestr) >> 1;
if ( messagestr[0] == '0' && messagestr[1] == 'x' && is_hexstr(messagestr+2,n-2) > 0 )
{
message = malloc(n-2);
decode_hex(message,n-2,messagestr+2);
n -= 2;
} else message = (uint8_t *)messagestr, n <<= 1;
if ( (siglen= bitcoin_sign(sig,sizeof(sig),message,n,privkey)) > 0 )
{
sigstr[0] = sig64str[0] = 0;
//init_hexbytes_noT(sigstr,sig,siglen);
len = nn_base64_encode(sig,siglen,sig64str,sizeof(sig64str));
sig64str[len++] = '=';
sig64str[len++] = 0;
jaddstr(retjson,"result",sig64str);
}
if ( message != (void *)messagestr )
free(message);
} else jaddstr(retjson,"error","invalid address (can be wif, wallet address or privkey hex)");
}
return(jprint(retjson,1));
}
THREE_STRINGS(bitcoinrpc,verifymessage,address,sig,message)
{
cJSON *retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
// tx
ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime)
{
bits256 txid; int32_t vout,offset,scriptlen=0,p2shlen=0,i,n; uint32_t sequenceid; uint8_t addrtype,rmd160[20],script[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 )
{
if ( (n= cJSON_GetArraySize(vins)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(vins,i);
p2shlen = scriptlen = 0;
if ( (str= jstr(item,"scriptPubKey")) != 0 || (str= jstr(item,"scriptPubkey")) != 0 )
{
scriptlen = (int32_t)strlen(str) >> 1;
decode_hex(script,scriptlen,str);
}
if ( (str= jstr(item,"redeemScript")) != 0 )
{
p2shlen = (int32_t)strlen(str) >> 1;
decode_hex(redeemscript,p2shlen,str);
}
vout = jint(item,"vout");
if ( jobj(item,"sequenceid") != 0 )
sequenceid = juint(item,"sequenceid");
else sequenceid = 0xffffffff;
txid = jbits256(item,"txid");
bitcoin_addinput(coin,txobj,txid,vout,sequenceid,script,scriptlen,redeemscript,p2shlen);
}
}
if ( (n= cJSON_GetArraySize(vouts)) > 0 )
{
item = vouts->child;
while ( item != 0 )
{
if ( (field= jfieldname(item)) != 0 )
{
if ( strcmp(field,"data") == 0 )
{
if ( (hexstr= jstr(item,"data")) != 0 )
{
scriptlen = (int32_t)strlen(hexstr) >> 1;
offset = 0;
if ( is_hexstr(hexstr,scriptlen) > 0 )
{
decode_hex(script+4,scriptlen,hexstr);
script[3] = SCRIPT_OPRETURN;
scriptlen++;
/* 1-75 0x01-0x4b (special) data The next opcode bytes is data to be pushed onto the stack
OP_PUSHDATA1 76 0x4c (special) data The next byte contains the number of bytes to be pushed onto the stack.
OP_PUSHDATA2 77 0x4d*/
if ( scriptlen < 76 )
{
script[2] = scriptlen;
offset = 2;
scriptlen++;
}
else if ( scriptlen <= 0xff )
{
script[2] = scriptlen;
script[1] = 0x4c;
offset = 1;
scriptlen += 2;
}
else if ( scriptlen <= 0xffff )
{
script[2] = ((scriptlen >> 8) & 0xff);
script[1] = (scriptlen & 0xff);
script[0] = 0x4d;
offset = 0;
scriptlen += 3;
}
else continue;
if ( (obj= jobj(item,"amount")) != 0 )
satoshis = get_API_float(obj) * SATOSHIDEN;
else satoshis = 0;
bitcoin_addoutput(coin,txobj,script+offset,scriptlen,satoshis);
}
}
break;
}
else
{
if ( bitcoin_addr2rmd160(&addrtype,rmd160,field) == sizeof(rmd160) )
{
scriptlen = bitcoin_standardspend(script,0,rmd160);
satoshis = get_API_float(item) * SATOSHIDEN;
bitcoin_addoutput(coin,txobj,script,scriptlen,satoshis);
}
}
}
item = item->next;
}
}
if ( (txstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 )
{
jaddstr(retjson,"result",txstr);
free(txstr);
}
}
return(jprint(retjson,1));
}
/*struct bitcoin_unspent
{
bits256 txid,privkeys[16]; uint64_t value; int32_t vout,spendlen,p2shlen; uint32_t sequence;
uint8_t addrtype,rmd160[20],pubkey[65],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE];
};
struct bitcoin_spend
{
char changeaddr[64]; uint8_t change160[20];
int32_t numinputs;
int64_t txfee,input_satoshis,satoshis,change;
struct bitcoin_unspent inputs[];
};*/
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();
//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";
if ( strcmp(sighash,"ALL") != 0 )
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 )
{
spend = calloc(1,sizeof(*spend) + (sizeof(*spend->inputs) * numinputs));
spend->numinputs = numinputs;
for (i=0; i<n; i++)
{
item = jitem(privkeys,i);
privkeystr = jstr(item,0);
privkey = iguana_str2priv(myinfo,coin,privkeystr);
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);
}
}
txobj = iguana_signtx(coin,&txid,&signedtx,spend,txobj);
free(spend);
free_json(txobj);
if ( signedtx != 0 )
{
jaddstr(retjson,"result",signedtx);
free(signedtx);
}
}
}
return(jprint(retjson,1));
}
TWOINTS_AND_ARRAY(bitcoinrpc,listunspent,minconf,maxconf,array)
{
int32_t numrmds; uint8_t *rmdarray; cJSON *retjson = cJSON_CreateArray();
if ( minconf == 0 )
minconf = 1;
if ( maxconf == 0 )
maxconf = 9999999;
rmdarray = iguana_rmdarray(coin,&numrmds,array,0);
iguana_unspents(myinfo,coin,retjson,minconf,maxconf,rmdarray,numrmds,0);
if ( rmdarray != 0 )
free(rmdarray);
return(jprint(retjson,1));
}
STRING_AND_INT(iguana,bundleaddresses,activecoin,height) STRING_AND_INT(iguana,bundleaddresses,activecoin,height)
{ {
struct iguana_info *ptr; struct iguana_info *ptr;
@ -585,19 +207,31 @@ STRING_AND_INT(iguana,bundlehashes,activecoin,height)
} }
// low priority RPC // low priority RPC
ZERO_ARGS(bitcoinrpc,gettxoutsetinfo)
{
cJSON *retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
INT_AND_ARRAY(bitcoinrpc,lockunspent,flag,array) HASH_AND_TWOINTS(bitcoinrpc,listsinceblock,blockhash,target,flag)
{ {
/*"transactions" : [
{
"account" : "doc test",
"address" : "mmXgiR6KAhZCyQ8ndr2BCfEq1wNG2UnyG6",
"category" : "receive",
"amount" : 0.10000000,
"vout" : 0,
"confirmations" : 76478,
"blockhash" : "000000000017c84015f254498c62a7c884a51ccd75d4dd6dbdcb6434aa3bd44d",
"blockindex" : 1,
"blocktime" : 1399294967,
"txid" : "85a98fdf1529f7d5156483ad020a51b7f3340e47448cf932f470b72ff01a6821",
"walletconflicts" : [
],
"time" : 1399294967,
"timereceived" : 1418924714
},*/
cJSON *retjson = cJSON_CreateObject(); cJSON *retjson = cJSON_CreateObject();
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
ZERO_ARGS(bitcoinrpc,listlockunspent) ZERO_ARGS(bitcoinrpc,gettxoutsetinfo)
{ {
cJSON *retjson = cJSON_CreateObject(); cJSON *retjson = cJSON_CreateObject();
return(jprint(retjson,1)); return(jprint(retjson,1));
@ -616,6 +250,43 @@ ZERO_ARGS(bitcoinrpc,getrawchangeaddress)
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
SS_D_I_S(bitcoinrpc,move,fromaccount,toaccount,amount,minconf,comment)
{
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
ZERO_ARGS(bitcoinrpc,checkwallet)
{
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
return(jprint(retjson,1));
}
ZERO_ARGS(bitcoinrpc,repairwallet)
{
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
return(jprint(retjson,1));
}
#undef IGUANA_ARGS #undef IGUANA_ARGS
#include "../includes/iguana_apiundefs.h" #include "../includes/iguana_apiundefs.h"

10
iguana/swaps/iguana_BTCswap.c

@ -92,6 +92,16 @@ void disp_tx(struct supernet_info *myinfo,struct iguana_info *coin,char *str,cha
printf("disp_tx (%s) -> %s.(%s)\n",txbytes,str,jprint(txobj,1)); printf("disp_tx (%s) -> %s.(%s)\n",txbytes,str,jprint(txobj,1));
} }
void iguana_addinputs(struct iguana_info *coin,struct bitcoin_spend *spend,cJSON *txobj,uint32_t sequence)
{
int32_t i;
for (i=0; i<spend->numinputs; i++)
{
spend->inputs[i].sequence = sequence;
bitcoin_addinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,spend->inputs[i].sequence,spend->inputs[i].spendscript,spend->inputs[i].spendlen,spend->inputs[i].p2shscript,spend->inputs[i].p2shlen);
}
}
struct bitcoin_statetx *instantdex_feetx(struct supernet_info *myinfo,struct instantdex_accept *A) struct bitcoin_statetx *instantdex_feetx(struct supernet_info *myinfo,struct instantdex_accept *A)
{ {
int32_t n,len; char *feetx = 0; struct iguana_info *coin; bits256 txid; cJSON *txobj; struct bitcoin_spend *spend; int64_t insurance; uint8_t paymentscript[128]; struct bitcoin_statetx *ptr = 0; int32_t n,len; char *feetx = 0; struct iguana_info *coin; bits256 txid; cJSON *txobj; struct bitcoin_spend *spend; int64_t insurance; uint8_t paymentscript[128]; struct bitcoin_statetx *ptr = 0;

1
iguana/tests/sendmany

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"sendmany\", \"params\":[\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\":0.01, \"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 2]}"

2
iguana/tests/sendtoaddress

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"sendtoaddress\",\"params\":[\"17outUgtsnLkguDuXm14tcQ7dMbdD8KZGK\", 0.001]}"

18
includes/iguana_apideclares.h

@ -59,28 +59,28 @@ TWO_STRINGS(bitcoinrpc,setaccount,address,account);
INT_ARRAY_STRING(bitcoinrpc,createmultisig,M,pubkeys,ignore); INT_ARRAY_STRING(bitcoinrpc,createmultisig,M,pubkeys,ignore);
INT_ARRAY_STRING(bitcoinrpc,addmultisigaddress,M,pubkeys,account); INT_ARRAY_STRING(bitcoinrpc,addmultisigaddress,M,pubkeys,account);
DOUBLE_ARG(bitcoinrpc,settxfee,amount);
STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighash); // STRING_ARG(bitcoinrpc,submitblock,rawbytes);
STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees); // STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees); //
SS_D_I_S(bitcoinrpc,move,fromaccount,toaccount,amount,minconf,comment); // STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighash); //
SS_D_I_SS(bitcoinrpc,sendfrom,fromaccount,toaddress,amount,minconf,comment,comment2); //
S_A_I_S(bitcoinrpc,sendmany,fromaccount,array,minconf,comment); //
S_D_SS(bitcoinrpc,sendtoaddress,address,amount,comment,comment2); //
DOUBLE_ARG(bitcoinrpc,settxfee,amount);
HASH_AND_TWOINTS(bitcoinrpc,listsinceblock,blockhash,target,flag); //
TWO_STRINGS(bitcoinrpc,signmessage,address,message); // TWO_STRINGS(bitcoinrpc,signmessage,address,message); //
THREE_STRINGS(bitcoinrpc,verifymessage,address,sig,message); // THREE_STRINGS(bitcoinrpc,verifymessage,address,sig,message); //
// maybe later SS_D_I_SS(bitcoinrpc,sendfrom,fromaccount,toaddress,amount,minconf,comment,comment2); //
S_A_I_S(bitcoinrpc,sendmany,fromaccount,payments,minconf,comment); //
S_D_SS(bitcoinrpc,sendtoaddress,address,amount,comment,comment2); //
// maybe later
HASH_AND_TWOINTS(bitcoinrpc,listsinceblock,blockhash,target,flag);
ZERO_ARGS(bitcoinrpc,gettxoutsetinfo); ZERO_ARGS(bitcoinrpc,gettxoutsetinfo);
INT_AND_ARRAY(bitcoinrpc,lockunspent,flag,array); INT_AND_ARRAY(bitcoinrpc,lockunspent,flag,array);
ZERO_ARGS(bitcoinrpc,listlockunspent); ZERO_ARGS(bitcoinrpc,listlockunspent);
ZERO_ARGS(bitcoinrpc,getrawchangeaddress); ZERO_ARGS(bitcoinrpc,getrawchangeaddress);
ZERO_ARGS(bitcoinrpc,checkwallet); ZERO_ARGS(bitcoinrpc,checkwallet);
ZERO_ARGS(bitcoinrpc,repairwallet); ZERO_ARGS(bitcoinrpc,repairwallet);
SS_D_I_S(bitcoinrpc,move,fromaccount,toaccount,amount,minconf,comment);
STRING_ARG(iguana,initfastfind,activecoin); STRING_ARG(iguana,initfastfind,activecoin);
STRING_ARG(iguana,peers,activecoin); STRING_ARG(iguana,peers,activecoin);

Loading…
Cancel
Save