Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New rpc calls for mobile #1449

Merged
merged 7 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ class CBlockIndex
sigma::spend_info_container sigmaSpentSerials;
std::unordered_map<Scalar, int> lelantusSpentSerials;
std::unordered_map<GroupElement, int> spentLTags;
// linking tag hash mapped to tx hash
std::unordered_map<uint256, uint256> ltagTxhash;

//! list of disabling sporks active at this block height
//! std::map {feature name} -> {block number when feature is re-enabled again, parameter}
Expand Down Expand Up @@ -303,6 +305,7 @@ class CBlockIndex
sparkMintedCoins.clear();
sparkSetHash.clear();
spentLTags.clear();
ltagTxhash.clear();
sparkTxHashContext.clear();
sigmaSpentSerials.clear();
lelantusSpentSerials.clear();
Expand Down Expand Up @@ -563,6 +566,7 @@ class CDiskBlockIndex : public CBlockIndex

if (GetBoolArg("-mobile", false)) {
READWRITE(sparkTxHashContext);
READWRITE(ltagTxhash);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getusedcoinserials", 0 },
{ "getlatestcoinids", 0 },
{ "getsparkmintmetadata", 0 },
{ "getmempooltxs", 0 },

//Lelantus
{ "mintspark", 0 },
Expand Down
161 changes: 161 additions & 0 deletions src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,63 @@ UniValue getusedcoinstags(const JSONRPCRequest& request)
return ret;
}

UniValue getusedcoinstagstxhashes(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"getusedcoinstagstxhashes\n"
"\nReturns the set of used coin tags paired with tx ids in which it was spent, this rpc required -mobile argument, \n"
"\nArguments:\n"
"{\n"
" \"startNumber \" (int) Number of elements already existing on user side\n"
"}\n"
"\nResult:\n"
"{\n"
" \"tags\" (std::string[]) array of Serialized GroupElements paired with unit256 (tx ids) \n"
"}\n"
);

int startNumber;
try {
startNumber = std::stol(request.params[0].get_str());
} catch (std::logic_error const & e) {
throw std::runtime_error(std::string("An exception occurred while parsing parameters: ") + e.what());
}

spark::CSparkState* sparkState = spark::CSparkState::GetState();
std::unordered_map<GroupElement, int, spark::CLTagHash> tags;
std::unordered_map<uint256, uint256> ltagTxhash;
{
LOCK(cs_main);
tags = sparkState->GetSpends();
ltagTxhash = sparkState->GetSpendTxIds();
}
UniValue serializedTagsTxIds(UniValue::VARR);
int i = 0;
for ( auto it = tags.begin(); it != tags.end(); ++it, ++i) {
if ((tags.size() - i - 1) < startNumber)
continue;
std::vector<unsigned char> serialized;
serialized.resize(34);
it->first.serialize(serialized.data());
std::vector<UniValue> data;
data.push_back(EncodeBase64(serialized.data(), 34));
uint256 txid;
uint256 ltagHash = primitives::GetLTagHash(it->first);
if (ltagTxhash.count(ltagHash) > 0)
txid = ltagTxhash[ltagHash];
data.push_back(EncodeBase64(txid.begin(), txid.size()));
UniValue entity(UniValue::VARR);
entity.push_backV(data);
serializedTagsTxIds.push_back(entity);
}

UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("tagsandtxids", serializedTagsTxIds));

return ret;
}
levonpetrosyan93 marked this conversation as resolved.
Show resolved Hide resolved

UniValue getsparklatestcoinid(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
Expand Down Expand Up @@ -1431,6 +1488,107 @@ UniValue getsparklatestcoinid(const JSONRPCRequest& request)
return UniValue(latestCoinId);
}

UniValue getmempoolsparktxids(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
"getmempoolsparktxids\n"
"\nReturns spark transaction ids existing in the mempool.\n"
);

