Pull in upstream npsv updates from jl777/komodo@1f874d46c5
This commit is contained in:
@@ -325,5 +325,8 @@ void CCLogPrintStream(const char *category, int level, T print_to_stream)
|
||||
// use: LOGSTREAM("yourcategory", your-debug-level, stream << "some log data" << data2 << data3 << ... << std::endl);
|
||||
#define LOGSTREAM(category, level, logoperator) CCLogPrintStream( category, level, [=](std::ostringstream &stream) {logoperator;} )
|
||||
|
||||
int32_t CC_vinselect(int32_t *aboveip, int64_t *abovep, int32_t *belowip, int64_t *belowp, struct CC_utxo utxos[], int32_t numunspents, int64_t value);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2539,3 +2539,11 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
|
||||
}
|
||||
return(siglen);
|
||||
}
|
||||
|
||||
bool komodo_hardfork_active(uint32_t time)
|
||||
{
|
||||
//TODO: set hardfork height for HUSH
|
||||
return false;
|
||||
//return ( (ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Height() > nDecemberHardforkHeight) || (ASSETCHAINS_SYMBOL[0] != 0 && time > nStake
|
||||
}
|
||||
|
||||
|
||||
@@ -431,6 +431,20 @@ void NSPV_broadcast_purge(struct NSPV_broadcastresp *ptr)
|
||||
memset(ptr,0,sizeof(*ptr));
|
||||
}
|
||||
|
||||
int32_t NSPV_rwremoterpcresp(int32_t rwflag,uint8_t *serialized,struct NSPV_remoterpcresp *ptr, int32_t slen)
|
||||
{
|
||||
int32_t len = 0;
|
||||
len+=iguana_rwbuf(rwflag,&serialized[len],sizeof(ptr->method),(uint8_t*)ptr->method);
|
||||
len+=iguana_rwbuf(rwflag,&serialized[len],slen-len,(uint8_t*)ptr->json);
|
||||
return(len);
|
||||
}
|
||||
|
||||
void NSPV_remoterpc_purge(struct NSPV_remoterpcresp *ptr)
|
||||
{
|
||||
if ( ptr != 0 )
|
||||
memset(ptr,0,sizeof(*ptr));
|
||||
}
|
||||
|
||||
// useful utility functions
|
||||
|
||||
uint256 NSPV_doublesha256(uint8_t *data,int32_t datalen)
|
||||
|
||||
@@ -44,12 +44,16 @@
|
||||
#define NSPV_TXIDSRESP 0x0f
|
||||
#define NSPV_MEMPOOL 0x10
|
||||
#define NSPV_MEMPOOLRESP 0x11
|
||||
#define NSPV_CCMODULEUTXOS 0x12
|
||||
#define NSPV_CCMODULEUTXOSRESP 0x13
|
||||
#define NSPV_MEMPOOL_ALL 0
|
||||
#define NSPV_MEMPOOL_ADDRESS 1
|
||||
#define NSPV_MEMPOOL_ISSPENT 2
|
||||
#define NSPV_MEMPOOL_INMEMPOOL 3
|
||||
#define NSPV_MEMPOOL_CCEVALCODE 4
|
||||
#define NSPV_CC_TXIDS 16
|
||||
#define NSPV_REMOTERPC 0x14
|
||||
#define NSPV_REMOTERPCRESP 0x15
|
||||
|
||||
int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,uint256 &hashblock,int32_t &txheight,int32_t ¤theight,int64_t extradata,uint32_t tiptime,int64_t &rewardsum);
|
||||
UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis);
|
||||
@@ -179,4 +183,10 @@ struct NSPV_CCmtxinfo
|
||||
struct NSPV_utxoresp used[NSPV_MAXVINS];
|
||||
};
|
||||
|
||||
struct NSPV_remoterpcresp
|
||||
{
|
||||
char method[64];
|
||||
char json[11000];
|
||||
};
|
||||
|
||||
#endif // KOMODO_NSPV_DEFSH
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
// NSPV_get... functions need to return the exact serialized length, which is the size of the structure minus size of pointers, plus size of allocated data
|
||||
|
||||
#include "notarisationdb.h"
|
||||
#include "rpc/server.h"
|
||||
|
||||
static std::map<std::string,bool> nspv_remote_commands = {{"channelsopen", true},{"channelspayment", true},{"channelsclose", true},{"channelsrefund", true},
|
||||
{"channelslist", true},{"channelsinfo", true},{"oraclescreate", true},{"oraclesfund", true},{"oraclesregister", true},{"oraclessubscribe", true},
|
||||
{"oraclesdata", true},{"oraclesinfo", false},{"oracleslist", false},{"gatewaysbind", true},{"gatewaysdeposit", true},{"gatewaysclaim", true},{"gatewayswithdraw", true},
|
||||
{"gatewayspartialsign", true},{"gatewayscompletesigning", true},{"gatewaysmarkdone", true},{"gatewayspendingdeposits", true},{"gatewayspendingwithdraws", true},
|
||||
{"gatewaysprocessed", true},{"gatewaysinfo", false},{"gatewayslist", false},{"faucetfund", true},{"faucetget", true}};
|
||||
|
||||
struct NSPV_ntzargs
|
||||
{
|
||||
@@ -206,6 +213,229 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC
|
||||
return(0);
|
||||
}
|
||||
|
||||
class BaseCCChecker {
|
||||
public:
|
||||
/// base check function
|
||||
/// @param vouts vouts where checked vout and opret are
|
||||
/// @param nvout vout index to check
|
||||
/// @param evalcode which must be in the opret
|
||||
/// @param funcids allowed funcids in string
|
||||
/// @param filtertxid txid that should be in the opret (after funcid)
|
||||
virtual bool checkCC(uint256 txid, const std::vector<CTxOut> &vouts, int32_t nvout, uint8_t evalcode, std::string funcids, uint256 filtertxid) = 0;
|
||||
};
|
||||
|
||||
/// default cc vout checker for use in NSPV_getccmoduleutxos
|
||||
/// checks if a vout is cc, has required evalcode, allowed funcids and txid
|
||||
/// check both cc opret and last vout opret
|
||||
/// maybe customized in via inheritance
|
||||
class DefaultCCChecker : public BaseCCChecker {
|
||||
|
||||
private:
|
||||
|
||||
public:
|
||||
DefaultCCChecker() { }
|
||||
virtual bool checkCC(uint256 txid, const std::vector<CTxOut> &vouts, int32_t nvout, uint8_t evalcode, std::string funcids, uint256 filtertxid)
|
||||
{
|
||||
CScript opret, dummy;
|
||||
std::vector< vscript_t > vParams;
|
||||
vscript_t vopret;
|
||||
|
||||
if (nvout < vouts.size())
|
||||
{
|
||||
// first check if it is cc vout
|
||||
if (vouts[nvout].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams))
|
||||
{
|
||||
// try to find cc opret
|
||||
if (vParams.size() > 0)
|
||||
{
|
||||
COptCCParams p(vParams[0]); // parse vout data
|
||||
if (p.vData.size() > 0)
|
||||
{
|
||||
vopret = p.vData[0]; // get opret data
|
||||
}
|
||||
}
|
||||
// if no cc opret check last vout opret
|
||||
if (vopret.size() == 0)
|
||||
{
|
||||
GetOpReturnData(vouts.back().scriptPubKey, vopret);
|
||||
}
|
||||
if (vopret.size() > 2)
|
||||
{
|
||||
uint8_t opretEvalcode, opretFuncid;
|
||||
uint256 opretTxid;
|
||||
bool isEof = true;
|
||||
bool isCreateTx = false;
|
||||
|
||||
// parse opret first 3 fields:
|
||||
bool parseOk = E_UNMARSHAL(vopret,
|
||||
ss >> opretEvalcode;
|
||||
ss >> opretFuncid;
|
||||
if (funcids.size() > 0 && opretFuncid == funcids[0]) // this means that we check txid only for second+ funcid in array (considering that the first funcid is the creation txid itself like tokens)
|
||||
{
|
||||
isCreateTx = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss >> opretTxid;
|
||||
isCreateTx = false;
|
||||
}
|
||||
isEof = ss.eof(); );
|
||||
|
||||
opretTxid = revuint256(opretTxid);
|
||||
std::cerr << __func__ << " " << "opretEvalcode=" << opretEvalcode << " opretFuncid=" << (char)opretFuncid << " isCreateTx=" << isCreateTx << " opretTxid=" << opretTxid.GetHex() << std::endl;
|
||||
if( parseOk /*parseOk=true if eof reached*/|| !isEof /*more data means okay*/)
|
||||
{
|
||||
if (evalcode == opretEvalcode && std::find(funcids.begin(), funcids.end(), (char)opretFuncid) != funcids.end() &&
|
||||
(isCreateTx && filtertxid == txid || !isCreateTx && filtertxid == opretTxid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static class DefaultCCChecker defaultCCChecker;
|
||||
|
||||
// table of pluggable cc vout checkers for usage in NSPV_getccmoduleutxos
|
||||
// if the checker is not in the table for a evalcode then defaultCCChecker is used
|
||||
static std::map<uint8_t, class BaseCCChecker*> ccCheckerTable =
|
||||
{
|
||||
};
|
||||
|
||||
// implements SPV server's part, gets cc module utxos, filtered by evalcode, funcid and txid on opret, for the specified amount
|
||||
// if the amount param is 0 returns total available filtere utxo amount and returns no utxos
|
||||
// first char funcid in the string param is considered as the creation tx funcid so filtertxid is compared to the creation txid itself
|
||||
// for other funcids filtertxid is compared to the txid in opreturn
|
||||
int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_t amount, uint8_t evalcode, std::string funcids, uint256 filtertxid)
|
||||
{
|
||||
int64_t total = 0, totaladded = 0;
|
||||
uint32_t locktime;
|
||||
int32_t tipheight=0, len, maxlen;
|
||||
int32_t maxinputs = CC_MAXVINS;
|
||||
|
||||
std::vector<struct CC_utxo> utxoSelected;
|
||||
utxoSelected.reserve(CC_MAXVINS);
|
||||
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
SetCCunspents(unspentOutputs, coinaddr, true);
|
||||
|
||||
maxlen = MAX_BLOCK_SIZE(tipheight) - 512;
|
||||
//maxlen /= sizeof(*ptr->utxos); // TODO why was this? we need maxlen in bytes, don't we?
|
||||
|
||||
//ptr->numutxos = (uint16_t)unspentOutputs.size();
|
||||
//if (ptr->numutxos >= 0 && ptr->numutxos < maxlen)
|
||||
//{
|
||||
ptr->utxos = NULL;
|
||||
ptr->numutxos = 0;
|
||||
strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1);
|
||||
ptr->CCflag = 1;
|
||||
tipheight = chainActive.LastTip()->GetHeight();
|
||||
ptr->nodeheight = tipheight; // will be checked in libnspv
|
||||
//}
|
||||
|
||||
// select all appropriate utxos:
|
||||
std::cerr << __func__ << " " << "searching addr=" << coinaddr << std::endl;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++)
|
||||
{
|
||||
if (myIsutxo_spentinmempool(ignoretxid, ignorevin, it->first.txhash, (int32_t)it->first.index) == 0)
|
||||
{
|
||||
//const CCoins *pcoins = pcoinsTip->AccessCoins(it->first.txhash); <-- no opret in coins
|
||||
CTransaction tx;
|
||||
uint256 hashBlock;
|
||||
int32_t nvout = it->first.index;
|
||||
if (myGetTransaction(it->first.txhash, tx, hashBlock))
|
||||
{
|
||||
class BaseCCChecker *baseChecker = ccCheckerTable[evalcode];
|
||||
|
||||
// if a checker is set for evalcode use it otherwise use the default checker:
|
||||
if (baseChecker && baseChecker->checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid) || defaultCCChecker.checkCC(it->first.txhash, tx.vout, nvout, evalcode, funcids, filtertxid))
|
||||
{
|
||||
std::cerr << __func__ << " " << "filtered utxo with amount=" << tx.vout[nvout].nValue << std::endl;
|
||||
|
||||
struct CC_utxo utxo;
|
||||
utxo.txid = it->first.txhash;
|
||||
utxo.vout = (int32_t)it->first.index;
|
||||
utxo.nValue = it->second.satoshis;
|
||||
//utxo.height = it->second.blockHeight;
|
||||
utxoSelected.push_back(utxo);
|
||||
total += it->second.satoshis;
|
||||
}
|
||||
}
|
||||
else
|
||||
std::cerr << __func__ << " " << "ERROR: cant load tx for txid, please reindex" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (amount == 0) {
|
||||
// just return total value
|
||||
ptr->total = total;
|
||||
len = (int32_t)(sizeof(*ptr) - sizeof(ptr->utxos)/*subtract not serialized part of NSPV_utxoresp*/);
|
||||
return len;
|
||||
}
|
||||
|
||||
// pick optimal utxos for the requested amount
|
||||
CAmount remains = amount;
|
||||
std::vector<struct CC_utxo> utxoAdded;
|
||||
|
||||
while (utxoSelected.size() > 0)
|
||||
{
|
||||
int64_t below = 0, above = 0;
|
||||
int32_t abovei = -1, belowi = -1, ind = -1;
|
||||
|
||||
if (CC_vinselect(&abovei, &above, &belowi, &below, utxoSelected.data(), utxoSelected.size(), remains) < 0)
|
||||
{
|
||||
std::cerr << "error CC_vinselect" << " remains=" << remains << " amount=" << amount << " abovei=" << abovei << " belowi=" << belowi << " ind=" << " utxoSelected.size()=" << utxoSelected.size() << ind << std::endl;
|
||||
return 0;
|
||||
}
|
||||
if (abovei >= 0) // best is 'above'
|
||||
ind = abovei;
|
||||
else if (belowi >= 0) // second try is 'below'
|
||||
ind = belowi;
|
||||
else
|
||||
{
|
||||
std::cerr << "error finding unspent" << " remains=" << remains << " amount=" << amount << " abovei=" << abovei << " belowi=" << belowi << " ind=" << " utxoSelected.size()=" << utxoSelected.size() << ind << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
utxoAdded.push_back(utxoSelected[ind]);
|
||||
total += utxoSelected[ind].nValue;
|
||||
remains -= utxoSelected[ind].nValue;
|
||||
|
||||
// remove used utxo[ind]:
|
||||
utxoSelected[ind] = utxoSelected.back();
|
||||
utxoSelected.pop_back();
|
||||
|
||||
if (total >= amount) // found the requested amount
|
||||
break;
|
||||
if (utxoAdded.size() >= maxinputs) // reached maxinputs
|
||||
break;
|
||||
}
|
||||
ptr->numutxos = (uint16_t)utxoAdded.size();
|
||||
ptr->total = total;
|
||||
ptr->utxos = (NSPV_utxoresp*)calloc(ptr->numutxos, sizeof(ptr->utxos[0]));
|
||||
|
||||
for (uint16_t i = 0; i < ptr->numutxos; i++)
|
||||
{
|
||||
ptr->utxos[i].satoshis = utxoAdded[i].nValue;
|
||||
ptr->utxos[i].txid = utxoAdded[i].txid;
|
||||
ptr->utxos[i].vout = utxoAdded[i].vout;
|
||||
}
|
||||
|
||||
len = (int32_t)(sizeof(*ptr) - sizeof(ptr->utxos)/*subtract not serialized part of NSPV_utxoresp*/ + sizeof(*ptr->utxos)*ptr->numutxos);
|
||||
if (len < maxlen)
|
||||
return len; // good length
|
||||
else
|
||||
{
|
||||
NSPV_utxosresp_purge(ptr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC,int32_t skipcount,uint32_t filter)
|
||||
{
|
||||
int32_t maxlen,txheight,ind=0,n = 0,len = 0; CTransaction tx; uint256 hashBlock;
|
||||
@@ -425,6 +655,63 @@ int32_t NSPV_mempooltxids(struct NSPV_mempoolresp *ptr,char *coinaddr,uint8_t is
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n)
|
||||
{
|
||||
std::vector<uint256> txids; int32_t i,len = 0; UniValue result; std::string response;
|
||||
UniValue request(UniValue::VOBJ),rpc_result(UniValue::VOBJ); JSONRequest jreq; CPubKey mypk;
|
||||
|
||||
try
|
||||
{
|
||||
request.read(json,n);
|
||||
jreq.parse(request);
|
||||
strcpy(ptr->method,jreq.strMethod.c_str());
|
||||
len+=sizeof(ptr->method);
|
||||
std::map<std::string, bool>::iterator it = nspv_remote_commands.find(jreq.strMethod);
|
||||
if (it==nspv_remote_commands.end())
|
||||
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not supported!");
|
||||
const CRPCCommand *cmd=tableRPC[jreq.strMethod];
|
||||
if (!cmd)
|
||||
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
|
||||
if (it->second)
|
||||
{
|
||||
if (!request.exists("mypk"))
|
||||
throw JSONRPCError(RPC_PARSE_ERROR, "No pubkey supplied in remote rpc request, necessary for this type of rpc");
|
||||
std::string str=request["mypk"].get_str();
|
||||
mypk=pubkey2pk(ParseHex(str));
|
||||
if (!mypk.IsValid())
|
||||
throw JSONRPCError(RPC_PARSE_ERROR, "Not valid pubkey passed in remote rpc call");
|
||||
}
|
||||
//TODO: if ((result = cmd->actor(jreq.params,false,mypk)).isObject() || result.isArray())
|
||||
if ((result = cmd->actor(jreq.params,false)).isObject() || result.isArray())
|
||||
{
|
||||
rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
|
||||
response=rpc_result.write();
|
||||
memcpy(ptr->json,response.c_str(),response.size());
|
||||
len+=response.size();
|
||||
return (len);
|
||||
}
|
||||
else throw JSONRPCError(RPC_MISC_ERROR, "Error in executing RPC on remote node");
|
||||
}
|
||||
catch (const UniValue& objError)
|
||||
{
|
||||
rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
|
||||
response=rpc_result.write();
|
||||
}
|
||||
catch (const runtime_error& e)
|
||||
{
|
||||
rpc_result = JSONRPCReplyObj(NullUniValue,JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
|
||||
response=rpc_result.write();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
rpc_result = JSONRPCReplyObj(NullUniValue,JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
|
||||
response=rpc_result.write();
|
||||
}
|
||||
memcpy(ptr->json,response.c_str(),response.size());
|
||||
len+=response.size();
|
||||
return (len);
|
||||
}
|
||||
|
||||
uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint256 txid)
|
||||
{
|
||||
uint8_t *rawtx = 0;
|
||||
@@ -860,7 +1147,85 @@ void komodo_nSPVreq(CNode *pfrom,std::vector<uint8_t> request) // received a req
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( request[0] == NSPV_REMOTERPC )
|
||||
{
|
||||
if ( timestamp > pfrom->prevtimes[ind] )
|
||||
{
|
||||
struct NSPV_remoterpcresp R; int32_t p;
|
||||
p = 1;
|
||||
p+=iguana_rwnum(0,&request[p],sizeof(slen),&slen);
|
||||
memset(&R,0,sizeof(R));
|
||||
if (request.size() == p+slen && (slen=NSPV_remoterpc(&R,(char *)&request[p],slen))>0 )
|
||||
{
|
||||
response.resize(1 + slen);
|
||||
response[0] = NSPV_REMOTERPCRESP;
|
||||
NSPV_rwremoterpcresp(1,&response[1],&R,slen);
|
||||
pfrom->PushMessage("nSPV",response);
|
||||
pfrom->prevtimes[ind] = timestamp;
|
||||
NSPV_remoterpc_purge(&R);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (request[0] == NSPV_CCMODULEUTXOS) // get cc module utxos from coinaddr for the requested amount, evalcode, funcid list and txid
|
||||
{
|
||||
//fprintf(stderr,"utxos: %u > %u, ind.%d, len.%d\n",timestamp,pfrom->prevtimes[ind],ind,len);
|
||||
if (timestamp > pfrom->prevtimes[ind])
|
||||
{
|
||||
struct NSPV_utxosresp U;
|
||||
char coinaddr[64];
|
||||
int64_t amount;
|
||||
uint8_t evalcode;
|
||||
char funcids[27];
|
||||
uint256 filtertxid;
|
||||
bool errorFormat = false;
|
||||
const int32_t BITCOINADDRESSMINLEN = 20;
|
||||
|
||||
int32_t minreqlen = sizeof(uint8_t) + sizeof(uint8_t) + BITCOINADDRESSMINLEN + sizeof(amount) + sizeof(evalcode) + sizeof(uint8_t) + sizeof(filtertxid);
|
||||
int32_t maxreqlen = sizeof(uint8_t) + sizeof(uint8_t) + sizeof(coinaddr)-1 + sizeof(amount) + sizeof(evalcode) + sizeof(uint8_t) + sizeof(funcids)-1 + sizeof(filtertxid);
|
||||
|
||||
if (len >= minreqlen && len <= maxreqlen)
|
||||
{
|
||||
n = 1;
|
||||
int32_t addrlen = request[n++];
|
||||
if (addrlen < sizeof(coinaddr))
|
||||
{
|
||||
memcpy(coinaddr, &request[n], addrlen);
|
||||
coinaddr[addrlen] = 0;
|
||||
n += addrlen;
|
||||
iguana_rwnum(0, &request[n], sizeof(amount), &amount);
|
||||
n += sizeof(amount);
|
||||
iguana_rwnum(0, &request[n], sizeof(evalcode), &evalcode);
|
||||
n += sizeof(evalcode);
|
||||
|
||||
int32_t funcidslen = request[n++];
|
||||
if (funcidslen < sizeof(funcids))
|
||||
{
|
||||
memcpy(funcids, &request[n], funcidslen);
|
||||
funcids[funcidslen] = 0;
|
||||
n += funcidslen;
|
||||
iguana_rwbignum(0, &request[n], sizeof(filtertxid), (uint8_t *)&filtertxid);
|
||||
std::cerr << __func__ << " " << "request addr=" << coinaddr << " amount=" << amount << " evalcode=" << (int)evalcode << " funcids=" << funcids << " filtertxid=" << filtertxid.GetHex() << std::endl;
|
||||
|
||||
memset(&U, 0, sizeof(U));
|
||||
if ((slen = NSPV_getccmoduleutxos(&U, coinaddr, amount, evalcode, funcids, filtertxid)) > 0)
|
||||
{
|
||||
std::cerr << __func__ << " " << "created utxos, slen=" << slen << std::endl;
|
||||
response.resize(1 + slen);
|
||||
response[0] = NSPV_CCMODULEUTXOSRESP;
|
||||
if (NSPV_rwutxosresp(1, &response[1], &U) == slen)
|
||||
{
|
||||
pfrom->PushMessage("nSPV", response);
|
||||
pfrom->prevtimes[ind] = timestamp;
|
||||
std::cerr << __func__ << " " << "returned nSPV response" << std::endl;
|
||||
}
|
||||
NSPV_utxosresp_purge(&U);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // KOMODO_NSPVFULLNODE_H
|
||||
|
||||
@@ -203,6 +203,12 @@ void komodo_nSPVresp(CNode *pfrom,std::vector<uint8_t> response) // received a r
|
||||
NSPV_rwbroadcastresp(0,&response[1],&NSPV_broadcastresult);
|
||||
fprintf(stderr,"got broadcast response %u size.%d %s retcode.%d\n",timestamp,(int32_t)response.size(),NSPV_broadcastresult.txid.GetHex().c_str(),NSPV_broadcastresult.retcode);
|
||||
break;
|
||||
case NSPV_CCMODULEUTXOSRESP:
|
||||
NSPV_utxosresp_purge(&NSPV_utxosresult);
|
||||
NSPV_rwutxosresp(0, &response[1], &NSPV_utxosresult);
|
||||
fprintf(stderr, "got cc module utxos response %u size.%d\n", timestamp, (int32_t)response.size());
|
||||
break;
|
||||
|
||||
default: fprintf(stderr,"unexpected response %02x size.%d at %u\n",response[0],(int32_t)response.size(),timestamp);
|
||||
break;
|
||||
}
|
||||
@@ -925,4 +931,51 @@ UniValue NSPV_broadcast(char *hex)
|
||||
return(NSPV_broadcast_json(&B,txid));
|
||||
}
|
||||
|
||||
// gets cc utxos filtered by evalcode, funcid and txid in opret, for the specified amount
|
||||
// if amount == 0 returns total and no utxos
|
||||
// funcids is string of funcid symbols like "ct". The first symbol is considered as creation tx funcid and filtertxid will be compared to the creation tx id itself.
|
||||
// For second+ funcids the filtertxid will be compared to txid in opret
|
||||
UniValue NSPV_ccmoduleutxos(char *coinaddr, int64_t amount, uint8_t evalcode, std::string funcids, uint256 filtertxid)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); uint8_t msg[512]; int32_t i, iter, slen, len = 0;
|
||||
uint8_t CCflag = 1;
|
||||
|
||||
NSPV_utxosresp_purge(&NSPV_utxosresult);
|
||||
if (bitcoin_base58decode(msg, coinaddr) != 25)
|
||||
{
|
||||
result.push_back(Pair("result", "error"));
|
||||
result.push_back(Pair("error", "invalid address"));
|
||||
return(result);
|
||||
}
|
||||
msg[len++] = NSPV_CCMODULEUTXOS;
|
||||
|
||||
slen = (int32_t)strlen(coinaddr);
|
||||
msg[len++] = slen;
|
||||
memcpy(&msg[len], coinaddr, slen), len += slen;
|
||||
|
||||
len += iguana_rwnum(1, &msg[len], sizeof(amount), &amount);
|
||||
len += iguana_rwnum(1, &msg[len], sizeof(evalcode), &evalcode);
|
||||
|
||||
slen = (int32_t)(funcids.size());
|
||||
msg[len++] = slen;
|
||||
memcpy(&msg[len], funcids.data(), slen), len += slen;
|
||||
|
||||
len += iguana_rwbignum(1, &msg[len], sizeof(filtertxid), (uint8_t *)&filtertxid);
|
||||
for (iter = 0; iter<3; iter++)
|
||||
if (NSPV_req(0, msg, len, NODE_ADDRINDEX, msg[0] >> 1) != 0)
|
||||
{
|
||||
for (i = 0; i<NSPV_POLLITERS; i++)
|
||||
{
|
||||
usleep(NSPV_POLLMICROS);
|
||||
if ((NSPV_inforesult.height == 0 || NSPV_utxosresult.nodeheight >= NSPV_inforesult.height) && strcmp(coinaddr, NSPV_utxosresult.coinaddr) == 0 && CCflag == NSPV_utxosresult.CCflag)
|
||||
return(NSPV_utxosresp_json(&NSPV_utxosresult));
|
||||
}
|
||||
}
|
||||
else sleep(1);
|
||||
result.push_back(Pair("result", "error"));
|
||||
result.push_back(Pair("error", "no utxos result"));
|
||||
result.push_back(Pair("lastpeer", NSPV_lastpeer));
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif // KOMODO_NSPVSUPERLITE_H
|
||||
|
||||
@@ -388,8 +388,13 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis) // what its a
|
||||
mtx.nExpiryHeight = 0;
|
||||
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
|
||||
mtx.nVersion = SAPLING_TX_VERSION;
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 )
|
||||
mtx.nLockTime = (uint32_t)time(NULL) - 777;
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
|
||||
if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) )
|
||||
mtx.nLockTime = (uint32_t)time(NULL) - 777;
|
||||
else
|
||||
mtx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast();
|
||||
}
|
||||
|
||||
memset(used,0,sizeof(used));
|
||||
|
||||
if ( NSPV_addinputs(used,mtx,satoshis+txfee,64,NSPV_utxosresult.utxos,NSPV_utxosresult.numutxos) > 0 )
|
||||
|
||||
Reference in New Issue
Block a user