From 6cb639c2b7ffa7e0e37638d9f4ebc126bc09e057 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 13 Jul 2019 01:49:05 -1100 Subject: [PATCH] nspv_listtransactions initial --- src/komodo_nSPV.h | 59 ++++++++++++++++++++++++++++++++++- src/komodo_nSPV_defs.h | 19 ++++++++++++ src/komodo_nSPV_fullnode.h | 62 +++++++++++++++++++++++++++++++++++++ src/komodo_nSPV_superlite.h | 40 +++++++++++++++++++++++- src/net.h | 2 +- src/rpc/server.cpp | 1 + src/rpc/server.h | 1 + src/wallet/rpcdump.cpp | 21 +++++++++++++ 8 files changed, 202 insertions(+), 3 deletions(-) diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 67bfd6bb0..22bf48244 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -17,7 +17,7 @@ // todo: // myprivkey, scrub all destination buffers -// oversized tx +// new p2p messages: getrawmempool, getaddresstxids // headers "sync" make sure it connects to prior blocks to notarization. use getinfo hdrht to get missing hdrs @@ -139,6 +139,63 @@ void NSPV_utxosresp_copy(struct NSPV_utxosresp *dest,struct NSPV_utxosresp *ptr) } } +int32_t NSPV_rwtxidresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidresp *ptr) +{ + int32_t len = 0; + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); + return(len); +} + +int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsresp *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 = (struct NSPV_txidresp *)calloc(sizeof(*ptr->txids),ptr->numtxids); // relies on uint16_t being "small" to prevent mem exhaustion + 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->CCflag),&ptr->CCflag); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad8),&ptr->pad8); + 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); + } + return(len); +} + +void NSPV_txidsresp_purge(struct NSPV_txidsresp *ptr) +{ + if ( ptr != 0 ) + { + if ( ptr->txids != 0 ) + free(ptr->txids); + memset(ptr,0,sizeof(*ptr)); + } +} + +void NSPV_txidsresp_copy(struct NSPV_txidsresp *dest,struct NSPV_txidsresp *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 31c53fa22..a50d10d77 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -39,6 +39,10 @@ #define NSPV_SPENTINFORESP 0x0b #define NSPV_BROADCAST 0x0c #define NSPV_BROADCASTRESP 0x0d +#define NSPV_TXIDS 0x0e +#define NSPV_TXIDSRESP 0x0f +#define NSPV_MEMPOOL 0x10 +#define NSPV_MEMPOOLRESP 0x11 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); @@ -73,6 +77,21 @@ struct NSPV_utxosresp uint16_t numutxos; uint8_t CCflag,pad8; }; +struct NSPV_txidresp +{ + uint256 txid; + int64_t satoshis; + int32_t vout,height; +}; + +struct NSPV_txidsresp +{ + struct NSPV_txidresp *txids; + char coinaddr[64]; + int32_t nodeheight; + uint16_t numtxids; uint8_t CCflag,pad8; +}; + struct NSPV_ntz { uint256 blockhash,txid,othertxid; diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 9e44df3a7..d480fa821 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -185,6 +185,39 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC return(0); } +int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC) +{ + int32_t maxlen,txheight,n = 0,len = 0; + std::vector > addressIndex; + SetCCtxids(addressIndex,coinaddr,isCC); + maxlen = MAX_BLOCK_SIZE(tipheight) - 512; + maxlen /= sizeof(*ptr->txids); + strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + ptr->CCflag = isCC; + if ( (ptr->numtxids= (int32_t)addressIndex.size()) >= 0 && ptr->numtxids < maxlen ) + { + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + ptr->txids = (struct NSPV_txidresp *)calloc(ptr->numtxids,sizeof(*ptr->txids)); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + { + ptr->txids[n].txid = it->first.txhash; + ptr->txids[n].vout = (int32_t)it->first.index; + ptr->txids[n].satoshis = (int64_t)it->second; + ptr->txids[n].height = (int64_t)it->first.blockHeight; + n++; + } + if ( len < maxlen ) + { + 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; @@ -394,6 +427,35 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } } } + else if ( request[0] == NSPV_TXIDS ) + { + if ( timestamp > pfrom->prevtimes[ind] ) + { + struct NSPV_txidsresp T; char coinaddr[64]; + if ( len < 64 && (request[1] == len-2 || request[1] == len-3) ) + { + uint8_t isCC = 0; + memcpy(coinaddr,&request[2],request[1]); + coinaddr[request[1]] = 0; + if ( request[1] == len-3 ) + isCC = (request[len-1] != 0); + if ( isCC != 0 ) + fprintf(stderr,"%s isCC.%d\n",coinaddr,isCC); + memset(&T,0,sizeof(T)); + if ( (slen= NSPV_getaddresstxids(&T,coinaddr,isCC)) > 0 ) + { + response.resize(1 + slen); + response[0] = NSPV_TXIDSRESP; + if ( NSPV_rwtxidsresp(1,&response[1],&T) == slen ) + { + pfrom->PushMessage("nSPV",response); + pfrom->prevtimes[ind] = timestamp; + } + NSPV_txidsresp_purge(&T); + } + } + } + } 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 259f9cbc3..b63d19064 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -31,6 +31,7 @@ char NSPV_wifstr[64],NSPV_pubkeystr[67],NSPV_lastpeer[128]; std::string NSPV_address; struct NSPV_inforesp NSPV_inforesult; struct NSPV_utxosresp NSPV_utxosresult; +struct NSPV_txidsresp NSPV_txidsresult; struct NSPV_spentinfo NSPV_spentresult; struct NSPV_ntzsresp NSPV_ntzsresult; struct NSPV_ntzsproofresp NSPV_ntzsproofresult; @@ -158,7 +159,12 @@ void komodo_nSPVresp(CNode *pfrom,std::vector response) // received a r case NSPV_UTXOSRESP: NSPV_utxosresp_purge(&NSPV_utxosresult); NSPV_rwutxosresp(0,&response[1],&NSPV_utxosresult); - fprintf(stderr,"got utxos response %u size.%d\n",timestamp,(int32_t)response.size()); // update utxos list + fprintf(stderr,"got utxos response %u size.%d\n",timestamp,(int32_t)response.size()); + break; + case NSPV_TXIDSRESP: + NSPV_txidsresp_purge(&NSPV_txidsresult); + NSPV_rwtxidsresp(0,&response[1],&NSPV_txidsresult); + fprintf(stderr,"got txids response %u size.%d\n",timestamp,(int32_t)response.size()); break; case NSPV_NTZSRESP: NSPV_ntzsresp_purge(&NSPV_ntzsresult); @@ -553,6 +559,38 @@ UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag) return(result); } +UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag) +{ + UniValue result(UniValue::VOBJ); uint8_t msg[64]; int32_t i,iter,slen,len = 0; + if ( NSPV_txidsresult.nodeheight >= NSPV_inforesult.height && strcmp(coinaddr,NSPV_txidsresult.coinaddr) == 0 && CCflag == NSPV_txidsresult.CCflag ) + return(NSPV_txidsresp_json(&NSPV_txidsresult)); + NSPV_txidsresp_purge(&NSPV_txidsresult); + if ( 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_TXIDS; + msg[len++] = slen; + memcpy(&msg[len],coinaddr,slen), len += slen; + msg[len++] = (CCflag != 0); + for (iter=0; iter<3; iter++); + if ( NSPV_req(0,msg,len,NODE_ADDRINDEX,msg[0]>>1) != 0 ) + { + for (i=0; i= NSPV_inforesult.height && strcmp(coinaddr,NSPV_txidsresult.coinaddr) == 0 && CCflag == NSPV_txidsresult.CCflag ) + return(NSPV_txidsresp_json(&NSPV_txidsresult)); + } + } else sleep(1); + result.push_back(Pair("result","error")); + result.push_back(Pair("error","no txid result")); + 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/net.h b/src/net.h index 0b8dcd901..2fa4e31b1 100644 --- a/src/net.h +++ b/src/net.h @@ -276,7 +276,7 @@ public: int64_t nLastRecv; int64_t nTimeConnected; int64_t nTimeOffset; - uint32_t prevtimes[8]; + uint32_t prevtimes[16]; CAddress addr; std::string addrName; CService addrLocal; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1c8a65fe5..51c43cbe4 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_listtransactions",&nspv_listtransactions, true }, { "nSPV", "nspv_spentinfo", &nspv_spentinfo, true }, { "nSPV", "nspv_notarizations", &nspv_notarizations, true }, { "nSPV", "nspv_hdrsproof", &nspv_hdrsproof, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 0e8c9db11..0450ce016 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -467,6 +467,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_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 82e44190c..43cd53e4a 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -975,6 +975,7 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp) UniValue NSPV_getinfo_req(int32_t reqht); UniValue NSPV_login(char *wifstr); UniValue NSPV_logout(); +UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag); UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag); UniValue NSPV_broadcast(char *hex); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); @@ -1029,6 +1030,26 @@ UniValue nspv_listunspent(const UniValue& params, bool fHelp) else throw runtime_error("nspv_listunspent address [isCC]\n"); } +UniValue nspv_listtransactions(const UniValue& params, bool fHelp) +{ + int32_t CCflag = 0; + if ( fHelp || params.size() > 2 ) + throw runtime_error("nspv_listtransactions address [isCC]\n"); + if ( params.size() == 0 ) + { + if ( NSPV_address.size() != 0 ) + return(NSPV_addresstxids((char *)NSPV_address.c_str(),0)); + else throw runtime_error("nspv_listtransactions address [isCC]\n"); + } + if ( params.size() >= 1 ) + { + if ( params.size() == 2 ) + CCflag = atoi((char *)params[1].get_str().c_str()); + return(NSPV_addresstxids((char *)params[0].get_str().c_str(),CCflag)); + } + else throw runtime_error("nspv_listtransactions address [isCC]\n"); +} + UniValue nspv_spentinfo(const UniValue& params, bool fHelp) { uint256 txid; int32_t vout;