UniValue result(UniValue::VARR);
std::vector<TxMempoolInfo> txs = mempool.infoAll();
for (auto it = txs.begin(); it != txs.end(); it++) {
if (!it->tx->IsSparkTransaction())
continue;
result.push_back(EncodeBase64(it->tx->GetHash().begin(), it->tx->GetHash().size()));
}

return result;
}
levonpetrosyan93 marked this conversation as resolved.
Show resolved Hide resolved

UniValue getmempoolsparktxs(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"getmempoolsparktxs\n"
"\nReturns spark metadata for each transaction id, in case tx already was removed from mempool, nothing will be returned for specific id.\n"
"\nArguments:\n"
" \"txids\"\n"
" [\n"
" {\n"
" \"txid\" (string) The transaction hash\n"
" }\n"
" ,...\n"
" ]\n"
"\nResult:\n"
"txid , {\n"
" \"lTags\" Array of GroupElements, or a string 'MintTX' in case it is mint tx\n"
" \"serial_context\" byte array which is used to identify the output spark coins, it is unique for each ix\n"
" \"coins\" Array of serialized spar::Coin elements, the output coins of the tx\n"
"}\n"
+ HelpExampleCli("getmempoolsparktxs", "'{\"txids\": [\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\",\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\"]}'")
+ HelpExampleRpc("getmempoolsparktxs", "{\"txids\": [\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\",\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\"]}")

);

UniValue txids = find_value(request.params[0].get_obj(), "txids");

UniValue result(UniValue::VOBJ);
for(UniValue const & element : txids.getValues()){
uint256 txid;
txid.SetHex(element.get_str());
CTransactionRef tx = mempool.get(txid);
if (tx == nullptr || !tx->IsSparkTransaction())
continue;

UniValue data(UniValue::VOBJ);
std::vector<UniValue> lTags_;
UniValue lTags_json(UniValue::VARR);
if (tx->IsSparkSpend())
{
try {
spark::SpendTransaction spend = spark::ParseSparkSpend(*tx);
auto lTags = spend.getUsedLTags();
for ( auto it = lTags.begin(); it != lTags.end(); ++it) {
std::vector<unsigned char> serialized;
serialized.resize(34);
it->serialize(serialized.data());
lTags_.push_back(EncodeBase64(serialized.data(), 34));
}
} catch (const std::exception &) {
continue;
}
} else {
lTags_.push_back("MintTX");
}
lTags_json.push_backV(lTags_);

data.push_back(Pair("lTags ", lTags_json)); // Spend lTags for corresponding tx,

std::vector<unsigned char> serial_context = spark::getSerialContext(*tx);
UniValue serial_context_json(UniValue::VARR);
serial_context_json.push_back(EncodeBase64(serial_context.data(), serial_context.size()));
data.push_back(Pair("serial_context", serial_context_json)); // spark serial context

std::vector<spark::Coin> coins = spark::GetSparkMintCoins(*tx);
std::vector<UniValue> serialized_coins;
UniValue serialized_json(UniValue::VARR);
for (auto& coin: coins) {
CDataStream serializedCoin(SER_NETWORK, PROTOCOL_VERSION);
serializedCoin << coin;
std::vector<unsigned char> vch(serializedCoin.begin(), serializedCoin.end());
serialized_coins.push_back(EncodeBase64(vch.data(), size_t(vch.size()))); // coi
}
serialized_json.push_backV(serialized_coins);
data.push_back(Pair("coins", serialized_json));

result.push_back(Pair(EncodeBase64(txid.begin(), txid.size()), data));
}

return result;
}
levonpetrosyan93 marked this conversation as resolved.
Show resolved Hide resolved

