diff --git a/src/aegis/application.cpp b/src/aegis/application.cpp index 6fd3d76..429f987 100644 --- a/src/aegis/application.cpp +++ b/src/aegis/application.cpp @@ -7,132 +7,137 @@ using ICONation::Aegis::Db::Db; namespace ICONation::Aegis { - Application::Application (int argc, char **argv) - : Common::Application::Application (argc, argv) - { - // Arg 1 (optional) : ICON endpoint URL - m_endpoint = (argc > 1) ? argv[1] : "https://ctz.solidwallet.io/api/v3"; - // m_endpoint = (argc > 1) ? argv[1] : "https://bicon.net.solidwallet.io/api/v3"; - // m_endpoint = (argc > 1) ? argv[1] : "http://iconation.team:9100/api/v3"; - // Arg 2 (optional) : Number of threads - int threads = (argc > 2) ? atoi (argv[2]) : 5; - m_cacheSize = (argc > 3) ? atoi (argv[3]) : 50; - - // Create client - m_client = std::make_unique (m_endpoint); - - // Create block downloader - m_downloader = std::make_unique (threads, m_endpoint); - - Common::Dbg::info ("Launching Aegis with the following parameters :"); - Common::Dbg::info (" Endpoint : {}", m_endpoint); - Common::Dbg::info (" Threads : {}", threads); - Common::Dbg::info (" Cache Size : {}", m_cacheSize); - } - - Application::~Application (void) - { - // Stop threading before delete - Common::Dbg::warn ("Stopping Application..."); - if (m_downloader->running()) { - m_downloader->stop(); - m_downloader->join(); - } - } - - void Application::print_usage (void) +Application::Application(int argc, char **argv) + : Common::Application::Application(argc, argv) +{ + // Arg 1 (optional) : ICON endpoint URL + m_endpoint = (argc > 1) ? argv[1] : "https://ctz.solidwallet.io/api/v3"; + // m_endpoint = (argc > 1) ? argv[1] : "https://bicon.net.solidwallet.io/api/v3"; + // m_endpoint = (argc > 1) ? argv[1] : "http://iconation.team:9100/api/v3"; + // Arg 2 (optional) : Number of threads + int threads = (argc > 2) ? atoi(argv[2]) : 5; + m_cacheSize = (argc > 3) ? atoi(argv[3]) : 50; + + // Create client + m_client = std::make_unique(m_endpoint); + + // Create block downloader + m_downloader = std::make_unique(threads, m_endpoint); + + Common::Dbg::info("Launching Aegis with the following parameters :"); + Common::Dbg::info(" Endpoint : {}", m_endpoint); + Common::Dbg::info(" Threads : {}", threads); + Common::Dbg::info(" Cache Size : {}", m_cacheSize); +} + +Application::~Application(void) +{ + // Stop threading before delete + Common::Dbg::warn("Stopping Application..."); + if (m_downloader->running()) { - info ("=========================================="); - info (" +++ Aegis v1.1 +++++++++++++"); - info (" Usage : {} [endpoint] [number of threads] [cache size]", m_binary_name); - info (" Exemple : {} https://ctz.solidwallet.io/api/v3 5 50", m_binary_name); - info ("=========================================="); + m_downloader->stop(); + m_downloader->join(); } +} - void Application::bootstrap (void) - { - warn ("Bootstrapping..."); +void Application::print_usage(void) +{ + info("=========================================="); + info(" +++ Aegis v%s +++++++++++++", APP_VERSION); + info(" Usage : {} [endpoint] [number of threads] [cache size]", m_binary_name); + info(" Exemple : {} https://ctz.solidwallet.io/api/v3 5 50", m_binary_name); + info("=========================================="); +} + +void Application::bootstrap(void) +{ + warn("Bootstrapping..."); - // Bootstrap db - m_db.bootstrap (m_client->icx()); + // Bootstrap db + m_db.bootstrap(m_client->icx()); - // Get & insert genesis block - GenesisBlock genesis = m_client->get_genesis_block (); - ::Db::Id id = m_db.genesis_insert (genesis); - } + // Get & insert genesis block + GenesisBlock genesis = m_client->get_genesis_block(); + ::Db::Id id = m_db.genesis_insert(genesis); +} - void Application::check_bootstrap (void) +void Application::check_bootstrap(void) +{ + if (m_db.need_bootstrap()) { - if (m_db.need_bootstrap()) { - // No block has been created yet - bootstrap(); - } + // No block has been created yet + bootstrap(); } +} - void Application::insert_cache (std::list &cache) +void Application::insert_cache(std::list &cache) +{ + Common::Dbg::info("Inserting block height {} to {} into database...", + cache.front().height(), cache.back().height()); + + // Insert everything + m_db.start_transaction(); + for (auto &block : cache) { - Common::Dbg::info ("Inserting block height {} to {} into database...", - cache.front().height(), cache.back().height()); + m_db.block_insert(block); + } + m_db.commit(); - // Insert everything - m_db.start_transaction(); - for (auto &block : cache) { - m_db.block_insert (block); - } - m_db.commit(); + cache.clear(); +} - cache.clear(); - } +int Application::main(void) +{ + // Bootstrap + check_bootstrap(); - int Application::main (void) + while (true) { - // Bootstrap - check_bootstrap(); + // Get latest block + Block lastRemoteBlock = m_client->get_last_block(); + Block lastLocalBlock = m_db.block_get(m_db.last_block_id()); - while (true) + if (lastRemoteBlock.height() == lastLocalBlock.height()) { - // Get latest block - Block lastRemoteBlock = m_client->get_last_block(); - Block lastLocalBlock = m_db.block_get (m_db.last_block_id()); - - if (lastRemoteBlock.height() == lastLocalBlock.height()) { - break; - } + break; + } - Common::Dbg::info ("Current height : {} | Remote height : {}", lastLocalBlock.height(), lastRemoteBlock.height()); + Common::Dbg::info("Current height : {} | Remote height : {}", lastLocalBlock.height(), lastRemoteBlock.height()); - // Start downloading blocks - m_downloader->start_download (lastLocalBlock.height() + 1, lastRemoteBlock.height()); + // Start downloading blocks + m_downloader->start_download(lastLocalBlock.height() + 1, lastRemoteBlock.height()); - // Block cache for bulk insertion - std::list cache; + // Block cache for bulk insertion + std::list cache; - while (lastLocalBlock.height() < lastRemoteBlock.height()) - { - // Get the next block height - Block::Height newBlockHeight = lastLocalBlock.height() + 1; - - // Get the next block from cache - Block newBlock = m_downloader->get_block (newBlockHeight); + while (lastLocalBlock.height() < lastRemoteBlock.height()) + { + // Get the next block height + Block::Height newBlockHeight = lastLocalBlock.height() + 1; - // Insert it in cache - cache.emplace_back(newBlock); + // Get the next block from cache + Block newBlock = m_downloader->get_block(newBlockHeight); - if (cache.size() > m_cacheSize) { - insert_cache (cache); - } + // Insert it in cache + cache.emplace_back(newBlock); - // Update to the next block - lastLocalBlock = newBlock; + if (cache.size() > m_cacheSize) + { + insert_cache(cache); } - // Insert remaining items - insert_cache (cache); + // Update to the next block + lastLocalBlock = newBlock; } - m_downloader->stop(); - m_downloader->join(); - - return 0; + // Insert remaining items + insert_cache(cache); } -} \ No newline at end of file + + m_downloader->stop(); + m_downloader->join(); + + return 0; +} +} // namespace ICONation::Aegis \ No newline at end of file diff --git a/src/aegis/application.h b/src/aegis/application.h index be5ef5f..e9e6e67 100644 --- a/src/aegis/application.h +++ b/src/aegis/application.h @@ -5,42 +5,45 @@ #include "sdk/sdk.h" #include "blockdownloader.h" +#define APP_VERSION "1.2" + namespace ICONation::Aegis { - class Application : public Common::Application::Application - { - // Allocators - public: - Application (int argc, char **argv); - ~Application (void); - - // States - private: - void check_bootstrap (void); - void bootstrap (void); - - // Main loop - private: - int main (void) override; - - // Block Downloader - private: - std::unique_ptr m_downloader; - - // Usage - public: - void print_usage (void) override; - - // SDK Client - private: - std::unique_ptr m_client; - std::string m_endpoint; - - // Database - public: - void insert_cache (std::list &cache); - private: - int m_cacheSize; - Db::Db m_db; - }; -} \ No newline at end of file +class Application : public Common::Application::Application +{ + // Allocators +public: + Application(int argc, char **argv); + ~Application(void); + + // States +private: + void check_bootstrap(void); + void bootstrap(void); + + // Main loop +private: + int main(void) override; + + // Block Downloader +private: + std::unique_ptr m_downloader; + + // Usage +public: + void print_usage(void) override; + + // SDK Client +private: + std::unique_ptr m_client; + std::string m_endpoint; + + // Database +public: + void insert_cache(std::list &cache); + +private: + int m_cacheSize; + Db::Db m_db; +}; +} // namespace ICONation::Aegis \ No newline at end of file diff --git a/src/aegis/blockdownloader.cpp b/src/aegis/blockdownloader.cpp index 48d14ac..0eae3fa 100644 --- a/src/aegis/blockdownloader.cpp +++ b/src/aegis/blockdownloader.cpp @@ -9,103 +9,109 @@ using namespace ICONation::SDK::Blockchain; namespace ICONation::BlockDownloader { - Client::Client (int threads, const std::string &endpoint) - : m_endpoint (endpoint), - m_threads (threads) - { - } +Client::Client(int threads, const std::string &endpoint) + : m_endpoint(endpoint), + m_threads(threads) +{ +} - Block Client::get_block (const Block::Height &height) - { - Block result; - bool wait = true; +Block Client::get_block(const Block::Height &height) +{ + Block result; + bool wait = true; - while (wait) + while (wait) + { + // Protect m_cache + m_mutex.lock(); + if (m_cache.find(height) != m_cache.end()) { - // Protect m_cache - m_mutex.lock(); - if (m_cache.find (height) != m_cache.end()) { - result = m_cache[height]; - wait = false; - } - m_mutex.unlock(); - - // Wait a little bit for the cache - std::this_thread::sleep_for (std::chrono::milliseconds (1)); + result = m_cache[height]; + wait = false; } + m_mutex.unlock(); - return result; + // Wait a little bit for the cache + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - void Client::start_download (Block::Height current, Block::Height target) - { - m_thread = std::thread (&Client::download, this, current, target); - } + return result; +} - void Client::join (void) - { - return m_thread.join(); - } +void Client::start_download(Block::Height current, Block::Height target) +{ + m_thread = std::thread(&Client::download, this, current, target); +} + +void Client::join(void) +{ + return m_thread.join(); +} + +void Client::download(Block::Height current, Block::Height target) +{ + const std::string endpoint = m_endpoint; + m_running = true; + Block::Height lastBlockDownloaded = current; - void Client::download (Block::Height current, Block::Height target) + // Download the whole gap + while (m_running && lastBlockDownloaded <= target) { - const std::string endpoint = m_endpoint; - m_running = true; - Block::Height lastBlockDownloaded = current; + current = lastBlockDownloaded; + progschj::ThreadPool blockPool(m_threads); + std::vector> blocks; - // Download the whole gap - while (m_running && lastBlockDownloaded <= target) + // Launch m_threads asynchronous requests + for (int i = 0; (i < m_threads) && (current <= target); i++) { - current = lastBlockDownloaded; - progschj::ThreadPool blockPool (m_threads); - std::vector> blocks; - - // Launch m_threads asynchronous requests - for (int i = 0; (i < m_threads) && (current <= target); i++) - { - blocks.emplace_back ( - blockPool.enqueue([endpoint, current, target] { - std::unique_ptr client = std::make_unique (endpoint); - while (true) { - try { - return client->get_block_by_height (current); - } catch (std::exception &e) { - Common::Dbg::error ("Application exception :"); - Common::Dbg::error (" - Type : {}", typeid(e).name()); - Common::Dbg::error (" - Reason : {}", e.what()); - Common::Dbg::warn ("Retrying to download block {} ...", current); - } + blocks.emplace_back( + blockPool.enqueue([endpoint, current, target] { + std::unique_ptr client = std::make_unique(endpoint); + while (true) + { + try + { + return client->get_block_by_height(current); + } + catch (std::exception &e) + { + Common::Dbg::error("Application exception :"); + Common::Dbg::error(" - Type : {}", typeid(e).name()); + Common::Dbg::error(" - Reason : {}", e.what()); + Common::Dbg::warn("Retrying to download block {} ...", current); } - }) - ); + } + })); - current += 1; - // Don't spam too much, limit 200 requests / second should be enough - std::this_thread::sleep_for (std::chrono::milliseconds (5)); - } + current += 1; + // Don't spam too much, limit 200 requests / second should be enough + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } - // Put the results in cache - for (auto &&result : blocks) + // Put the results in cache + for (auto &&result : blocks) + { + try { - try { - Block block = result.get(); + Block block = result.get(); - // Protect m_cache - m_mutex.lock(); - m_cache [block.height()] = block; - m_mutex.unlock(); - lastBlockDownloaded = block.height(); - - } catch (std::exception &e) { - Common::Dbg::error ("Application exception :"); - Common::Dbg::error (" - Type : {}", typeid(e).name()); - Common::Dbg::error (" - Reason : {}", e.what()); - Common::Dbg::warn ("Retrying to insert block in cache {} ...", lastBlockDownloaded); - break; - } + // Protect m_cache + m_mutex.lock(); + m_cache[block.height()] = block; + m_mutex.unlock(); + lastBlockDownloaded = block.height(); + } + catch (std::exception &e) + { + Common::Dbg::error("Application exception :"); + Common::Dbg::error(" - Type : {}", typeid(e).name()); + Common::Dbg::error(" - Reason : {}", e.what()); + Common::Dbg::warn("Retrying to insert block in cache {} ...", lastBlockDownloaded); + break; } } - - stop(); } -} \ No newline at end of file + + stop(); +} +} // namespace ICONation::BlockDownloader \ No newline at end of file diff --git a/src/aegis/blockdownloader.h b/src/aegis/blockdownloader.h index c4ad6f5..d0e3832 100644 --- a/src/aegis/blockdownloader.h +++ b/src/aegis/blockdownloader.h @@ -7,43 +7,45 @@ namespace ICONation::BlockDownloader { - class Client - { - // Allocators - public: - Client (int threads, const std::string &endpoint); - ~Client (void) = default; - - // States - public: - void start_download (SDK::Blockchain::Block::Height current, SDK::Blockchain::Block::Height target); - bool running (void) { return m_running; } - void stop (void) { m_running = false; } - private: - void download (SDK::Blockchain::Block::Height current, SDK::Blockchain::Block::Height target); - bool m_running = false; - - // Endpoint - private: - std::string m_endpoint; - - // Threads - private: - int m_threads; - - // Cache - public: - SDK::Blockchain::Block get_block (const SDK::Blockchain::Block::Height &height); - - // Threading - private: - std::thread m_thread; - std::mutex m_mutex; - public: - void join (void); - - // Blocks cache - private: - std::map m_cache; - }; -} \ No newline at end of file +class Client +{ + // Allocators +public: + Client(int threads, const std::string &endpoint); + ~Client(void) = default; + + // States +public: + void start_download(SDK::Blockchain::Block::Height current, SDK::Blockchain::Block::Height target); + bool running(void) { return m_running; } + void stop(void) { m_running = false; } + +private: + void download(SDK::Blockchain::Block::Height current, SDK::Blockchain::Block::Height target); + bool m_running = false; + + // Endpoint +private: + std::string m_endpoint; + + // Threads +private: + int m_threads; + + // Cache +public: + SDK::Blockchain::Block get_block(const SDK::Blockchain::Block::Height &height); + + // Threading +private: + std::thread m_thread; + std::mutex m_mutex; + +public: + void join(void); + + // Blocks cache +private: + std::map m_cache; +}; +} // namespace ICONation::BlockDownloader \ No newline at end of file diff --git a/src/db/db.cpp b/src/db/db.cpp index 5899820..7f95621 100644 --- a/src/db/db.cpp +++ b/src/db/db.cpp @@ -8,373 +8,311 @@ using namespace mysqlx; namespace ICONation::Aegis::Db { - Db::Db (const std::string &host, const int port, const std::string &user, const std::string &password, const std::string &schema) - { - m_sql = std::make_unique (host, port, user, password, schema); - } +Db::Db(const std::string &host, const int port, const std::string &user, const std::string &password, const std::string &schema) +{ + m_sql = std::make_unique(host, port, user, password, schema); +} - static void reset_table (std::unique_ptr &sql, const std::string &table) - { - } +static void reset_table(std::unique_ptr &sql, const std::string &table) +{ +} - void Db::disable_foreign_checks (void) - { - m_sql->session()->sql ("SET FOREIGN_KEY_CHECKS=0;").execute(); - } +void Db::disable_foreign_checks(void) +{ + m_sql->session()->sql("SET FOREIGN_KEY_CHECKS=0;").execute(); +} - void Db::enable_foreign_checks (void) - { - m_sql->session()->sql ("SET FOREIGN_KEY_CHECKS=1;").execute(); - } +void Db::enable_foreign_checks(void) +{ + m_sql->session()->sql("SET FOREIGN_KEY_CHECKS=1;").execute(); +} - void Db::clear (const std::string &schema) - { - disable_foreign_checks(); - m_sql->session()->sql (fmt::format ("USE {};", schema)).execute(); - - // Clear all these tables - std::vector tables = { - "account", - "balance", - "block", - "icx", - "internal_transaction", - "irc2", - "transaction", - "transaction_message" - }; - - std::for_each (tables.begin(), tables.end(), [this] (const std::string &table) { - m_sql->schema()->getTable(table).remove().execute(); - m_sql->session()->sql (fmt::format ("ALTER TABLE {} AUTO_INCREMENT = 1;", table)).execute(); - }); - - enable_foreign_checks(); - } +void Db::clear(const std::string &schema) +{ + disable_foreign_checks(); + m_sql->session()->sql(fmt::format("USE {};", schema)).execute(); + + // Clear all these tables + std::vector tables = { + "account", + "balance", + "block", + "icx", + "internal_transaction", + "irc2", + "transaction", + "transaction_message"}; + + std::for_each(tables.begin(), tables.end(), [this](const std::string &table) { + m_sql->schema()->getTable(table).remove().execute(); + m_sql->session()->sql(fmt::format("ALTER TABLE {} AUTO_INCREMENT = 1;", table)).execute(); + }); + + enable_foreign_checks(); +} + +void Db::start_transaction(void) +{ + m_sql->session()->startTransaction(); +} - void Db::start_transaction (void) - { - m_sql->session()->startTransaction(); - } +void Db::commit(void) +{ + m_sql->session()->commit(); +} - void Db::commit (void) - { - m_sql->session()->commit(); - } +void Db::rollback(void) +{ + m_sql->session()->rollback(); +} - void Db::rollback (void) - { - m_sql->session()->rollback(); - } +bool Db::need_bootstrap(void) +{ + return m_sql->schema()->getTable("icx").select("id").execute().count() == 0; +} - bool Db::need_bootstrap (void) - { - return m_sql->schema()->getTable("icx").select("id").execute().count() == 0; - } +void Db::bootstrap(const ICX &icx) +{ + disable_foreign_checks(); - void Db::bootstrap (const ICX &icx) - { - disable_foreign_checks(); + // Insert native ICX token + m_sql->schema()->getTable("icx").insert("name", "symbol", "total_supply", "decimals").values(icx.name(), icx.symbol(), icx.totalSupply().get_str(), icx.decimals()).execute(); - // Insert native ICX token - m_sql->schema()->getTable ("icx") - .insert ("name", "symbol", "total_supply", "decimals") - .values (icx.name(), icx.symbol(), icx.totalSupply().get_str(), icx.decimals()) - .execute(); + enable_foreign_checks(); +} - enable_foreign_checks(); - } +// === Account ================================================================================= +Db::Id Db::account_insert(const Account &account) +{ + return m_sql->schema()->getTable("account").insert("hash").values(account.address().repr()).execute().getAutoIncrementValue(); +} - // === Account ================================================================================= - Db::Id Db::account_insert (const Account &account) - { - return m_sql->schema()->getTable ("account") - .insert ("hash") - .values (account.address().repr()) - .execute() - .getAutoIncrementValue(); - } +Db::Id Db::account_id(const Address &address) +{ + Row row = m_sql->schema()->getTable("account").select("id").where("hash = :hash").bind("hash", address.repr()).execute().fetchOne(); - Db::Id Db::account_id (const Address &address) + if (row.isNull()) { - Row row = m_sql->schema()->getTable ("account") - .select ("id") - .where ("hash = :hash") - .bind ("hash", address.repr()) - .execute().fetchOne(); - - if (row.isNull()) { - // Create a new account - return account_insert (Account (address)); - } - - return row[0].get(); + // Create a new account + return account_insert(Account(address)); } - // === Token ================================================================================= - Db::Id Db::token_irc2_insert (const IRC2 &irc2) + return row[0].get(); +} + +// === Token ================================================================================= +Db::Id Db::token_irc2_insert(const IRC2 &irc2) +{ + return m_sql->schema()->getTable("irc2").insert("score", "name", "symbol", "total_supply", "decimals").values(irc2.score().repr(), irc2.name(), irc2.symbol(), irc2.totalSupply().get_str(), irc2.decimals()).execute().getAutoIncrementValue(); +} + +Db::Id Db::token_icx_insert(const ICX &icx) +{ + return m_sql->schema()->getTable("icx").insert("name", "symbol", "total_supply", "decimals").values(icx.name(), icx.symbol(), icx.totalSupply().get_str(), icx.decimals()).execute().getAutoIncrementValue(); +} + +Db::Id Db::token_irc2_id(const IRC2 &irc2) +{ + Row row = m_sql->schema()->getTable("irc2").select("id").where("score = :score").bind("score", irc2.score().repr()).execute().fetchOne(); + + if (row.isNull()) { - return m_sql->schema()->getTable ("irc2") - .insert ("score", "name", "symbol", "total_supply", "decimals") - .values ( - irc2.score().repr(), - irc2.name(), - irc2.symbol(), - irc2.totalSupply().get_str(), - irc2.decimals()) - .execute() - .getAutoIncrementValue(); + // Create a new token + return token_irc2_insert(irc2); } - Db::Id Db::token_icx_insert (const ICX &icx) + return row[0].get(); +} + +Db::Id Db::token_icx_id(const ICX &icx) +{ + Row row = m_sql->schema()->getTable("icx").select("id").where("name = :name").bind("name", icx.name()).execute().fetchOne(); + + if (row.isNull()) { - return m_sql->schema()->getTable ("icx") - .insert ("name", "symbol", "total_supply", "decimals") - .values ( - icx.name(), - icx.symbol(), - icx.totalSupply().get_str(), - icx.decimals()) - .execute() - .getAutoIncrementValue(); + // Create a new token + return token_icx_insert(icx); } - Db::Id Db::token_irc2_id (const IRC2 &irc2) + return row[0].get(); +} + +Db::Id Db::token_insert(const Token &token) +{ + switch (token.type()) { - Row row = m_sql->schema()->getTable ("irc2") - .select ("id") - .where ("score = :score") - .bind ("score", irc2.score().repr()) - .execute().fetchOne(); - - if (row.isNull()) { - // Create a new token - return token_irc2_insert (irc2); - } - - return row[0].get(); + case Token::Type::ICX: + { + const ICX &icx = dynamic_cast(token); + return token_icx_insert(icx); } + break; - Db::Id Db::token_icx_id (const ICX &icx) + case Token::Type::IRC2: { - Row row = m_sql->schema()->getTable ("icx") - .select ("id") - .where ("name = :name") - .bind ("name", icx.name()) - .execute().fetchOne(); - - if (row.isNull()) { - // Create a new token - return token_icx_insert (icx); - } - - return row[0].get(); + const IRC2 &irc2 = dynamic_cast(token); + return token_irc2_insert(irc2); } + break; - Db::Id Db::token_insert (const Token &token) - { - switch (token.type()) - { - case Token::Type::ICX: { - const ICX &icx = dynamic_cast(token); - return token_icx_insert (icx); - } break; - - case Token::Type::IRC2: { - const IRC2 &irc2 = dynamic_cast(token); - return token_irc2_insert (irc2); - } break; - - default: - throw Exception::TokenDoesntExist (token.name()); - } + default: + throw Exception::TokenDoesntExist(token.name()); } +} - Db::Id Db::token_id (const Token &token) +Db::Id Db::token_id(const Token &token) +{ + switch (token.type()) { - switch (token.type()) - { - case Token::Type::ICX: { - const ICX &icx = dynamic_cast(token); - return token_icx_id (icx); - } break; - - case Token::Type::IRC2: { - const IRC2 &irc2 = dynamic_cast(token); - return token_irc2_id (irc2); - } break; - - default: - throw Exception::TokenDoesntExist (token.name()); - } + case Token::Type::ICX: + { + const ICX &icx = dynamic_cast(token); + return token_icx_id(icx); } + break; - // === Transaction ================================================================================= - Db::Id Db::transaction_id (const Transaction &transaction, const Id &parentBlock) + case Token::Type::IRC2: { - Row row = m_sql->schema()->getTable ("transaction") - .select ("id") - .where ("hash = :hash") - .bind ("hash", transaction.hash().repr()) - .execute().fetchOne(); - - if (row.isNull()) { - // Create a new account - return transaction_insert (transaction, parentBlock); - } - - return row[0].get(); + const IRC2 &irc2 = dynamic_cast(token); + return token_irc2_id(irc2); } + break; - Db::Id Db::transaction_insert (const Transaction &transaction, const Id &parentBlock) - { - // Make sure the destination account has been created - account_id (transaction.to()); - - Id transactionId = m_sql->schema()->getTable ("transaction") - .insert ( - "block", "from", "to", "hash", "amount", "step_limit", "step_used", "step_price") - .values ( - parentBlock, - transaction.from().repr(), - transaction.to().repr(), - transaction.hash().value(), - transaction.amount().get_str(), - transaction.stepLimit().get_ui(), - transaction.stepUsed().get_ui(), - transaction.stepPrice().get_ui()) - .execute() - .getAutoIncrementValue(); - - // Insert internal transactions inside the transaction - for (const auto &internalTx : transaction.internalTransactions()) { - internal_transaction_insert (internalTx, transactionId); - } - - // Insert transaction message - if (transaction.message().size() != 0) { - transaction_message_insert (transaction.message(), transactionId); - } - - return transactionId; + default: + throw Exception::TokenDoesntExist(token.name()); } +} - // === Internal Transaction ================================================================================= - void Db::transaction_message_insert (const std::string &message, const Id &parentTransaction) +// === Transaction ================================================================================= +Db::Id Db::transaction_id(const Transaction &transaction, const Id &parentBlock) +{ + Row row = m_sql->schema()->getTable("transaction").select("id").where("hash = :hash").bind("hash", transaction.hash().repr()).execute().fetchOne(); + + if (row.isNull()) { - m_sql->schema()->getTable ("transaction_message") - .insert ("transaction", "data") - .values (parentTransaction, message) - .execute(); + // Create a new account + return transaction_insert(transaction, parentBlock); } - - // === Internal Transaction ================================================================================= - Db::Id Db::internal_transaction_insert (const InternalTransaction &internalTransaction, const Id &parentTransaction) + + return row[0].get(); +} + +Db::Id Db::transaction_insert(const Transaction &transaction, const Id &parentBlock) +{ + // Make sure the destination account has been created + account_id(transaction.to()); + + Id transactionId = m_sql->schema()->getTable("transaction").insert("block", "from", "to", "hash", "amount", "step_limit", "step_used", "step_price").values(parentBlock, transaction.from().repr(), transaction.to().repr(), transaction.hash().value(), transaction.amount().get_str(), transaction.stepLimit().get_ui(), transaction.stepUsed().get_ui(), transaction.stepPrice().get_ui()).execute().getAutoIncrementValue(); + + // Insert internal transactions inside the transaction + for (const auto &internalTx : transaction.internalTransactions()) { - // Make sure the destination account has been created - account_id (internalTransaction.to()); - - // Get the token ID - Id tokenId = token_id (internalTransaction.token()); - - Id transactionId = m_sql->schema()->getTable ("internal_transaction") - .insert ( - "transaction", "from", "to", "token", "token_type", "amount") - .values ( - parentTransaction, - internalTransaction.from().repr(), - internalTransaction.to().repr(), - tokenId, - (int) internalTransaction.token().type(), - internalTransaction.amount().get_str()) - .execute() - .getAutoIncrementValue(); - - return transactionId; + internal_transaction_insert(internalTx, transactionId); } - // === Block ================================================================================= - Db::Id Db::block_id (const Block &block) + // Insert transaction message + if (transaction.message().size() != 0) { - Row row = m_sql->schema()->getTable ("block") - .select ("id") - .where ("hash = :hash") - .bind ("hash", block.hash().repr()) - .execute().fetchOne(); - - if (row.isNull()) { - // Create a new block - block_insert (block); - } - - return row[0].get(); + transaction_message_insert(transaction.message(), transactionId); } - Block Db::block_get (const Db::Id &blockId) + return transactionId; +} + +// === Internal Transaction ================================================================================= +void Db::transaction_message_insert(const std::string &message, const Id &parentTransaction) +{ + m_sql->schema()->getTable("transaction_message").insert("transaction", "data").values(parentTransaction, message).execute(); +} + +// === Internal Transaction ================================================================================= +Db::Id Db::internal_transaction_insert(const InternalTransaction &internalTransaction, const Id &parentTransaction) +{ + // Make sure the destination account has been created + account_id(internalTransaction.to()); + + // Get the token ID + Id tokenId = token_id(internalTransaction.token()); + + Id transactionId = m_sql->schema()->getTable("internal_transaction").insert("transaction", "from", "to", "token", "token_type", "amount").values(parentTransaction, internalTransaction.from().repr(), internalTransaction.to().repr(), tokenId, (int)internalTransaction.token().type(), internalTransaction.amount().get_str()).execute().getAutoIncrementValue(); + + return transactionId; +} + +// === Block ================================================================================= +Db::Id Db::block_id(const Block &block) +{ + Row row = m_sql->schema()->getTable("block").select("id").where("hash = :hash").bind("hash", block.hash().repr()).execute().fetchOne(); + + if (row.isNull()) { - Row row = m_sql->schema()->getTable ("block") - .select ("height", "hash", "previous_block", "timestamp") - .where ("id = :id") - .bind ("id", blockId) - .execute().fetchOne(); - - if (row.isNull()) { - throw Exception::BlockDoesntExist (blockId); - } - - Block::Height height = row[0].get(); - Block::Hash hash (row[1].get()); - Block::Hash previous (row[2].get()); - Block::Timestamp timestamp = row[3].get(); - - return Block (height, hash, previous, timestamp); + // Create a new block + block_insert(block); } - Db::Id Db::block_insert_query (const Block &block) + return row[0].get(); +} + +Block Db::block_get(const Db::Id &blockId) +{ + Row row = m_sql->schema()->getTable("block").select("height", "hash", "previous_block", "timestamp").where("id = :id").bind("id", blockId).execute().fetchOne(); + + if (row.isNull()) { - return m_sql->schema()->getTable ("block") - .insert ("previous_block", "hash", "timestamp", "height") - .values (block.hashPreviousBlock().value(), block.hash().value(), block.timestamp(), block.height()) - .execute() - .getAutoIncrementValue(); + throw Exception::BlockDoesntExist(blockId); } - Db::Id Db::block_insert (const Block &block) - { - Result result; + Block::Height height = row[0].get(); + Block::Hash hash(row[1].get()); + Block::Hash previous(row[2].get()); + Block::Timestamp timestamp = row[3].get(); - // Insert block - Id blockId = block_insert_query (block); + return Block(height, hash, previous, timestamp); +} - // Insert transaction inside the block - for (const auto &tx : block.transactions()) { - transaction_insert (tx, blockId); - } +Db::Id Db::block_insert_query(const Block &block) +{ + return m_sql->schema()->getTable("block").insert("previous_block", "hash", "timestamp", "height").values(block.hashPreviousBlock().value(), block.hash().value(), block.timestamp(), block.height()).execute().getAutoIncrementValue(); +} - return blockId; - } +Db::Id Db::block_insert(const Block &block) +{ + Result result; + + // Insert block + Id blockId = block_insert_query(block); - // === Genesis ================================================================================= - Db::Id Db::genesis_insert (const GenesisBlock &genesis) + // Insert transaction inside the block + for (const auto &tx : block.transactions()) { - // Genesis block doesn't respect the previous block hash definition - // Disable the foreign key checks temporarly before inserting - disable_foreign_checks(); - Id blockId = block_insert_query (genesis); - enable_foreign_checks(); - - // Insert transaction inside the block - for (const auto &account : genesis.accounts()) { - account_insert (account); - } - - return blockId; + transaction_insert(tx, blockId); } - // === Meta ================================================================================= - Db::Id Db::last_block_id (void) + return blockId; +} + +// === Genesis ================================================================================= +Db::Id Db::genesis_insert(const GenesisBlock &genesis) +{ + // Genesis block doesn't respect the previous block hash definition + // Disable the foreign key checks temporarly before inserting + disable_foreign_checks(); + Id blockId = block_insert_query(genesis); + enable_foreign_checks(); + + // Insert transaction inside the block + for (const auto &account : genesis.accounts()) { - Row row = m_sql->schema()->getTable ("block").select("max(id)").execute().fetchOne(); - return row[0].get(); + account_insert(account); } -} \ No newline at end of file + + return blockId; +} + +// === Meta ================================================================================= +Db::Id Db::last_block_id(void) +{ + Row row = m_sql->schema()->getTable("block").select("max(id)").execute().fetchOne(); + return row[0].get(); +} +} // namespace ICONation::Aegis::Db \ No newline at end of file diff --git a/src/db/db.h b/src/db/db.h index b724be0..538d29b 100644 --- a/src/db/db.h +++ b/src/db/db.h @@ -6,78 +6,81 @@ namespace ICONation::Aegis::Db { - class Db - { - // Db specific types - public: - typedef uint64_t Id; - - public: - Db (const std::string &host=DEFAULT_HOST, const int port=DEFAULT_PORT, - const std::string &user=DEFAULT_USER, const std::string &password=DEFAULT_PASSWORD, - const std::string &schema=DEFAULT_SCHEMA); - ~Db (void) = default; - - // States - public: - bool need_bootstrap (void); - void bootstrap (const SDK::Blockchain::ICX &icx); - void clear (const std::string &schema=DEFAULT_SCHEMA); - void start_transaction (void); - void commit (void); - void rollback (void); - - // Account - public: - Id account_insert (const SDK::Blockchain::Account &account); - Id account_id (const SDK::Blockchain::Address &address); - - // Transaction - public: - Id transaction_id (const SDK::Blockchain::Transaction &transaction, const Id &parentBlock); - Id transaction_insert (const SDK::Blockchain::Transaction &transaction, const Id &parentBlock); - - // Internal Transaction - public: - Id internal_transaction_insert (const SDK::Blockchain::InternalTransaction &internalTransaction, const Id &parentTransaction); - - // Transaction message - public: - void transaction_message_insert (const std::string &message, const Id &parentTransaction); - - // Block - public: - // Normal block - Id block_id (const SDK::Blockchain::Block &block); - SDK::Blockchain::Block block_get (const Db::Id &blockId); - Id block_insert (const SDK::Blockchain::Block &block); - // Genesis block - Id genesis_insert (const SDK::Blockchain::GenesisBlock &block); - private: - Id block_insert_query (const SDK::Blockchain::Block &block); - - // Token - public: - Id token_insert (const SDK::Blockchain::Token &token); - private: - Id token_irc2_insert (const SDK::Blockchain::IRC2 &irc2); - Id token_icx_insert (const SDK::Blockchain::ICX &icx); - private: - Id token_irc2_id (const SDK::Blockchain::IRC2 &irc2); - Id token_icx_id (const SDK::Blockchain::ICX &icx); - Id token_id (const SDK::Blockchain::Token &token); - - // State - public: - void enable_foreign_checks (void); - void disable_foreign_checks (void); - - // Meta - public: - Id last_block_id (void); - - // Database - private: - std::unique_ptr m_sql; - }; -} \ No newline at end of file +class Db +{ + // Db specific types +public: + typedef uint64_t Id; + +public: + Db(const std::string &host = DEFAULT_HOST, const int port = DEFAULT_PORT, + const std::string &user = DEFAULT_USER, const std::string &password = DEFAULT_PASSWORD, + const std::string &schema = DEFAULT_SCHEMA); + ~Db(void) = default; + + // States +public: + bool need_bootstrap(void); + void bootstrap(const SDK::Blockchain::ICX &icx); + void clear(const std::string &schema = DEFAULT_SCHEMA); + void start_transaction(void); + void commit(void); + void rollback(void); + + // Account +public: + Id account_insert(const SDK::Blockchain::Account &account); + Id account_id(const SDK::Blockchain::Address &address); + + // Transaction +public: + Id transaction_id(const SDK::Blockchain::Transaction &transaction, const Id &parentBlock); + Id transaction_insert(const SDK::Blockchain::Transaction &transaction, const Id &parentBlock); + + // Internal Transaction +public: + Id internal_transaction_insert(const SDK::Blockchain::InternalTransaction &internalTransaction, const Id &parentTransaction); + + // Transaction message +public: + void transaction_message_insert(const std::string &message, const Id &parentTransaction); + + // Block +public: + // Normal block + Id block_id(const SDK::Blockchain::Block &block); + SDK::Blockchain::Block block_get(const Db::Id &blockId); + Id block_insert(const SDK::Blockchain::Block &block); + // Genesis block + Id genesis_insert(const SDK::Blockchain::GenesisBlock &block); + +private: + Id block_insert_query(const SDK::Blockchain::Block &block); + + // Token +public: + Id token_insert(const SDK::Blockchain::Token &token); + +private: + Id token_irc2_insert(const SDK::Blockchain::IRC2 &irc2); + Id token_icx_insert(const SDK::Blockchain::ICX &icx); + +private: + Id token_irc2_id(const SDK::Blockchain::IRC2 &irc2); + Id token_icx_id(const SDK::Blockchain::ICX &icx); + Id token_id(const SDK::Blockchain::Token &token); + + // State +public: + void enable_foreign_checks(void); + void disable_foreign_checks(void); + + // Meta +public: + Id last_block_id(void); + + // Database +private: + std::unique_ptr m_sql; +}; +} // namespace ICONation::Aegis::Db \ No newline at end of file diff --git a/src/db/exception.h b/src/db/exception.h index c9c28ac..7d05c96 100644 --- a/src/db/exception.h +++ b/src/db/exception.h @@ -9,21 +9,21 @@ namespace ICONation::Aegis::Db::Exception { - struct BlockDoesntExist : public std::runtime_error - { - BlockDoesntExist (const SDK::Blockchain::Block::Hash &hash) throw() - : std::runtime_error (fmt::format ("Block '{}' doesn't exist", hash)) {} +struct BlockDoesntExist : public std::runtime_error +{ + BlockDoesntExist(const SDK::Blockchain::Block::Hash &hash) throw() + : std::runtime_error(fmt::format("Block '{}' doesn't exist", hash)) {} - BlockDoesntExist (const Db::Db::Id &id) throw() - : std::runtime_error (fmt::format ("Block ID '{}' doesn't exist", id)) {} - }; + BlockDoesntExist(const Db::Db::Id &id) throw() + : std::runtime_error(fmt::format("Block ID '{}' doesn't exist", id)) {} +}; - struct TokenDoesntExist : public std::runtime_error - { - TokenDoesntExist (const SDK::Blockchain::Token::Name &name) throw() - : std::runtime_error (fmt::format ("Token '{}' doesn't exist", name)) {} +struct TokenDoesntExist : public std::runtime_error +{ + TokenDoesntExist(const SDK::Blockchain::Token::Name &name) throw() + : std::runtime_error(fmt::format("Token '{}' doesn't exist", name)) {} - TokenDoesntExist (const Db::Db::Id &id) throw() - : std::runtime_error (fmt::format ("Token ID '{}' doesn't exist", id)) {} - }; -} + TokenDoesntExist(const Db::Db::Id &id) throw() + : std::runtime_error(fmt::format("Token ID '{}' doesn't exist", id)) {} +}; +} // namespace ICONation::Aegis::Db::Exception diff --git a/src/db/sql.cpp b/src/db/sql.cpp index 75cde8e..b9e6a8b 100644 --- a/src/db/sql.cpp +++ b/src/db/sql.cpp @@ -2,14 +2,14 @@ namespace ICONation::Aegis::Db { - SQL::SQL ( - const std::string &host, - const unsigned port, - const mysqlx::string &user, - const std::string &password, - const std::string &schema - ) { - m_session = std::make_unique (host, port, user, password); - m_schema = std::make_unique (m_session->getSchema (schema)); - } -} \ No newline at end of file +SQL::SQL( + const std::string &host, + const unsigned port, + const mysqlx::string &user, + const std::string &password, + const std::string &schema) +{ + m_session = std::make_unique(host, port, user, password); + m_schema = std::make_unique(m_session->getSchema(schema)); +} +} // namespace ICONation::Aegis::Db \ No newline at end of file diff --git a/src/db/sql.h b/src/db/sql.h index cae8477..03168f7 100644 --- a/src/db/sql.h +++ b/src/db/sql.h @@ -5,35 +5,36 @@ namespace ICONation::Aegis::Db { - const int DEFAULT_PORT = 33060; - const std::string DEFAULT_HOST = "localhost"; - const std::string DEFAULT_USER = "icon"; - const std::string DEFAULT_PASSWORD = "icon"; - const std::string DEFAULT_SCHEMA = "iconation"; - - class SQL - { - public: - SQL ( - const std::string &host, - const unsigned port, - const mysqlx::string &user, - const std::string &password, - const std::string &schema - ); - - ~SQL() = default; - - // MySQL Session - public: - std::unique_ptr &session (void) { return m_session; } - private: - std::unique_ptr m_session; - - // MySQL Schema - public: - std::unique_ptr &schema (void) { return m_schema; } - private: - std::unique_ptr m_schema; - }; -} \ No newline at end of file +const int DEFAULT_PORT = 33060; +const std::string DEFAULT_HOST = "localhost"; +const std::string DEFAULT_USER = "icon"; +const std::string DEFAULT_PASSWORD = "icon"; +const std::string DEFAULT_SCHEMA = "iconation"; + +class SQL +{ +public: + SQL( + const std::string &host, + const unsigned port, + const mysqlx::string &user, + const std::string &password, + const std::string &schema); + + ~SQL() = default; + + // MySQL Session +public: + std::unique_ptr &session(void) { return m_session; } + +private: + std::unique_ptr m_session; + + // MySQL Schema +public: + std::unique_ptr &schema(void) { return m_schema; } + +private: + std::unique_ptr m_schema; +}; +} // namespace ICONation::Aegis::Db \ No newline at end of file diff --git a/src/threadpool/threadpool.h b/src/threadpool/threadpool.h index b23e34b..0655fb8 100644 --- a/src/threadpool/threadpool.h +++ b/src/threadpool/threadpool.h @@ -38,15 +38,15 @@ #include #include +namespace progschj +{ -namespace progschj { - -class ThreadPool { +class ThreadPool +{ public: - explicit ThreadPool(std::size_t threads - = (std::max)(2u, std::thread::hardware_concurrency())); - template - auto enqueue(F&& f, Args&&... args) + explicit ThreadPool(std::size_t threads = (std::max)(2u, std::thread::hardware_concurrency())); + template + auto enqueue(F &&f, Args &&... args) -> std::future::type>; void wait_until_empty(); void wait_until_nothing_in_flight(); @@ -55,14 +55,14 @@ class ThreadPool { ~ThreadPool(); private: - void emplace_back_worker (std::size_t worker_number); + void emplace_back_worker(std::size_t worker_number); // need to keep track of threads so we can join them - std::vector< std::thread > workers; + std::vector workers; // target pool size std::size_t pool_size; // the task queue - std::queue< std::function > tasks; + std::queue> tasks; // queue length limit std::size_t max_queue_size = 100000; // stop signal @@ -79,18 +79,18 @@ class ThreadPool { struct handle_in_flight_decrement { - ThreadPool & tp; + ThreadPool &tp; - handle_in_flight_decrement(ThreadPool & tp_) + handle_in_flight_decrement(ThreadPool &tp_) : tp(tp_) - { } + { + } ~handle_in_flight_decrement() { - std::size_t prev - = std::atomic_fetch_sub_explicit(&tp.in_flight, - std::size_t(1), - std::memory_order_acq_rel); + std::size_t prev = std::atomic_fetch_sub_explicit(&tp.in_flight, + std::size_t(1), + std::memory_order_acq_rel); if (prev == 1) { std::unique_lock guard(tp.in_flight_mutex); @@ -102,50 +102,45 @@ class ThreadPool { // the constructor just launches some amount of workers inline ThreadPool::ThreadPool(std::size_t threads) - : pool_size(threads) - , in_flight(0) + : pool_size(threads), in_flight(0) { for (std::size_t i = 0; i != threads; ++i) emplace_back_worker(i); } // add new work item to the pool -template -auto ThreadPool::enqueue(F&& f, Args&&... args) +template +auto ThreadPool::enqueue(F &&f, Args &&... args) -> std::future::type> { using return_type = typename std::result_of::type; - auto task = std::make_shared< std::packaged_task >( - std::bind(std::forward(f), std::forward(args)...) - ); + auto task = std::make_shared>( + std::bind(std::forward(f), std::forward(args)...)); std::future res = task->get_future(); std::unique_lock lock(queue_mutex); - if (tasks.size () >= max_queue_size) + if (tasks.size() >= max_queue_size) // wait for the queue to empty or be stopped condition_producers.wait(lock, - [this] - { - return tasks.size () < max_queue_size - || stop; - }); + [this] { + return tasks.size() < max_queue_size || stop; + }); // don't allow enqueueing after stopping the pool if (stop) throw std::runtime_error("enqueue on stopped ThreadPool"); - tasks.emplace([task](){ (*task)(); }); + tasks.emplace([task]() { (*task)(); }); std::atomic_fetch_add_explicit(&in_flight, - std::size_t(1), - std::memory_order_relaxed); + std::size_t(1), + std::memory_order_relaxed); condition_consumers.notify_one(); return res; } - // the destructor joins all threads inline ThreadPool::~ThreadPool() { @@ -154,7 +149,7 @@ inline ThreadPool::~ThreadPool() condition_consumers.notify_all(); condition_producers.notify_all(); pool_size = 0; - condition_consumers.wait(lock, [this]{ return this->workers.empty(); }); + condition_consumers.wait(lock, [this] { return this->workers.empty(); }); assert(in_flight == 0); } @@ -162,14 +157,14 @@ inline void ThreadPool::wait_until_empty() { std::unique_lock lock(this->queue_mutex); this->condition_producers.wait(lock, - [this]{ return this->tasks.empty(); }); + [this] { return this->tasks.empty(); }); } inline void ThreadPool::wait_until_nothing_in_flight() { std::unique_lock lock(this->in_flight_mutex); this->in_flight_condition.wait(lock, - [this]{ return this->in_flight == 0; }); + [this] { return this->in_flight == 0; }); } inline void ThreadPool::set_queue_size_limit(std::size_t limit) @@ -208,12 +203,11 @@ inline void ThreadPool::set_pool_size(std::size_t limit) this->condition_consumers.notify_all(); } -inline void ThreadPool::emplace_back_worker (std::size_t worker_number) +inline void ThreadPool::emplace_back_worker(std::size_t worker_number) { workers.emplace_back( - [this, worker_number] - { - for(;;) + [this, worker_number] { + for (;;) { std::function task; bool notify; @@ -221,15 +215,12 @@ inline void ThreadPool::emplace_back_worker (std::size_t worker_number) { std::unique_lock lock(this->queue_mutex); this->condition_consumers.wait(lock, - [this, worker_number]{ - return this->stop || !this->tasks.empty() - || pool_size < worker_number + 1; }); + [this, worker_number] { return this->stop || !this->tasks.empty() || pool_size < worker_number + 1; }); // deal with downsizing of thread pool or shutdown - if ((this->stop && this->tasks.empty()) - || (!this->stop && pool_size < worker_number + 1)) + if ((this->stop && this->tasks.empty()) || (!this->stop && pool_size < worker_number + 1)) { - std::thread & last_thread = this->workers.back(); + std::thread &last_thread = this->workers.back(); std::thread::id this_id = std::this_thread::get_id(); if (this_id == last_thread.get_id()) { @@ -247,8 +238,7 @@ inline void ThreadPool::emplace_back_worker (std::size_t worker_number) { task = std::move(this->tasks.front()); this->tasks.pop(); - notify = this->tasks.size() + 1 == max_queue_size - || this->tasks.empty(); + notify = this->tasks.size() + 1 == max_queue_size || this->tasks.empty(); } else continue; @@ -264,8 +254,7 @@ inline void ThreadPool::emplace_back_worker (std::size_t worker_number) task(); } - } - ); + }); } } // namespace progschj diff --git a/tests/main.cpp b/tests/main.cpp index 36c8d84..4b354c2 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -8,63 +8,71 @@ using namespace ICONation::Common; using namespace ICONation::SDK::Blockchain; using namespace ICONation::Aegis; -#define DEBUG_TRY_CATCH(_x) \ - try { _x; } catch (const std::exception &e) { \ - Dbg::error ("Application exception :"); \ - Dbg::error (" - Type : {}", typeid(e).name()); \ - Dbg::error (" - Reason : {}", e.what()); \ +#define DEBUG_TRY_CATCH(_x) \ + try \ + { \ + _x; \ + } \ + catch (const std::exception &e) \ + { \ + Dbg::error("Application exception :"); \ + Dbg::error(" - Type : {}", typeid(e).name()); \ + Dbg::error(" - Reason : {}", e.what()); \ } namespace ICONation::SDK::Tests { - const int TEST_PORT = 33060; - const std::string TEST_HOST = "localhost"; - const std::string TEST_USER = "icon"; - const std::string TEST_PASSWORD = "icon"; - const std::string TEST_SCHEMA = "iconation_test"; +const int TEST_PORT = 33060; +const std::string TEST_HOST = "localhost"; +const std::string TEST_USER = "icon"; +const std::string TEST_PASSWORD = "icon"; +const std::string TEST_SCHEMA = "iconation_test"; - Db::Db db (TEST_HOST, TEST_PORT, TEST_USER, TEST_PASSWORD, TEST_SCHEMA); - SDK::Client testnet ("http://iconation.team:9000/api/v3", EULJIRO); - SDK::Client mainnet ("http://iconation.team:9100/api/v3", MAINNET); +Db::Db db(TEST_HOST, TEST_PORT, TEST_USER, TEST_PASSWORD, TEST_SCHEMA); +SDK::Client testnet("http://iconation.team:9000/api/v3", EULJIRO); +SDK::Client mainnet("http://iconation.team:9100/api/v3", MAINNET); - TEST (Db, InsertTransactionMessage) - { - Block block; +TEST(Db, InsertTransactionMessage) +{ + Block block; - // Weird case - db.clear(); - block = mainnet.get_block_by_height (58520); - db.disable_foreign_checks(); - db.block_insert (block); - db.enable_foreign_checks(); + // Weird case + db.clear(); + block = mainnet.get_block_by_height(58520); + db.disable_foreign_checks(); + db.block_insert(block); + db.enable_foreign_checks(); - // Normal case - db.clear(); - block = testnet.get_block_by_height (56189); - db.disable_foreign_checks(); - db.block_insert (block); - db.enable_foreign_checks(); - } + // Normal case + db.clear(); + block = testnet.get_block_by_height(56189); + db.disable_foreign_checks(); + db.block_insert(block); + db.enable_foreign_checks(); } +} // namespace ICONation::SDK::Tests -int main (int argc, char **argv) +int main(int argc, char **argv) { using ICONation::SDK::Tests::db; - using ICONation::SDK::Tests::testnet; using ICONation::SDK::Tests::TEST_SCHEMA; - - try { - Dbg::warn ("Preparing tests..."); - db.clear (TEST_SCHEMA); + using ICONation::SDK::Tests::testnet; + + try + { + Dbg::warn("Preparing tests..."); + db.clear(TEST_SCHEMA); ICX::Loop icxSupply = testnet.get_total_supply(); - db.bootstrap (ICX ("ICX", "ICX", icxSupply, 18)); + db.bootstrap(ICX("ICX", "ICX", icxSupply, 18)); - testing::InitGoogleTest (&argc, argv); + testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); - } catch (const std::exception &e) { - Dbg::error ("Application exception :"); - Dbg::error (" - Type : {}", typeid(e).name()); - Dbg::error (" - Reason : {}", e.what()); + } + catch (const std::exception &e) + { + Dbg::error("Application exception :"); + Dbg::error(" - Type : {}", typeid(e).name()); + Dbg::error(" - Reason : {}", e.what()); } return 0;