Skip to content

Commit ea33b59

Browse files
committed
fixed:
- sort by token code, supply, name - updating tokens after loading the blockchain - do not return NOT_FOUND when requesting balance - filters
1 parent 0a06873 commit ea33b59

4 files changed

Lines changed: 127 additions & 105 deletions

File tree

api/include/apihandler.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,10 +665,14 @@ class APIHandler : public APIHandlerInterface {
665665
return executor_;
666666
}
667667

668+
bool isBDLoaded() { return isBDLoaded_; }
669+
668670
private:
669671
::csstats::AllStats stats_;
670672
executor::Executor& executor_;
671673

674+
bool isBDLoaded_{ false };
675+
672676
struct smart_trxns_queue {
673677
cs::SpinLock lock{ATOMIC_FLAG_INIT};
674678
std::condition_variable_any new_trxn_cv{};
@@ -784,7 +788,7 @@ class APIHandler : public APIHandlerInterface {
784788

785789
std::optional<std::string> checkTransaction(const ::api::Transaction&);
786790

787-
TokensMaster tm;
791+
TokensMaster tm_;
788792

789793
const uint8_t ERROR_CODE = 1;
790794

api/include/tokens.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ struct Token {
3737
uint64_t realHoldersCount = 0; // Non-zero balance
3838

3939
// TmpÑache: name, symbol, totalSupply, balance
40-
std::string name { "not loaded" };
41-
std::string symbol { "not loaded" };
42-
std::string totalSupply { "not loaded" };
40+
std::string name;
41+
std::string symbol;
42+
std::string totalSupply;
4343

4444
struct HolderInfo {
4545
std::string balance { "0" };
@@ -60,7 +60,7 @@ class TokensMaster {
6060

6161
void checkNewState(const csdb::Address& sc, const csdb::Address& initiator, const api::SmartContractInvocation&, const std::string& newState);
6262

63-
void loadTokenInfo(const std::vector<csdb::Address>& vaddr, const std::function<void(const TokensMap&, const HoldersMap&)>);
63+
void loadTokenInfo(const std::function<void(const TokensMap&, const HoldersMap&)>);
6464

6565
static bool isTransfer(const std::string& method, const std::vector<general::Variant>& params);
6666

@@ -85,9 +85,9 @@ class TokensMaster {
8585

8686
void updateTokenChaches(const csdb::Address& addr, const std::string& newState, const TokenInvocationData::Params& params);
8787

88-
private:
89-
void refreshTokenState(const csdb::Address& token, const std::string& newState, bool checkBalance = true);
88+
void refreshTokenState(const csdb::Address& token, const std::string& newState, bool checkBalance = false);
9089

90+
private:
9191
void initiateHolder(Token&, const csdb::Address& token, const csdb::Address& holder, bool increaseTransfers = false);
9292

9393
api::APIHandler* api_;

api/src/apihandler.cpp

Lines changed: 63 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ APIHandler::APIHandler(BlockChain& blockchain, cs::SolverCore& _solver, executor
3232
#ifdef MONITOR_NODE
3333
, stats(blockchain)
3434
#endif
35-
, tm(this) {
35+
, tm_(this) {
3636
#ifdef MONITOR_NODE
3737
if (static bool firstTime = true; firstTime) {
3838
stats_.second.resize(::csstats::collectionPeriods.size());
@@ -171,7 +171,6 @@ void APIHandler::WalletBalanceGet(api::WalletBalanceGetResult& _return, const ge
171171
BlockChain::WalletData wallData{};
172172
BlockChain::WalletId wallId{};
173173
if (!s_blockchain.findWalletData(addr, wallData, wallId)) {
174-
SetResponseStatus(_return.status, APIRequestStatusType::NOT_FOUND);
175174
return;
176175
}
177176
_return.balance.integral = wallData.balance_.integral();
@@ -309,7 +308,7 @@ api::SealedTransaction APIHandler::convertTransaction(const csdb::Transaction& t
309308

310309
if (is_smart_deploy(sci)) {
311310
result.trxn.type = api::TransactionType::TT_SmartDeploy;
312-
tm.loadTokenInfo(std::vector<csdb::Address>(1, target), [&isToken, &target, &result](const TokensMap& tokens, const HoldersMap&) {
311+
tm_.loadTokenInfo([&isToken, &target, &result](const TokensMap& tokens, const HoldersMap&) {
313312
auto it = tokens.find(target);
314313
if (it != tokens.end()) {
315314
isToken = true;
@@ -332,7 +331,7 @@ api::SealedTransaction APIHandler::convertTransaction(const csdb::Transaction& t
332331
bool isTransfer = TokensMaster::isTransfer(sci.method, sci.params);
333332
result.trxn.type = api::TransactionType::TT_SmartExecute;
334333
if (isTransfer) {
335-
tm.loadTokenInfo(std::vector<csdb::Address>(1, target), [&isToken, &isTransfer, &target, &result](const TokensMap& tokens, const HoldersMap&) {
334+
tm_.loadTokenInfo([&isToken, &isTransfer, &target, &result](const TokensMap& tokens, const HoldersMap&) {
336335
auto it = tokens.find(target);
337336
if (it != tokens.end()) {
338337
isToken = true;
@@ -572,7 +571,7 @@ api::SmartContract APIHandler::fetch_smart_body(const csdb::Transaction& tr) {
572571
res.address = fromByteArray(s_blockchain.getAddressByType(tr.target(), BlockChain::AddressType::PublicKey).public_key());
573572

574573
#ifdef TOKENS_CACHE
575-
tm.loadTokenInfo(std::vector<csdb::Address>(1, tr.target()), [&tr, &res](const TokensMap& tokens, const HoldersMap&) {
574+
tm_.loadTokenInfo([&tr, &res](const TokensMap& tokens, const HoldersMap&) {
576575
auto it = tokens.find(tr.target());
577576
if (it != tokens.end())
578577
res.smartContractDeploy.tokenStandard = it->second.tokenStandard;
@@ -931,6 +930,22 @@ void APIHandler::SmartContractGet(api::SmartContractGetResult& _return, const ge
931930

932931
void APIHandler::store_block_slot(const csdb::Pool& pool) {
933932
updateSmartCachesPool(pool);
933+
#ifdef TOKENS_CACHE
934+
if(!isBDLoaded_) {
935+
isBDLoaded_ = true;
936+
tm_.loadTokenInfo([&](const TokensMap& tokens, const HoldersMap&) {
937+
int count{}, i{};
938+
size_t tokenSize = tokens.size();
939+
cslog() << "tokens are loading(" << tokenSize <<")...";
940+
for (auto& tk : tokens) {
941+
if (tokenSize > 100 && !(i++ % (tokenSize / 10)))
942+
cslog() << "loading tokens: " << 10*(count++) << "%";
943+
tm_.refreshTokenState(tk.first, cs::SmartContracts::get_contract_state(get_s_blockchain(), tk.first), true);
944+
}
945+
cslog() << "tokens loaded!";
946+
});
947+
}
948+
#endif
934949
}
935950

936951
void APIHandler::collect_all_stats_slot(const csdb::Pool& pool) {
@@ -1061,6 +1076,8 @@ bool APIHandler::updateSmartCachesTransaction(csdb::Transaction trxn, cs::Sequen
10611076
auto newHashStr = trxn.user_field(cs::trx_uf::new_state::Hash).template value<std::string>();
10621077
if (!newHashStr.empty())
10631078
std::copy(newHashStr.begin(), newHashStr.end(), res.hash.begin());
1079+
else
1080+
res.hash = cs::Zero::hash;
10641081
res.retVal = trxn.user_field(cs::trx_uf::new_state::RetVal).template value<std::string>();
10651082
res.isOld = (res.hash == oldHash.hash);
10661083
res.condFlg = true;
@@ -1072,12 +1089,12 @@ bool APIHandler::updateSmartCachesTransaction(csdb::Transaction trxn, cs::Sequen
10721089
auto caller_pk = s_blockchain.getAddressByType(execTrans.source(), BlockChain::AddressType::PublicKey);
10731090

10741091
if (is_smart_deploy(smart))
1075-
tm.checkNewDeploy(target_pk, caller_pk, smart);
1092+
tm_.checkNewDeploy(target_pk, caller_pk, smart);
10761093

10771094
// state also will be updated in update_smart_state_slot()
10781095
std::string newState = cs::SmartContracts::get_contract_state(s_blockchain, target_pk);
10791096
if (!newState.empty())
1080-
tm.checkNewState(target_pk, caller_pk, smart, newState);
1097+
tm_.checkNewState(target_pk, caller_pk, smart, newState);
10811098
}
10821099
}
10831100
}
@@ -1406,7 +1423,7 @@ void putTokenInfo(api::TokenInfo& ti, const general::Address& addr, const Token&
14061423
}
14071424

14081425
template <typename ResultType>
1409-
void tokenTransactionsInternal(ResultType& _return, APIHandler& handler, TokensMaster& tm, const general::Address& token, bool transfersOnly, bool filterByWallet, int64_t offset,
1426+
void tokenTransactionsInternal(ResultType& _return, APIHandler& handler, TokensMaster& tm_, const general::Address& token, bool transfersOnly, bool filterByWallet, int64_t offset,
14101427
int64_t limit, const csdb::Address& wallet = csdb::Address()) {
14111428
if (!validatePagination(_return, handler, offset, limit)) {
14121429
return;
@@ -1416,9 +1433,9 @@ void tokenTransactionsInternal(ResultType& _return, APIHandler& handler, TokensM
14161433
bool tokenFound = false;
14171434
std::string code;
14181435

1419-
tm.loadTokenInfo(std::vector<csdb::Address>(1, addr), [&addr, &tokenFound, &transfersOnly, &filterByWallet, &code, &wallet, &_return](const TokensMap& tm, const HoldersMap&) {
1420-
auto it = tm.find(addr);
1421-
tokenFound = !(it == tm.end());
1436+
tm_.loadTokenInfo([&addr, &tokenFound, &transfersOnly, &filterByWallet, &code, &wallet, &_return](const TokensMap& tm_, const HoldersMap&) {
1437+
auto it = tm_.find(addr);
1438+
tokenFound = !(it == tm_.end());
14221439
if (tokenFound) {
14231440
code = it->second.symbol;
14241441
if (transfersOnly && !filterByWallet) {
@@ -1604,18 +1621,7 @@ void APIHandler::ExecuteCountGet(ExecuteCountGetResult& _return, const std::stri
16041621

16051622
void APIHandler::TokenBalancesGet(api::TokenBalancesResult& _return, const general::Address& address) {
16061623
const csdb::Address addr = BlockChain::getAddressFromKey(address);
1607-
1608-
std::vector<csdb::Address> vtokenAddr;
1609-
tm.loadTokenInfo({}, [&vtokenAddr, &addr](const TokensMap& tokens, const HoldersMap& holders) {
1610-
if (auto holderIt = holders.find(addr); holderIt != holders.end()) {
1611-
for (const auto& tokAddr : holderIt->second) {
1612-
if (tokens.find(tokAddr) != tokens.end())
1613-
vtokenAddr.push_back(tokAddr);
1614-
}
1615-
}
1616-
});
1617-
1618-
tm.loadTokenInfo(vtokenAddr, [&_return, &addr](const TokensMap& tokens, const HoldersMap& holders) {
1624+
tm_.loadTokenInfo([&_return, &addr](const TokensMap& tokens, const HoldersMap& holders) {
16191625
auto holderIt = holders.find(addr);
16201626
if (holderIt != holders.end()) {
16211627
for (const auto& tokAddr : holderIt->second) {
@@ -1645,7 +1651,7 @@ void APIHandler::TokenBalancesGet(api::TokenBalancesResult& _return, const gener
16451651
}
16461652

16471653
void APIHandler::TokenTransfersGet(api::TokenTransfersResult& _return, const general::Address& token, int64_t offset, int64_t limit) {
1648-
tokenTransactionsInternal(_return, *this, tm, token, true, false, offset, limit);
1654+
tokenTransactionsInternal(_return, *this, tm_, token, true, false, offset, limit);
16491655
}
16501656

16511657
void APIHandler::TokenTransferGet(api::TokenTransfersResult& _return, const general::Address& token, const TransactionId& id) {
@@ -1654,9 +1660,9 @@ void APIHandler::TokenTransferGet(api::TokenTransfersResult& _return, const gene
16541660
const csdb::Address addr = BlockChain::getAddressFromKey(token);
16551661

16561662
std::string code{};
1657-
tm.loadTokenInfo(std::vector(1, addr), [&addr, &code](const TokensMap& tm, const HoldersMap&) {
1658-
const auto it = tm.find(addr);
1659-
if (it != tm.cend()) {
1663+
tm_.loadTokenInfo([&addr, &code](const TokensMap& tm_, const HoldersMap&) {
1664+
const auto it = tm_.find(addr);
1665+
if (it != tm_.cend()) {
16601666
code = it->second.symbol;
16611667
}
16621668
});
@@ -1718,16 +1724,15 @@ void APIHandler::TokenTransfersListGet(api::TokenTransfersResult& _return, int64
17181724
uint64_t totalTransfers = 0;
17191725
std::multimap<cs::Sequence, csdb::Address> tokenTransPools;
17201726

1721-
tm.loadTokenInfo({}, [&totalTransfers, &tokenTransPools, this](const TokensMap& tm, const HoldersMap&) {
1722-
for (auto& t : tm) {
1727+
tm_.loadTokenInfo([&totalTransfers, &tokenTransPools, this](const TokensMap& tm_, const HoldersMap&) {
1728+
for (auto& t : tm_) {
17231729
totalTransfers += t.second.transfersCount;
17241730
tokenTransPools.insert(std::make_pair(s_blockchain.getLastTransaction(t.first).pool_seq(), t.first));
17251731
}
17261732
});
17271733

17281734
_return.count = uint32_t(totalTransfers);
17291735

1730-
std::vector<csdb::Address> tokenAddrs;
17311736
cs::Sequence seq = s_blockchain.getLastNonEmptyBlock().first;
17321737
while (limit && seq != cs::kWrongSequence && tokenTransPools.size()) {
17331738
auto it = tokenTransPools.find(seq);
@@ -1748,7 +1753,6 @@ void APIHandler::TokenTransfersListGet(api::TokenTransfersResult& _return, int64
17481753
csdb::Address target_pk = s_blockchain.getAddressByType(t.target(), BlockChain::AddressType::PublicKey);
17491754
auto addrPair = TokensMaster::getTransferData(target_pk, smart.method, smart.params);
17501755
addTokenResult(_return, target_pk, "", pool, t, smart, addrPair, s_blockchain);
1751-
tokenAddrs.push_back(target_pk);
17521756
if (--limit == 0) {
17531757
break;
17541758
}
@@ -1770,9 +1774,9 @@ void APIHandler::TokenTransfersListGet(api::TokenTransfersResult& _return, int64
17701774
seq = s_blockchain.getPreviousNonEmptyBlock(seq).first;
17711775
}
17721776

1773-
tm.loadTokenInfo(tokenAddrs, [&_return](const TokensMap& tm, const HoldersMap&) {
1777+
tm_.loadTokenInfo([&_return](const TokensMap& tm_, const HoldersMap&) {
17741778
for (auto& transfer : _return.transfers) {
1775-
if(auto it = tm.find(BlockChain::getAddressFromKey(transfer.token)); it != tm.end())
1779+
if(auto it = tm_.find(BlockChain::getAddressFromKey(transfer.token)); it != tm_.end())
17761780
transfer.code = it->second.symbol;
17771781
}
17781782
});
@@ -1782,19 +1786,19 @@ void APIHandler::TokenTransfersListGet(api::TokenTransfersResult& _return, int64
17821786

17831787
void APIHandler::TokenWalletTransfersGet(api::TokenTransfersResult& _return, const general::Address& token, const general::Address& address, int64_t offset, int64_t limit) {
17841788
const csdb::Address wallet = BlockChain::getAddressFromKey(address);
1785-
tokenTransactionsInternal(_return, *this, tm, token, true, true, offset, limit, wallet);
1789+
tokenTransactionsInternal(_return, *this, tm_, token, true, true, offset, limit, wallet);
17861790
}
17871791

17881792
void APIHandler::TokenTransactionsGet(api::TokenTransactionsResult& _return, const general::Address& token, int64_t offset, int64_t limit) {
1789-
tokenTransactionsInternal(_return, *this, tm, token, false, false, offset, limit);
1793+
tokenTransactionsInternal(_return, *this, tm_, token, false, false, offset, limit);
17901794
}
17911795

17921796
void APIHandler::TokenInfoGet(api::TokenInfoResult& _return, const general::Address& token) {
17931797
bool found = false;
17941798
const csdb::Address addr = BlockChain::getAddressFromKey(token);
1795-
tm.loadTokenInfo(std::vector<csdb::Address>(1, addr), [&token, &addr, &found, &_return](const TokensMap& tm, const HoldersMap&) {
1796-
auto tIt = tm.find(addr);
1797-
if (tIt != tm.end()) {
1799+
tm_.loadTokenInfo([&token, &addr, &found, &_return](const TokensMap& tm_, const HoldersMap&) {
1800+
auto tIt = tm_.find(addr);
1801+
if (tIt != tm_.end()) {
17981802
found = true;
17991803
putTokenInfo(_return.token, token, tIt->second);
18001804
}
@@ -1846,9 +1850,9 @@ void APIHandler::TokenHoldersGet(api::TokenHoldersResult& _return, const general
18461850
}
18471851

18481852
const csdb::Address addr = BlockChain::getAddressFromKey(token);
1849-
tm.loadTokenInfo(std::vector<csdb::Address>(1, addr), [&token, &addr, &found, &offset, &limit, &_return, comparator](const TokensMap& tm, const HoldersMap&) {
1850-
auto tIt = tm.find(addr);
1851-
if (tIt != tm.end()) {
1853+
tm_.loadTokenInfo([&token, &addr, &found, &offset, &limit, &_return, comparator](const TokensMap& tm_, const HoldersMap&) {
1854+
auto tIt = tm_.find(addr);
1855+
if (tIt != tm_.end()) {
18521856
found = true;
18531857
_return.count = (uint32_t) tIt->second.realHoldersCount;
18541858

@@ -1891,23 +1895,14 @@ void APIHandler::TokensListGet(api::TokensListResult& _return, int64_t offset, i
18911895

18921896
switch (order) {
18931897
case TL_Code:
1894-
#ifdef SLOW_WORK
18951898
comparator = getComparator<VT>(&Token::symbol, desc);
18961899
break;
1897-
#endif
1898-
[[fallthrough]];
18991900
case TL_Name:
1900-
#ifdef SLOW_WORK
19011901
comparator = getComparator<VT>(&Token::name, desc);
19021902
break;
1903-
#endif
1904-
[[fallthrough]];
19051903
case TL_TotalSupply:
1906-
#ifdef SLOW_WORK
19071904
comparator = [desc](const VT& lhs, const VT& rhs) { return desc ^ (stod(lhs.second.totalSupply) < stod(rhs.second.totalSupply)); };
19081905
break;
1909-
#endif
1910-
[[fallthrough]];
19111906
case TL_Address:
19121907
comparator = [desc](const VT& lhs, const VT& rhs) { return desc ^ (lhs.first < rhs.first); };
19131908
break;
@@ -1922,39 +1917,34 @@ void APIHandler::TokensListGet(api::TokensListResult& _return, int64_t offset, i
19221917
break;
19231918
};
19241919

1925-
std::vector<csdb::Address> sortTokenAddrs;
1926-
tm.loadTokenInfo({}, [&, comparator](const TokensMap& tm, const HoldersMap&) {
1927-
_return.count = (uint32_t)tm.size();
1928-
applyToSortedMap(tm, comparator, [&](const TokensMap::value_type& t) {
1929-
if (--offset >= 0)
1920+
tm_.loadTokenInfo([&, comparator](const TokensMap& tm_, const HoldersMap&) {
1921+
_return.count = (uint32_t)tm_.size();
1922+
applyToSortedMap(tm_, comparator, [&](const TokensMap::value_type& t) {
1923+
if (--offset >= 0) {
19301924
return true;
1925+
}
19311926

19321927
api::TokenInfo tok;
19331928
putTokenInfo(tok, fromByteArray(t.first.public_key()), t.second);
1934-
sortTokenAddrs.push_back(BlockChain::getAddressFromKey(tok.address));
1929+
1930+
// filters
1931+
auto posName = tok.name.find(filters.name);
1932+
auto posCode = tok.code.find(filters.code);
1933+
if ((posName != std::string::npos && posCode != std::string::npos && tok.tokenStandard == filters.tokenStandard) ||
1934+
(posName && posCode && !tok.tokenStandard) ||
1935+
(posName && filters.code.empty() && !tok.tokenStandard) ||
1936+
(filters.name.empty() && posCode && tok.tokenStandard) ||
1937+
(filters.name.empty() && posCode && !tok.tokenStandard) ||
1938+
(filters.name.empty() && filters.code.empty() && tok.tokenStandard) ||
1939+
(filters.name.empty() && filters.code.empty() && !tok.tokenStandard))
1940+
_return.tokens.push_back(tok);
19351941

19361942
if (--limit == 0)
19371943
return false;
19381944

19391945
return true;
1946+
});
19401947
});
1941-
});
1942-
1943-
tm.loadTokenInfo(sortTokenAddrs, [&](const TokensMap& tm, const HoldersMap&) {
1944-
api::TokenInfo tok;
1945-
for (auto t : tm) {
1946-
if ((t.second.name.find(filters.name) != std::string::npos && t.second.symbol.find(filters.code) != std::string::npos && t.second.tokenStandard == filters.tokenStandard) ||
1947-
(t.second.name.find(filters.name) && t.second.symbol.find(filters.code) && !t.second.tokenStandard) ||
1948-
(t.second.name.find(filters.name) && filters.code.empty() && !t.second.tokenStandard) ||
1949-
(filters.name.empty() && t.second.symbol.find(filters.code) && t.second.tokenStandard) ||
1950-
(filters.name.empty() && t.second.symbol.find(filters.code) && !t.second.tokenStandard) ||
1951-
(filters.name.empty() && filters.code.empty() && t.second.tokenStandard) ||
1952-
(filters.name.empty() && filters.code.empty() && !t.second.tokenStandard)) {
1953-
putTokenInfo(tok, fromByteArray(t.first.public_key()), t.second);
1954-
_return.tokens.push_back(tok);
1955-
}
1956-
}
1957-
});
19581948

19591949
SetResponseStatus(_return.status, APIRequestStatusType::SUCCESS);
19601950
}

0 commit comments

Comments
 (0)