UniValue checkifmncollateral(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 2)
Expand Down Expand Up @@ -1762,7 +1920,10 @@ static const CRPCCommand commands[] =
{ "mobile", "getsparkanonymityset", &getsparkanonymityset, false },
{ "mobile", "getsparkmintmetadata", &getsparkmintmetadata, true },
{ "mobile", "getusedcoinstags", &getusedcoinstags, false },
{ "mobile", "getusedcoinstagstxhashes", &getusedcoinstagstxhashes, false },
{ "mobile", "getsparklatestcoinid", &getsparklatestcoinid, true },
{ "mobile", "getmempoolsparktxids", &getmempoolsparktxids, true },
{ "mobile", "getmempoolsparktxs", &getmempoolsparktxs, true },

{ "mobile", "checkifmncollateral", &checkifmncollateral, false },

Expand Down
4 changes: 4 additions & 0 deletions src/rpc/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,11 @@ static const CRPCCommand vRPCCommands[] =
{ "mobile", "getsparkanonymityset", &getsparkanonymityset, false },
{ "mobile", "getsparkmintmetadata", &getsparkmintmetadata, true },
{ "mobile", "getusedcoinstags", &getusedcoinstags, false },
{ "mobile", "getusedcoinstagstxhashes", &getusedcoinstagstxhashes, false },
{ "mobile", "getsparklatestcoinid", &getsparklatestcoinid, true },
{ "mobile", "getmempoolsparktxids", &getmempoolsparktxids, true },
{ "mobile", "getmempoolsparktxs", &getmempoolsparktxs, true },


{ "mobile", "checkifmncollateral", &checkifmncollateral, false },

Expand Down
3 changes: 3 additions & 0 deletions src/rpc/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,10 @@ extern UniValue getlatestcoinid(const JSONRPCRequest& params);
extern UniValue getsparkanonymityset(const JSONRPCRequest& params);
extern UniValue getsparkmintmetadata(const JSONRPCRequest& params);
extern UniValue getusedcoinstags(const JSONRPCRequest& params);
extern UniValue getusedcoinstagstxhashes(const JSONRPCRequest& params);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add documentation for getusedcoinstagstxhashes.

The function getusedcoinstagstxhashes is introduced to extend the functionality of the existing getusedcoinstags by also providing the transaction hash in which the coin was spent. It's crucial to have proper documentation for new RPC methods to ensure they are used correctly and understood by other developers or API consumers.

extern UniValue getsparklatestcoinid(const JSONRPCRequest& params);
extern UniValue getmempoolsparktxids(const JSONRPCRequest& params);
extern UniValue getmempoolsparktxs(const JSONRPCRequest& params);
levonpetrosyan93 marked this conversation as resolved.
Show resolved Hide resolved

extern UniValue checkifmncollateral(const JSONRPCRequest& params);

Expand Down
24 changes: 23 additions & 1 deletion src/spark/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,16 @@ bool ConnectBlockSpark(
}

