diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index b90c75dc8..541eeb8d2 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -18,13 +18,12 @@ // new p2p messages: getrawmempool and support myIsutxo_spentinmempool and mytxid_inmempool -// myprivkey, scrub all destination buffers - -// make req for utxo/txid more sane? // headers "sync" make sure it connects to prior blocks to notarization. use getinfo hdrht to get missing hdrs +// Myprivkey(uint8_t *privkey), scrub all destination privkey buffers // make sure to sanity check all vector lengths on receipt // make sure no files are updated (this is to allow nSPV=1 and later nSPV=0 without affecting database) +// make req for utxo/txid more sane? (optional) // bug: under load, fullnode was returning all 0 nServices #ifndef KOMODO_NSPV_H @@ -200,6 +199,56 @@ void NSPV_txidsresp_copy(struct NSPV_txidsresp *dest,struct NSPV_txidsresp *ptr) } } +int32_t NSPV_rwmempoolresp(int32_t rwflag,uint8_t *serialized,struct NSPV_mempoolresp *ptr) +{ + int32_t i,len = 0; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); + if ( ptr->numtxids != 0 ) + { + if ( ptr->txids == 0 ) + ptr->txids = (uint256 *)calloc(sizeof(*ptr->txids),ptr->numtxids); + for (i=0; inumtxids; i++) + len += NSPV_rwtxidresp(rwflag,&serialized[len],&ptr->txids[i]); + } + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad32),&ptr->pad32); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->funcid),&ptr->funcid); + if ( rwflag != 0 ) + { + memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); + len += sizeof(ptr->coinaddr); + } + else + { + memcpy(ptr->coinaddr,&serialized[len],sizeof(ptr->coinaddr)); + len += sizeof(ptr->coinaddr); + } + fprintf(stderr,"NSPV_rwmempoolresp rwlen.%d\n",len); + return(len); +} + +void NSPV_mempoolresp_purge(struct NSPV_mempoolresp *ptr) +{ + if ( ptr != 0 ) + { + if ( ptr->txids != 0 ) + free(ptr->txids); + memset(ptr,0,sizeof(*ptr)); + } +} + +void NSPV_mempoolresp_copy(struct NSPV_mempoolresp *dest,struct NSPV_mempoolresp *ptr) +{ + *dest = *ptr; + if ( ptr->txids != 0 ) + { + dest->txids = (uint256 *)malloc(ptr->numtxids * sizeof(*ptr->txids)); + memcpy(dest->txids,ptr->txids,ptr->numtxids * sizeof(*ptr->txids)); + } +} + int32_t NSPV_rwntz(int32_t rwflag,uint8_t *serialized,struct NSPV_ntz *ptr) { int32_t len = 0; diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 40fbea8e4..ddba19cb6 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -43,6 +43,10 @@ #define NSPV_TXIDSRESP 0x0f #define NSPV_MEMPOOL 0x10 #define NSPV_MEMPOOLRESP 0x11 +#define NSPV_MEMPOOL_ALL 0 +#define NSPV_MEMPOOL_ADDRESS 1 +#define NSPV_MEMPOOL_ISSPENT 2 +#define NSPV_MEMPOOL_INMEMPOOL 3 int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,int64_t extradata,uint32_t tiptime,int64_t &rewardsum); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); @@ -92,6 +96,14 @@ struct NSPV_txidsresp uint16_t numtxids,CCflag; }; +struct NSPV_mempoolresp +{ + uint256 *txids; + char coinaddr[64]; + int32_t nodeheight,vout,pad32; + uint16_t numtxids; uint8_t CCflag,funcid; +}; + struct NSPV_ntz { uint256 blockhash,txid,othertxid; diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 421b976b7..09f8df4d2 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -157,26 +157,29 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC if ( skipcount >= ptr->numutxos ) skipcount = ptr->numutxos-1; ptr->skipcount = skipcount; - ptr->utxos = (struct NSPV_utxoresp *)calloc(ptr->numutxos-skipcount,sizeof(*ptr->utxos)); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + if ( ptr->numutxos-skipcount > 0 ) { - // if gettxout is != null to handle mempool + ptr->utxos = (struct NSPV_utxoresp *)calloc(ptr->numutxos-skipcount,sizeof(*ptr->utxos)); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - if ( n >= skipcount ) + // if gettxout is != null to handle mempool { - ptr->utxos[ind].txid = it->first.txhash; - ptr->utxos[ind].vout = (int32_t)it->first.index; - ptr->utxos[ind].satoshis = it->second.satoshis; - ptr->utxos[ind].height = it->second.blockHeight; - if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) + if ( n >= skipcount ) { - ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[ind].txid,ptr->utxos[ind].vout,ptr->utxos[ind].height,ptr->utxos[ind].satoshis,tipheight); - interest += ptr->utxos[ind].extradata; + ptr->utxos[ind].txid = it->first.txhash; + ptr->utxos[ind].vout = (int32_t)it->first.index; + ptr->utxos[ind].satoshis = it->second.satoshis; + ptr->utxos[ind].height = it->second.blockHeight; + if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) + { + ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[ind].txid,ptr->utxos[ind].vout,ptr->utxos[ind].height,ptr->utxos[ind].satoshis,tipheight); + interest += ptr->utxos[ind].extradata; + } + ind++; + total += it->second.satoshis; } - ind++; - total += it->second.satoshis; + n++; } - n++; } } ptr->numutxos = ind; @@ -209,22 +212,24 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC skipcount = 0; if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 && ptr->numtxids < maxlen ) { - // scan mempool add to end if ( skipcount >= ptr->numtxids ) skipcount = ptr->numtxids-1; ptr->skipcount = skipcount; - ptr->txids = (struct NSPV_txidresp *)calloc(ptr->numtxids-skipcount,sizeof(*ptr->txids)); - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + if ( ptr->numtxids-skipcount > 0 ) { - if ( n >= skipcount ) + ptr->txids = (struct NSPV_txidresp *)calloc(ptr->numtxids-skipcount,sizeof(*ptr->txids)); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) { - ptr->txids[ind].txid = it->first.txhash; - ptr->txids[ind].vout = (int32_t)it->first.index; - ptr->txids[ind].satoshis = (int64_t)it->second; - ptr->txids[ind].height = (int64_t)it->first.blockHeight; - ind++; + if ( n >= skipcount ) + { + ptr->txids[ind].txid = it->first.txhash; + ptr->txids[ind].vout = (int32_t)it->first.index; + ptr->txids[ind].satoshis = (int64_t)it->second; + ptr->txids[ind].height = (int64_t)it->first.blockHeight; + ind++; + } + n++; } - n++; } ptr->numtxids = ind; len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); @@ -236,6 +241,52 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC return(0); } +/*struct NSPV_mempoolresp +{ + uint256 *txids; + char coinaddr[64]; + int32_t nodeheight; + uint16_t numtxids; uint8_t CCflag,funcid; +}; + +#define NSPV_MEMPOOL_ALL 0 +#define NSPV_MEMPOOL_ADDRESS 1 +#define NSPV_MEMPOOL_ISSPENT 2 +#define NSPV_MEMPOOL_INMEMPOOL 3 + */ + +int32_t NSPV_mempoolfuncs(std::vector &txids,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid) +{ + +} + +int32_t NSPV_mempooltxids(struct NSPV_mempoolresp *ptr,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid,int32_t vout) +{ + std::vector txids; int32_t i,len = 0; + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + ptr->CCflag = isCC; + ptr->txid = txid; + ptr->vout = vout; + ptr->funcid = funcid; + NSPV_mempoolfuncs(txids,coinaddr,isCC,funcid,txid); + if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 ) + { + if ( ptr->numtxids > 0 ) + { + ptr->txids = (uint256 *)calloc(ptr->numtxids,sizeof(*ptr->txids)); + for (i=0; inumtxids; i++) + iguana_rwbignum(0,&txids[i],sizeof(*ptr->txids),(uint8_t *)&ptr->txids[i]); + } + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); + return(len); + } + if ( ptr->txids != 0 ) + free(ptr->txids); + memset(ptr,0,sizeof(*ptr)); + return(0); +} + uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint256 txid) { uint8_t *rawtx = 0; @@ -383,7 +434,7 @@ int32_t NSPV_getspentinfo(struct NSPV_spentinfo *ptr,uint256 txid,int32_t vout) void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a request { - int32_t len,slen,ind,reqheight; std::vector response; uint32_t timestamp = (uint32_t)time(NULL); + int32_t len,slen,ind,reqheight,n; std::vector response; uint32_t timestamp = (uint32_t)time(NULL); if ( (len= request.size()) > 0 ) { if ( (ind= request[0]>>1) >= sizeof(pfrom->prevtimes)/sizeof(*pfrom->prevtimes) ) @@ -485,6 +536,38 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } else fprintf(stderr,"len.%d req1.%d\n",len,request[1]); } } + else if ( request[0] == NSPV_MEMPOOL ) + { + if ( timestamp > pfrom->prevtimes[ind] ) + { + struct NSPV_mempoolresp M; char coinaddr[64]; + if ( len < sizeof(M)+64 ) + { + int32_t vout; uint256 txid; uint8_t funcid,isCC = 0; + n = 1; + len += iguana_rwnum(0,&request[len],sizeof(funcid),&funcid); + len += iguana_rwnum(0,&request[len],sizeof(vout),&vout); + len += iguana_rwbignum(0,&request[len],sizeof(txid),(uint8_t *)&txid); + slen = request[len++]; + memcpy(coinaddr,&request[len],slen), len += slen; + //if ( isCC != 0 ) + fprintf(stderr,"(%s) isCC.%d funcid.%d %s/v%d\n",coinaddr,isCC,funcid,txid.GetHex().c_str(),vout); + memset(&M,0,sizeof(M)); + if ( (slen= NSPV_mempooltxids(&M,coinaddr,isCC,funcid,txid,vout)) > 0 ) + { + fprintf(stderr,"NSPV_mempooltxids slen.%d\n",slen); + response.resize(1 + slen); + response[0] = NSPV_MEMPOOLRESP; + if ( NSPV_rwmempoolresp(1,&response[1],&M) == slen ) + { + pfrom->PushMessage("nSPV",response); + pfrom->prevtimes[ind] = timestamp; + } + NSPV_mempoolresp_purge(&T); + } + } else fprintf(stderr,"len.%d req1.%d\n",len,request[1]); + } + } else if ( request[0] == NSPV_NTZS ) { if ( timestamp > pfrom->prevtimes[ind] ) diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index eae964123..ba763f191 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -32,6 +32,7 @@ std::string NSPV_address; struct NSPV_inforesp NSPV_inforesult; struct NSPV_utxosresp NSPV_utxosresult; struct NSPV_txidsresp NSPV_txidsresult; +struct NSPV_mempoolresp NSPV_mempoolresult; struct NSPV_spentinfo NSPV_spentresult; struct NSPV_ntzsresp NSPV_ntzsresult; struct NSPV_ntzsproofresp NSPV_ntzsproofresult; @@ -166,7 +167,12 @@ void komodo_nSPVresp(CNode *pfrom,std::vector response) // received a r NSPV_rwtxidsresp(0,&response[1],&NSPV_txidsresult); fprintf(stderr,"got txids response %u size.%d %s CC.%d num.%d\n",timestamp,(int32_t)response.size(),NSPV_txidsresult.coinaddr,NSPV_txidsresult.CCflag,NSPV_txidsresult.numtxids); break; - case NSPV_NTZSRESP: + case NSPV_MEMPOOLRESP: + NSPV_mempoolresp_purge(&NSPV_mempoolresult); + NSPV_rwmempoolresp(0,&response[1],&NSPV_mempoolresult); + fprintf(stderr,"got mempool response %u size.%d %s CC.%d num.%d funcid.%d\n",timestamp,(int32_t)response.size(),NSPV_mempoolresult.coinaddr,NSPV_mempoolresult.CCflag,NSPV_mempoolresult.numtxids,NSPV_mempoolresult.funcid); + break; + case NSPV_NTZSRESP: NSPV_ntzsresp_purge(&NSPV_ntzsresult); NSPV_rwntzsresp(0,&response[1],&NSPV_ntzsresult); if ( NSPV_ntzsresp_find(NSPV_ntzsresult.reqheight) == 0 ) @@ -630,6 +636,40 @@ UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount) return(result); } +UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 txid,int32_t vout) +{ + UniValue result(UniValue::VOBJ); uint8_t msg[64]; int32_t i,iter,slen,len = 0; + NSPV_mempoolresp_purge(&NSPV_mempoolresult); + if ( coinaddr[0] != 0 && bitcoin_base58decode(msg,coinaddr) != 25 ) + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","invalid address")); + return(result); + } + slen = (int32_t)strlen(coinaddr); + msg[len++] = NSPV_MEMPOOL; + msg[len++] = (CCflag != 0); + len += iguana_rwnum(1,&msg[len],sizeof(funcid),&funcid); + len += iguana_rwnum(1,&msg[len],sizeof(vout),&vout); + len += iguana_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); + msg[len++] = slen; + memcpy(&msg[len],coinaddr,slen), len += slen; + for (iter=0; iter<3; iter++); + if ( NSPV_req(0,msg,len,NODE_NSPV,msg[0]>>1) != 0 ) + { + for (i=0; i= NSPV_inforesult.height && strcmp(coinaddr,NSPV_mempoolresult.coinaddr) == 0 && CCflag == NSPV_mempoolresult.CCflag && txid == NSPV_mempoolresult.txid && vout == NSPV_mempoolresult.vout && funcid == NSPV_mempoolresult.funcid ) + return(NSPV_mempoolresp_json(&NSPV_mempoolresult)); + } + } else sleep(1); + result.push_back(Pair("result","error")); + result.push_back(Pair("error","no txid result")); + result.push_back(Pair("lastpeer",NSPV_lastpeer)); + return(result); +} + UniValue NSPV_notarizations(int32_t reqheight) { uint8_t msg[64]; int32_t i,iter,len = 0; struct NSPV_ntzsresp N,*ptr; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 51c43cbe4..ebc1293e2 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -420,6 +420,7 @@ static const CRPCCommand vRPCCommands[] = { "nSPV", "nspv_getinfo", &nspv_getinfo, true }, { "nSPV", "nspv_login", &nspv_login, true }, { "nSPV", "nspv_listunspent", &nspv_listunspent, true }, + { "nSPV", "nspv_mempool", &nspv_mempool, true }, { "nSPV", "nspv_listtransactions",&nspv_listtransactions, true }, { "nSPV", "nspv_spentinfo", &nspv_spentinfo, true }, { "nSPV", "nspv_notarizations", &nspv_notarizations, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 0450ce016..0865307c9 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -468,6 +468,7 @@ extern UniValue importgatewayprocessed(const UniValue& params, bool fHelp); extern UniValue nspv_getinfo(const UniValue& params, bool fHelp); extern UniValue nspv_login(const UniValue& params, bool fHelp); extern UniValue nspv_listtransactions(const UniValue& params, bool fHelp); +extern UniValue nspv_mempool(const UniValue& params, bool fHelp); extern UniValue nspv_listunspent(const UniValue& params, bool fHelp); extern UniValue nspv_spentinfo(const UniValue& params, bool fHelp); extern UniValue nspv_notarizations(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index fbca72fda..2df09f1c6 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -977,6 +977,7 @@ UniValue NSPV_login(char *wifstr); UniValue NSPV_logout(); UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount); UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag,int32_t skipcount); +UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 txid,int32_t vout); UniValue NSPV_broadcast(char *hex); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); UniValue NSPV_spentinfo(uint256 txid,int32_t vout); @@ -1032,6 +1033,26 @@ UniValue nspv_listunspent(const UniValue& params, bool fHelp) else throw runtime_error("nspv_listunspent [address [isCC [skipcount]]]\n"); } +UniValue nspv_mempool(const UniValue& params, bool fHelp) +{ + UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 txid,int32_t vout); + int32_t vout = 0,CCflag = 0; uint256 txid; uint8_t funcid; char *coinaddr; + memset(&txid,0,sizeof(txid)); + if ( fHelp || params.size() > 5 ) + throw runtime_error("nspv_mempool func(0 all, 1 address, 2 txid spent, 3 txid inmempool) address isCC [txid vout]]]\n"); + funcid = atoi((char *)params[0].get_str().c_str()); + coinaddr = (char *)params[1].get_str().c_str); + CCflag = atoi((char *)params[2].get_str().c_str()); + if ( params.size() > 3 ) + { + if ( params.size() != 5 ) + throw runtime_error("nspv_mempool func(0 all, 1 address, 2 txid spent, 3 txid inmempool) address isCC [txid vout]]]\n"); + txid = Parseuint256((char *)params[3].get_str().c_str()); + vout = atoi((char *)params[4].get_str().c_str()); + } + return(NSPV_mempooltxids(coinaddr,CCflag,funcid,txid,vout)); +} + UniValue nspv_listtransactions(const UniValue& params, bool fHelp) { int32_t skipcount = 0,CCflag = 0;