diff --git a/src/komodo_defs.h b/src/komodo_defs.h index cef5c4d1c..6ac777898 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -337,5 +337,6 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 int32_t komodo_currentheight(); int32_t komodo_notarized_bracket(struct notarized_checkpoint *nps[2],int32_t height); +uint256 Parseuint256(const char *hexstr); #endif diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index fa02fe187..64d432717 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -575,13 +575,14 @@ 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; std::vector response; uint32_t timestamp; - timestamp = (uint32_t)time(NULL); + int32_t len,slen,ind; 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) ) + ind = (int32_t)(sizeof(pfrom->prevtimes)/sizeof(*pfrom->prevtimes)) - 1; if ( request[0] == NSPV_INFO ) // info { - if ( len == 1 && timestamp > pfrom->lastinfo + ASSETCHAINS_BLOCKTIME/2 ) + if ( len == 1 && timestamp > pfrom->prevtimes[ind] + ASSETCHAINS_BLOCKTIME/2 ) { struct NSPV_inforesp I; memset(&I,0,sizeof(I)); @@ -591,14 +592,14 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req response[0] = NSPV_INFORESP; NSPV_rwinforesp(1,&response[1],&I); pfrom->PushMessage("nSPV",response); - pfrom->lastinfo = timestamp; + pfrom->prevtimes[ind] = timestamp; NSPV_inforesp_purge(&I); } } } else if ( request[0] == NSPV_UTXOS ) { - if ( timestamp > pfrom->lastutxos + ASSETCHAINS_BLOCKTIME/2 ) + if ( timestamp > pfrom->prevtimes[ind] ) { struct NSPV_utxosresp U; char coinaddr[64]; if ( len < 64 && request[1] == len-2 ) @@ -606,43 +607,47 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req memcpy(coinaddr,&request[2],request[1]); coinaddr[request[1]] = 0; memset(&U,0,sizeof(U)); - slen = NSPV_getaddressutxos(&U,coinaddr); - printf("getaddressutxos.(%s) slen.%d\n",coinaddr,slen); - response.resize(1 + slen); - response[0] = NSPV_UTXOSRESP; - if ( NSPV_rwutxosresp(1,&response[1],&U) == slen ) + if ( (slen= NSPV_getaddressutxos(&U,coinaddr)) > 0 ) { - pfrom->PushMessage("nSPV",response); - pfrom->lastutxos = timestamp; + printf("getaddressutxos.(%s) slen.%d\n",coinaddr,slen); + response.resize(1 + slen); + response[0] = NSPV_UTXOSRESP; + if ( NSPV_rwutxosresp(1,&response[1],&U) == slen ) + { + pfrom->PushMessage("nSPV",response); + pfrom->prevtimes[ind] = timestamp; + } + NSPV_utxosresp_purge(&U); } - NSPV_utxosresp_purge(&U); } } } else if ( request[0] == NSPV_NTZS ) { - if ( timestamp > pfrom->lastntzs ) + if ( timestamp > pfrom->prevtimes[ind] ) { struct NSPV_ntzsresp N; int32_t height; if ( len == 1+sizeof(height) ) { iguana_rwnum(0,&request[1],sizeof(height),&height); memset(&N,0,sizeof(N)); - slen = NSPV_getntzsresp(&N,height); - response.resize(1 + slen); - response[0] = NSPV_NTZSRESP; - if ( NSPV_rwntzsresp(1,&response[1],&N) == slen ) + if ( (slen= NSPV_getntzsresp(&N,height)) > 0 ) { - pfrom->PushMessage("nSPV",response); - pfrom->lastntzs = timestamp; + response.resize(1 + slen); + response[0] = NSPV_NTZSRESP; + if ( NSPV_rwntzsresp(1,&response[1],&N) == slen ) + { + pfrom->PushMessage("nSPV",response); + pfrom->prevtimes[ind] = timestamp; + } + NSPV_ntzsresp_purge(&N); } - NSPV_ntzsresp_purge(&N); } } } else if ( request[0] == NSPV_NTZPROOF ) { - if ( timestamp > pfrom->lastproof ) + if ( timestamp > pfrom->prevtimes[ind] ) { struct NSPV_ntzsproofresp P; int32_t prevht,nextht; if ( len == 1+sizeof(prevht)+sizeof(nextht) ) @@ -659,7 +664,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if ( NSPV_rwntzsproofresp(1,&response[1],&P) == slen ) { pfrom->PushMessage("nSPV",response); - pfrom->lastproof = timestamp; + pfrom->prevtimes[ind] = timestamp; } NSPV_ntzsproofresp_purge(&P); } @@ -669,7 +674,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } else if ( request[0] == NSPV_TXPROOF ) { - if ( timestamp > pfrom->lastproof ) + if ( timestamp > pfrom->prevtimes[ind] ) { struct NSPV_txproof P; uint256 txid; int32_t height; if ( len == 1+sizeof(txid)+sizeof(height) ) @@ -677,21 +682,23 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req iguana_rwnum(0,&request[1],sizeof(height),&height); iguana_rwbignum(0,&request[1+sizeof(height)],sizeof(txid),(uint8_t *)&txid); memset(&P,0,sizeof(P)); - slen = NSPV_gettxproof(&P,txid,height); - response.resize(1 + slen); - response[0] = NSPV_TXPROOFRESP; - if ( NSPV_rwtxproof(1,&response[1],&P) == slen ) + if ( (slen= NSPV_gettxproof(&P,txid,height)) > 0 ) { - pfrom->PushMessage("nSPV",response); - pfrom->lastproof = timestamp; + response.resize(1 + slen); + response[0] = NSPV_TXPROOFRESP; + if ( NSPV_rwtxproof(1,&response[1],&P) == slen ) + { + pfrom->PushMessage("nSPV",response); + pfrom->prevtimes[ind] = timestamp; + } + NSPV_txproof_purge(&P); } - NSPV_txproof_purge(&P); } } } else if ( request[0] == NSPV_SPENTINFO ) { - if ( timestamp > pfrom->lastspent ) + if ( timestamp > pfrom->prevtimes[ind] ) { struct NSPV_spentinfo S; int32_t vout; uint256 txid; if ( len == 1+sizeof(txid)+sizeof(vout) ) @@ -706,7 +713,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if ( NSPV_rwspentinfo(1,&response[1],&S) == slen ) { pfrom->PushMessage("nSPV",response); - pfrom->lastspent = timestamp; + pfrom->prevtimes[ind] = timestamp; } NSPV_spentinfo_purge(&S); } @@ -716,12 +723,179 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } } -// on nSPV client -uint32_t NSPV_lastinfo,NSPV_lastutxos; +// nSPV client +uint32_t NSPV_lastinfo,NSPV_lastutxos,NSPV_logintime; +char NSPV_wifstr[64]; +std::string NSPV_address; int32_t NSPV_numutxos,NSPV_numspends; +struct NSPV_inforesp NSPV_inforesult; +struct NSPV_utxosresp NSPV_utxosresult; struct NSPV_utxo *NSPV_utxos; struct NSPV_spentinfo *NSPV_spends; +CNode *NSPV_req(CNode *pnode,uint8_t *msg,int32_t len,uint32_t mask,int32_t ind) +{ + int32_t flag = 0; uint32_t timestamp = (uint32_t)time(NULL); + if ( pnode == 0 ) + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode *pnode,vNodes) + { + if ( pnode->hSocket == INVALID_SOCKET ) + continue; + if ( (pnode->nServices & mask) == mask && timestamp > pnode->prevtimes[ind] ) + { + flag = 1; + break; + } + } + } else flag = 1; + if ( pnode != 0 ) + { + std::vector request; + request.resize(len); + memcpy(&request[0],msg,len); + pnode->PushMessage("getnSPV",request); + pnode->prevtimes[ind] = timestamp; + return(pnode); + } + return(0); +} + +void komodo_NSPV_spentinfoclear() +{ + if ( NSPV_spends != 0 ) + free(NSPV_spends); + NSPV_spends = 0; + NSPV_numspends = 0; +} + +UniValue NSPV_spentinfo_json(struct NSPV_spentinfo *ptr) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result","success")); + result.push_back(Pair("txid",ptr->txid.GetHex())); + result.push_back(Pair("vout",(int64_t)ptr->vout)); + result.push_back(Pair("spentheight",(int64_t)ptr->spent.height)); + result.push_back(Pair("spenttxid",ptr->spent.txid.GetHex())); + result.push_back(Pair("spentvini",(int64_t)ptr->spentvini)); + result.push_back(Pair("spenttxlen",(int64_t)ptr->spent.txlen)); + result.push_back(Pair("spenttxprooflen",(int64_t)ptr->spent.txprooflen)); + return(result); +} + +UniValue NSPV_ntz_json(struct NSPV_ntz *ptr) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("notarized_height",(int64_t)ptr->height)); + result.push_back(Pair("notarized_blockhash",ptr->blockhash.GetHex())); + result.push_back(Pair("notarization_txid",ptr->txid.GetHex())); + result.push_back(Pair("notarization_txidheight",(int64_t)ptr->txidheight)); + result.push_back(Pair("notarization_desttxid",ptr->othertxid.GetHex())); + return(result); +} + +UniValue NSPV_getinfo() +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result","success")); + result.push_back(Pair("height",(int64_t)ptr->height)); + result.push_back(Pair("chaintip",ptr->blockhash.GetHex())); + result.push_back(Pair("notarization",NSPV_ntz_json(&ptr->notarization))); + return(result); +} + +UniValue NSPV_utxoresp_json(struct NSPV_utxosresp *utxos,int32_t numutxos) +{ + UniValue array(UniValue::VARR); int32_t i; + for (i=0; iutxos,ptr->numutxos))); + result.push_back(Pair("height",(int64_t)ptr->height)); + result.push_back(Pair("numutxos",(int64_t)ptr->numutxos)); + result.push_back(Pair("balance",AmountFromValue(ptr->total))); + result.push_back(Pair("interest",AmountFromValue(ptr->interest))); + return(result); +} + +UniValue NSPV_spentinfo(uint256 txid,int32_t vout) +{ + uint8_t msg[64]; struct NSPV_spentinfo I; int32_t i,len = 0; + for (i=0; i>1) != 0 ) + usleep(250000); + for (i=0; i>1) != 0 ) + usleep(250000); + } + if ( NSPV_utxosresult.nodeheight >= NSPV_inforesult.height ) + { + return(NSPV_utxosresp_json(NSPV_utxosresult)); + } + result.push_back(Pair("result","error")); + result.push_back(Pair("error","no utxos result")); + return(result); +} + void komodo_nSPVresp(CNode *pfrom,std::vector response) // received a response { int32_t len; uint32_t timestamp = (uint32_t)time(NULL); @@ -730,11 +904,12 @@ void komodo_nSPVresp(CNode *pfrom,std::vector response) // received a r switch ( response[0] ) { case NSPV_INFORESP: - // deser and display - fprintf(stderr,"got info response %u size.%d\n",timestamp,(int32_t)response.size()); // update current height and ntrz status + NSPV_rwinforesp(0,&response[1],&NSPV_inforesult); + fprintf(stderr,"got info response %u size.%d height.%d\n",timestamp,(int32_t)response.size(),NSPV_inforesult.height); // update current height and ntrz status break; case NSPV_UTXOSRESP: - // deser and process + 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 break; case NSPV_NTZSRESP: @@ -755,50 +930,18 @@ void komodo_nSPVresp(CNode *pfrom,std::vector response) // received a r } } -void komodo_NSPV_spentinfoclear() +void komodo_nSPV(CNode *pto) // polling loop from SendMessages { - if ( NSPV_spends != 0 ) - free(NSPV_spends); - NSPV_spends = 0; - NSPV_numspends = 0; -} - -struct NSPV_spentinfo komodo_NSPV_spentinfo(uint256 txid,int32_t vout) // just a primitive example of how to add new rpc to p2p msg -{ - std::vector request; struct NSPV_spentinfo I; int32_t i,numsent = 0; uint32_t timestamp; - timestamp = (uint32_t)time(NULL); - for (i=0; i NSPV_logintime+60 ) { - I = NSPV_spends[i]; - if ( I.txid == txid && I.vout == vout ) - return(I); - } - LOCK(cs_vNodes); - BOOST_FOREACH(CNode *pnode, vNodes) - { - if ( pnode->hSocket == INVALID_SOCKET ) - continue; - if ( (pnode->nServices & NODE_SPENTINDEX) != 0 && timestamp > pnode->lastspent ) - { - if ( 0 ) // submit actual request - { - request.resize(1); - request[0] = NSPV_SPENTINFO; - pnode->lastspent = timestamp; - pnode->PushMessage("getnSPV",request); - if ( ++numsent >= 3 ) - break; - } - } + fprintf(stderr,"scrub wif from NSPV memory\n"); + memset(NSPV_wifstr,0,sizeof(NSPV_wifstr)); + NSPV_logintime = 0; } -} - -void komodo_nSPV(CNode *pto) -{ - std::vector request; int32_t i; uint32_t timestamp = (uint32_t)time(NULL); if ( (pto->nServices & NODE_NSPV) == 0 ) return; - if ( timestamp > pto->lastntzs || timestamp > pto->lastproof ) + /*if ( timestamp > pto->lastntzs || timestamp > pto->lastproof ) { for (i=0; i NSPV_lastutxos + ASSETCHAINS_BLOCKTIME/2 ) - { - if ( (pto->nServices & NODE_ADDRINDEX) != 0 && timestamp > pto->lastutxos + ASSETCHAINS_BLOCKTIME ) - { - // get utxo since lastheight - //if ( (rand() % 100) < 10 ) - { - char coinaddr[64]; int32_t slen; - Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG); - slen = (int32_t)strlen(coinaddr); - if ( slen < 64 ) - { - request.resize(1 + 1 + slen); - request[0] = NSPV_UTXOS; - request[1] = slen; - memcpy(&request[2],coinaddr,slen); - NSPV_lastutxos = pto->lastutxos = timestamp; - fprintf(stderr,"request address %s\n",coinaddr); - pto->PushMessage("getnSPV",request); - } - } - } - } - if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->lastinfo + ASSETCHAINS_BLOCKTIME ) + }*/ + if ( timestamp > NSPV_lastinfo + ASSETCHAINS_BLOCKTIME/2 && timestamp > pto->prevtimes[NSPV_INFO>>1] + ASSETCHAINS_BLOCKTIME/2 ) { - if ( (rand() % 100) < 10 ) + if ( (rand() % 100) < 10 ) // randomize which peer to query { - // query current height, blockhash, notarization info - request.resize(1); - request[0] = NSPV_INFO; - NSPV_lastinfo = pto->lastinfo = timestamp; - pto->PushMessage("getnSPV",request); + msg[len++] = NSPV_INFO; + NSPV_req(pto,msg,len,NODE_NSPV,NSPV_INFO>>1); } } } diff --git a/src/net.h b/src/net.h index dc21d1133..0b8dcd901 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 lastutxos,lastinfo,lastntzs,lastproof,lastspent; + uint32_t prevtimes[8]; CAddress addr; std::string addrName; CService addrLocal; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 75360fd35..937ae0632 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -416,6 +416,12 @@ static const CRPCCommand vRPCCommands[] = { "FSM", "FSMlist", &FSMlist, true }, { "FSM", "FSMinfo", &FSMinfo, true }, + // fsm + { "nSPV", "nspv_getinfo", &nspv_getinfo, true }, + { "nSPV", "nspv_login", &nspv_login, true }, + { "nSPV", "nspv_listunspent", &nspv_listunspent, true }, + { "nSPV", "nspv_spentinfo", &nspv_spentinfo, true }, + // rewards { "rewards", "rewardslist", &rewardslist, true }, { "rewards", "rewardsinfo", &rewardsinfo, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index d447d2472..bc895ee53 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -455,6 +455,11 @@ extern UniValue importgatewaypendingdeposits(const UniValue& params, bool fHelp) extern UniValue importgatewaypendingwithdraws(const UniValue& params, bool fHelp); 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_listunspent(const UniValue& params, bool fHelp); +extern UniValue nspv_spentinfo(const UniValue& params, bool fHelp); + extern UniValue getblocksubsidy(const UniValue& params, bool fHelp); extern UniValue z_exportkey(const UniValue& params, bool fHelp); // in rpcdump.cpp diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index d35b09a96..f133b1c07 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -971,3 +971,40 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp) return EncodeViewingKey(vk); } + +UniValue NSPV_getinfo(); +UniValue NSPV_login(char *wifstr); +UniValue NSPV_addressutxos(char *coinaddr); +UniValue NSPV_spentinfo(uint256 txid,int32_t vout); + +UniValue nspv_getinfo(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() != 0 ) + throw runtime_error("nspv_getinfo\n"); + return(NSPV_getinfo()); +} + +UniValue nspv_login(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() != 1 ) + throw runtime_error("nspv_login wif\n"); + return(NSPV_login((char *)params[0].get_str().c_str())); +} + +UniValue nspv_listunspent(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() != 1 ) + throw runtime_error("nspv_listunspent address\n"); + return(NSPV_addressutxos((char *)params[0].get_str().c_str())); +} + +UniValue nspv_spentinfo(const UniValue& params, bool fHelp) +{ + uint256 txid; int32_t vout; + if ( fHelp || params.size() != 2 ) + throw runtime_error("nspv_spentinfo txid vout\n"); + txid = Parseuint256((char *)params[0].get_str().c_str()); + vout = atoi((char *)params[1].get_str().c_str()); + return(NSPV_spentinfo(txid,vout)); +} +