if (!fJustCheck) {
BOOST_FOREACH(auto& lTag, pblock->sparkTxInfo->spentLTags) {
BOOST_FOREACH (auto& lTag, pblock->sparkTxInfo->spentLTags) {
pindexNew->spentLTags.insert(lTag);
sparkState.AddSpend(lTag.first, lTag.second);
}
if (GetBoolArg("-mobile", false)) {
BOOST_FOREACH (auto& lTag, pblock->sparkTxInfo->ltagTxhash) {
pindexNew->ltagTxhash.insert(lTag);
sparkState.AddLTagTxHash(lTag.first, lTag.second);
}
}
}
else {
return true;
Expand Down Expand Up @@ -693,6 +699,9 @@ bool CheckSparkSpendTransaction(
if (sparkTxInfo && !sparkTxInfo->fInfoIsComplete) {
for (size_t i = 0; i < lTags.size(); i++) {
sparkTxInfo->spentLTags.insert(std::make_pair(lTags[i], ids[i]));
if (GetBoolArg("-mobile", false)) {
sparkTxInfo->ltagTxhash.insert(std::make_pair(primitives::GetLTagHash(lTags[i]), hashTx));
}
}
}
}
Expand Down Expand Up @@ -1038,6 +1047,10 @@ void CSparkState::AddSpend(const GroupElement& lTag, int coinGroupId) {
}
}

void CSparkState::AddLTagTxHash(const uint256& lTagHash, const uint256& txHash) {
ltagTxhash[lTagHash] = txHash;
}

void CSparkState::RemoveSpend(const GroupElement& lTag) {
auto iter = usedLTags.find(lTag);
if (iter != usedLTags.end()) {
Expand Down Expand Up @@ -1074,6 +1087,11 @@ void CSparkState::AddBlock(CBlockIndex *index) {
for (auto const &lTags : index->spentLTags) {
AddSpend(lTags.first, lTags.second);
}
if (GetBoolArg("-mobile", false)) {
for (auto const &elem : index->ltagTxhash) {
AddLTagTxHash(elem.first, elem.second);
}
}
}

void CSparkState::RemoveBlock(CBlockIndex *index) {
Expand Down Expand Up @@ -1320,6 +1338,10 @@ std::unordered_map<GroupElement, int, spark::CLTagHash> const & CSparkState::Get
return usedLTags;
}

std::unordered_map<uint256, uint256> const& CSparkState::GetSpendTxIds() const {
return ltagTxhash;
}

std::unordered_map<int, CSparkState::SparkCoinGroupInfo> const& CSparkState::GetCoinGroups() const {
return coinGroups;
}
Expand Down
5 changes: 5 additions & 0 deletions src/spark/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CSparkTxInfo {

// linking tag for every spend (map from lTag to coin group id)
std::unordered_map<GroupElement, int> spentLTags;
std::unordered_map<uint256, uint256> ltagTxhash;

// information about transactions in the block is complete
bool fInfoIsComplete;
Expand Down Expand Up @@ -168,6 +169,7 @@ class CSparkState {
void AddMintsToStateAndBlockIndex(CBlockIndex *index, const CBlock* pblock);

void AddSpend(const GroupElement& lTag, int coinGroupId);
void AddLTagTxHash(const uint256& lTagHash, const uint256& txHash);
void RemoveSpend(const GroupElement& lTag);
// Add everything from the block to the state
void AddBlock(CBlockIndex *index);
Expand Down Expand Up @@ -213,6 +215,7 @@ class CSparkState {

std::unordered_map<spark::Coin, CMintedCoinInfo, spark::CoinHash> const & GetMints() const;
std::unordered_map<GroupElement, int, spark::CLTagHash> const & GetSpends() const;
std::unordered_map<uint256, uint256> const& GetSpendTxIds() const;
std::unordered_map<int, SparkCoinGroupInfo> const & GetCoinGroups() const;
std::unordered_map<GroupElement, uint256, spark::CLTagHash> const & GetMempoolLTags() const;

Expand All @@ -238,6 +241,8 @@ class CSparkState {
std::unordered_map<spark::Coin, CMintedCoinInfo, spark::CoinHash> mintedCoins;
// Set of all used coin linking tags.
std::unordered_map<GroupElement, int, spark::CLTagHash> usedLTags;
// linking tag hash mapped to tx hash
std::unordered_map<uint256, uint256> ltagTxhash;

typedef std::map<int, size_t> metainfo_container_t;
metainfo_container_t extendedMintMetaInfo, mintMetaInfo, spendMetaInfo;
Expand Down
1 change: 1 addition & 0 deletions src/txdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::function<CBlockIndex*(const uint256
pindexNew->sparkSetHash = diskindex.sparkSetHash;
pindexNew->spentLTags = diskindex.spentLTags;
pindexNew->sparkTxHashContext = diskindex.sparkTxHashContext;
pindexNew->ltagTxhash = diskindex.ltagTxhash;

pindexNew->activeDisablingSporks = diskindex.activeDisablingSporks;

Expand Down
Loading