From 32e7eb844002ff8f3c2eed92f02dba7dac1d4533 Mon Sep 17 00:00:00 2001 From: gsstoykov Date: Wed, 16 Oct 2024 17:34:05 +0300 Subject: [PATCH] feat: Added Integration Test for NodeCreateTransaction and FQDN support (#787) Signed-off-by: gsstoykov --- HederaApi.cmake | 4 +- src/sdk/main/include/IPv4Address.h | 9 +- src/sdk/main/include/Status.h | 97 ++++++++++++++++++- src/sdk/main/include/impl/Node.h | 6 ++ src/sdk/main/src/Endpoint.cc | 9 +- src/sdk/main/src/IPv4Address.cc | 31 ++++-- src/sdk/main/src/Status.cc | 50 +++++++++- src/sdk/main/src/impl/Node.cc | 4 + src/sdk/tests/integration/CMakeLists.txt | 1 + .../NodeCreateTransactionIntegrationTests.cc | 96 ++++++++++++++++++ 10 files changed, 293 insertions(+), 14 deletions(-) create mode 100644 src/sdk/tests/integration/NodeCreateTransactionIntegrationTests.cc diff --git a/HederaApi.cmake b/HederaApi.cmake index bd7766013..6b5275dc0 100644 --- a/HederaApi.cmake +++ b/HederaApi.cmake @@ -1,5 +1,5 @@ -set(HAPI_LIBRARY_HASH "46507656510baa279f3ce6d94e0044ef47128ba051467a3748ed55e6cb779db3" CACHE STRING "Use the configured hash to verify the Hedera API protobuf library release") -set(HAPI_LIBRARY_URL "https://github.com/hashgraph/hedera-protobufs-cpp/releases/download/v0.54.0/hapi-library-bb992044.tar.gz" CACHE STRING "Use the configured URL to download the Hedera API protobuf library package") +set(HAPI_LIBRARY_HASH "248299d525ec55425b755565726fc40a9bb9aa8335447f7c07956c9ace1ef64c" CACHE STRING "Use the configured hash to verify the Hedera API protobuf library release") +set(HAPI_LIBRARY_URL "https://github.com/hashgraph/hedera-protobufs-cpp/releases/download/v0.55.0/hapi-library-32c2a4a2.tar.gz" CACHE STRING "Use the configured URL to download the Hedera API protobuf library package") set(HAPI_LOCAL_LIBRARY_PATH "" CACHE STRING "Overrides the configured HAPI_LIBRARY_URL setting and instead uses the local path to retrieve the artifacts") diff --git a/src/sdk/main/include/IPv4Address.h b/src/sdk/main/include/IPv4Address.h index e90ba1e67..a57a1a725 100644 --- a/src/sdk/main/include/IPv4Address.h +++ b/src/sdk/main/include/IPv4Address.h @@ -56,11 +56,18 @@ class IPv4Address */ [[nodiscard]] std::string toString() const; + /** + * Check if the IPV4Address is empty. + * + * @return The boolean representation of an IPV4Address empty state. + */ + [[nodiscard]] bool isEmpty() const; + private: /** * The four octets of the address. */ - std::array mAddress; + std::vector mAddress; }; } // namespace Hedera diff --git a/src/sdk/main/include/Status.h b/src/sdk/main/include/Status.h index 27a730909..197cc9cf1 100644 --- a/src/sdk/main/include/Status.h +++ b/src/sdk/main/include/Status.h @@ -1596,7 +1596,102 @@ enum class Status * The client SHOULD query mirror node to determine the status of the pending * airdrop and whether the sender can fulfill the offer. */ - INVALID_TOKEN_IN_PENDING_AIRDROP + INVALID_TOKEN_IN_PENDING_AIRDROP, + + /** + * A transaction failed because the consensus node identified is + * deleted from the address book. + */ + NODE_DELETED, + + /** + * A transaction failed because the consensus node identified is not valid or + * does not exist in state. + */ + INVALID_NODE_ID, + + /** + * A transaction failed because one or more entries in the list of + * service endpoints for the `gossip_endpoint` field is invalid.
+ * The most common cause for this response is a service endpoint that has + * the domain name (DNS) set rather than address and port. + */ + INVALID_GOSSIP_ENDPOINT, + + /** + * A transaction failed because the node account identifier provided + * does not exist or is not valid.
+ * One common source of this error is providing a node account identifier + * using the "alias" form rather than "numeric" form. + */ + INVALID_NODE_ACCOUNT_ID, + + /** + * A transaction failed because the description field cannot be encoded + * as UTF-8 or is more than 100 bytes when encoded. + */ + INVALID_NODE_DESCRIPTION, + + /** + * A transaction failed because one or more entries in the list of + * service endpoints for the `service_endpoint` field is invalid.
+ * The most common cause for this response is a service endpoint that has + * the domain name (DNS) set rather than address and port. + */ + INVALID_SERVICE_ENDPOINT, + + /** + * A transaction failed because the TLS certificate provided for the + * node is missing or invalid.
+ * The certificate MUST be a TLS certificate of a type permitted for gossip + * signatures.
+ * The value presented MUST be a UTF-8 NFKD encoding of the TLS + * certificate.
+ * The certificate encoded MUST be in PEM format.
+ * The `gossip_ca_certificate` field is REQUIRED and MUST NOT be empty. + */ + INVALID_GOSSIP_CA_CERTIFICATE, + + /** + * A transaction failed because the hash provided for the gRPC certificate + * is present but invalid.
+ * The `grpc_certificate_hash` MUST be a SHA-384 hash.
+ * The input hashed MUST be a UTF-8 NFKD encoding of the actual TLS + * certificate.
+ * The certificate to be encoded MUST be in PEM format. + */ + INVALID_GRPC_CERTIFICATE, + + /** + * The maximum number of nodes allowed in the address book have been created. + */ + MAX_NODES_CREATED, + + /** + * In ServiceEndpoint, domain_name and ipAddressV4 are mutually exclusive + */ + IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT, + + /** + * Fully qualified domain name is not allowed in gossip_endpoint + */ + GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN, + + /** + * In ServiceEndpoint, domain_name size too large + */ + FQDN_SIZE_TOO_LARGE, + + /** + * ServiceEndpoint is invalid + */ + INVALID_ENDPOINT, + + /** + * The number of gossip endpoints exceeds the limit + */ + GOSSIP_ENDPOINTS_EXCEEDED_LIMIT + }; /** diff --git a/src/sdk/main/include/impl/Node.h b/src/sdk/main/include/impl/Node.h index 953754b14..07eb4f0f0 100644 --- a/src/sdk/main/include/impl/Node.h +++ b/src/sdk/main/include/impl/Node.h @@ -20,6 +20,7 @@ #ifndef HEDERA_SDK_CPP_IMPL_NODE_H_ #define HEDERA_SDK_CPP_IMPL_NODE_H_ +#include #include #include #include @@ -236,6 +237,11 @@ class Node : public BaseNode */ std::unique_ptr mUtilStub = nullptr; + /** + * Pointer to the gRPC stub used to communicate with the address book service living on the remote node. + */ + std::unique_ptr mAddressBookStub = nullptr; + /** * The AccountId that runs the remote node represented by this Node. */ diff --git a/src/sdk/main/src/Endpoint.cc b/src/sdk/main/src/Endpoint.cc index e22780cd8..6cfd208ea 100644 --- a/src/sdk/main/src/Endpoint.cc +++ b/src/sdk/main/src/Endpoint.cc @@ -46,7 +46,14 @@ std::unique_ptr Endpoint::toProtobuf() const //----- std::string Endpoint::toString() const { - return mAddress.toString() + ':' + std::to_string(mPort); + if (!mAddress.isEmpty()) + { + return mAddress.toString() + ':' + std::to_string(mPort); + } + else + { + return mDomainName + ':' + std::to_string(mPort); + } } //----- diff --git a/src/sdk/main/src/IPv4Address.cc b/src/sdk/main/src/IPv4Address.cc index a0c946932..d9b30f525 100644 --- a/src/sdk/main/src/IPv4Address.cc +++ b/src/sdk/main/src/IPv4Address.cc @@ -18,6 +18,7 @@ * */ #include "IPv4Address.h" +#include "exceptions/IllegalStateException.h" #include @@ -32,23 +33,41 @@ IPv4Address IPv4Address::fromBytes(const std::vector& bytes) } IPv4Address iPv4Address; - std::copy(bytes.cbegin(), bytes.cend(), iPv4Address.mAddress.begin()); + + for (const auto& byte : bytes) + { + iPv4Address.mAddress.push_back(byte); + } return iPv4Address; } //----- std::vector IPv4Address::toBytes() const { - return { mAddress.at(0), mAddress.at(1), mAddress.at(2), mAddress.at(3) }; + return mAddress; } //----- std::string IPv4Address::toString() const { - return std::to_string(std::to_integer(mAddress.at(0))) + '.' + - std::to_string(std::to_integer(mAddress.at(1))) + '.' + - std::to_string(std::to_integer(mAddress.at(2))) + '.' + - std::to_string(std::to_integer(mAddress.at(3))); + if (mAddress.size() != 4) + { + throw IllegalStateException("Incorrect byte array size, should be 4 bytes but is " + + std::to_string(mAddress.size())); + } + else + { + return std::to_string(std::to_integer(mAddress.at(0))) + '.' + + std::to_string(std::to_integer(mAddress.at(1))) + '.' + + std::to_string(std::to_integer(mAddress.at(2))) + '.' + + std::to_string(std::to_integer(mAddress.at(3))); + } +} + +//----- +bool IPv4Address::isEmpty() const +{ + return mAddress.empty(); } } // namespace Hedera diff --git a/src/sdk/main/src/Status.cc b/src/sdk/main/src/Status.cc index 36b8f96d7..f23426045 100644 --- a/src/sdk/main/src/Status.cc +++ b/src/sdk/main/src/Status.cc @@ -346,7 +346,22 @@ const std::unordered_map gProtobufResponseCodeT { proto::ResponseCodeEnum::THROTTLED_AT_CONSENSUS, Status::THROTTLED_AT_CONSENSUS }, { proto::ResponseCodeEnum::INVALID_PENDING_AIRDROP_ID, Status::INVALID_PENDING_AIRDROP_ID }, { proto::ResponseCodeEnum::TOKEN_AIRDROP_WITH_FALLBACK_ROYALTY, Status::TOKEN_AIRDROP_WITH_FALLBACK_ROYALTY }, - { proto::ResponseCodeEnum::INVALID_TOKEN_IN_PENDING_AIRDROP, Status::INVALID_TOKEN_IN_PENDING_AIRDROP } + { proto::ResponseCodeEnum::INVALID_TOKEN_IN_PENDING_AIRDROP, Status::INVALID_TOKEN_IN_PENDING_AIRDROP }, + { proto::ResponseCodeEnum::NODE_DELETED, Status::NODE_DELETED }, + { proto::ResponseCodeEnum::INVALID_NODE_ID, Status::INVALID_NODE_ID }, + { proto::ResponseCodeEnum::INVALID_GOSSIP_ENDPOINT, Status::INVALID_GOSSIP_ENDPOINT }, + { proto::ResponseCodeEnum::INVALID_NODE_ACCOUNT_ID, Status::INVALID_NODE_ACCOUNT_ID }, + { proto::ResponseCodeEnum::INVALID_NODE_DESCRIPTION, Status::INVALID_NODE_DESCRIPTION }, + { proto::ResponseCodeEnum::INVALID_SERVICE_ENDPOINT, Status::INVALID_SERVICE_ENDPOINT }, + { proto::ResponseCodeEnum::INVALID_GOSSIP_CA_CERTIFICATE, Status::INVALID_GOSSIP_CA_CERTIFICATE }, + { proto::ResponseCodeEnum::INVALID_GRPC_CERTIFICATE, Status::INVALID_GRPC_CERTIFICATE }, + { proto::ResponseCodeEnum::MAX_NODES_CREATED, Status::MAX_NODES_CREATED }, + { proto::ResponseCodeEnum::IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT, + Status::IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT }, + { proto::ResponseCodeEnum::GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN, Status::GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN }, + { proto::ResponseCodeEnum::FQDN_SIZE_TOO_LARGE, Status::FQDN_SIZE_TOO_LARGE }, + { proto::ResponseCodeEnum::INVALID_ENDPOINT, Status::INVALID_ENDPOINT }, + { proto::ResponseCodeEnum::GOSSIP_ENDPOINTS_EXCEEDED_LIMIT, Status::GOSSIP_ENDPOINTS_EXCEEDED_LIMIT } }; //----- @@ -672,7 +687,22 @@ const std::unordered_map gStatusToProtobufRespo { Status::THROTTLED_AT_CONSENSUS, proto::ResponseCodeEnum::THROTTLED_AT_CONSENSUS }, { Status::INVALID_PENDING_AIRDROP_ID, proto::ResponseCodeEnum::INVALID_PENDING_AIRDROP_ID }, { Status::TOKEN_AIRDROP_WITH_FALLBACK_ROYALTY, proto::ResponseCodeEnum::TOKEN_AIRDROP_WITH_FALLBACK_ROYALTY }, - { Status::INVALID_TOKEN_IN_PENDING_AIRDROP, proto::ResponseCodeEnum::INVALID_TOKEN_IN_PENDING_AIRDROP } + { Status::INVALID_TOKEN_IN_PENDING_AIRDROP, proto::ResponseCodeEnum::INVALID_TOKEN_IN_PENDING_AIRDROP }, + { Status::NODE_DELETED, proto::ResponseCodeEnum::NODE_DELETED }, + { Status::INVALID_NODE_ID, proto::ResponseCodeEnum::INVALID_NODE_ID }, + { Status::INVALID_GOSSIP_ENDPOINT, proto::ResponseCodeEnum::INVALID_GOSSIP_ENDPOINT }, + { Status::INVALID_NODE_ACCOUNT_ID, proto::ResponseCodeEnum::INVALID_NODE_ACCOUNT_ID }, + { Status::INVALID_NODE_DESCRIPTION, proto::ResponseCodeEnum::INVALID_NODE_DESCRIPTION }, + { Status::INVALID_SERVICE_ENDPOINT, proto::ResponseCodeEnum::INVALID_SERVICE_ENDPOINT }, + { Status::INVALID_GOSSIP_CA_CERTIFICATE, proto::ResponseCodeEnum::INVALID_GOSSIP_CA_CERTIFICATE }, + { Status::INVALID_GRPC_CERTIFICATE, proto::ResponseCodeEnum::INVALID_GRPC_CERTIFICATE }, + { Status::MAX_NODES_CREATED, proto::ResponseCodeEnum::MAX_NODES_CREATED }, + { Status::IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT, + proto::ResponseCodeEnum::IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT }, + { Status::GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN, proto::ResponseCodeEnum::GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN }, + { Status::FQDN_SIZE_TOO_LARGE, proto::ResponseCodeEnum::FQDN_SIZE_TOO_LARGE }, + { Status::INVALID_ENDPOINT, proto::ResponseCodeEnum::INVALID_ENDPOINT }, + { Status::GOSSIP_ENDPOINTS_EXCEEDED_LIMIT, proto::ResponseCodeEnum::GOSSIP_ENDPOINTS_EXCEEDED_LIMIT } }; //----- @@ -980,7 +1010,21 @@ const std::unordered_map gStatusToString = { { Status::THROTTLED_AT_CONSENSUS, "THROTTLED_AT_CONSENSUS" }, { Status::INVALID_PENDING_AIRDROP_ID, "INVALID_PENDING_AIRDROP_ID" }, { Status::TOKEN_AIRDROP_WITH_FALLBACK_ROYALTY, "TOKEN_AIRDROP_WITH_FALLBACK_ROYALTY" }, - { Status::INVALID_TOKEN_IN_PENDING_AIRDROP, "INVALID_TOKEN_IN_PENDING_AIRDROP" } + { Status::INVALID_TOKEN_IN_PENDING_AIRDROP, "INVALID_TOKEN_IN_PENDING_AIRDROP" }, + { Status::NODE_DELETED, "NODE_DELETED" }, + { Status::INVALID_NODE_ID, "INVALID_NODE_ID" }, + { Status::INVALID_GOSSIP_ENDPOINT, "INVALID_GOSSIP_ENDPOINT" }, + { Status::INVALID_NODE_ACCOUNT_ID, "INVALID_NODE_ACCOUNT_ID" }, + { Status::INVALID_NODE_DESCRIPTION, "INVALID_NODE_DESCRIPTION" }, + { Status::INVALID_SERVICE_ENDPOINT, "INVALID_SERVICE_ENDPOINT" }, + { Status::INVALID_GOSSIP_CA_CERTIFICATE, "INVALID_GOSSIP_CA_CERTIFICATE" }, + { Status::INVALID_GRPC_CERTIFICATE, "INVALID_GRPC_CERTIFICATE" }, + { Status::MAX_NODES_CREATED, "MAX_NODES_CREATED" }, + { Status::IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT, "IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT" }, + { Status::GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN, "GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN" }, + { Status::FQDN_SIZE_TOO_LARGE, "FQDN_SIZE_TOO_LARGE" }, + { Status::INVALID_ENDPOINT, "INVALID_ENDPOINT" }, + { Status::GOSSIP_ENDPOINTS_EXCEEDED_LIMIT, "GOSSIP_ENDPOINTS_EXCEEDED_LIMIT" } }; } // namespace Hedera \ No newline at end of file diff --git a/src/sdk/main/src/impl/Node.cc b/src/sdk/main/src/impl/Node.cc index 74663d3af..eebd8827c 100644 --- a/src/sdk/main/src/impl/Node.cc +++ b/src/sdk/main/src/impl/Node.cc @@ -105,6 +105,8 @@ grpc::Status Node::submitTransaction(proto::TransactionBody::DataCase funcEnum, switch (funcEnum) { + case proto::TransactionBody::DataCase::kNodeCreate: + return mAddressBookStub->createNode(&context, transaction, response); case proto::TransactionBody::DataCase::kConsensusCreateTopic: return mConsensusStub->createTopic(&context, transaction, response); case proto::TransactionBody::DataCase::kConsensusDeleteTopic: @@ -286,6 +288,7 @@ void Node::initializeStubs() if (!mSmartContractStub) mSmartContractStub = proto::SmartContractService::NewStub(getChannel()); if (!mTokenStub) mTokenStub = proto::TokenService::NewStub(getChannel()); if (!mUtilStub) mUtilStub = proto::UtilService::NewStub(getChannel()); + if (!mAddressBookStub) mAddressBookStub = proto::AddressBookService::NewStub(getChannel()); // clang-format on } @@ -301,6 +304,7 @@ void Node::closeStubs() mSmartContractStub = nullptr; mTokenStub = nullptr; mUtilStub = nullptr; + mAddressBookStub = nullptr; } } // namespace Hedera::internal diff --git a/src/sdk/tests/integration/CMakeLists.txt b/src/sdk/tests/integration/CMakeLists.txt index 70c0909b1..826eafa36 100644 --- a/src/sdk/tests/integration/CMakeLists.txt +++ b/src/sdk/tests/integration/CMakeLists.txt @@ -34,6 +34,7 @@ add_executable(${TEST_PROJECT_NAME} JSONIntegrationTests.cc MirrorNodeGatewayIntegrationTests.cc NetworkVersionInfoQueryIntegrationTests.cc + NodeCreateTransactionIntegrationTests.cc PrngTransactionIntegrationTests.cc QueryIntegrationTests.cc ScheduleCreateTransactionIntegrationTests.cc diff --git a/src/sdk/tests/integration/NodeCreateTransactionIntegrationTests.cc b/src/sdk/tests/integration/NodeCreateTransactionIntegrationTests.cc new file mode 100644 index 000000000..73cb28598 --- /dev/null +++ b/src/sdk/tests/integration/NodeCreateTransactionIntegrationTests.cc @@ -0,0 +1,96 @@ +/*- + * + * 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 "BaseIntegrationTest.h" +#include "ED25519PrivateKey.h" +#include "NodeCreateTransaction.h" +#include "TransactionRecord.h" +#include "TransactionResponse.h" +#include "impl/HexConverter.h" +#include "impl/Utilities.h" + +#include + +using namespace Hedera; + +class NodeCreateTransactionIntegrationTests : public BaseIntegrationTest +{ +protected: + [[nodiscard]] const AccountId& getAccountId() const { return mAccountId; } + [[nodiscard]] const std::vector& getGossipEndpoints() const { return mGossipEndpoints; } + [[nodiscard]] const std::vector& getGrpcServiceEndpoints() const { return mGrpcServiceEndpoints; } + [[nodiscard]] const std::vector getGossipCertificate() const + { + return internal::HexConverter::hexToBytes(mGossipCertificateDer); + } + +private: + const AccountId mAccountId = AccountId::fromString("0.0.4"); + const Endpoint endpoint1 = Endpoint().setDomainName("test.com").setPort(123); + const Endpoint endpoint2 = Endpoint().setDomainName("test2.com").setPort(123); + const std::vector mGossipEndpoints = { endpoint1, endpoint2 }; + const std::vector mGrpcServiceEndpoints = { endpoint1, endpoint2 }; + const std::string mGossipCertificateDer = + "3082052830820310a003020102020101300d06092a864886f70d01010c05003010310e300c060355040313056e6f6465333024170d32343130" + "30383134333233395a181332313234313030383134333233392e3337395a3010310e300c060355040313056e6f64653330820222300d06092a" + "864886f70d01010105000382020f003082020a0282020100af111cff0c4ad8125d2f4b8691ce87332fecc867f7a94ddc0f3f96514cc4224d44" + "af516394f7384c1ef0a515d29aa6116b65bc7e4d7e2d848cf79fbfffedae3a6583b3957a438bdd780c4981b800676ea509bc8c619ae04093b5" + "fc642c4484152f0e8bcaabf19eae025b630028d183a2f47caf6d9f1075efb30a4248679d871beef1b7e9115382270cbdb68682fae4b1fd592c" + "adb414d918c0a8c23795c7c5a91e22b3e90c410825a2bc1a840efc5bf9976a7f474c7ed7dc047e4ddd2db631b68bb4475f173baa3edc234c4b" + "ed79c83e2f826f79e07d0aade2d984da447a8514135bfa4145274a7f62959a23c4f0fae5adc6855974e7c04164951d052beb5d45cb1f3cdfd0" + "05da894dea9151cb62ba43f4731c6bb0c83e10fd842763ba6844ef499f71bc67fa13e4917fb39f2ad18112170d31cdcb3c61c9e3253accf703" + "dbd8427fdcb87ece78b787b6cfdc091e8fedea8ad95dc64074e1fc6d0e42ea2337e18a5e54e4aaab3791a98dfcef282e2ae1caec9cf986fabe" + "8f36e6a21c8711647177e492d264415e765a86c58599cd97b103cb4f6a01d2edd06e3b60470cf64daca7aecf831197b466cae04baeeac19840" + "a05394bef628aed04b611cfa13677724b08ddfd662b02fd0ef0af17eb7f4fb8c1c17fbe9324f6dc7bcc02449622636cc45ec04909b3120ab4d" + "f4726b21bf79e955fe8f832699d2196dcd7a58bfeafb170203010001a38186308183300f0603551d130101ff04053003020100300e0603551d" + "0f0101ff0404030204b030200603551d250101ff0416301406082b0601050507030106082b06010505070302301d0603551d0e041604146431" + "18e05209035edd83d44a0c368de2fb2fe4c0301f0603551d23041830168014643118e05209035edd83d44a0c368de2fb2fe4c0300d06092a86" + "4886f70d01010c05000382020100ad41c32bb52650eb4b76fce439c9404e84e4538a94916b3dc7983e8b5c58890556e7384601ca7440dde682" + "33bb07b97bf879b64487b447df510897d2a0a4e789c409a9b237a6ad240ad5464f2ce80c58ddc4d07a29a74eb25e1223db6c00e334d7a27d32" + "bfa6183a82f5e35bccf497c2445a526eabb0c068aba9b94cc092ea4756b0dcfb574f6179f0089e52b174ccdbd04123eeb6d70daeabd8513fcb" + "a6be0bc2b45ca9a69802dae11cc4d9ff6053b3a87fd8b0c6bf72fffc3b81167f73cca2b3fd656c5d353c8defca8a76e2ad535f984870a590af" + "4e28fed5c5a125bf360747c5e7742e7813d1bd39b5498c8eb6ba72f267eda034314fdbc596f6b967a0ef8be5231d364e634444c84e64bd7919" + "425171016fcd9bb05f01c58a303dee28241f6e860fc3aac3d92aad7dac2801ce79a3b41a0e1f1509fc0d86e96d94edb18616c000152490f645" + "61713102128990fedd3a5fa642f2ff22dc11bc4dc5b209986a0c3e4eb2bdfdd40e9fdf246f702441cac058dd8d0d51eb0796e2bea2ce1b37b2" + "a2f468505e1f8980a9f66d719df034a6fbbd2f9585991d259678fb9a4aebdc465d22c240351ed44abffbdd11b79a706fdf7c40158d3da87f68" + "d7bd557191a8016b5b899c07bf1b87590feb4fa4203feea9a2a7a73ec224813a12b7a21e5dc93fcde4f0a7620f570d31fe27e9b8d65b74db7d" + "c18a5e51adc42d7805d4661938"; +}; + +//----- +TEST_F(NodeCreateTransactionIntegrationTests, DISABLED_CanExecuteNodeCreateTransaction) +{ + // Given + const std::shared_ptr adminKey = ED25519PrivateKey::generatePrivateKey(); + + // When / Then + TransactionResponse txResponse; + ASSERT_NO_THROW(txResponse = NodeCreateTransaction() + .setAccountId(getAccountId()) + .setGossipEndpoints(getGossipEndpoints()) + .setServiceEndpoints(getGrpcServiceEndpoints()) + .setGossipCaCertificate(getGossipCertificate()) + .setAdminKey(adminKey->getPublicKey()) + .freezeWith(&getTestClient()) + .sign(adminKey) + .execute(getTestClient())); + + TransactionReceipt txReceipt; + ASSERT_NO_THROW(txReceipt = txResponse.getReceipt(getTestClient())); +} \ No newline at end of file