From 1e57a436cba9299cc52f111777faae82e711e35f Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 15 Feb 2017 08:09:59 +0200 Subject: [PATCH] utxorawtx --- basilisk/basilisk.c | 24 +++++++++++- basilisk/basilisk_bitcoin.c | 51 ++++++++++++++++++++++++ iguana/iguana_payments.c | 74 +++++++++++++++++++++++++++++++++++ iguana/tests/refresh | 2 +- iguana/tests/utxorawtx | 2 + includes/iguana_apideclares.h | 1 + includes/iguana_funcs.h | 1 + 7 files changed, 152 insertions(+), 3 deletions(-) create mode 100755 iguana/tests/utxorawtx diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c index aef320fbd..010c5c0b9 100755 --- a/basilisk/basilisk.c +++ b/basilisk/basilisk.c @@ -1115,7 +1115,7 @@ TWO_STRINGS(basilisk,refresh,symbol,address) break; if ( i == n ) { - printf("FOUND NEW %s\n",jprint(item2,0)); + //printf("FOUND NEW %s\n",jprint(item2,0)); jaddi(array3,jduplicate(item2)); } } @@ -1138,7 +1138,10 @@ TWO_STRINGS(basilisk,refresh,symbol,address) { if ( jdouble(item2,"value") > 0 ) { - //printf("%s, ",jprint(item2,0)); + jaddbits256(item2,"txid",txid); + jaddnum(item2,"vout",vout); + jaddnum(item2,"amount",jdouble(item2,"value")); + //printf("%s\n",jprint(item2,0)); jaddi(array3,item2); } else free_json(item2); @@ -1152,4 +1155,21 @@ TWO_STRINGS(basilisk,refresh,symbol,address) } return(clonestr("{\"error\":\"invalid coin or address specified\"}")); } + +STRING_ARRAY_OBJ_STRING(basilisk,utxorawtx,symbol,utxos,vals,ignore) +{ + char *destaddr,*changeaddr; uint64_t satoshis,txfee; int32_t completed,sendflag; + sendflag = jint(vals,"sendflag"); + satoshis = jdouble(vals,"amount") * SATOSHIDEN; + destaddr = jstr(vals,"destaddr"); + changeaddr = jstr(vals,"changeaddr"); + if ( destaddr != 0 && changeaddr != 0 && symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 ) + { + if ( (txfee= jdouble(vals,"txfee") * SATOSHIDEN) == 0 ) + txfee = coin->txfee; + return(iguana_utxorawtx(myinfo,coin,destaddr,changeaddr,satoshis,txfee,&completed,sendflag,utxos)); + } + return(clonestr("{\"error\":\"invalid coin or address specified\"}")); +} + #include "../includes/iguana_apiundefs.h" diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index ee9ae2fb6..cd64de56d 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -580,6 +580,57 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi return(rawtx); } +char *iguana_utxorawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *destaddr,char *changeaddr,uint64_t satoshis,uint64_t txfee,int32_t *completedp,int32_t sendflag,cJSON *utxos) +{ + uint8_t script[35],rmd160[20],addrtype; bits256 txid; int32_t spendlen; cJSON *retjson,*txobj=0,*vins=0; char *rawtx=0,*signedtx=0; + *completedp = 0; + if ( iguana_addressvalidate(coin,&addrtype,destaddr) < 0 || iguana_addressvalidate(coin,&addrtype,changeaddr) < 0 ) + return(clonestr("{\"error\":\"invalid coin address\"}")); + bitcoin_addr2rmd160(&addrtype,rmd160,changeaddr); + if ( addrtype != coin->chain->pubtype ) + return(clonestr("{\"error\":\"invalid dest changeaddr type\"}")); + bitcoin_addr2rmd160(&addrtype,rmd160,destaddr); + if ( addrtype != coin->chain->pubtype ) + return(clonestr("{\"error\":\"invalid dest address type\"}")); + retjson = cJSON_CreateObject(); + if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,1,0)) != 0 ) + { + spendlen = bitcoin_standardspend(script,0,rmd160); + bitcoin_txoutput(txobj,script,spendlen,satoshis); + if ( (rawtx= iguana_calcutxorawtx(myinfo,coin,&vins,txobj,satoshis,changeaddr,txfee,utxos,"",0,0)) != 0 ) + { + jaddstr(retjson,"rawtx",rawtx); + if ( (signedtx= iguana_signrawtx(myinfo,coin,0,&txid,completedp,vins,rawtx,0,0)) != 0 ) + { + if ( *completedp != 0 ) + { + jaddbits256(retjson,"txid",txid); + jaddstr(retjson,"signedtx",signedtx); + if ( sendflag != 0 ) + { + //printf("send signedtx.(%s)\n",signedtx); + txid = iguana_sendrawtransaction(myinfo,coin,signedtx); + jaddbits256(retjson,"sentflag",txid); + } + } + } else printf("error signing raw utxoduplicates tx\n"); + } + } + jaddstr(retjson,"result","success"); + if ( *completedp != 0 ) + jadd(retjson,"completed",jtrue()); + else jadd(retjson,"completed",jfalse()); + if ( vins != 0 ) + free_json(vins); + if ( txobj != 0 ) + free_json(txobj); + if ( rawtx != 0 ) + free(rawtx); + if ( signedtx != 0 ) + free(signedtx); + return(jprint(retjson,1)); +} + char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj,struct vin_info *V) { uint8_t buf[4096]; int32_t oplen,offset,minconf,spendlen; cJSON *vins,*addresses,*txobj = 0; uint32_t locktime; char *opreturn,*spendscriptstr,*changeaddr,*rawtx = 0; int64_t amount,txfee,burnamount; diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index 25999b922..9a9a1938a 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -518,6 +518,80 @@ char *iguana_calcrawtx(struct supernet_info *myinfo,struct iguana_info *coin,cJS return(rawtx); } +char *iguana_calcutxorawtx(struct supernet_info *myinfo,struct iguana_info *coin,cJSON **vinsp,cJSON *txobj,int64_t satoshis,char *changeaddr,int64_t txfee,cJSON *utxos,char *remoteaddr,struct vin_info *V,int32_t maxmode) +{ + uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; int32_t allocflag=0,max,i,n,num,spendlen; char *spendscriptstr,*rawtx=0; bits256 txid; cJSON *sobj,*vins=0,*item; uint64_t value,avail=0,total,change,interests; struct iguana_outpoint *unspents = 0; + *vinsp = 0; + max = 0; + interests = 0; + if ( (n= cJSON_GetArraySize(utxos)) == 0 ) + return(0); + for (i=0; i= satoshis+txfee ) + { + if ( (vins= iguana_RTinputsjson(myinfo,coin,&total,satoshis + txfee,unspents,num,maxmode)) != 0 ) + { + if ( total < (satoshis + txfee) ) + { + free_json(vins); + free(unspents); + printf("insufficient total %.8f vs (%.8f + %.8f)\n",dstr(total),dstr(satoshis),dstr(txfee)); + return(0); + } + total += interests; + if ( (change= (total - (satoshis + txfee))) > 10000 && (changeaddr == 0 || changeaddr[0] == 0) ) + { + printf("no changeaddr for %.8f\n",dstr(change)); + free_json(vins); + free(unspents); + return(0); + } + iguana_createvins(myinfo,coin,txobj,vins); + if ( change > 10000 ) + { + if ( iguana_addressvalidate(coin,&addrtype,changeaddr) < 0 ) + { + free_json(vins); + free(unspents); + printf("illegal destination address.(%s)\n",changeaddr); + return(0); + } + bitcoin_addr2rmd160(&addrtype,rmd160,changeaddr); + spendlen = bitcoin_standardspend(spendscript,0,rmd160); + bitcoin_txoutput(txobj,spendscript,spendlen,change); + } + if ( vins != 0 && V == 0 ) + { + V = calloc(cJSON_GetArraySize(vins),sizeof(*V)), allocflag = 1; + //iguana_vinprivkeys(myinfo,coin,V,vins); + } + rawtx = bitcoin_json2hex(myinfo,coin,&txid,txobj,V); + if ( allocflag != 0 ) + free(V); + } + } + free(unspents); + *vinsp = vins; + return(rawtx); +} + void iguana_RTunspentslock(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins) { struct iguana_outpoint spentpt; char coinaddr[64]; int32_t i,RTspentflag,num,spentheight,lockedflag; diff --git a/iguana/tests/refresh b/iguana/tests/refresh index dce520f7a..d6b1839aa 100755 --- a/iguana/tests/refresh +++ b/iguana/tests/refresh @@ -1,2 +1,2 @@ #!/bin/bash -curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"basilisk\",\"method\":\"refresh\",\"symbol\":\"KMD\",\"address\":\"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc\",\"timeout\":600000}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"basilisk\",\"method\":\"refresh\",\"symbol\":\"KMD\",\"address\":\"RRyBxbrAPRUBCUpiJgJZYrkxqrh8x5ta9Z\",\"timeout\":600000}" diff --git a/iguana/tests/utxorawtx b/iguana/tests/utxorawtx new file mode 100755 index 000000000..7da2fc353 --- /dev/null +++ b/iguana/tests/utxorawtx @@ -0,0 +1,2 @@ +#!/bin/bash +curl --url "http://127.0.0.1:7778" --data "{\"symbol\":\"KMD\",\"agent\":\"basilisk\",\"method\":\"utxorawtx\",\"vals\":{\"changeaddr\":\"RNmvQtThVZAbc1tFEFmKAnJZrc9XqciNog\",\"destaddr\":\"RHfraY22xd9aAuuUJ6Yjb6HFUXh535z6Lg\",\"txfee\":0.00011,\"amount\":0.01,\"sendflag\":0},\"utxos\":[{\"bestblock\":\"000000a7d7b317af7169a156f6b4b9538293da2a3707a69aa3048998a87fbf2c\",\"confirmations\":0,\"value\":1,\"scriptPubKey\":{\"asm\":\"OP_DUP OP_HASH160 b7128d2ee837cf03e30a2c0e3e0181f7b9669bb6 OP_EQUALVERIFY OP_CHECKSIG\",\"hex\":\"76a914b7128d2ee837cf03e30a2c0e3e0181f7b9669bb688ac\",\"reqSigs\":1,\"type\":\"pubkeyhash\",\"addresses\":[\"RRyBxbrAPRUBCUpiJgJZYrkxqrh8x5ta9Z\"]},\"version\":1,\"coinbase\":false,\"randipbits\":3350674129,\"coin\":\"KMD\",\"txid\":\"94e8c4acd20e5d59d9a6a69375c74749b1eba5821d0f218b44c3ce3d8f6989ec\",\"vout\":1,\"amount\":1}]}" diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index d1d87c0b6..a22544875 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -77,6 +77,7 @@ HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr); TWO_STRINGS(basilisk,refresh,symbol,address); +STRING_ARRAY_OBJ_STRING(basilisk,utxorawtx,symbol,utxos,vals,ignore); HASH_ARRAY_STRING(basilisk,getmessage,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,sendmessage,hash,vals,hexstr); diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index 4a00dfe4a..84cb74bc5 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -639,6 +639,7 @@ int32_t init_sharenrs(uint8_t sharenrs[255],uint8_t *orig,int32_t m,int32_t n); void iguana_schnorr(struct supernet_info *myinfo); void iguana_fixsecp(struct supernet_info *myinfo); +char *iguana_calcutxorawtx(struct supernet_info *myinfo,struct iguana_info *coin,cJSON **vinsp,cJSON *txobj,int64_t satoshis,char *changeaddr,int64_t txfee,cJSON *utxos,char *remoteaddr,struct vin_info *V,int32_t maxmode); #include "../includes/iguana_api.h"