From b6f4663afdcbc524d75d01efbf0a1e8572ad9adc Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Thu, 24 Oct 2024 12:13:41 -0400 Subject: [PATCH 1/3] feat: can initialize client consensus node network with mirror node address book Signed-off-by: Rob Walworth --- src/sdk/examples/CMakeLists.txt | 5 ++ src/sdk/examples/GetAddressBookExample.cc | 5 ++ ...eClientWithMirrorNodeAddressBookExample.cc | 51 +++++++++++++++++++ src/sdk/main/include/Client.h | 6 +++ src/sdk/main/src/AddressBookQuery.cc | 1 + src/sdk/main/src/Client.cc | 12 +++++ 6 files changed, 80 insertions(+) create mode 100644 src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc diff --git a/src/sdk/examples/CMakeLists.txt b/src/sdk/examples/CMakeLists.txt index 2d53267a2..f4cabd27e 100644 --- a/src/sdk/examples/CMakeLists.txt +++ b/src/sdk/examples/CMakeLists.txt @@ -36,6 +36,8 @@ set(GET_ACCOUNT_INFO_EXAMPLE_NAME ${PROJECT_NAME}-get-account-info-example) set(GET_ADDRESS_BOOK_EXAMPLE_NAME ${PROJECT_NAME}-get-address-book-example) set(GET_EXCHANGE_RATES_EXAMPLE_NAME ${PROJECT_NAME}-get-exchange-rates-example) set(GET_FILE_CONTENTS_EXAMPLE_NAME ${PROJECT_NAME}-get-file-contents-example) +set(INITIALIZE_CLIENT_WITH_MIRROR_NODE_ADDRESS_BOOK_EXAMPLE_NAME + ${PROJECT_NAME}-initialize-client-with-mirror-node-address-book-example) set(MULTI_APP_TRANSFER_EXAMPLE_NAME ${PROJECT_NAME}-multi-app-transfer-example) set(MULTI_SIG_OFFLINE_EXAMPLE_NAME ${PROJECT_NAME}-multi-sig-offline-example) set(NFT_ADD_REMOVE_ALLOWANCES_EXAMPLE_NAME ${PROJECT_NAME}-nft-add-remove-allowances-example) @@ -90,6 +92,7 @@ add_executable(${GET_ACCOUNT_INFO_EXAMPLE_NAME} GetAccountInfoExample.cc) add_executable(${GET_ADDRESS_BOOK_EXAMPLE_NAME} GetAddressBookExample.cc) add_executable(${GET_EXCHANGE_RATES_EXAMPLE_NAME} GetExchangeRatesExample.cc) add_executable(${GET_FILE_CONTENTS_EXAMPLE_NAME} GetFileContentsExample.cc) +add_executable(${INITIALIZE_CLIENT_WITH_MIRROR_NODE_ADDRESS_BOOK_EXAMPLE_NAME} InitializeClientWithMirrorNodeAddressBookExample.cc) add_executable(${MULTI_APP_TRANSFER_EXAMPLE_NAME} MultiAppTransferExample.cc) add_executable(${MULTI_SIG_OFFLINE_EXAMPLE_NAME} MultiSigOfflineExample.cc) add_executable(${NFT_ADD_REMOVE_ALLOWANCES_EXAMPLE_NAME} NftAddRemoveAllowancesExample.cc) @@ -166,6 +169,7 @@ target_link_libraries(${GET_ACCOUNT_INFO_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) target_link_libraries(${GET_ADDRESS_BOOK_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) target_link_libraries(${GET_EXCHANGE_RATES_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) target_link_libraries(${GET_FILE_CONTENTS_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) +target_link_libraries(${INITIALIZE_CLIENT_WITH_MIRROR_NODE_ADDRESS_BOOK_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) target_link_libraries(${MULTI_APP_TRANSFER_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) target_link_libraries(${MULTI_SIG_OFFLINE_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) target_link_libraries(${NFT_ADD_REMOVE_ALLOWANCES_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) @@ -222,6 +226,7 @@ install(TARGETS ${GET_ADDRESS_BOOK_EXAMPLE_NAME} ${GET_EXCHANGE_RATES_EXAMPLE_NAME} ${GET_FILE_CONTENTS_EXAMPLE_NAME} + ${INITIALIZE_CLIENT_WITH_MIRROR_NODE_ADDRESS_BOOK_EXAMPLE_NAME} ${MULTI_APP_TRANSFER_EXAMPLE_NAME} ${MULTI_SIG_OFFLINE_EXAMPLE_NAME} ${NFT_ADD_REMOVE_ALLOWANCES_EXAMPLE_NAME} diff --git a/src/sdk/examples/GetAddressBookExample.cc b/src/sdk/examples/GetAddressBookExample.cc index 896f3ba87..31338920a 100644 --- a/src/sdk/examples/GetAddressBookExample.cc +++ b/src/sdk/examples/GetAddressBookExample.cc @@ -17,11 +17,16 @@ * limitations under the License. * */ +#include "AccountCreateTransaction.h" #include "AddressBookQuery.h" #include "Client.h" +#include "ED25519PrivateKey.h" #include "FileId.h" #include "NodeAddressBook.h" +#include "TransactionReceipt.h" +#include "TransactionResponse.h" +#include #include using namespace Hedera; diff --git a/src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc b/src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc new file mode 100644 index 000000000..1d44842b4 --- /dev/null +++ b/src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc @@ -0,0 +1,51 @@ +/*- + * + * Hedera C++ SDK + * + * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "AccountCreateTransaction.h" +#include "Client.h" +#include "ED25519PrivateKey.h" +#include "TransactionReceipt.h" +#include "TransactionResponse.h" + +#include +#include + +using namespace Hedera; + +int main(int argc, char** argv) +{ + dotenv::init(); + const AccountId operatorAccountId = AccountId::fromString(std::getenv("OPERATOR_ID")); + const std::shared_ptr operatorPrivateKey = ED25519PrivateKey::fromString(std::getenv("OPERATOR_KEY")); + + // Initialize the client with the testnet mirror node. + Client client; + client.setOperator(operatorAccountId, operatorPrivateKey); + client.setMirrorNetwork({ "testnet.mirrornode.hedera.com:443" }); + + // Get the address book from the mirror node and use it to populate the Client's consensus network. + client.populateNetworkFromMirrorNodeAddressBook(); + + // Attempt to execute a transaction. + TransactionReceipt txReceipt = + AccountCreateTransaction().setKey(ED25519PrivateKey::generatePrivateKey()).execute(client).getReceipt(client); + std::cout << "Created account " << txReceipt.mAccountId->toString() << std::endl; + + return 0; +} diff --git a/src/sdk/main/include/Client.h b/src/sdk/main/include/Client.h index 57d7b9d5a..393ffb62d 100644 --- a/src/sdk/main/include/Client.h +++ b/src/sdk/main/include/Client.h @@ -385,6 +385,12 @@ class Client */ Client& setMirrorNetwork(const std::vector& network); + /** + * Populate this Client's consensus network by getting the address book from this Client's mirror network. This + * requires a mirror network to be manually set already. + */ + void populateNetworkFromMirrorNodeAddressBook(); + /** * Get the list of mirror nodes on this Client's network. * diff --git a/src/sdk/main/src/AddressBookQuery.cc b/src/sdk/main/src/AddressBookQuery.cc index c6d4aacb8..944ae75a1 100644 --- a/src/sdk/main/src/AddressBookQuery.cc +++ b/src/sdk/main/src/AddressBookQuery.cc @@ -24,6 +24,7 @@ #include "exceptions/MaxAttemptsExceededException.h" #include "impl/MirrorNetwork.h" #include "impl/MirrorNode.h" +#include "impl/Utilities.h" #include #include diff --git a/src/sdk/main/src/Client.cc b/src/sdk/main/src/Client.cc index 36fe085bd..d5954e448 100644 --- a/src/sdk/main/src/Client.cc +++ b/src/sdk/main/src/Client.cc @@ -23,6 +23,7 @@ #include "AccountId.h" #include "AddressBookQuery.h" #include "Defaults.h" +#include "FileId.h" #include "Hbar.h" #include "Logger.h" #include "NodeAddressBook.h" @@ -695,6 +696,17 @@ Client& Client::setMirrorNetwork(const std::vector& network) return *this; } +//----- +void Client::populateNetworkFromMirrorNodeAddressBook() +{ + auto network = + std::make_shared(internal::Network::forNetwork(internal::Network::getNetworkFromAddressBook( + AddressBookQuery().setFileId(FileId::ADDRESS_BOOK).execute(*this), internal::BaseNodeAddress::PORT_NODE_PLAIN))); + + std::unique_lock lock(mImpl->mMutex); + mImpl->mNetwork = network; +} + //----- std::vector Client::getMirrorNetwork() const { From 90394311b68b329b8f06ecd2d0de12503a10763d Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Thu, 24 Oct 2024 12:17:02 -0400 Subject: [PATCH 2/3] refactor: fix testing remnants Signed-off-by: Rob Walworth --- src/sdk/examples/GetAddressBookExample.cc | 5 ----- src/sdk/main/src/AddressBookQuery.cc | 1 - 2 files changed, 6 deletions(-) diff --git a/src/sdk/examples/GetAddressBookExample.cc b/src/sdk/examples/GetAddressBookExample.cc index 31338920a..896f3ba87 100644 --- a/src/sdk/examples/GetAddressBookExample.cc +++ b/src/sdk/examples/GetAddressBookExample.cc @@ -17,16 +17,11 @@ * limitations under the License. * */ -#include "AccountCreateTransaction.h" #include "AddressBookQuery.h" #include "Client.h" -#include "ED25519PrivateKey.h" #include "FileId.h" #include "NodeAddressBook.h" -#include "TransactionReceipt.h" -#include "TransactionResponse.h" -#include #include using namespace Hedera; diff --git a/src/sdk/main/src/AddressBookQuery.cc b/src/sdk/main/src/AddressBookQuery.cc index 944ae75a1..c6d4aacb8 100644 --- a/src/sdk/main/src/AddressBookQuery.cc +++ b/src/sdk/main/src/AddressBookQuery.cc @@ -24,7 +24,6 @@ #include "exceptions/MaxAttemptsExceededException.h" #include "impl/MirrorNetwork.h" #include "impl/MirrorNode.h" -#include "impl/Utilities.h" #include #include From 5513c8d27b35560f3dd46651f5b70d8e0fd4e53c Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 30 Oct 2024 11:27:46 -0400 Subject: [PATCH 3/3] refactor: consolidate initialization of client to a static function Signed-off-by: Rob Walworth --- ...eClientWithMirrorNodeAddressBookExample.cc | 9 +++----- src/sdk/main/include/Client.h | 16 ++++++++----- src/sdk/main/src/Client.cc | 23 ++++++++++--------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc b/src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc index 1d44842b4..4896b9a56 100644 --- a/src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc +++ b/src/sdk/examples/InitializeClientWithMirrorNodeAddressBookExample.cc @@ -34,13 +34,10 @@ int main(int argc, char** argv) const AccountId operatorAccountId = AccountId::fromString(std::getenv("OPERATOR_ID")); const std::shared_ptr operatorPrivateKey = ED25519PrivateKey::fromString(std::getenv("OPERATOR_KEY")); - // Initialize the client with the testnet mirror node. - Client client; + // Initialize the client with the testnet mirror node. This will also get the address book from the mirror node and + // use it to populate the Client's consensus network. + Client client = Client::forMirrorNetwork({ "testnet.mirrornode.hedera.com:443" }); client.setOperator(operatorAccountId, operatorPrivateKey); - client.setMirrorNetwork({ "testnet.mirrornode.hedera.com:443" }); - - // Get the address book from the mirror node and use it to populate the Client's consensus network. - client.populateNetworkFromMirrorNodeAddressBook(); // Attempt to execute a transaction. TransactionReceipt txReceipt = diff --git a/src/sdk/main/include/Client.h b/src/sdk/main/include/Client.h index 393ffb62d..de7ce7ea0 100644 --- a/src/sdk/main/include/Client.h +++ b/src/sdk/main/include/Client.h @@ -82,6 +82,16 @@ class Client */ [[nodiscard]] static Client forNetwork(const std::unordered_map& networkMap); + /** + * Construct a Client pre-configured for a specific mirror network. This will attempt to pull the network address + * book from the input mirror network and establish its consensus network with that. + * + * @param mirrorNetwork The mirror node network from which to grab the address book and initialize the Client's + * consensus network. + * @return A Client with the input mirror network and the corresponding address book consensus network + */ + [[nodiscard]] static Client forMirrorNetwork(const std::vector& mirrorNetwork); + /** * Construct a Client by a name. The name must be one of "mainnet", "testnet", or "previewnet", otherwise this will * throw std::invalid_argument. @@ -385,12 +395,6 @@ class Client */ Client& setMirrorNetwork(const std::vector& network); - /** - * Populate this Client's consensus network by getting the address book from this Client's mirror network. This - * requires a mirror network to be manually set already. - */ - void populateNetworkFromMirrorNodeAddressBook(); - /** * Get the list of mirror nodes on this Client's network. * diff --git a/src/sdk/main/src/Client.cc b/src/sdk/main/src/Client.cc index d5954e448..a11b549dc 100644 --- a/src/sdk/main/src/Client.cc +++ b/src/sdk/main/src/Client.cc @@ -174,6 +174,18 @@ Client Client::forNetwork(const std::unordered_map& netw return client; } +//----- +Client Client::forMirrorNetwork(const std::vector& mirrorNetwork) +{ + Client client; + client.setMirrorNetwork(mirrorNetwork); + client.mImpl->mNetwork = + std::make_shared(internal::Network::forNetwork(internal::Network::getNetworkFromAddressBook( + AddressBookQuery().setFileId(FileId::ADDRESS_BOOK).execute(client), internal::BaseNodeAddress::PORT_NODE_PLAIN))); + + return client; +} + //----- Client Client::forName(std::string_view name) { @@ -696,17 +708,6 @@ Client& Client::setMirrorNetwork(const std::vector& network) return *this; } -//----- -void Client::populateNetworkFromMirrorNodeAddressBook() -{ - auto network = - std::make_shared(internal::Network::forNetwork(internal::Network::getNetworkFromAddressBook( - AddressBookQuery().setFileId(FileId::ADDRESS_BOOK).execute(*this), internal::BaseNodeAddress::PORT_NODE_PLAIN))); - - std::unique_lock lock(mImpl->mMutex); - mImpl->mNetwork = network; -} - //----- std::vector Client::getMirrorNetwork() const {