Skip to content

Commit

Permalink
Merge branch 'main' into 00166-test-for-networking-configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
deyanzz authored Oct 20, 2023
2 parents cf91ebf + 9a3cdaa commit 5eb7f73
Show file tree
Hide file tree
Showing 25 changed files with 841 additions and 40 deletions.
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@
*.bak

### VisualStudioCode template
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.vscode/
*.code-workspace

# Local History for Visual Studio Code
Expand Down
8 changes: 8 additions & 0 deletions sdk/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ 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(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)
set(PRNG_EXAMPLE_NAME ${PROJECT_NAME}-prng-example)
set(SCHEDULE_EXAMPLE_NAME ${PROJECT_NAME}-schedule-example)
set(SCHEDULE_IDENTICAL_TRANSACTION_EXAMPLE_NAME ${PROJECT_NAME}-schedule-identical-transaction-example)
set(SCHEDULE_MULTI_SIG_TRANSACTION_EXAMPLE_NAME ${PROJECT_NAME}-schedule-multisig-transaction-example)
Expand Down Expand Up @@ -68,7 +70,9 @@ 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(${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)
add_executable(${PRNG_EXAMPLE_NAME} PrngExample.cc)
add_executable(${SCHEDULE_EXAMPLE_NAME} ScheduleExample.cc)
add_executable(${SCHEDULE_IDENTICAL_TRANSACTION_EXAMPLE_NAME} ScheduleIdenticalTransactionExample.cc)
add_executable(${SCHEDULE_MULTI_SIG_TRANSACTION_EXAMPLE_NAME} ScheduleMultiSigTransactionExample.cc)
Expand Down Expand Up @@ -129,7 +133,9 @@ 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(${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})
target_link_libraries(${PRNG_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${SCHEDULE_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${SCHEDULE_IDENTICAL_TRANSACTION_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${SCHEDULE_MULTI_SIG_TRANSACTION_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
Expand Down Expand Up @@ -173,7 +179,9 @@ install(TARGETS
${GET_EXCHANGE_RATES_EXAMPLE_NAME}
${GET_FILE_CONTENTS_EXAMPLE_NAME}
${MULTI_APP_TRANSFER_EXAMPLE_NAME}
${MULTI_SIG_OFFLINE_EXAMPLE_NAME}
${NFT_ADD_REMOVE_ALLOWANCES_EXAMPLE_NAME}
${PRNG_EXAMPLE_NAME}
${SCHEDULE_EXAMPLE_NAME}
${SCHEDULE_IDENTICAL_TRANSACTION_EXAMPLE_NAME}
${SCHEDULE_MULTI_SIG_TRANSACTION_EXAMPLE_NAME}
Expand Down
94 changes: 94 additions & 0 deletions sdk/examples/MultiSigOfflineExample.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*-
*
* Hedera C++ SDK
*
* Copyright (C) 2020 - 2023 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 "AccountBalance.h"
#include "AccountBalanceQuery.h"
#include "AccountCreateTransaction.h"
#include "Client.h"
#include "ECDSAsecp256k1PrivateKey.h"
#include "ED25519PrivateKey.h"
#include "KeyList.h"
#include "Status.h"
#include "TransactionReceipt.h"
#include "TransactionResponse.h"
#include "TransferTransaction.h"
#include "WrappedTransaction.h"

#include <cstddef>
#include <iostream>
#include <memory>
#include <vector>

using namespace Hedera;

int main(int argc, char** argv)
{
if (argc < 3)
{
std::cout << "Please input account ID and private key" << std::endl;
return 1;
}

// Get a client for the Hedera testnet, and set the operator account ID and key such that all generated transactions
// will be paid for by this account and be signed by this key.
Client client = Client::forTestnet();
client.setOperator(AccountId::fromString(argv[1]), ED25519PrivateKey::fromString(argv[2]));

// Generate a multi-sig account.
const std::shared_ptr<ED25519PrivateKey> key1 = ED25519PrivateKey::generatePrivateKey();
const std::shared_ptr<ECDSAsecp256k1PrivateKey> key2 = ECDSAsecp256k1PrivateKey::generatePrivateKey();
const AccountId accountId = AccountCreateTransaction()
.setKey(std::make_shared<KeyList>(KeyList::of({ key1, key2 })))
.setInitialBalance(Hbar(5LL))
.execute(client)
.getReceipt(client)
.mAccountId.value();
std::cout << "Created multi-sig account with ID " << accountId.toString() << std::endl;

// Create a transfer of 2 Hbar from the new account to the operator account.
TransferTransaction transferTransaction = TransferTransaction()
.setNodeAccountIds({ AccountId(3ULL) })
.addHbarTransfer(accountId, Hbar(-2LL))
.addHbarTransfer(client.getOperatorAccountId().value(), Hbar(2LL))
.freezeWith(&client);

// Serialize the transaction and "send" it to its signatories.
std::vector<std::byte> transferTransactionBytes = transferTransaction.toBytes();
WrappedTransaction wrappedTransferTransaction = Transaction<TransferTransaction>::fromBytes(transferTransactionBytes);

// Users sign the transaction with their private keys.
const std::vector<std::byte> key1Signature = key1->signTransaction(wrappedTransferTransaction);
const std::vector<std::byte> key2Signature = key2->signTransaction(wrappedTransferTransaction);

// Add the signatures.
transferTransaction = *wrappedTransferTransaction.getTransaction<TransferTransaction>();
transferTransaction.signWithOperator(client);
transferTransaction.addSignature(key1->getPublicKey(), key1Signature);
transferTransaction.addSignature(key2->getPublicKey(), key2Signature);

// Execute the transaction with all signatures.
transferTransaction.execute(client).getReceipt(client);

// Get the balance of the multi-sig account.
std::cout << "Balance of multi-sign account (should be 3 Hbar): "
<< AccountBalanceQuery().setAccountId(accountId).execute(client).getBalance().toTinybars()
<< HbarUnit::TINYBAR().getSymbol() << std::endl;

return 0;
}
48 changes: 48 additions & 0 deletions sdk/examples/PrngExample.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*-
*
* Hedera C++ SDK
*
* Copyright (C) 2020 - 2023 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 "Client.h"
#include "ED25519PrivateKey.h"
#include "PrngTransaction.h"
#include "TransactionRecord.h"
#include "TransactionResponse.h"

#include <iostream>

using namespace Hedera;

int main(int argc, char** argv)
{
if (argc < 3)
{
std::cout << "Please input account ID and private key" << std::endl;
return 1;
}

// Get a client for the Hedera testnet, and set the operator account ID and key such that all generated transactions
// will be paid for by this account and be signed by this key.
Client client = Client::forTestnet();
client.setOperator(AccountId::fromString(argv[1]), ED25519PrivateKey::fromString(argv[2]));

// Get a random number between 0 and 100.
const TransactionRecord txRecord = PrngTransaction().setRange(100).execute(client).getRecord(client);
std::cout << "Randomly generated number: " << txRecord.mPrngNumber.value() << std::endl;

return 0;
}
1 change: 1 addition & 0 deletions sdk/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ add_library(${PROJECT_NAME} STATIC
src/NodeAddress.cc
src/NodeAddressBook.cc
src/PrivateKey.cc
src/PrngTransaction.cc
src/ProxyStaker.cc
src/PublicKey.cc
src/Query.cc
Expand Down
17 changes: 17 additions & 0 deletions sdk/main/include/PrivateKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@

#include "Key.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>

namespace Hedera
{
template<typename SdkRequestType>
class Transaction;

class PublicKey;
class WrappedTransaction;
}

namespace Hedera::internal::OpenSSLUtils
Expand Down Expand Up @@ -119,6 +124,18 @@ class PrivateKey : public Key
*/
[[nodiscard]] virtual std::vector<std::byte> toBytesRaw() const = 0;

/**
* Sign a Transaction with this PrivateKey.
*
* @param transaction The Transaction to sign.
* @return The generated signature.
* @throws IllegalStateException If there is not exactly one node account ID set for the Transaction or if the
* Transaction is not frozen and doesn't have a TransactionId set.
*/
template<typename SdkRequestType>
std::vector<std::byte> signTransaction(Transaction<SdkRequestType>& transaction) const;
std::vector<std::byte> signTransaction(WrappedTransaction& transaction) const;

/**
* Get this PrivateKey's chain code. It is possible that the chain code could be empty.
*
Expand Down
141 changes: 141 additions & 0 deletions sdk/main/include/PrngTransaction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*-
*
* Hedera C++ SDK
*
* Copyright (C) 2020 - 2023 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.
*
*/
#ifndef HEDERA_SDK_CPP_PRNG_TRANSACTION_H_
#define HEDERA_SDK_CPP_PRNG_TRANSACTION_H_

#include "Transaction.h"

namespace proto
{
class UtilPrngTransactionBody;
class TransactionBody;
}

namespace Hedera
{
/**
* A transaction that generates a pseudorandom number. When the pseudorandom number generate transaction executes, its
* transaction record will contain the 384-bit array of pseudorandom bytes. The transaction has an optional range
* parameter. If the parameter is given and is positive, then the record will contain a 32-bit pseudorandom integer r,
* where 0 <= r < range instead of containing the 384 pseudorandom bits.
*
* When the nth transaction needs a pseudorandom number, it is given the running hash of all records up to and including
* the record for transaction n-3. If it needs 384 bits, then it uses the entire hash. If it needs 256 bits, it uses the
* first 256 bits of the hash. If it needs a random number r that is in the range 0 <= r < range, then it lets x be the
* first 32 bits of the hash (interpreted as a signed integer).
*
* The choice of using the hash up to transaction n-3 rather than n-1 is to ensure the transactions can be processed
* quickly. Because the thread calculating the hash will have more time to complete it before it is needed. The use of
* n-3 rather than n-1000000 is to make it hard to predict the pseudorandom number in advance.
*/
class PrngTransaction : public Transaction<PrngTransaction>
{
public:
PrngTransaction() = default;

/**
* Construct from a TransactionBody protobuf object.
*
* @param transactionBody The TransactionBody protobuf object from which to construct.
* @throws std::invalid_argument If the input TransactionBody does not represent a UtilPrng.
*/
explicit PrngTransaction(const proto::TransactionBody& transactionBody);

/**
* Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects.
*
* @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf
* objects.
*/
explicit PrngTransaction(const std::map<TransactionId, std::map<AccountId, proto::Transaction>>& transactions);

/**
* Set the range of the pseudorandom number to generate.
*
* @param range The range of the pseudorandom number to generate.
* @return A reference to this PrngTransaction object with the newly-set range.
* @throws IllegalStateException If this PrngTransaction is frozen.
*/
PrngTransaction& setRange(int range);

/**
* Get the range of the pseudorandom number to generate.
*
* @return The the range of the pseudorandom number to generate.
*/
[[nodiscard]] inline int getRange() const { return mRange; }

private:
friend class WrappedTransaction;

/**
* Derived from Executable. Submit a Transaction protobuf object which contains this PrngTransaction's data to a Node.
*
* @param request The Transaction protobuf object to submit.
* @param node The Node to which to submit the request.
* @param deadline The deadline for submitting the request.
* @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information
* from the gRPC server.
* @return The gRPC status of the submission.
*/
[[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request,
const std::shared_ptr<internal::Node>& node,
const std::chrono::system_clock::time_point& deadline,
proto::TransactionResponse* response) const override;

/**
* Derived from Transaction. Verify that all the checksums in this PrngTransaction are valid.
*
* @param client The Client that should be used to validate the checksums.
* @throws BadEntityException This PrngTransaction's checksums are not valid.
*/
void validateChecksums(const Client& client) const override;

/**
* Derived from Transaction. Build and add the PrngTransaction protobuf representation to the Transaction protobuf
* object.
*
* @param body The TransactionBody protobuf object being built.
*/
void addToBody(proto::TransactionBody& body) const override;

/**
* Initialize this PrngTransaction from its source TransactionBody protobuf object.
*/
void initFromSourceTransactionBody();

/**
* Build a UtilPrngTransactionBody protobuf object from this PrngTransaction object.
*
* @return A pointer to a UtilPrngTransactionBody protobuf object filled with this PrngTransaction object's data.
*/
[[nodiscard]] proto::UtilPrngTransactionBody* build() const;

/**
* The range from which to return the pseudorandom number. If this is , a 384-bit pseudorandom number will be returned
* in the TransactionRecord. If this is set, a 32-bit pseudorandom number will be returned between 0 and the specified
* range.
*/
int mRange = 0;
};

} // namespace Hedera

#endif // HEDERA_SDK_CPP_PRNG_TRANSACTION_H_
2 changes: 2 additions & 0 deletions sdk/main/include/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ class Transaction
[[nodiscard]] virtual TransactionId getCurrentTransactionId() const;

private:
friend class PrivateKey;

/**
* Build and add the derived Transaction's protobuf representation to the Transaction protobuf object.
*
Expand Down
Loading

0 comments on commit 5eb7f73

Please sign in to comment.