diff --git a/crypto777/iguana_utils.c b/crypto777/iguana_utils.c index 5e9634294..67b50b721 100755 --- a/crypto777/iguana_utils.c +++ b/crypto777/iguana_utils.c @@ -321,7 +321,7 @@ int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex) { int32_t adjust,i = 0; //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,64) == 0 ) + if ( is_hexstr(hex,n) == 0 ) { memset(bytes,0,n); return(n); diff --git a/iguana/iguana777.h b/iguana/iguana777.h index d5161ef96..57eb016f6 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -955,7 +955,7 @@ cJSON *iguana_createvins(struct supernet_info *myinfo,struct iguana_info *coin,c bits256 bitcoin_pubkey33(void *ctx,uint8_t *data,bits256 privkey); bits256 bitcoin_randkey(void *ctx); int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig64,bits256 messagehash2,uint8_t *pubkey); -int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRIPTSIZE],cJSON *scriptobj,int32_t interpret,int64_t nLockTime,struct vin_info *V); +int32_t bitcoin_assembler(struct iguana_info *coin,cJSON *logarray,uint8_t script[IGUANA_MAXSCRIPTSIZE],cJSON *scriptobj,int32_t interpret,int64_t nLockTime,struct vin_info *V); cJSON *iguana_spendasm(struct iguana_info *coin,uint8_t *spendscript,int32_t spendlen); int64_t iguana_unspentavail(struct iguana_info *coin,uint64_t hdrsi_unspendind,int32_t minconf,int32_t maxconf); struct iguana_utxo iguana_utxofind(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t spent_unspentind,int32_t *RTspendflagp,int32_t lockflag); @@ -970,6 +970,8 @@ int32_t instantdex_peerhas_clear(struct supernet_info *myinfo,struct iguana_info int32_t instantdex_quote(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,uint8_t *serialized,int32_t recvlen); void instantdex_update(struct supernet_info *myinfo); cJSON *iguana_getaddressesbyaccount(struct supernet_info *myinfo,struct iguana_info *coin,char *account); +int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLockTime,struct vin_info *V,int32_t numvins); +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); extern int32_t HDRnet,netBLOCKS; diff --git a/iguana/iguana_interpreter.c b/iguana/iguana_interpreter.c index 36dad141d..902549602 100755 --- a/iguana/iguana_interpreter.c +++ b/iguana/iguana_interpreter.c @@ -474,10 +474,15 @@ static int32_t iguana_num(struct iguana_stackdata Snum) static int32_t iguana_pushdata(struct iguana_interpreter *stacks,int64_t num64,uint8_t *numbuf,int32_t numlen) { - struct iguana_stackdata Snum; cJSON *item = 0; char str[256]; int32_t num = (int32_t)num64; + struct iguana_stackdata Snum; cJSON *item = 0; char tmpstr[2048]; int32_t num = (int32_t)num64; if ( stacks->maxstackdepth > 0 ) { - printf("PUSHDATA.[%d]\n",numlen); + /*if ( numbuf != 0 ) + { + int32_t i; for (i=0; istackdepth < stacks->maxstackdepth ) { if ( stacks->logarray != 0 ) @@ -490,44 +495,21 @@ static int32_t iguana_pushdata(struct iguana_interpreter *stacks,int64_t num64,u iguana_rwnum(1,(void *)&num,numlen,numbuf); numlen = sizeof(num); Snum.U.val = num; - if ( item != 0 ) - jaddnum(item,"push",num); } else if ( numlen <= sizeof(int64_t) ) { iguana_rwnum(1,(void *)&num64,numlen,numbuf); numlen = sizeof(num64); Snum.U.val64 = num64; - if ( item != 0 ) - jadd64bits(item,"push",num64); } else if ( numlen == 20 ) - { memcpy(Snum.U.rmd160,numbuf,20); - if ( item != 0 ) - { - init_hexbytes_noT(str,Snum.U.rmd160,20); - jaddstr(item,"push",str); - } - } else if ( numlen == sizeof(bits256) ) - { iguana_rwbignum(1,Snum.U.hash2.bytes,sizeof(Snum.U.hash2),numbuf); - if ( item != 0 ) - jaddbits256(item,"push",Snum.U.hash2); - } else if ( numlen == 33 ) - { memcpy(Snum.U.pubkey,numbuf,numlen); - if ( item != 0 ) - jaddnum(item,"push",numlen); - } else if ( numlen < 74 ) - { memcpy(Snum.U.sig,numbuf,numlen); - if ( item != 0 ) - jaddnum(item,"push",numlen); - } else { Snum.data = malloc(numlen); @@ -536,10 +518,24 @@ static int32_t iguana_pushdata(struct iguana_interpreter *stacks,int64_t num64,u jaddnum(item,"push",numlen); } Snum.size = numlen; + if ( item != 0 ) + { + init_hexbytes_noT(tmpstr,numbuf,numlen); + jaddstr(item,"push",tmpstr); + } } else if ( num64 <= 0xffffffff ) // what about negative numbers? + { Snum.U.val = num, Snum.size = sizeof(num); - else Snum.U.val64 = num64, Snum.size = sizeof(num64); + if ( item != 0 ) + jaddnum(item,"push",Snum.U.val); + } + else + { + Snum.U.val64 = num64, Snum.size = sizeof(num64); + if ( item != 0 ) + jaddnum(item,"push",Snum.U.val64); + } if ( item != 0 ) { jaddnum(item,"depth",stacks->stackdepth); @@ -575,18 +571,18 @@ static int32_t iguana_cmp(struct iguana_stackdata *a,struct iguana_stackdata *b) if ( a->size == b->size ) { if ( a->size == 4 ) - return(a->U.val == b->U.val); + return(a->U.val != b->U.val); else if ( a->size == 8 ) - return(a->U.val64 == b->U.val64); + return(a->U.val64 != b->U.val64); else if ( a->size == 20 ) - return(memcmp(a->U.rmd160,b->U.rmd160,sizeof(a->U.rmd160)) == 0); + return(memcmp(a->U.rmd160,b->U.rmd160,sizeof(a->U.rmd160))); else if ( a->size == 32 ) - return(memcmp(a->U.hash2.bytes,b->U.hash2.bytes,sizeof(a->U.hash2)) == 0); + return(memcmp(a->U.hash2.bytes,b->U.hash2.bytes,sizeof(a->U.hash2))); else if ( a->size == 33 ) - return(memcmp(a->U.pubkey,b->U.pubkey,33) == 0); + return(memcmp(a->U.pubkey,b->U.pubkey,33)); else if ( a->size < 74 ) - return(memcmp(a->U.sig,b->U.sig,a->size) == 0); - else return(memcmp(a->data,b->data,sizeof(a->size)) == 0); + return(memcmp(a->U.sig,b->U.sig,a->size)); + else return(memcmp(a->data,b->data,sizeof(a->size))); } return(-1); } @@ -709,12 +705,12 @@ int32_t iguana_checksig(struct iguana_info *coin,struct iguana_stackdata pubkeya uint8_t pubkey[MAX_SCRIPT_ELEMENT_SIZE],sig[MAX_SCRIPT_ELEMENT_SIZE]; int32_t plen,siglen; plen = iguana_databuf(pubkey,pubkeyarg); siglen = iguana_databuf(sig,sigarg); - /*int32_t i; for (i=0; i 0 && siglen > 0 && siglen < 74 ) return(bitcoin_verify(coin->ctx,sig,siglen-1,sigtxid,pubkey,plen) == 0); return(0); @@ -891,11 +887,11 @@ cJSON *iguana_spendasm(struct iguana_info *coin,uint8_t *spendscript,int32_t spe return(spendasm); } -int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRIPTSIZE],cJSON *interpreter,int32_t interpret,int64_t nLockTime,struct vin_info *V) +int32_t bitcoin_assembler(struct iguana_info *coin,cJSON *logarray,uint8_t script[IGUANA_MAXSCRIPTSIZE],cJSON *interpreter,int32_t interpret,int64_t nLockTime,struct vin_info *V) { struct bitcoin_opcode *op; cJSON *array = 0; struct iguana_interpreter STACKS,*stacks = &STACKS; struct iguana_stackdata args[MAX_PUBKEYS_PER_MULTISIG]; - uint8_t databuf[MAX_SCRIPT_ELEMENT_SIZE]; char *asmstr,*str,*hexstr; + uint8_t databuf[MAX_SCRIPT_ELEMENT_SIZE]; char *asmstr,*str,*hexstr; cJSON *item; int32_t c,numops,plen,numvars,numused,numargs=0,i,j,k,n,len,val,datalen,errs=0; iguana_optableinit(coin); if ( (asmstr= jstr(interpreter,"interpreter")) == 0 ) @@ -910,8 +906,9 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI { stacks = calloc(1,sizeof(*stacks) + sizeof(*stacks->stack)*2*IGUANA_MAXSTACKITEMS); stacks->maxstackdepth = IGUANA_MAXSTACKITEMS; - if ( interpret > 1 ) - stacks->logarray = cJSON_CreateArray(); + if ( (stacks->logarray= logarray) != 0 ) + item = cJSON_CreateObject(); + else item = 0; if ( V->M == 0 && V->N == 0 ) V->N = V->M = 1; for (i=0; iN; i++) @@ -936,6 +933,11 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI iguana_pushdata(stacks,0,V->signers[i].pubkey,plen); } } + if ( item != 0 && stacks->logarray != 0 ) + { + jaddstr(item,"spendasm",asmstr); + jaddi(stacks->logarray,item); + } if ( V->extras != 0 ) { if ( (n= cJSON_GetArraySize(V->extras)) > 0 ) @@ -991,7 +993,7 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI str--; if ( (n= iguana_dataparse(stacks,script,k,str,&len)) > 0 ) { - k += n; + k = n; str += len; continue; } @@ -1028,8 +1030,6 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI if ( op->opcode <= IGUANA_OP_16 || ++numops <= MAX_OPS_PER_SCRIPT ) { script[k++] = op->opcode; - if ( stacks->logarray ) - jaddistr(stacks->logarray,(char *)op->hh.key); if ( (op->flags & IGUANA_ALWAYSILLEGAL) != 0 ) { printf("disabled opcode.%s at offset.%ld\n",str,(long)str-(long)asmstr); @@ -1067,6 +1067,20 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI for (i=0; ilogarray != 0 ) + { + char tmpstr[1096]; + item = cJSON_CreateObject(); + array = cJSON_CreateArray(); + for (i=0; ihh.key,array); + jaddi(stacks->logarray,item); + } if ( (op->flags & IGUANA_NOPFLAG) != 0 ) continue; if ( (op->flags & IGUANA_CONTROLFLAG) != 0 ) @@ -1320,6 +1334,7 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI } if ( iguana_isnonz(stacks->stack[stacks->stackdepth-1]) == 0 ) break; + iguana_pop(stacks); } } else @@ -1344,6 +1359,7 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI { errs++; printf("empty stack error\n"); + jaddstr(interpreter,"error","empty stack"); jadd(interpreter,"result",jfalse()); } else if ( iguana_isnonz(stacks->stack[--stacks->stackdepth]) != 0 ) @@ -1351,8 +1367,8 @@ int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRI printf("Evaluate true, depth.%d errs.%d\n",stacks->stackdepth,errs); jadd(interpreter,"result",jtrue()); } - if ( stacks->logarray != 0 ) - printf("LOG.(%s)\n",jprint(stacks->logarray,1)); + //if ( stacks->logarray != 0 ) + // printf("LOG.(%s)\n",jprint(stacks->logarray,0)); if ( numargs > 0 ) { for (i=0; i 0 ) + { + maxsize = (int32_t)strlen(rawtx); + serialized = malloc(maxsize); + serialized2 = malloc(maxsize); + len = 0; + V = calloc(numinputs,sizeof(*V)); + for (i=0; ibundlescount-1)) > 0 ) + { + msgtx.vins[i].spendscript = V[i].spendscript; + msgtx.vins[i].spendlen = V[i].spendlen; + V[i].hashtype = iguana_vinscriptparse(coin,&V[i],&sigsize,&pubkeysize,&p2shsize,&suffixlen,msgtx.vins[i].vinscript,msgtx.vins[i].scriptlen); + V[i].suffixlen = suffixlen; + memcpy(V[i].spendscript,msgtx.vins[i].spendscript,msgtx.vins[i].spendlen); + V[i].spendlen = msgtx.vins[i].spendlen; + printf("V %.8f (%s) spendscript.[%d] scriptlen.%d\n",dstr(V[i].amount),V[i].coinaddr,V[i].spendlen,V[i].spendlen); + } + } + if ( (complete= bitcoin_verifyvins(coin,&signedtxid,&signedtx,&msgtx,serialized2,maxsize,V,1)) > 0 && signedtx != 0 ) + { + log = cJSON_CreateArray(); + if ( iguana_interpreter(coin,log,j64bits(txobj,"locktime"),V,numinputs) < 0 ) + { + jaddstr(retjson,"error","interpreter rejects tx"); + } + jadd(retjson,"interpreter",log); + } + jaddnum(retjson,"complete",complete); + free(serialized), free(serialized2); + } + } + //char str[65]; printf("got txid.(%s)\n",bits256_str(str,txid)); + } + return(jprint(retjson,1)); +} + STRING_ARG(bitcoinrpc,decoderawtransaction,rawtx) { cJSON *txobj = 0; bits256 txid; diff --git a/iguana/iguana_rpc.c b/iguana/iguana_rpc.c index 33d862853..89ace68eb 100755 --- a/iguana/iguana_rpc.c +++ b/iguana/iguana_rpc.c @@ -495,6 +495,11 @@ static char *decoderawtransaction(RPCARGS) return(sglue1(0,CALLGLUE,"bitcoinrpc","decoderawtransaction","rawtx",params[0])); } +static char *validaterawtransaction(RPCARGS) +{ + return(sglue1(0,CALLGLUE,"bitcoinrpc","validaterawtransaction","rawtx",params[0])); +} + static char *decodescript(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","decodescript","scriptstr",params[0])); @@ -570,6 +575,7 @@ struct RPC_info { char *name; char *(*rpcfunc)(RPCARGS); int32_t flag0,remotefla { "importprivkey", &importprivkey, false, false }, { "getrawtransaction", &getrawtransaction, false, false }, { "createrawtransaction", &createrawtransaction, false, false }, + { "validaterawtransaction", &validaterawtransaction, false, true }, { "decoderawtransaction", &decoderawtransaction, false, true }, { "decodescript", &decodescript, false, true }, { "signrawtransaction", &signrawtransaction, false, false }, diff --git a/iguana/iguana_sign.c b/iguana/iguana_sign.c index e5354f5ab..100554eb3 100755 --- a/iguana/iguana_sign.c +++ b/iguana/iguana_sign.c @@ -124,7 +124,7 @@ cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin) 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) { 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)); + //printf("PARSEVIN.(%s) vin.%p\n",jprint(vinobj,0),vin); if ( V == 0 ) memset(vin,0,sizeof(*vin)); vin->prev_vout = -1; @@ -154,6 +154,7 @@ int32_t iguana_parsevinobj(struct supernet_info *myinfo,struct iguana_info *coin decode_hex(serialized,n,hexstr); vin->vinscript = serialized; vin->scriptlen = n; + len += n; } //else printf("iguana_parsevinobj: hex script missing (%s)\n",jprint(vinobj,0)); if ( V != 0 ) { @@ -189,7 +190,7 @@ int32_t iguana_parsevinobj(struct supernet_info *myinfo,struct iguana_info *coin } if ( vin->vinscript != 0 ) serialized = &vin->vinscript[vin->scriptlen]; - len = vin->scriptlen; + len += vin->scriptlen; if ( redeemstr != 0 ) { n = (int32_t)strlen(redeemstr) >> 1; @@ -1046,24 +1047,40 @@ cJSON *bitcoin_txoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentsc return(txobj); } -int32_t iguana_interpreter(struct iguana_info *coin,int64_t nLockTime,struct vin_info *V,int32_t numvins) +int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLockTime,struct vin_info *V,int32_t numvins) { - uint8_t script[IGUANA_MAXSCRIPTSIZE]; int32_t vini,scriptlen,errs = 0; cJSON *spendscript; + uint8_t script[IGUANA_MAXSCRIPTSIZE]; char str[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t vini,scriptlen,errs = 0; cJSON *spendscript,*item; for (vini=0; vini 0 && signedtx != 0 ) { - if ( iguana_interpreter(coin,j64bits(txobj,"locktime"),V,numinputs) < 0 ) + if ( iguana_interpreter(coin,0,j64bits(txobj,"locktime"),V,numinputs) < 0 ) { printf("iguana_interpreter error.(%s)\n",signedtx); complete = 0; diff --git a/iguana/main.c b/iguana/main.c index 6bbd9696f..546dc7872 100755 --- a/iguana/main.c +++ b/iguana/main.c @@ -1156,7 +1156,7 @@ void iguana_appletests(struct supernet_info *myinfo) if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":64,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":4,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) { free(str); - if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":64,\"newcoin\":\"BTC\",\"active\":1,\"numhelpers\":4,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) + if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":64,\"newcoin\":\"BTC\",\"active\":1,\"numhelpers\":4,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) { free(str); if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"alice\",\"password\":\"alice\",\"passphrase\":\"alice\"}"),0,myinfo->rpcport)) != 0 ) diff --git a/iguana/tests/validaterawtransaction b/iguana/tests/validaterawtransaction new file mode 100755 index 000000000..01dd46707 --- /dev/null +++ b/iguana/tests/validaterawtransaction @@ -0,0 +1 @@ +curl --url "http://127.0.0.1:7778" --data "{\"method\":\"validaterawtransaction\",\"params\":[\"01000000ddd7325701272cab4a805aa14aa5c73ebd44abb4a6819fdc7218ee26340c0ebd70ecd77efc010000006b483045022100bc7b4fc4ec5d9a01778c751996642fe49665fdb03aea0aa99b9bb56ce57b5e7e022051ec6437f0174a58eeacc249e7c2b7f82eac4f79888f226d2f1dadf94455a0cb012102d884bfbe1703cb3e3fb2d560c6c69155875a43e0d5f640c75a7b6c8bd17b99e5ffffffff02a0860100000000001976a9142ef2840b34e90449eb9abda6d6162d40d704639788ac90bb911d000000001976a914dcc39f9cfc5558b09fc7862535cafc98e5a4d63088ac00000000\"]}" diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index a8a64a0ec..22da5f095 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -27,6 +27,7 @@ TWOINTS_AND_ARRAY(bitcoinrpc,listunspent,minconf,maxconf,array); STRING_ARG(bitcoinrpc,decodescript,scriptstr); STRING_ARG(bitcoinrpc,decoderawtransaction,rawtx); +STRING_ARG(bitcoinrpc,validaterawtransaction,rawtx); ARRAY_OBJ_INT(bitcoinrpc,createrawtransaction,vins,vouts,locktime); ZERO_ARGS(bitcoinrpc,makekeypair);