jl777
9 years ago
24 changed files with 4822 additions and 4618 deletions
@ -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 |
|||
rm -f ../agents/libcrypto777.a; ar rcu ../agents/libcrypto777.a *.o |
|||
|
@ -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 |
File diff suppressed because it is too large
@ -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 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 |
|||
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 |
@ -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" |
@ -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); |
|||
} |
@ -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" |
|||
|
File diff suppressed because it is too large
@ -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); |
|||
} |
File diff suppressed because it is too large
@ -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); |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"sendmany\", \"params\":[\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\":0.01, \"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 2]}" |
@ -0,0 +1,2 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"sendtoaddress\",\"params\":[\"17outUgtsnLkguDuXm14tcQ7dMbdD8KZGK\", 0.001]}" |
|||
|
Loading…
Reference in new issue