diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index d6189f7f6..26246d837 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -430,14 +430,14 @@ char *iguana_calcrawtx(struct supernet_info *myinfo,struct iguana_info *coin,cJS 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; + struct iguana_outpoint spentpt; char coinaddr[64]; int32_t i,RTspentflag,num,spentheight,lockedflag; if ( coin->MAXPEERS == 1 || coin->RELAYNODE != 0 || coin->VALIDATENODE != 0 ) { num = cJSON_GetArraySize(vins); for (i=0; ichain->bundlesize; outpt.unspentind = unspentind; - iguana_RTutxofind(coin,outpt,&RTspendflag,!flag); + iguana_RTutxofunc(coin,&spentheight,&lockedflag,outpt,&RTspendflag,!flag,0); } } } diff --git a/iguana/iguana_realtime.c b/iguana/iguana_realtime.c index 1574c136d..205413b05 100755 --- a/iguana/iguana_realtime.c +++ b/iguana/iguana_realtime.c @@ -13,6 +13,8 @@ * * ******************************************************************************/ +// verify undo cases for hhutxo, and all 4 permutations of setting + #include "iguana777.h" //#define ENABLE_RAMCHAIN @@ -573,8 +575,8 @@ void iguana_RTunspent(struct iguana_info *coin,struct iguana_RTtxid *RTptr,struc return; } } - if ( (unspent->spentflag == 0 && polarity < 0) || (unspent->spentflag != 0 && polarity > 0) ) - printf("unspent spentflag.%d opposite when polarity.%lld\n",unspent->spentflag,(long long)polarity); + if ( (unspent->spend == 0 && polarity < 0) || (unspent->spend != 0 && polarity > 0) ) + printf("unspent spend.%p opposite when polarity.%lld\n",unspent->spend,(long long)polarity); iguana_RTcoinaddr(coin,RTptr,block,polarity,coinaddr,unspent->rmd160,0,value,unspent); if ( polarity < 0 ) RTptr->unspents[vout] = 0; @@ -590,7 +592,7 @@ void iguana_RTunspent(struct iguana_info *coin,struct iguana_RTtxid *RTptr,struc void iguana_RTspend(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_RTtxid *RTptr,struct iguana_block *block,int64_t polarity,uint8_t *script,int32_t scriptlen,bits256 txid,int32_t vini,bits256 prev_hash,int32_t prev_vout) { - struct iguana_RTspend *spend; struct iguana_RTtxid *spentRTptr; struct iguana_RTunspent *unspent=0; char str[65],str2[65],coinaddr[64]; uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; int32_t spendlen,height; uint64_t value; + struct iguana_RTspend *spend; struct iguana_RTtxid *spentRTptr; struct iguana_RTunspent *unspent=0; char str[65],str2[65],coinaddr[64]; uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; uint32_t unspentind; int32_t spendlen,height; uint64_t value; struct iguana_outpoint spentpt; //printf("RTspend %s vini.%d spend.(%s/v%d) %lld\n",bits256_str(str,txid),vini,bits256_str(str2,prev_hash),prev_vout,(long long)polarity); if ( vini == 0 && bits256_nonz(prev_hash) == 0 && prev_vout < 0 ) return; @@ -630,21 +632,27 @@ void iguana_RTspend(struct supernet_info *myinfo,struct iguana_info *coin,struct } else { - if ( iguana_unspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,prev_hash,prev_vout,coin->bundlescount,0) == 0 ) + if ( (unspentind= iguana_unspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,prev_hash,prev_vout,coin->bundlescount,0)) == 0 ) printf("iguana_RTspend cant find spentRTptr.(%s) search history\n",bits256_str(str,prev_hash)); else { + int32_t spentheight,lockedflag,RTspentflag; bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); //printf("found unspentind (%s %.8f).%d spendlen.%d\n",coinaddr,dstr(value),addrtype,spendlen); unspent = iguana_RTunspent_create(rmd160,value,spendscript,spendlen>0?spendlen:0,0,prev_vout); + memset(&spentpt,0,sizeof(spentpt)); + spentpt.unspentind = unspentind; + spentpt.hdrsi = height / coin->chain->bundlesize; + iguana_RTutxofunc(coin,&spentheight,&lockedflag,spentpt,&RTspentflag,0,RTptr->height); } } if ( unspent != 0 ) { bitcoin_address(coinaddr,coin->chain->pubtype,unspent->rmd160,sizeof(unspent->rmd160)); iguana_RTcoinaddr(coin,RTptr,block,polarity,coinaddr,unspent->rmd160,1,unspent->value,unspent); - unspent->spend = spend; - unspent->spentflag = (polarity > 0); + if ( polarity < 0 ) + unspent->spend = 0; + else unspent->spend = spend; } } } else printf("iguana_RTspend txid mismatch %llx != %llx\n",(long long)RTptr->txid.txid,(long long)txid.txid); @@ -665,7 +673,7 @@ void iguana_RTtxid_free(struct iguana_RTtxid *RTptr) void iguana_RTdataset_free(struct iguana_info *coin) { - struct iguana_RTtxid *RTptr,*tmp; struct iguana_RTaddr *RTaddr,*tmp2; + struct iguana_RTtxid *RTptr,*tmp; struct iguana_RTaddr *RTaddr,*tmp2; struct iguana_hhutxo *hhutxo,*tmphh; HASH_ITER(hh,coin->RTdataset,RTptr,tmp) { HASH_DELETE(hh,coin->RTdataset,RTptr); @@ -676,6 +684,11 @@ void iguana_RTdataset_free(struct iguana_info *coin) HASH_DELETE(hh,coin->RTaddrs,RTaddr); free(RTaddr); } + HASH_ITER(hh,coin->utxotable,hhutxo,tmphh) + { + HASH_DELETE(hh,coin->utxotable,hhutxo); + free(hhutxo); + } } struct iguana_RTtxid *iguana_RTtxid_create(struct iguana_info *coin,struct iguana_block *block,int64_t polarity,int32_t txi,int32_t txn_count,bits256 txid,int32_t numvouts,int32_t numvins,uint32_t locktime,uint32_t version,uint32_t timestamp) diff --git a/iguana/iguana_unspents.c b/iguana/iguana_unspents.c index 9002dbd02..5f1c9cd87 100755 --- a/iguana/iguana_unspents.c +++ b/iguana/iguana_unspents.c @@ -495,6 +495,7 @@ int64_t iguana_RTpkhashbalance(struct supernet_info *myinfo,struct iguana_info * outpt.isptr = 0; outpt.unspentind = unspentind; outpt.value = U[unspentind].value; + RTspend = 0; if ( iguana_RTspentflag(myinfo,coin,&RTspend,&spentheight,ramchain,outpt,lastheight,minconf,maxconf,U[unspentind].value) == 0 ) { if ( *nump < max && unspents != 0 ) @@ -891,7 +892,7 @@ int32_t iguana_RTuvaltxid(struct supernet_info *myinfo,bits256 *txidp,struct igu uint64_t iguana_unspentavail(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_outpoint outpt,int32_t minconf,int32_t maxconf) { - struct iguana_ramchain *ramchain; struct iguana_bundle *bp; int64_t RTspend; int32_t spentheight,spentflag; struct iguana_unspent *U,*u; struct iguana_ramchaindata *rdata; + struct iguana_ramchain *ramchain; struct iguana_bundle *bp; int64_t RTspend=0; int32_t spentheight,spentflag; struct iguana_unspent *U,*u; struct iguana_ramchaindata *rdata; if ( (bp= coin->bundles[outpt.hdrsi]) == 0 ) return(-1); ramchain = &bp->ramchain;//(bp == coin->current) ? &coin->RTramchain : &bp->ramchain; diff --git a/iguana/iguana_volatiles.c b/iguana/iguana_volatiles.c index 428c77b50..b784c1815 100755 --- a/iguana/iguana_volatiles.c +++ b/iguana/iguana_volatiles.c @@ -16,12 +16,6 @@ #include "iguana777.h" #ifdef DEPRECATED_HHUTXO -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) { @@ -106,93 +100,143 @@ int32_t iguana_utxoupdate(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t } #endif -struct iguana_utxo iguana_RTutxofind(struct iguana_info *coin,struct iguana_outpoint spentpt,int32_t *RTspendflagp,int32_t lockflag) +struct iguana_hhutxo *iguana_hhutxofind(struct iguana_info *coin,uint64_t uval) { - uint64_t val; struct iguana_utxo utxo; struct iguana_ramchain *ramchain; struct iguana_bundle *bp; struct iguana_ramchaindata *rdata; - *RTspendflagp = 0; + struct iguana_hhutxo *hhutxo; + HASH_FIND(hh,coin->utxotable,&uval,sizeof(uval),hhutxo); + return(hhutxo); +} + +int32_t iguana_RTutxofunc(struct iguana_info *coin,int32_t *fromheightp,int32_t *lockedflagp,struct iguana_outpoint spentpt,int32_t *RTspendflagp,int32_t lockflag,int32_t fromheight) +{ + uint64_t val; struct iguana_hhutxo *hhutxo; struct iguana_utxo utxo; struct iguana_ramchain *ramchain; struct iguana_bundle *bp; struct iguana_ramchaindata *rdata; struct iguana_RTunspent *unspent; int32_t spentflag = 0; + *RTspendflagp = *lockedflagp = *fromheightp = 0; memset(&utxo,0,sizeof(utxo)); if ( coin->disableUTXO != 0 ) { printf("skip utxofind when disabled\n"); - return(utxo); + return(0); } - if ( (bp= coin->bundles[spentpt.hdrsi]) == 0 ) - return(utxo); - ramchain = &bp->ramchain;//(bp == coin->current) ? &coin->RTramchain : &bp->ramchain; - if ( (rdata= ramchain->H.data) == 0 ) - return(utxo); - val = ((uint64_t)spentpt.hdrsi << 32) | spentpt.unspentind; - if ( spentpt.unspentind > 0 && spentpt.unspentind < rdata->numunspents ) + if ( spentpt.isptr != 0 ) { - if ( ramchain->Uextras != 0 ) + if ( (unspent= spentpt.ptr) != 0 ) { - utxo = ramchain->Uextras[spentpt.unspentind]; - if ( lockflag != 0 ) + if ( lockflag == 0 && fromheight == 0 ) { - /*if ( (hhutxo= iguana_hhutxofind(coin,val)) == 0 ) - { - hhutxo = calloc(1,sizeof(*hhutxo)); - hhutxo->uval = val; - HASH_ADD_KEYPTR(hh,coin->utxotable,&hhutxo->uval,sizeof(hhutxo->uval),hhutxo); - }*/ - printf("iguana_utxofind: need to change to new RT lock method\n"); + if ( unspent->spend != 0 ) + spentflag = 1; + if ( unspent->locked != 0 ) + *lockedflagp = 1; + *fromheightp = unspent->fromheight; + } + else if ( fromheight != 0 ) + { + unspent->fromheight = fromheight; + if ( unspent->spend == 0 ) + printf("unexpected null spend when fromheight.%d\n",fromheight); } + else if ( lockflag != 0 ) + unspent->locked = 1; } - if ( ramchain->Uextras == 0 || utxo.spentflag == 0 ) + else { - /*if ( (hhutxo= iguana_hhutxofind(coin,val)) != 0 ) + printf("missing spentpt ptr when isptr?\n"); + return(0); + } + } + else + { + if ( (bp= coin->bundles[spentpt.hdrsi]) == 0 ) + return(0); + ramchain = &bp->ramchain;//(bp == coin->current) ? &coin->RTramchain : &bp->ramchain; + if ( (rdata= ramchain->H.data) == 0 ) + return(0); + val = ((uint64_t)spentpt.hdrsi << 32) | spentpt.unspentind; + if ( (utxo.fromheight= fromheight) != 0 ) + utxo.spentflag = 1; + if ( spentpt.unspentind > 0 && spentpt.unspentind < rdata->numunspents ) + { + if ( ramchain->Uextras != 0 ) { + utxo = ramchain->Uextras[spentpt.unspentind]; if ( lockflag != 0 ) { - if ( hhutxo->u.lockedflag == 0 ) - hhutxo->u.lockedflag = 1; - else printf("iguana_hhutxofind warning: locking already locked [%d].%u\n",spentpt.hdrsi,spentpt.unspentind); - } else hhutxo->u.lockedflag = 0; - utxo = hhutxo->u; - if ( utxo.spentflag != 0 || utxo.lockedflag != 0 ) - *RTspendflagp = 1; - }*/ - //printf("iguana_utxofind: need to change to new RT method\n"); + if ( (hhutxo= iguana_hhutxofind(coin,val)) == 0 ) + { + hhutxo = calloc(1,sizeof(*hhutxo)); + hhutxo->uval = val; + hhutxo->u = utxo; + HASH_ADD_KEYPTR(hh,coin->utxotable,&hhutxo->uval,sizeof(hhutxo->uval),hhutxo); + } + printf("iguana_utxofind: need to change to new RT lock method\n"); + } + } + if ( ramchain->Uextras == 0 || utxo.spentflag == 0 ) + { + if ( (hhutxo= iguana_hhutxofind(coin,val)) != 0 ) + utxo = hhutxo->u; + //printf("iguana_utxofind: need to change to new RT method\n"); + } + } + else + { + printf("illegal unspentind.%u vs %u hdrs.%d\n",spentpt.unspentind,rdata->numunspents,spentpt.hdrsi); } } - else + if ( lockflag != 0 ) { - printf("illegal unspentind.%u vs %u hdrs.%d\n",spentpt.unspentind,rdata->numunspents,spentpt.hdrsi); - } - //if ( flag != 0 ) - // portable_mutex_unlock(&coin->RTmutex); - return(utxo); + if ( utxo.lockedflag == 0 ) + utxo.lockedflag = 1; + else printf("iguana_hhutxofind warning: locking already locked [%d].%u\n",spentpt.hdrsi,spentpt.unspentind); + } else utxo.lockedflag = 0; + if ( utxo.spentflag != 0 || utxo.lockedflag != 0 ) + *RTspendflagp = 1; + return(utxo.spentflag); } int32_t iguana_RTspentflag(struct supernet_info *myinfo,struct iguana_info *coin,int64_t *RTspendp,int32_t *spentheightp,struct iguana_ramchain *ramchain,struct iguana_outpoint spentpt,int32_t height,int32_t minconf,int32_t maxconf,uint64_t amount) { - uint32_t numunspents; int32_t RTspentflag; struct iguana_utxo utxo; uint64_t confs,RTspend = 0; - struct iguana_ramchaindata *rdata; + uint32_t numunspents; int32_t RTspentflag,spentflag,lockedflag,fromheight; uint64_t confs;//,RTspend = 0; + struct iguana_ramchaindata *rdata; struct iguana_RTunspent *unspent; *spentheightp = -1; if ( coin->disableUTXO != 0 ) { //printf("skip spentflag when disabled\n"); return(0); } + if ( spentpt.isptr != 0 ) + { + if ( (unspent= spentpt.ptr) != 0 ) + { + if ( unspent->spend != 0 ) + { + *RTspendp += (amount == 0) ? coin->txfee : amount; + return(1); + } + else if ( unspent->locked != 0 ) + return(-1); + } else printf("missing spentpt ptr when isptr?\n"); + return(0); + } if ( (rdata= ramchain->H.data) == 0 ) return(0); numunspents = rdata->numunspents; - utxo = iguana_RTutxofind(coin,spentpt,&RTspentflag,0); + spentflag = iguana_RTutxofunc(coin,&fromheight,&lockedflag,spentpt,&RTspentflag,0,0); if ( RTspentflag != 0 ) - *RTspendp = (amount == 0) ? coin->txfee : amount; - if ( utxo.spentflag != 0 && utxo.fromheight == 0 ) + *RTspendp += (amount == 0) ? coin->txfee : amount; + if ( spentflag != 0 && fromheight == 0 ) { printf("illegal unspentind.%u vs %u hdrs.%d zero fromheight?\n",spentpt.unspentind,numunspents,spentpt.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) ) + //printf("[%d] u%u %.8f, spentheight.%d vs height.%d spentflag.%d\n",spent_hdrsi,spent_unspentind,dstr(amount),fromheight,height,spentflag); + *spentheightp = fromheight; + if ( (confs= coin->blocks.hwmchain.height - fromheight) >= minconf && confs < maxconf && (height <= 0 || fromheight < height) ) { - (*RTspendp) += RTspend; - if ( utxo.spentflag != 0 ) + //(*RTspendp) += RTspend; + if ( spentflag != 0 ) return(1); - else if ( utxo.lockedflag != 0 ) + else if ( lockedflag != 0 ) return(-1); else return(0); } diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index 34f547c57..97685fb29 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -454,7 +454,7 @@ int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig64,bits256 mess 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); uint64_t iguana_unspentavail(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_outpoint outpt,int32_t minconf,int32_t maxconf); -struct iguana_utxo iguana_RTutxofind(struct iguana_info *coin,struct iguana_outpoint spentpt,int32_t *RTspendflagp,int32_t lockflag); +int32_t iguana_RTutxofunc(struct iguana_info *coin,int32_t *fromheightp,int32_t *lockedflagp,struct iguana_outpoint spentpt,int32_t *RTspendflagp,int32_t lockflag,int32_t spentheight); int32_t iguana_signrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeys); cJSON *iguana_privkeysjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins); char *iguana_RTinputaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,struct iguana_outpoint *spentptp,cJSON *vinobj); diff --git a/includes/iguana_structs.h b/includes/iguana_structs.h index 572f2f42f..d14e8c6b4 100755 --- a/includes/iguana_structs.h +++ b/includes/iguana_structs.h @@ -249,12 +249,12 @@ struct iguana_pkhash { uint8_t rmd160[20]; uint32_t pkind; } __attribute__((pack // dynamic struct iguana_account { int64_t total; uint32_t lastunspentind; } __attribute__((packed)); -struct iguana_hhaccount { UT_hash_handle hh; uint64_t pval; struct iguana_account a; } __attribute__((packed)); struct iguana_utxo { uint32_t fromheight:31,lockedflag:1,prevunspentind:31,spentflag:1,spendind; } __attribute__((packed)); #ifdef DEPRECATED_HHUTXO -struct iguana_hhutxo { UT_hash_handle hh; uint64_t uval; struct iguana_utxo u; } __attribute__((packed)); +struct iguana_hhaccount { UT_hash_handle hh; uint64_t pval; struct iguana_account a; } __attribute__((packed)); #endif +struct iguana_hhutxo { UT_hash_handle hh; uint64_t uval; struct iguana_utxo u; } __attribute__((packed)); struct iguana_utxoaddr { UT_hash_handle hh; int64_t histbalance; uint32_t pkind:31,searchedhist:1; uint16_t hdrsi; uint8_t rmd160[20]; } __attribute__((packed)); // GLOBAL one zero to non-zero write (unless reorg) @@ -392,12 +392,12 @@ struct iguana_RTunspent { uint8_t rmd160[20]; int64_t value; - int32_t vout,height; + int32_t vout,height,fromheight; struct iguana_RTtxid *parent; struct iguana_RTspend *spend; struct iguana_RTunspent *prevunspent; int16_t scriptlen; - uint8_t spentflag,validflag; + uint8_t locked,validflag; uint8_t script[]; }; @@ -456,8 +456,9 @@ struct iguana_info uint64_t bloomsearches,bloomhits,bloomfalse,collisions,txfee_perkb,txfee; uint8_t *blockspace; int32_t blockspacesize; struct OS_memspace blockMEM; bits256 APIblockhash,APItxid; char *APIblockstr; + struct iguana_hhutxo *utxotable; #ifdef DEPRECATED_HHUTXO - struct iguana_hhutxo *utxotable; struct iguana_hhaccount *accountstable; + struct iguana_hhaccount *accountstable; #endif char lastdispstr[2048]; double txidfind_totalmillis,txidfind_num,spendtxid_totalmillis,spendtxid_num;