From cc0a30764c6ed2bb61b8ad4b2703528b3610d797 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 5 Sep 2016 01:47:09 -0300 Subject: [PATCH] Revert "Revert "txdetails and helper functions, proposed fix for #59"" This reverts commit 02ae9881ae2e62f52e9b3e22a7cd210901b16e95. --- iguana/iguana_payments.c | 63 ++++++++++++++++++++++------- iguana/iguana_realtime.c | 86 ++++++++++++++++++++++++++++++++-------- iguana/iguana_wallet.c | 6 +-- includes/iguana_funcs.h | 4 ++ 4 files changed, 124 insertions(+), 35 deletions(-) diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index 79f58a38c..d811bfdf8 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -831,9 +831,44 @@ THREE_STRINGS(bitcoinrpc,verifymessage,address,sig,message) } else return(clonestr("{\"error\":\"sig is too long\"}")); } +int64_t iguana_txdetails(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *item,bits256 txid,int32_t vout,int32_t height) +{ + struct iguana_block *block; bits256 hash2; uint64_t amount = 0; char coinaddr[64],account[512]; + /*{ + "category": "receive", + "amount": 0.50000000, + "label": "", + "confirmations": 24466, + "blockhash": "00000000000000000517ce625737579f91162c46ad9eaccad0f52ca13715b156", + "blockindex": 78, + "blocktime": 1448045745, + }*/ + jaddbits256(item,"txid",txid); + if ( vout >= 0 ) + { + jaddnum(item,"vout",vout); + if ( (amount= iguana_txidamount(myinfo,coin,txid,vout)) != 0 ) + jaddnum(item,"amount",dstr(amount)); + } + else if ( vout == -1 ) + jadd(item,"coinbase",jtrue()); + jaddstr(item,"category",iguana_txidcategory(myinfo,coin,account,coinaddr,txid,vout)); + if ( account[0] != 0 && jobj(item,"account") == 0 ) + jaddstr(item,"account",account); + if ( coinaddr[0] != 0 ) + jaddstr(item,"address",coinaddr); + hash2 = iguana_blockhash(coin,height); + jaddbits256(item,"blockhash",hash2); + if ( (block= iguana_blockfind("rawtx",coin,hash2)) != 0 ) + jaddnum(item,"blocktime",block->RO.timestamp); + jaddnum(item,"height",height); + jaddnum(item,"confirmations",coin->blocks.hwmchain.height - height); + return(amount); +} + HASH_AND_INT(bitcoinrpc,getrawtransaction,txid,verbose) { - struct iguana_txid *tx,T; char *txbytes; bits256 checktxid; int32_t len=0,height,extralen=65536; cJSON *retjson,*txobj; uint8_t *extraspace; struct iguana_block *block; bits256 hash2; struct iguana_RTtxid *RTptr; + struct iguana_txid *tx,T; char *txbytes; bits256 checktxid; int32_t len=0,height,extralen=65536; cJSON *retjson,*txobj; uint8_t *extraspace; struct iguana_RTtxid *RTptr; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); HASH_FIND(hh,coin->RTdataset,txid.bytes,sizeof(txid),RTptr); @@ -861,12 +896,7 @@ HASH_AND_INT(bitcoinrpc,getrawtransaction,txid,verbose) free(txbytes); if ( txobj != 0 ) { - hash2 = iguana_blockhash(coin,height); - jaddbits256(txobj,"blockhash",hash2); - if ( (block= iguana_blockfind("rawtx",coin,hash2)) != 0 ) - jaddnum(txobj,"blocktime",block->RO.timestamp); - jaddnum(txobj,"height",height); - jaddnum(txobj,"confirmations",coin->blocks.hwmchain.height - height); + iguana_txdetails(myinfo,coin,txobj,tx->txid,-2,height); return(jprint(txobj,1)); } } @@ -894,14 +924,19 @@ HASH_AND_INT(bitcoinrpc,getrawtransaction,txid,verbose) jaddbits256(retjson,"blockhash",blockhash); jaddnum(retjson,"height",height); free(txbytes); - } else jaddstr(retjson,"error","cant find txid in block"); + } + else if ( coin->RTheight > 0 ) + jaddstr(retjson,"error","cant find txid in block"); + else jaddstr(retjson,"error","not in realtime mode yet"); free(blockstr); free(data); } else jaddstr(retjson,"error","cant find blockhash"); return(jprint(retjson,1)); } } - return(clonestr("{\"error\":\"cant find txid\"}")); + if ( coin->RTheight > 0 ) + return(clonestr("{\"error\":\"cant find txid\"}")); + else return(clonestr("{\"error\":\"not in realtime mode yet\"}")); } int64_t iguana_lockval(int32_t finalized,int64_t locktime) @@ -1005,25 +1040,25 @@ char *iguana_validaterawtx(struct supernet_info *myinfo,struct iguana_info *coin STRING_AND_INT(bitcoinrpc,validaterawtransaction,rawtx,suppress) { - uint8_t *extraspace; int32_t extralen=65536;// char *retstr; struct iguana_msgtx msgtx; + uint8_t *extraspace; int32_t extralen=65536; char *retstr; struct iguana_msgtx msgtx; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); //cJSON *txobj; char *teststr= "{\"version\":1,\"locktime\":0,\"vin\":[{\"userdata\":\"20fe936da3707c8c4cc7eb0352160ec3f50b9454d46425df6347b2fbc5b2ec87ea00\",\"txid\":\"ee12e50b629d5d45438570fff841d1a2ba7d27f356de4aa06900c9a5e38cf141\",\"vout\":0,\"scriptPubKey\":{\"hex\":\"a9145cc47cc123e3f9b7dce0230009b9d3013a9e0c9687\"},\"suppress\":1,\"redeemScript\":\"6304165daa57b1752102a9669e63ef1ab04913615c2f3887ea3584f81e5f08feee9535b19ab3739d8afdac67a9143805600256ed8498ca1ec426759212e5835e8dc2882103a7b696908f77d69ec89887f8c4a0423b9e80b5974dc43301bd7d8abad07e1211ac68\"}],\"vout\":[{\"satoshis\":\"21821\",\"scriptPubkey\":{\"hex\":\"76a9143ef4734c1141725c095342095f6e0e7748b6c16588ac\"}}]}"; - cJSON *txobj; char *teststr= "{\"version\":1,\"locktime\":0,\"vin\":[{\"userdata\":\"206efad760ee54b9b2e2a038a821ef9f950eb0e248545ac202c3e2074cd14f92cb00\",\"txid\":\"3f4759381a62154f2f0eefed1e4433342548ad7b269f912820383b715a39273c\",\"vout\":0,\"scriptPubKey\":{\"hex\":\"a91446dcccef39c1d8c6da2ccc35dce2bfa7ec0d168887\"},\"suppress\":1,\"redeemScript\":\"63041c60aa57b1752103175cf93574c31637b8c2d8acd5319e3cd23761b5e418d32c6bcb194972ba9273ac67a9142d75daf71325feaa593b8f30989e462892189914882102a9669e63ef1ab04913615c2f3887ea3584f81e5f08feee9535b19ab3739d8afdac68\"}],\"vout\":[{\"satoshis\":\"18625\",\"scriptPubkey\":{\"hex\":\"76a914b7128d2ee837cf03e30a2c0e3e0181f7b9669bb688ac\"}}]}"; + //cJSON *txobj; char *teststr= "{\"version\":1,\"locktime\":0,\"vin\":[{\"userdata\":\"206efad760ee54b9b2e2a038a821ef9f950eb0e248545ac202c3e2074cd14f92cb00\",\"txid\":\"3f4759381a62154f2f0eefed1e4433342548ad7b269f912820383b715a39273c\",\"vout\":0,\"scriptPubKey\":{\"hex\":\"a91446dcccef39c1d8c6da2ccc35dce2bfa7ec0d168887\"},\"suppress\":1,\"redeemScript\":\"63041c60aa57b1752103175cf93574c31637b8c2d8acd5319e3cd23761b5e418d32c6bcb194972ba9273ac67a9142d75daf71325feaa593b8f30989e462892189914882102a9669e63ef1ab04913615c2f3887ea3584f81e5f08feee9535b19ab3739d8afdac68\"}],\"vout\":[{\"satoshis\":\"18625\",\"scriptPubkey\":{\"hex\":\"76a914b7128d2ee837cf03e30a2c0e3e0181f7b9669bb688ac\"}}]}"; // 01000000013c27395a713b382028919f267bad48253433441eedef0e2f4f15621a3859473f00000000d147304402207ecd423b55c1aa45a994c4eb4337ff0891692fbb69954a9ba024745a99c5272d02207cea696425feb5388153ab7f2608d66a66e4c95cfda2d44e98bc56e25994d3f701206efad760ee54b9b2e2a038a821ef9f950eb0e248545ac202c3e2074cd14f92cb004c6763041c60aa57b1752103175cf93574c31637b8c2d8acd5319e3cd23761b5e418d32c6bcb194972ba9273ac67a9142d75daf71325feaa593b8f30989e462892189914882102a9669e63ef1ab04913615c2f3887ea3584f81e5f08feee9535b19ab3739d8afdac68ffffffff01c1480000000000001976a914b7128d2ee837cf03e30a2c0e3e0181f7b9669bb688ac00000000 // 01000000013c27395a713b382028919f267bad48253433441eedef0e2f4f15621a3859473f00000000fd8b00206efad760ee54b9b2e2a038a821ef9f950eb0e248545ac202c3e2074cd14f92cb004c6763041c60aa57b1752103175cf93574c31637b8c2d8acd5319e3cd23761b5e418d32c6bcb194972ba9273ac67a9142d75daf71325feaa593b8f30989e462892189914882102a9669e63ef1ab04913615c2f3887ea3584f81e5f08feee9535b19ab3739d8afdac68ffffffff01c1480000000000001976a914b7128d2ee837cf03e30a2c0e3e0181f7b9669bb688ac00000000 //cJSON *txobj; char *teststr= "{\"version\":1,\"locktime\":0,\"vin\":[{\"userdata\":\"20ae439d344513eab8e718d8214fe6ae8133b8b5b594afd64da21d0e40b9c37cdd00\",\"txid\":\"2c1320315f4fb519cbf2b4d7b67855013b9a09a85e515df43b41d407a0083b09\",\"vout\":0,\"scriptPubKey\":{\"hex\":\"a9142e7674400d04217f770f2222126dc7fee44b06b487\"},\"suppress\":1,\"redeemScript\":\"63041686a657b1752102a9669e63ef1ab04913615c2f3887ea3584f81e5f08feee9535b19ab3739d8afdac67a914ed74c61c27656abc6c20687c3a9212ffdc6f34cd88210398a4cb9f6ea7c52a4e27455028a95e2e4e397a110fb75f072c2c58a8bdcbf4baac68\"}],\"vout\":[{\"satoshis\":\"16733\",\"scriptPubkey\":{\"hex\":\"76a91454a752f0d71b89d7c014ed0be29ca231c9546f9f88ac\"}}]}"; extraspace = calloc(1,extralen); - if ( (txobj= cJSON_Parse(teststr)) != 0 ) + /*if ( (txobj= cJSON_Parse(teststr)) != 0 ) { bits256 txid; rawtx = bitcoin_json2hex(myinfo,coin,&txid,txobj,0); txobj = bitcoin_hex2json(coin,coin->blocks.hwmchain.height,&txid,0,rawtx,extraspace,extralen,0,0,suppress); printf("RAWTX.(%s) -> (%s)\n",rawtx,jprint(txobj,0)); - } - //retstr = iguana_validaterawtx(myinfo,coin,coin->blocks.hwmchain.height,&msgtx,extraspace,extralen,rawtx,0,suppress); + }*/ + retstr = iguana_validaterawtx(myinfo,coin,coin->blocks.hwmchain.height,&msgtx,extraspace,extralen,rawtx,0,suppress); free(extraspace); return(rawtx); } diff --git a/iguana/iguana_realtime.c b/iguana/iguana_realtime.c index 649e52310..876ef26cc 100755 --- a/iguana/iguana_realtime.c +++ b/iguana/iguana_realtime.c @@ -763,17 +763,23 @@ struct iguana_RTtxid *iguana_RTtxid_create(struct iguana_info *coin,struct iguan return(RTptr); } -int64_t _RTgettxout(struct iguana_info *coin,int32_t *height,int32_t *scriptlen,uint8_t *script,uint8_t *rmd160,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool) +int64_t _RTgettxout(struct iguana_info *coin,int32_t *heightp,int32_t *scriptlenp,uint8_t *script,uint8_t *rmd160,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool) { - int64_t value = 0; struct iguana_RTtxid *RTptr; struct iguana_RTunspent *unspent = 0; + int32_t scriptlen; int64_t value = 0; struct iguana_RTtxid *RTptr; struct iguana_RTunspent *unspent = 0; HASH_FIND(hh,coin->RTdataset,txid.bytes,sizeof(txid),RTptr); + *heightp = -1; + if ( scriptlenp == 0 ) + scriptlenp = &scriptlen; + *scriptlenp = 0; + memset(rmd160,0,20); + coinaddr[0] = 0; if ( RTptr != 0 && (RTptr->height <= coin->blocks.hwmchain.height || mempool != 0) ) { if ( vout >= 0 && vout < RTptr->txn_count && (unspent= RTptr->unspents[vout]) != 0 ) { - *height = RTptr->height; - if ( (*scriptlen= unspent->scriptlen) > 0 ) - memcpy(script,unspent->script,*scriptlen); + *heightp = RTptr->height; + if ( unspent->spend == 0 && (*scriptlenp= unspent->scriptlen) > 0 ) + memcpy(script,unspent->script,*scriptlenp); memcpy(rmd160,unspent->rmd160,sizeof(unspent->rmd160)); bitcoin_address(coinaddr,coin->chain->pubtype,rmd160,sizeof(unspent->rmd160)); value = unspent->value; @@ -782,6 +788,21 @@ int64_t _RTgettxout(struct iguana_info *coin,int32_t *height,int32_t *scriptlen, return(value); } +int32_t _iguana_RTunspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,struct iguana_outpoint outpt,int64_t value) +{ + int32_t spendlen = 0; struct iguana_RTunspent *unspent; struct iguana_RTtxid *parent; + if ( outpt.isptr != 0 && (unspent= outpt.ptr) != 0 && (parent= unspent->parent) != 0 ) + { + if ( value != unspent->value ) + printf("_iguana_RTunspentfind: mismatched value %.8f != %.8f\n",dstr(value),dstr(unspent->value)); + if ( (spendlen= unspent->scriptlen) > 0 ) + memcpy(spendscript,unspent->script,spendlen); + *txidp = parent->txid; + *voutp = unspent->vout; + } + return(spendlen); +} + int32_t iguana_RTunspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *spendlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool) { char _coinaddr[64]; uint8_t rmd160[20]; int64_t value; @@ -796,19 +817,52 @@ int32_t iguana_RTunspentindfind(struct supernet_info *myinfo,struct iguana_info else return(iguana_unspentindfind(myinfo,coin,coinaddr,spendscript,spendlenp,valuep,heightp,txid,vout,lasthdrsi,mempool)); } -int32_t _iguana_RTunspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,struct iguana_outpoint outpt,int64_t value) +int32_t iguana_txidheight(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid) { - int32_t spendlen = 0; struct iguana_RTunspent *unspent; struct iguana_RTtxid *parent; - if ( outpt.isptr != 0 && (unspent= outpt.ptr) != 0 && (parent= unspent->parent) != 0 ) + int32_t spendlen,height = 0; uint64_t value; char coinaddr[64]; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE]; + iguana_RTunspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,txid,0,(coin->firstRTheight/coin->chain->bundlesize) - 1,0); + return(height); +} + +int64_t iguana_txidamount(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid,int32_t vout) +{ + int32_t spendlen,height = 0; uint64_t value; char coinaddr[64]; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE]; + iguana_RTunspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,txid,vout,(coin->firstRTheight/coin->chain->bundlesize) - 1,0); + return(value); +} + +char *iguana_txidcategory(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,bits256 txid,int32_t vout) +{ + struct iguana_waccount *wacct; struct iguana_waddress *waddr; int32_t ismine=1,spendlen,height = 0; uint64_t value; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE]; + iguana_RTunspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,txid,vout,(coin->firstRTheight/coin->chain->bundlesize) - 1,0); + account[0] = 0; + if ( coinaddr[0] != 0 ) { - if ( value != unspent->value ) - printf("_iguana_RTunspentfind: mismatched value %.8f != %.8f\n",dstr(value),dstr(unspent->value)); - if ( (spendlen= unspent->scriptlen) > 0 ) - memcpy(spendscript,unspent->script,spendlen); - *txidp = parent->txid; - *voutp = unspent->vout; - } - return(spendlen); + if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 ) + { + if ( waddr->scriptlen != 0 ) + return("isp2sh"); + else if ( waddr->wifstr[0] != 0 ) + ismine = 1; + if ( wacct != 0 ) + strcpy(account,wacct->account); + } + } else account[0] = 0; + if ( value != 0 ) + { + if ( spendlen == 0 ) + { + if ( ismine != 0 ) + return("send"); + else return("spent"); + } + else + { + if ( ismine != 0 ) + return("receive"); + else return("unspent"); + } + } else return("unknown"); } void iguana_RTunmap(uint8_t *ptr,uint32_t len) diff --git a/iguana/iguana_wallet.c b/iguana/iguana_wallet.c index f4eaa7461..34318df97 100755 --- a/iguana/iguana_wallet.c +++ b/iguana/iguana_wallet.c @@ -1576,11 +1576,7 @@ STRING_AND_THREEINTS(bitcoinrpc,listtransactions,account,count,skip,includewatch }*/ item = cJSON_CreateObject(); jaddstr(item,"account",wacct->account); - jaddstr(item,"address",coinaddr); - jaddbits256(item,"txid",txid); - jaddnum(item,"vout",vout); - //return(bitcoinrpc_getrawtransaction(IGUANA_CALLARGS,txid,1)); - + iguana_txdetails(myinfo,coin,item,txid,vout,iguana_txidheight(myinfo,coin,txid)); jaddi(retarray,item); } } diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index 70d51ac90..f1d5f066d 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -520,6 +520,10 @@ struct gecko_chain *category_find(bits256 categoryhash,bits256 subhash); void *category_subscribe(struct supernet_info *myinfo,bits256 category,bits256 keyhash); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); char *SuperNET_JSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port); +int64_t iguana_txdetails(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *item,bits256 txid,int32_t vout,int32_t height); +int32_t iguana_txidheight(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid); +int64_t iguana_txidamount(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid,int32_t vout); +char *iguana_txidcategory(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,bits256 txid,int32_t vout); struct supernet_info *SuperNET_accountfind(cJSON *json); cJSON *SuperNET_rosettajson(struct supernet_info *myinfo,bits256 privkey,int32_t showprivs); double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *sortbuf,int32_t max,double *totalvolp,char *base,char *rel,double basevolume,cJSON *argjson);