From 639e6a7f30e1ee4a27c257e06fbe7dc9e2d7b554 Mon Sep 17 00:00:00 2001 From: jl777 Date: Tue, 3 May 2016 11:50:16 -0500 Subject: [PATCH] test --- SuperNET/teleport777.c | 2 +- iguana/iguana777.h | 13 +- iguana/iguana_msg.c | 9 +- iguana/iguana_payments.c | 6 +- iguana/iguana_realtime.c | 2 +- iguana/iguana_scripts.c | 4 +- iguana/iguana_secp.c | 11 +- iguana/iguana_sign.c | 631 +++++++++++++++++++----------- iguana/iguana_stake.c | 2 + iguana/swaps/iguana_BTCswap.c | 4 +- iguana/tests/createrawtransaction | 2 +- iguana/tests/decoderawtransaction | 2 +- iguana/tests/sendrawtransaction | 2 + iguana/tests/signrawtransaction | 2 +- iguana/tests/signrawtransaction2 | 2 + includes/iguana_apideclares.h | 4 +- 16 files changed, 433 insertions(+), 265 deletions(-) create mode 100755 iguana/tests/sendrawtransaction create mode 100755 iguana/tests/signrawtransaction2 diff --git a/SuperNET/teleport777.c b/SuperNET/teleport777.c index 352cfa4a3..d32106c10 100755 --- a/SuperNET/teleport777.c +++ b/SuperNET/teleport777.c @@ -96,7 +96,7 @@ uint64_t parse_unspent_json(struct telepod *pod,struct coin777 *coin,cJSON *json copy_cJSON(&tmp,cJSON_GetObjectItem(json,"txid")), safecopy(pod->txid,tmp.buf,sizeof(pod->txid)); copy_cJSON(&tmp,cJSON_GetObjectItem(json,"address")), safecopy(pod->podaddr,tmp.buf,sizeof(pod->podaddr));; copy_cJSON(&tmp,cJSON_GetObjectItem(json,"scriptPubKey")), safecopy(pod->script,tmp.buf,sizeof(pod->script));; - amount = (uint64_t)(SATOSHIDEN * get_API_float(cJSON_GetObjectItem(json,"amount"))); + amount = (uint64_t)(SATOSHIDEN * jdouble(json,"amount")); pod->vout = juint(json,"vout"); pod->numconfirms = juint(json,"confirmations"); if ( pod->txid[0] != 0 && pod->podaddr[0] != 0 && pod->script[0] != 0 && amount != 0 && pod->vout >= 0 ) diff --git a/iguana/iguana777.h b/iguana/iguana777.h index 0772da15b..0bec6507a 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -257,7 +257,7 @@ struct iguana_msgblock uint32_t txn_count; } __attribute__((packed)); -struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*spendscript,*redeemscript,*pubkeys[16]; uint32_t prev_vout,scriptlen,spendlen,p2shlen,numpubkeys,sequence; } __attribute__((packed)); +struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,suffixlen,spendlen; } __attribute__((packed)); struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; } __attribute__((packed)); @@ -523,10 +523,9 @@ struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],r struct vin_info { - struct iguana_msgvin vin; - int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs; uint32_t sequence; - struct vin_signer signers[16]; - char coinaddr[65]; + struct iguana_msgvin vin; uint64_t amount; + int32_t M,N,validmask,spendlen,type,p2shlen,suffixlen,numpubkeys,numsigs,height,hashtype; + uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65]; uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE]; }; @@ -825,7 +824,7 @@ int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int3 cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys); int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V,int32_t numinputs); int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen); -char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson); +char *bitcoin_json2hex(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,cJSON *txjson,struct vin_info *V); int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr); char *issue_startForging(struct supernet_info *myinfo,char *secret); struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,char **retstrp,double *balancep,int32_t *numunspentsp,double minconfirms,char *account); @@ -934,7 +933,7 @@ int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t cJSON *iguana_p2shjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson,struct iguana_waddress *waddr); char *setaccount(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waddress **waddrp,char *account,char *coinaddr,char *redeemScript); char *iguana_APIrequest(struct iguana_info *coin,bits256 blockhash,bits256 txid,int32_t seconds); -int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t numinputs,int32_t sighashsingle); +int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t sighash); int64_t iguana_fastfindcreate(struct iguana_info *coin); int32_t bitcoin_validaddress(struct iguana_info *coin,char *coinaddr); int32_t iguana_volatileupdate(struct iguana_info *coin,int32_t incremental,struct iguana_ramchain *spentchain,int16_t spent_hdrsi,uint32_t spent_unspentind,uint32_t spent_pkind,uint64_t spent_value,uint32_t spendind,uint32_t fromheight); diff --git a/iguana/iguana_msg.c b/iguana/iguana_msg.c index c1a0be164..3a5c1be5a 100755 --- a/iguana/iguana_msg.c +++ b/iguana/iguana_msg.c @@ -333,12 +333,17 @@ int32_t iguana_getdata(struct iguana_info *coin,uint8_t *serialized,int32_t type int32_t iguana_rwvin(int32_t rwflag,struct OS_memspace *mem,uint8_t *serialized,struct iguana_msgvin *msg) { - int32_t len = 0; + int32_t len = 0; uint32_t tmp; 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 ( rwflag == 1 ) + tmp = msg->scriptlen; + len += iguana_rwvarint32(rwflag,&serialized[len],&tmp); if ( rwflag == 0 ) + { + msg->scriptlen = tmp; msg->vinscript = iguana_memalloc(mem,msg->scriptlen,1); + } len += iguana_rwmem(rwflag,&serialized[len],msg->scriptlen,msg->vinscript); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence); //char str[65]; printf("MSGvin.(%s/v%d) script[%d]\n",bits256_str(str,msg->prev_hash),msg->prev_vout,msg->scriptlen); diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index fb3289000..c08c57225 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -606,7 +606,7 @@ ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime) } else continue; if ( (obj= jobj(item,"amount")) != 0 ) - satoshis = get_API_float(obj) * SATOSHIDEN; + satoshis = jdouble(obj,0) * SATOSHIDEN; else satoshis = 0; bitcoin_addoutput(coin,txobj,spendscript+offset,spendlen,satoshis); } @@ -618,7 +618,7 @@ ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime) if ( bitcoin_addr2rmd160(&addrtype,rmd160,field) == sizeof(rmd160) ) { spendlen = bitcoin_standardspend(spendscript,0,rmd160); - satoshis = get_API_float(item) * SATOSHIDEN; + satoshis = jdouble(item,0) * SATOSHIDEN; bitcoin_addoutput(coin,txobj,spendscript,spendlen,satoshis); } } @@ -626,7 +626,7 @@ ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime) item = item->next; } } - if ( (txstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 ) + if ( (txstr= bitcoin_json2hex(myinfo,coin,&txid,txobj,0)) != 0 ) { jaddstr(retjson,"result",txstr); free(txstr); diff --git a/iguana/iguana_realtime.c b/iguana/iguana_realtime.c index 7f6cdfd70..be16a5ea3 100755 --- a/iguana/iguana_realtime.c +++ b/iguana/iguana_realtime.c @@ -191,7 +191,7 @@ void iguana_RTspendvectors(struct iguana_info *coin,struct iguana_bundle *bp) 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 BTC READY FOR REALTIME RPC <<<<<<\n"); //printf("iguana_balancegen [%d] (%d to %d)\n",bp->hdrsi,coin->RTstarti,(coin->RTheight-1)%bp->n); coin->RTstarti = (coin->RTheight % bp->n); } diff --git a/iguana/iguana_scripts.c b/iguana/iguana_scripts.c index 4495eb0ad..c12b6d914 100755 --- a/iguana/iguana_scripts.c +++ b/iguana/iguana_scripts.c @@ -808,7 +808,6 @@ int32_t iguana_vinscriptparse(struct iguana_info *coin,struct vin_info *vp,uint3 { int32_t hashtype; *sigsizep = *pubkeysizep = *p2shsizep = *suffixp = 0; - memset(vp,0,sizeof(*vp)); if ( bitcoin_scriptget(coin,&hashtype,sigsizep,pubkeysizep,suffixp,vp,vinscript,scriptlen,0) < 0 ) { printf("iguana_vinscriptparse: error parsing vinscript?\n"); @@ -1042,6 +1041,7 @@ int32_t iguana_metascript(struct iguana_info *coin,RAMCHAIN_FUNC,struct iguana_s memset(&V,0,sizeof(V)); if ( rawflag == 0 ) { + memset(&V,0,sizeof(V)); s->sighash = iguana_vinscriptparse(coin,&V,&sigsize,&pubkeysize,&p2shsize,&suffixlen,vinscript,vinscriptlen); //for (i=0; i<33; i++) // printf("%02x",V.signers[0].pubkey[i]); @@ -1149,6 +1149,7 @@ int32_t iguana_scriptspaceraw(struct iguana_info *coin,int32_t *scriptspacep,int } for (j=0; jtx_in; j++) { + memset(&V,0,sizeof(V)); iguana_vinscriptparse(coin,&V,&sigsize,&pubkeysize,&p2shsize,&suffixlen,tx->vins[j].vinscript,tx->vins[j].scriptlen); pubkeyspace += pubkeysize; p2shspace += p2shsize; @@ -1197,6 +1198,7 @@ int32_t iguana_ramchain_scriptspace(struct iguana_info *coin,int32_t *sigspacep, altspace += scriptlen; if ( scriptdata != 0 ) { + memset(&V,0,sizeof(V)); iguana_vinscriptparse(coin,&V,&sigsize,&pubkeysize,&p2shsize,&suffixlen,scriptdata,scriptlen); p2shspace += p2shsize; sigspace += sigsize; diff --git a/iguana/iguana_secp.c b/iguana/iguana_secp.c index 0ddfaa2f8..06ccb8d9c 100755 --- a/iguana/iguana_secp.c +++ b/iguana/iguana_secp.c @@ -15,14 +15,10 @@ #include #include +#include #include "../includes/curve25519.h" -#include "../includes/openssl/ec.h" -//#include "../includes/openssl/ecdsa.h" -#include "../includes/openssl/obj_mac.h" #include "../../secp256k1-zkp/include/secp256k1.h" -static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - bits256 bitcoin_pubkey33(secp256k1_context *ctx,uint8_t *data,bits256 privkey) { int32_t flag=0; size_t plen; bits256 pubkey; secp256k1_pubkey secppub; @@ -97,6 +93,11 @@ int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uin } #ifdef oldway +#include "../includes/openssl/ec.h" +#include "../includes/openssl/ecdsa.h" +#include "../includes/openssl/obj_mac.h" + +static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; struct bp_key { EC_KEY *k; }; diff --git a/iguana/iguana_sign.c b/iguana/iguana_sign.c index f1cfc290d..6b61d06a9 100755 --- a/iguana/iguana_sign.c +++ b/iguana/iguana_sign.c @@ -20,10 +20,14 @@ int32_t iguana_vinparse(struct iguana_info *coin,int32_t rwflag,uint8_t *serialized,struct iguana_msgvin *msg) { //int32_t sighash,i,plen,len = 0; struct vin_info V; uint32_t sigsize,pubkeysize,p2shsize,suffixlen; - int32_t len = 0; + int32_t p2shlen,len = 0; uint32_t tmp; 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 ( rwflag == 1 ) + tmp = msg->scriptlen; + len += iguana_rwvarint32(rwflag,&serialized[len],&tmp); + if ( rwflag == 0 ) + msg->scriptlen = tmp; if ( msg->scriptlen > IGUANA_MAXSCRIPTSIZE ) { printf("iguana_vinparse illegal scriptlen.%d\n",msg->scriptlen); @@ -36,49 +40,30 @@ int32_t iguana_vinparse(struct iguana_info *coin,int32_t rwflag,uint8_t *seriali } else if ( msg->vinscript != 0 && msg->scriptlen > 0 ) { - /*if ( msg->p2shlen > 0 || msg->pubkeys != 0 ) + memcpy(&serialized[len],msg->vinscript,msg->scriptlen), len += msg->scriptlen; // pubkeys here + if ( (p2shlen= msg->p2shlen) > 0 && msg->redeemscript != 0 ) { - sighash = iguana_vinscriptparse(coin,&V,&sigsize,&pubkeysize,&p2shsize,&suffixlen,msg->vinscript,msg->scriptlen); - if ( V.numsigs > 0 ) - { - for (i=0; ipubkeys != 0 && msg->numpubkeys > 0 ) - { - for (i=0; inumpubkeys; i++) - { - if ( (plen= bitcoin_pubkeylen(V.signers[i].pubkey)) > 0 ) - { - serialized[len++] = plen; - memcpy(&serialized[len],V.signers[i].pubkey,plen), len += plen; - } else serialized[len++] = 0; - } - } - if ( msg->p2shlen > 0 && msg->redeemscript != 0 ) + if ( p2shlen > msg->suffixlen ) { - if ( msg->p2shlen < 76 ) - serialized[len++] = msg->p2shlen; - else if ( msg->p2shlen <= 0xff ) + p2shlen -= msg->suffixlen; + if ( p2shlen < 76 ) + serialized[len++] = p2shlen; + else if ( p2shlen <= 0xff ) { serialized[len++] = 0x4c; - serialized[len++] = msg->p2shlen; + serialized[len++] = p2shlen; } - else if ( msg->p2shlen <= 0xffff ) + else if ( p2shlen <= 0xffff ) { serialized[len++] = 0x4d; - serialized[len++] = (msg->p2shlen & 0xff); - serialized[len++] = ((msg->p2shlen >> 8) & 0xff); + serialized[len++] = (p2shlen & 0xff); + serialized[len++] = ((p2shlen >> 8) & 0xff); } else return(-1); - memcpy(&serialized[len],msg->redeemscript,msg->p2shlen), len += plen; + memcpy(&serialized[len],msg->redeemscript,p2shlen), len += p2shlen; } - if ( suffixlen > 0 ) - memcpy(&serialized[len],&msg->vinscript[msg->scriptlen - suffixlen],suffixlen), len += suffixlen; - } else */ - memcpy(&serialized[len],msg->vinscript,msg->scriptlen), len += msg->scriptlen; + if ( msg->suffixlen > 0 ) + memcpy(&serialized[len],&msg->redeemscript[msg->scriptlen - msg->suffixlen],msg->suffixlen), len += msg->suffixlen; + } } len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence); if ( 0 ) @@ -188,19 +173,20 @@ cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin) iguana_addscript(coin,json,vin->spendscript,vin->spendlen,"scriptPubKey"); if ( vin->p2shlen > 0 ) iguana_addscript(coin,json,vin->redeemscript,vin->p2shlen,"redeemScript"); - if ( vin->numpubkeys > 0 ) - jadd(json,"pubkeys",iguana_pubkeysjson(vin->pubkeys,vin->numpubkeys)); } return(json); } -int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgvin *vin,cJSON *vinobj) +int32_t iguana_parsevinobj(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgvin *vin,cJSON *vinobj,struct vin_info *V) { - int32_t i,n,plen,len = 0; char *pubkeystr,*hexstr = 0,*redeemstr = 0,*spendstr = 0; cJSON *scriptjson = 0,*obj,*pubkeysjson = 0; + struct iguana_waddress *waddr; struct iguana_waccount *wacct; int32_t i,n,plen,len = 0; char *suffixstr,*pubkeystr,*hexstr = 0,*redeemstr = 0,*spendstr = 0; cJSON *scriptjson = 0,*obj,*pubkeysjson = 0; //printf("PARSEVIN.(%s)\n",jprint(vinobj,0)); - memset(vin,0,sizeof(*vin)); + if ( V == 0 ) + memset(vin,0,sizeof(*vin)); vin->prev_vout = -1; - vin->sequence = juint(vinobj,"sequence"); + if ( jobj(vinobj,"sequence") != 0 ) + vin->sequence = juint(vinobj,"sequence"); + else vin->sequence = 0xffffffff; if ( (hexstr= jstr(vinobj,"coinbase")) == 0 ) { vin->prev_hash = jbits256(vinobj,"txid"); @@ -217,58 +203,78 @@ int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t if ( (obj= jobj(vinobj,"redeemScript")) != 0 ) redeemstr = jstr(obj,"hex"); } - /*if ( (addrs= jarray(&n,vinobj,"addresses")) != 0 ) + } + if ( hexstr != 0 ) + { + n = (int32_t)strlen(hexstr) >> 1; + decode_hex(serialized,n,hexstr); + vin->vinscript = serialized; + vin->scriptlen = n; + } //else printf("iguana_parsevinobj: hex script missing (%s)\n",jprint(vinobj,0)); + if ( V != 0 ) + { + if ( vin->vinscript == 0 ) { - for (i=0; iunspentind= iguana_unspentindfind(coin,V->coinaddr,V->spendscript,&V->spendlen,&V->amount,&V->height,vin->prev_hash,vin->prev_vout,coin->bundlescount-1)) > 0 ) { - V.signers[i].coinaddr[0] = 0; - if ( (coinaddr= jstr(jitem(addrs,i),0)) != 0 ) - safecopy(V.signers[i].coinaddr,coinaddr,sizeof(V.signers[i].coinaddr)); + if ( V->coinaddr[0] != 0 && (waddr= iguana_waddresssearch(myinfo,coin,&wacct,V->coinaddr)) != 0 ) + { + memcpy(V->signers[0].pubkey,waddr->pubkey,bitcoin_pubkeylen(waddr->pubkey)); + } + printf("V %.8f (%s) spendscript.[%d]\n",dstr(V->amount),V->coinaddr,V->spendlen); } - }*/ + } if ( (pubkeysjson= jarray(&n,vinobj,"pubkeys")) != 0 ) { + if ( vin->vinscript == 0 ) + { + vin->vinscript = serialized; + vin->vinscript[0] = 0; + vin->scriptlen = 1; + } for (i=0; ipubkeys[i] = 0; - if ( (pubkeystr= jstr(jitem(pubkeysjson,i),0)) != 0 && (len= (int32_t)strlen(pubkeystr) >> 1) > 0 ) + if ( (pubkeystr= jstr(jitem(pubkeysjson,i),0)) != 0 && (plen= (int32_t)strlen(pubkeystr) >> 1) > 0 ) { - decode_hex(serialized,len,pubkeystr); - if ( (plen= bitcoin_pubkeylen(serialized)) == len ) - { - vin->pubkeys[i] = serialized; - //if ( V.signers[i].coinaddr[0] == 0 ) - // bitcoin_address(V.signers[i].coinaddr,coin->chain->pubtype,serialized,len); - serialized = &serialized[len]; - } + vin->vinscript[vin->scriptlen++] = plen; + decode_hex(&vin->vinscript[vin->scriptlen],plen,pubkeystr); + memcpy(V->signers[i].pubkey,&vin->vinscript[vin->scriptlen],plen); + vin->scriptlen += plen; } } - vin->numpubkeys = n; } - } - 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; - } - if ( redeemstr != 0 ) - { - n = (int32_t)strlen(redeemstr) >> 1; - decode_hex(serialized,n,redeemstr); - vin->redeemscript = serialized; - vin->p2shlen = n; - len += n; + if ( vin->vinscript != 0 ) + serialized = &vin->vinscript[vin->scriptlen]; + len = vin->scriptlen; + if ( redeemstr != 0 ) + { + n = (int32_t)strlen(redeemstr) >> 1; + decode_hex(serialized,n,redeemstr); + vin->redeemscript = serialized; + V->p2shlen = vin->p2shlen = n; + memcpy(V->p2shscript,serialized,n); + } + if ( (suffixstr= jstr(vinobj,"suffix")) != 0 && is_hexstr(suffixstr,(int32_t)strlen(suffixstr)) > 0 ) + { + if ( vin->redeemscript == 0 ) + { + vin->redeemscript = serialized; + vin->redeemscript[0] = 0; + } + n = (int32_t)strlen(suffixstr) >> 1; + decode_hex(&vin->redeemscript[vin->p2shlen],n,suffixstr); + vin->p2shlen += n; + } + len += vin->p2shlen; + serialized = vin->redeemscript != 0 ? &vin->redeemscript[vin->p2shlen] : &serialized[len]; + if ( spendstr != 0 ) + { + n = (int32_t)strlen(spendstr) >> 1; + decode_hex(serialized,n,spendstr); + vin->spendscript = serialized; + vin->spendlen = n; + } + len += vin->spendlen; } return(len); } @@ -277,7 +283,9 @@ int32_t iguana_parsevoutobj(struct iguana_info *coin,uint8_t *serialized,int32_t { int32_t len = 0; cJSON *skey; char *hexstr; memset(vout,0,sizeof(*vout)); - vout->value = jdouble(voutobj,"value") * SATOSHIDEN; + if ( jobj(voutobj,"satoshis") != 0 ) + vout->value = j64bits(voutobj,"satoshis"); + else vout->value = jdouble(voutobj,"value") * SATOSHIDEN; if ( (skey= jobj(voutobj,"scriptPubKey")) != 0 ) { if ( (hexstr= jstr(skey,"hex")) != 0 ) @@ -297,7 +305,7 @@ cJSON *iguana_voutjson(struct iguana_info *coin,struct iguana_msgvout *vout,int3 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)); + jadd64bits(json,"satoshis",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) ) @@ -458,9 +466,12 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t rwflag,cJSON *json,uint8 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) +bits256 iguana_parsetxobj(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *txstartp,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,cJSON *txobj,struct vin_info *V) // json -> serialized + (msg,V) { int32_t i,numvins,numvouts,len = 0; cJSON *array=0; bits256 txid; char vpnstr[64]; + memset(&txid,0,sizeof(txid)); + if ( txobj == 0 ) + return(txid); memset(msg,0,sizeof(*msg)); vpnstr[0] = 0; if ( (msg->version= juint(txobj,"version")) == 0 ) @@ -480,7 +491,7 @@ bits256 iguana_parsetxobj(struct iguana_info *coin,int32_t *txstartp,uint8_t *se if ( msg->tx_in > 0 && msg->tx_in*sizeof(struct iguana_msgvin) < maxsize ) { for (i=0; itx_in; i++) - len += iguana_parsevinobj(coin,&serialized[len],maxsize,&msg->vins[i],jitem(array,i)); + len += iguana_parsevinobj(myinfo,coin,&serialized[len],maxsize,&msg->vins[i],jitem(array,i),V!=0?&V[i]:0); } } if ( (array= jarray(&numvouts,txobj,"vout")) != 0 ) @@ -549,7 +560,7 @@ cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *payments char *hexstr; cJSON *item,*skey,*vouts = jduplicate(jobj(txobj,"vout")); jdelete(txobj,"vout"); item = cJSON_CreateObject(); - jaddnum(item,"value",dstr(satoshis)); + jadd64bits(item,"satoshis",satoshis); skey = cJSON_CreateObject(); hexstr = malloc(len*2 + 1); init_hexbytes_noT(hexstr,paymentscript,len); @@ -592,11 +603,16 @@ cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32 return(txobj); } -char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson) +char *bitcoin_json2hex(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,cJSON *txjson,struct vin_info *V) { int32_t txstart; uint8_t *serialized; struct iguana_msgtx msgtx; char *txbytes = 0; + if ( txjson == 0 ) + { + memset(txidp,0,sizeof(*txidp)); + return(0); + } serialized = malloc(IGUANA_MAXPACKETSIZE*1.5); - *txidp = iguana_parsetxobj(coin,&txstart,serialized,IGUANA_MAXPACKETSIZE*1.5,&msgtx,txjson); + *txidp = iguana_parsetxobj(myinfo,coin,&txstart,serialized,IGUANA_MAXPACKETSIZE*1.5,&msgtx,txjson,V); if ( msgtx.allocsize > 0 ) { txbytes = malloc(msgtx.allocsize*2 + 1); @@ -630,112 +646,151 @@ cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_ms return(txobj); } -int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t numinputs,int32_t sighashsingle) +bits256 bitcoin_sigtxid(struct iguana_info *coin,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr) { - 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 savelen,n2,i,j,k,plen,vini=0,flag,hashtype,retval,siglen,asmtype,numvouts; - numvouts = msgtx->tx_out; - vpnstr[0] = 0; - *signedtx = 0; - memset(signedtxidp,0,sizeof(*signedtxidp)); - retval = -numinputs; - for (vini=0; vinitx_in; i++) + { + if ( i == vini ) + { + dest.vins[i].vinscript = spendscript; + dest.vins[i].scriptlen = spendlen; + } + else + { + dest.vins[i].vinscript = (uint8_t *)""; + dest.vins[i].scriptlen = 0; + } + dest.vins[i].p2shlen = 0; + dest.vins[i].redeemscript = 0; + } + len = iguana_rwmsgtx(coin,1,0,serialized,maxlen,&dest,&txid,vpnstr); + if ( len > 0 ) + { + len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype); + revsigtxid = bits256_doublesha256(0,serialized,len); + for (i=0; itx_in; 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; - savelen = vp->spendlen; - if ( bitcoin_scriptget(coin,&hashtype,&sigsize,&pubkeysize,&suffixlen,vp,msgtx->vins[vini].vinscript,msgtx->vins[vini].scriptlen,asmtype) < 0 ) + msgtx->vins[vini].vinscript = script = &serialized[len]; + msgtx->vins[vini].vinscript[0] = 0; + scriptlen = 0; + for (j=0; jN; j++) + { + if ( (siglen= vp->signers[j].siglen) > 0 ) { - printf("cant get script for (%s).v%d\n",bits256_str(str,vp->vin.prev_hash),vp->vin.prev_vout); - continue; + script[scriptlen++] = siglen; + memcpy(&script[scriptlen],vp->signers[j].sig,siglen); + scriptlen += siglen; } - if ( vp->spendlen == 0 ) - vp->spendlen = savelen; - if ( sighashsingle != 0 && vini == 0 ) + } + for (j=0; jN; j++) + { + if ( (plen= bitcoin_pubkeylen(vp->signers[j].pubkey)) > 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; - printf("spendscript.[%d]\n",vp->spendlen); + script[scriptlen++] = plen; + memcpy(&script[scriptlen],vp->signers[j].pubkey,plen); + scriptlen += plen; + } + } + msgtx->vins[vini].scriptlen = scriptlen; + if ( vp->p2shscript != 0 && (p2shlen= vp->p2shlen) > 0 ) + { + msgtx->vins[vini].redeemscript = &script[scriptlen]; + if ( p2shlen < 76 ) + script[scriptlen++] = p2shlen; + else if ( p2shlen <= 0xff ) + { + script[scriptlen++] = 0x4c; + script[scriptlen++] = p2shlen; + } + else if ( p2shlen <= 0xffff ) + { + script[scriptlen++] = 0x4d; + script[scriptlen++] = (p2shlen & 0xff); + script[scriptlen++] = ((p2shlen >> 8) & 0xff); + } else return(-1); + memcpy(&script[scriptlen],vp->p2shscript,p2shlen), scriptlen += p2shlen; + if ( (msgtx->vins[vini].suffixlen= vp->suffixlen) > 0 ) + { + memcpy(&script[scriptlen],&vp->p2shscript[vp->p2shlen - vp->suffixlen],vp->suffixlen); + scriptlen += vp->suffixlen; + } + } + len += scriptlen; + } + return(len); +} + +int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,int32_t sighash) +{ + bits256 sigtxid; uint8_t *sig; struct vin_info *vp; char vpnstr[64]; int32_t plen,i,j,vini=0,flag=0,siglen,numvouts; + numvouts = msgtx->tx_out; + vpnstr[0] = 0; + *signedtx = 0; + memset(signedtxidp,0,sizeof(*signedtxidp)); + for (vini=0; vinitx_in; vini++) + { + sigtxid = bitcoin_sigtxid(coin,serialized,maxlen,msgtx,vini,msgtx->vins[vini].spendscript,msgtx->vins[vini].spendlen,sighash,vpnstr); + if ( bits256_nonz(sigtxid) != 0 ) + { + vp = &V[vini]; for (j=0; jN; j++) { - pubkey = vp->signers[j].pubkey; - if ( (plen= bitcoin_pubkeylen(pubkey)) < 0 ) + sig = vp->signers[j].sig; + siglen = vp->signers[j].siglen; + if ( bits256_nonz(vp->signers[j].privkey) != 0 ) { - if ( bits256_nonz(vp->signers[j].privkey) > 0 ) - { - pubkey = vp->signers[j].pubkey; - bitcoin_pubkey33(coin->ctx,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; - } + siglen = bitcoin_sign(coin->ctx,sig,sigtxid,vp->signers[j].privkey); + if ( (plen= bitcoin_pubkeylen(vp->signers[j].pubkey)) <= 0 ) + bitcoin_pubkey33(coin->ctx,vp->signers[j].pubkey,vp->signers[j].privkey); + sig[siglen++] = sighash; + vp->signers[j].siglen = siglen; + for (i=0; ichain->pubtype,pubkey,plen); - n2 = iguana_rwmsgtx(coin,1,0,serialized,maxsize,msgtx,&txid,vpnstr); - if ( n2 > 0 ) + if ( sig == 0 || siglen == 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; isigners[j].privkey) != 0 ) - { - siglen = bitcoin_sign(coin->ctx,vp->signers[j].sig,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; ictx,sig,vp->signers[j].siglen-1,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 \n",vini);//%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; + memset(vp->signers[j].pubkey,0,sizeof(vp->signers[j].pubkey)); + continue; + } + if ( bitcoin_verify(coin->ctx,sig,siglen-1,sigtxid,vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 ) + { + + printf("SIG.%d.%d ERROR\n",vini,j); + } + else + { + printf("SIG.%d.%d VERIFIED \n",vini,j);//%s (%s)\n",vini,*signedtx,jprint(txobj,1)); + flag++; + } } - if ( vp->type != IGUANA_SCRIPT_76A988AC && vp->type != IGUANA_SCRIPT_76AC ) - break; } } - return(retval); + iguana_msgtx_Vset(coin,serialized,maxlen,msgtx,V); + cJSON *txobj = cJSON_CreateObject(); + *signedtx = iguana_rawtxbytes(coin,txobj,msgtx); + //printf("SIGNEDTX.(%s)\n",jprint(txobj,1)); + *signedtxidp = msgtx->txid; + return(flag); } int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V,int32_t numinputs) @@ -749,9 +804,9 @@ int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **si 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 ) + if ( iguana_rwmsgtx(coin,0,0,serialized,maxsize,&msgtx,&txid,vpnstr) > 0 && numinputs == msgtx.tx_in ) { - if ( bitcoin_verifyvins(coin,signedtxidp,signedtx,&msgtx,serialized2,maxsize,V,numinputs,0) == 0 ) + if ( bitcoin_verifyvins(coin,signedtxidp,signedtx,&msgtx,serialized2,maxsize,V,SIGHASH_ALL) == 0 ) retval = 0; else printf("bitcoin_verifytx: bitcoin_verifyvins error\n"); } else printf("bitcoin_verifytx: error iguana_rwmsgtx\n"); @@ -791,7 +846,7 @@ cJSON *iguana_signtx(struct supernet_info *myinfo,struct iguana_info *coin,bits2 } else vitem = 0; vp->N = vp->M = 1; - if ( (rawtxstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 ) + if ( (rawtxstr= bitcoin_json2hex(myinfo,coin,&txid,txobj,0)) != 0 ) { for (j=0; jinputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++) { @@ -817,10 +872,10 @@ cJSON *iguana_signtx(struct supernet_info *myinfo,struct iguana_info *coin,bits2 } } /*if ( spend->inputs[i].spendlen > 0 ) - { - memcpy(vp->spendscript,spend->inputs[i].spendscript,spend->inputs[i].spendlen); - vp->spendlen = spend->inputs[i].spendlen; - }*/ + { + memcpy(vp->spendscript,spend->inputs[i].spendscript,spend->inputs[i].spendlen); + vp->spendlen = spend->inputs[i].spendlen; + }*/ if ( spend->inputs[i].p2shlen > 0 ) { memcpy(vp->p2shscript,spend->inputs[i].p2shscript,spend->inputs[i].p2shlen); @@ -857,8 +912,85 @@ cJSON *iguana_signtx(struct supernet_info *myinfo,struct iguana_info *coin,bits2 return(txobj); } -#include "../includes/iguana_apidefs.h" -#include "../includes/iguana_apideclares.h" +int32_t iguana_vininfo_create(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msgtx,cJSON *vins,int32_t numinputs,struct vin_info *V) +{ + int32_t i,plen,len = 0; struct vin_info *vp; struct iguana_waccount *wacct; struct iguana_waddress *waddr; uint32_t sigsize,pubkeysize,p2shsize,suffixlen; + msgtx->tx_in = numinputs; + maxsize -= (sizeof(struct iguana_msgvin) * msgtx->tx_in); + msgtx->vins = (struct iguana_msgvin *)&serialized[maxsize]; + if ( msgtx->tx_in > 0 && msgtx->tx_in*sizeof(struct iguana_msgvin) < maxsize ) + { + for (i=0; itx_in; i++) + { + vp = &V[i]; + len += iguana_parsevinobj(myinfo,coin,&serialized[len],maxsize,&msgtx->vins[i],jitem(vins,i),vp); + if ( msgtx->vins[i].spendscript == 0 ) + { + if ( (vp->unspentind= iguana_unspentindfind(coin,vp->coinaddr,vp->spendscript,&vp->spendlen,&vp->amount,&vp->height,msgtx->vins[i].prev_hash,msgtx->vins[i].prev_vout,coin->bundlescount-1)) > 0 ) + { + msgtx->vins[i].spendscript = vp->spendscript; + msgtx->vins[i].spendlen = vp->spendlen; + vp->hashtype = iguana_vinscriptparse(coin,V,&sigsize,&pubkeysize,&p2shsize,&suffixlen,vp->spendscript,vp->spendlen); + vp->suffixlen = suffixlen; + printf("V %.8f (%s) spendscript.[%d]\n",dstr(vp->amount),vp->coinaddr,vp->spendlen); + } + } + else + { + memcpy(vp->spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); + vp->spendlen = msgtx->vins[i].spendlen; + _iguana_calcrmd160(coin,vp); + if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) > 0 ) + bitcoin_address(vp->coinaddr,coin->chain->pubtype,vp->signers[0].pubkey,plen); + } + if ( vp->coinaddr[i] != 0 && (waddr= iguana_waddresssearch(myinfo,coin,&wacct,vp->coinaddr)) != 0 ) + { + vp->signers[0].privkey = waddr->privkey; + if ( bitcoin_pubkeylen(waddr->pubkey) != vp->spendscript[1] || vp->spendscript[vp->spendlen-1] != 0xac ) + memcpy(vp->signers[0].pubkey,waddr->pubkey,bitcoin_pubkeylen(waddr->pubkey)); + } + if ( vp->M == 0 && vp->N == 0 ) + vp->M = vp->N = 1; + } + } + /*for (i=0; itx_out; i++) + { + if ( msgtx->vouts[i].pk_script != 0 ) + { + for (j=0; jvouts[i].pk_scriptlen; j++) + printf("%02x",msgtx->vouts[i].pk_script[j]); + printf(" pk_script[%d]\n",i); + } + }*/ + return(len); +} + +void iguana_ensure_privkey(struct supernet_info *myinfo,struct iguana_info *coin,bits256 privkey) +{ + uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char coinaddr[128]; + bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); + bitcoin_address(coinaddr,coin->chain->pubtype,pubkey33,33); + //printf("privkey for (%s)\n",coinaddr); + if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) ) + { + if ( waddr == 0 ) + { + memset(&addr,0,sizeof(addr)); + iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,&addr,privkey); + if ( (wacct= iguana_waccountfind(myinfo,coin,"default")) != 0 ) + waddr = iguana_waddressadd(myinfo,coin,wacct,&addr,0); + } + if ( waddr != 0 ) + { + waddr->privkey = privkey; + if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->chain->wiftype) > 0 ) + { + waddr->wiftype = coin->chain->wiftype; + waddr->addrtype = coin->chain->pubtype; + } + } + } +} char *_setVsigner(struct iguana_info *coin,struct vin_info *V,int32_t ind,char *pubstr,char *wifstr) { @@ -870,18 +1002,22 @@ char *_setVsigner(struct iguana_info *coin,struct vin_info *V,int32_t ind,char * else return(0); } -int32_t bitcoin_txaddspend(struct iguana_info *coin,cJSON *txobj,char *destaddress,double destamount) +int32_t bitcoin_txaddspend(struct iguana_info *coin,cJSON *txobj,char *destaddress,uint64_t satoshis) { uint8_t outputscript[128],addrtype,rmd160[20]; int32_t scriptlen; - if ( bitcoin_validaddress(coin,destaddress) == 0 && destamount > 0. ) + if ( bitcoin_validaddress(coin,destaddress) == 0 && satoshis != 0 ) { bitcoin_addr2rmd160(&addrtype,rmd160,destaddress); scriptlen = bitcoin_standardspend(outputscript,0,rmd160); - bitcoin_addoutput(coin,txobj,outputscript,scriptlen,destamount * SATOSHIDEN); + bitcoin_addoutput(coin,txobj,outputscript,scriptlen,satoshis); return(0); } else return(-1); } +#include "../includes/iguana_apidefs.h" +#include "../includes/iguana_apideclares.h" + + 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],pubkeys[3][65],*pubkeyptrs[3]; int32_t spendlen; @@ -899,9 +1035,9 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount memset(&V,0,sizeof(V)); txobj = bitcoin_createtx(active,0); if ( destaddress[0] != 0 && destamount > 0. ) - bitcoin_txaddspend(active,txobj,destaddress,destamount); + bitcoin_txaddspend(active,txobj,destaddress,destamount * SATOSHIDEN); if ( destaddress2[0] != 0 && destamount2 > 0. ) - bitcoin_txaddspend(active,txobj,destaddress2,destamount2); + bitcoin_txaddspend(active,txobj,destaddress2,destamount2 * SATOSHIDEN); 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 ) @@ -929,7 +1065,7 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount bitcoin_addinput(active,txobj,vintxid,vinvout,0xffffffff,spendscript,spendlen,V.p2shscript,V.p2shlen,pubkeyptrs,N); bitcoin_address(msigaddr,active->chain->p2shtype,V.p2shscript,V.p2shlen); retjson = cJSON_CreateObject(); - if ( bitcoin_verifyvins(active,&signedtxid,&signedtx,&msgtx,serialized,sizeof(serialized),&V,1,0) == 0 ) + if ( bitcoin_verifyvins(active,&signedtxid,&signedtx,&msgtx,serialized,sizeof(serialized),&V,SIGHASH_ALL) == 0 ) { jaddstr(retjson,"result","msigtx"); if ( signedtx != 0 ) @@ -942,66 +1078,85 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighash) { - bits256 txid; uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char *privkeystr,coinaddr[128],*signedtx = 0; bits256 privkey; int32_t i,n,numinputs = 1; struct bitcoin_spend *spend; cJSON *txobj=0,*item,*retjson = cJSON_CreateObject(); + char *privkeystr,*signedtx = 0; struct vin_info *V; bits256 txid,signedtxid,privkey; int32_t len,i,n,maxsize,numinputs = 1; uint8_t *serialized=0,*serialized2=0,*serialized3=0; struct iguana_msgtx msgtx; cJSON *txobj,*item,*retjson; int uselessbitcoin_error = 0; + retjson = cJSON_CreateObject(); if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); if ( myinfo->expiration == 0 ) return(clonestr("{\"error\":\"need to unlock wallet\"}")); - //printf("rawtx.(%s) vins.(%s) privkeys.(%s) sighash.(%s)\n",rawtx,jprint(vins,0),jprint(privkeys,0),sighash); + //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 + jaddstr(retjson,"error","only sighash all (ALL) supported for now"); + maxsize = 65536; + if ( rawtx != 0 && rawtx[0] != 0 && (len= (int32_t)strlen(rawtx)>>1) < maxsize ) { - signedtx = clonestr(rawtx); - if ( (numinputs= cJSON_GetArraySize(vins)) > 0 && (n= cJSON_GetArraySize(privkeys)) > 0 ) + serialized = malloc(maxsize); + serialized2 = malloc(maxsize); + serialized3 = malloc(maxsize); + memset(&msgtx,0,sizeof(msgtx)); + decode_hex(serialized,len,rawtx); + if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,rawtx)) != 0 ) { - spend = calloc(1,sizeof(*spend) + (sizeof(*spend->inputs) * numinputs)); - spend->numinputs = numinputs; - for (i=0; iinputs[i].sequence = 0xffffffff; - spend->inputs[i].privkeys[0] = privkey; - if ( bits256_nonz(privkey) != 0 ) + if ( strcmp(rawtx,checkstr) != 0 ) { - bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); - memcpy(spend->inputs[i].pubkeys[0],pubkey33,33); - bitcoin_address(coinaddr,coin->chain->pubtype,pubkey33,33); - if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) ) - { - if ( waddr == 0 ) - { - memset(&addr,0,sizeof(addr)); - iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,&addr,privkey); - if ( (wacct= iguana_waccountfind(myinfo,coin,"default")) != 0 ) - waddr = iguana_waddressadd(myinfo,coin,wacct,&addr,0); - } - if ( waddr != 0 ) - { - waddr->privkey = privkey; - if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->chain->wiftype) > 0 ) - { - waddr->wiftype = coin->chain->wiftype; - waddr->addrtype = coin->chain->pubtype; - } - } - } + printf("RAW.(%s) ->\nNEW.(%s)\n",rawtx,checkstr); + free_json(txobj); + free(checkstr); + free(serialized); + free(serialized2); + free(serialized3); + jaddstr(retjson,"error",uselessbitcoin_error != 0 ? "-22" : "hex2json -> json2hex error"); + return(jprint(retjson,1)); } + free(checkstr); } - txobj = iguana_signtx(myinfo,coin,&txid,&signedtx,spend,txobj,vins); - free(spend); free_json(txobj); + } + if ( (numinputs= cJSON_GetArraySize(vins)) > 0 ) + V = calloc(numinputs,sizeof(*V)); + memset(&msgtx,0,sizeof(msgtx)); + if ( iguana_rwmsgtx(coin,0,0,serialized,maxsize,&msgtx,&txid,"") > 0 && numinputs == msgtx.tx_in ) + { + if ( (n= cJSON_GetArraySize(privkeys)) > 0 ) + { + for (i=0; i> 1; + decode_hex(script,scriptlen,testscript); + sigtxid = bitcoin_sigtxid(coin,serialized,sizeof(serialized),&msgtx,0,msgtx.vins[0].spendscript,msgtx.vins[0].spendlen,SIGHASH_ALL,""); + char str[65]; printf("sigtxid.(%s)\n",bits256_str(str,sigtxid));*/ + jaddstr(retjson,"error",uselessbitcoin_error != 0 ? "-22" : "couldnt load serialized tx or mismatched numinputs"); + } + free(serialized); + free(serialized2); + free(serialized3); + } else jaddstr(retjson,"error",uselessbitcoin_error != 0 ? "-22" : "no rawtx or rawtx too big"); return(jprint(retjson,1)); } diff --git a/iguana/iguana_stake.c b/iguana/iguana_stake.c index e2c8e4e03..5eedb3a84 100644 --- a/iguana/iguana_stake.c +++ b/iguana/iguana_stake.c @@ -1,4 +1,6 @@ #ifdef reference +// modify time.1462237906 modifier.baed58b98a00e41d + static const int64_t COIN_YEAR_REWARD = 5 * CENT; // 5% per year int nCoinbaseMaturity = 100; static const int STAKE_TIMESTAMP_MASK = 15; diff --git a/iguana/swaps/iguana_BTCswap.c b/iguana/swaps/iguana_BTCswap.c index c0db0509d..251b0d004 100755 --- a/iguana/swaps/iguana_BTCswap.c +++ b/iguana/swaps/iguana_BTCswap.c @@ -1083,7 +1083,7 @@ char *instantdex_bailintx(struct iguana_info *coin,bits256 *txidp,struct bitcoin bitcoin_addoutput(coin,txobj,changescript,scriptv2len,change); for (i=0; inuminputs; i++) bitcoin_addinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,0xffffffff); - rawtxstr = bitcoin_json2hex(coin,&txid,txobj); + rawtxstr = bitcoin_json2hex(coin,&txid,txobj,0); char str[65]; printf("%s_bailin.%s (%s)\n",isbob!=0?"bob":"alice",bits256_str(str,txid),rawtxstr); V = calloc(spend->numinputs,sizeof(*V)); for (i=0; inuminputs; i++) @@ -1126,7 +1126,7 @@ cJSON *instantdex_bailinspend(struct iguana_info *coin,bits256 privkey,uint64_t char *instantdex_bailinsign(struct iguana_info *coin,bits256 bailinpriv,char *sigstr,int32_t *siglenp,bits256 *txidp,struct vin_info *V,cJSON *txobj,int32_t isbob) { char *rawtxstr,*signedtx; - rawtxstr = bitcoin_json2hex(coin,txidp,txobj); + rawtxstr = bitcoin_json2hex(coin,txidp,txobj,0); char str[65]; printf("%s_payout.%s (%s)\n",isbob!=0?"bob":"alice",bits256_str(str,*txidp),rawtxstr); V->signers[isbob].privkey = bailinpriv; bitcoin_verifytx(coin,txidp,&signedtx,rawtxstr,V); diff --git a/iguana/tests/createrawtransaction b/iguana/tests/createrawtransaction index 20c40538e..47fc3c1cd 100755 --- a/iguana/tests/createrawtransaction +++ b/iguana/tests/createrawtransaction @@ -1,2 +1,2 @@ -curl --url "http://127.0.0.1:7778" --data "{\"method\":\"createrawtransaction\",\"params\":[[{\"txid\":\"fe9ba49c411ee7b3ae16f8de6f2e32b4ea469a8ff64766be113817646100bb56\",\"vout\":24}], {\"RV37MfeBD1QTeoLHteab3j4mFVrsSaGMJx\":0.00167}] }" +curl --url "http://127.0.0.1:7778" --data "{\"method\":\"createrawtransaction\",\"params\":[[{\"txid\":\"e8a0cc971e769de1fcf9d4abb734acb9ab4ab7f44d9eb7d9cd96707b847dd1f6\",\"vout\":0}], {\"RAoMou7euzvDwa9dQwjrNB5A41hrAWgvBt\":0.01,\"RV37MfeBD1QTeoLHteab3j4mFVrsSaGMJx\":0.0093}] }" diff --git a/iguana/tests/decoderawtransaction b/iguana/tests/decoderawtransaction index 2d7af546c..0e7dd82c7 100755 --- a/iguana/tests/decoderawtransaction +++ b/iguana/tests/decoderawtransaction @@ -1 +1 @@ -curl --url "http://127.0.0.1:7778" --data "{\"method\":\"decoderawtransaction\",\"params\":[\"0100000010fd23570156bb006164173811be6647f68f9a46eab4322e6fdef816aeb3e71e419ca49bfe1800000000ffffffff0168b30200000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\"]}" +curl --url "http://127.0.0.1:7778" --data "{\"method\":\"decoderawtransaction\",\"params\":[\"0100000095f4265701f6d17d847b7096cdd9b79e4df4b74aabb9ac34b7abd4f9fce19d761e97cca0e8000000006a47304402207ddad8357583b7b3707b3de1a2625b6054367c42a893edb10cd8fce4ea766895022079043096f5e278d131fafcc12d360c65f8cd4eaa81bc09ec709b5e34da7c0bdc012102d14a195654f536df6dfe5a38278d1b470d00f17de78eeb5ce9e9eea9edb2c212ffffffff0240420f00000000001976a91410acba3a841fae68aba4b5ff162714c493bcc04e88acd0300e00000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\"]}" diff --git a/iguana/tests/sendrawtransaction b/iguana/tests/sendrawtransaction new file mode 100755 index 000000000..c617b57a8 --- /dev/null +++ b/iguana/tests/sendrawtransaction @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:14632" --user "user:rzDbtP9UDZEbPcn" --data "{\"method\":\"sendrawtransaction\",\"params\":[\"0100000095f4265701f6d17d847b7096cdd9b79e4df4b74aabb9ac34b7abd4f9fce19d761e97cca0e8000000006a47304402207ddad8357583b7b3707b3de1a2625b6054367c42a893edb10cd8fce4ea766895022079043096f5e278d131fafcc12d360c65f8cd4eaa81bc09ec709b5e34da7c0bdc012102d14a195654f536df6dfe5a38278d1b470d00f17de78eeb5ce9e9eea9edb2c212ffffffff0240420f00000000001976a91410acba3a841fae68aba4b5ff162714c493bcc04e88acd0300e00000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\"]}" + diff --git a/iguana/tests/signrawtransaction b/iguana/tests/signrawtransaction index 7938666cc..02a68732d 100755 --- a/iguana/tests/signrawtransaction +++ b/iguana/tests/signrawtransaction @@ -1,2 +1,2 @@ -curl --url "http://127.0.0.1:7778" --data "{\"method\":\"signrawtransaction\",\"params\":[\"01000000dc4f24570156bb006164173811be6647f68f9a46eab4322e6fdef816aeb3e71e419ca49bfe1800000000ffffffff01588c0200000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\", [{\"txid\":\"fe9ba49c411ee7b3ae16f8de6f2e32b4ea469a8ff64766be113817646100bb56\",\"vout\":24}], [\"UqvuZXEAVXDXJkL4j4Xq6qoMdeJfPF1aNsCzmzfZaQ1ZgBTwfmWn\"], \"ALL\"] }" +curl --url "http://127.0.0.1:7778" --data "{\"method\":\"signrawtransaction\",\"params\":[\"0100000095f4265701f6d17d847b7096cdd9b79e4df4b74aabb9ac34b7abd4f9fce19d761e97cca0e80000000000ffffffff0240420f00000000001976a91410acba3a841fae68aba4b5ff162714c493bcc04e88acd0300e00000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\", [{\"txid\":\"e8a0cc971e769de1fcf9d4abb734acb9ab4ab7f44d9eb7d9cd96707b847dd1f6\",\"vout\":0,\"scriptPubKey\":\"2102d14a195654f536df6dfe5a38278d1b470d00f17de78eeb5ce9e9eea9edb2c212ac\"}], [\"UqvuZXEAVXDXJkL4j4Xq6qoMdeJfPF1aNsCzmzfZaQ1ZgBTwfmWn\"], \"ALL\"] }" diff --git a/iguana/tests/signrawtransaction2 b/iguana/tests/signrawtransaction2 new file mode 100755 index 000000000..a25bf319e --- /dev/null +++ b/iguana/tests/signrawtransaction2 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"coin\":\"BTC\",\"method\":\"signrawtransaction\",\"params\":[\"01000000dc4f24570156bb006164173811be6647f68f9a46eab4322e6fdef816aeb3e71e419ca49bfe1800000000ffffffff01588c0200000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\", [{\"txid\":\"fe9ba49c411ee7b3ae16f8de6f2e32b4ea469a8ff64766be113817646100bb56\",\"vout\":24}], [\"UqvuZXEAVXDXJkL4j4Xq6qoMdeJfPF1aNsCzmzfZaQ1ZgBTwfmWn\"], \"ALL\"] }" + diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index 73238035f..c572a0de0 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -62,11 +62,11 @@ INT_ARRAY_STRING(bitcoinrpc,addmultisigaddress,M,pubkeys,account); DOUBLE_ARG(bitcoinrpc,settxfee,amount); STRING_ARG(bitcoinrpc,submitblock,rawbytes); -STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees); // -STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighash); // +STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighash); TWO_STRINGS(bitcoinrpc,signmessage,address,message); // THREE_STRINGS(bitcoinrpc,verifymessage,address,sig,message); // +STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees); // SS_D_I_SS(bitcoinrpc,sendfrom,fromaccount,toaddress,amount,minconf,comment,comment2); // S_A_I_S(bitcoinrpc,sendmany,fromaccount,payments,minconf,comment); //