Skip to content

Commit

Permalink
feat(HIP-423): Long term scheduled transactions (#854)
Browse files Browse the repository at this point in the history
Signed-off-by: gsstoykov <georgi.stoykov@limechain.tech>
  • Loading branch information
gsstoykov authored Dec 11, 2024
1 parent 37ce60f commit 168baef
Show file tree
Hide file tree
Showing 77 changed files with 626 additions and 1,294 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/zxc-build-library.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ jobs:
# run: tree /F build

- name: Start the local node
run: npx hedera start --verbose=trace --detached --network-tag=0.54.0-alpha.5
run: npx hedera start --verbose=trace --detached --network-tag=0.57.0

- name: Start CTest suite (Debug)
run: ${{ steps.cgroup.outputs.exec }} ctest -j 6 -C Debug --test-dir build/${{ matrix.preset }}-debug --output-on-failure
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,7 @@ src/proto/*.proto
/proto/*.proto
/proto/mirror
/proto/state
/proto/auxiliary

### Ignore Generated Package Files
package
Expand Down
4 changes: 2 additions & 2 deletions HieroApi.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set(HAPI_VERSION_TAG "v0.55.0" CACHE STRING "Use the configured version tag for the Hiero API protobufs")
set(HAPI_VERSION_TAG "v0.57.0" CACHE STRING "Use the configured version tag for the Hiero API protobufs")

if (HAPI_VERSION_TAG STREQUAL "")
set(HAPI_VERSION_TAG "v0.55.0")
set(HAPI_VERSION_TAG "v0.57.0")
endif ()

# Fetch the protobuf definitions
Expand Down
4 changes: 4 additions & 0 deletions proto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ set(PROTO_FILES
util_prng.proto
util_service.proto

auxiliary/tss/tss_message.proto
auxiliary/tss/tss_share_signature.proto
auxiliary/tss/tss_vote.proto

mirror/consensus_service.proto
mirror/mirror_network_service.proto)
# End Protobuf Definitions
Expand Down
4 changes: 4 additions & 0 deletions src/sdk/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ 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(LONG_TERM_SCHEDULED_TRANSACTION_EXAMPLE_NAME ${PROJECT_NAME}-long-term-scheduled-transaction-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)
Expand Down Expand Up @@ -93,6 +94,7 @@ 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(${LONG_TERM_SCHEDULED_TRANSACTION_EXAMPLE_NAME} LongTermScheduledTransactionExample.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)
Expand Down Expand Up @@ -170,6 +172,7 @@ 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(${LONG_TERM_SCHEDULED_TRANSACTION_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})
Expand Down Expand Up @@ -227,6 +230,7 @@ install(TARGETS
${GET_EXCHANGE_RATES_EXAMPLE_NAME}
${GET_FILE_CONTENTS_EXAMPLE_NAME}
${INITIALIZE_CLIENT_WITH_MIRROR_NODE_ADDRESS_BOOK_EXAMPLE_NAME}
${LONG_TERM_SCHEDULED_TRANSACTION_EXAMPLE_NAME}
${MULTI_APP_TRANSFER_EXAMPLE_NAME}
${MULTI_SIG_OFFLINE_EXAMPLE_NAME}
${NFT_ADD_REMOVE_ALLOWANCES_EXAMPLE_NAME}
Expand Down
20 changes: 1 addition & 19 deletions src/sdk/examples/GetAccountBalanceExample.cc
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
/*-
*
* Hiero C++ SDK
*
* Copyright (C) 2020 - 2024 Hiero
*
* 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.
*
*/
// SPDX-License-Identifier: Apache-2.0
#include "AccountBalance.h"
#include "AccountBalanceQuery.h"
#include "Client.h"
Expand Down
20 changes: 1 addition & 19 deletions src/sdk/examples/GetAddressBookExample.cc
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
/*-
*
* Hiero C++ SDK
*
* Copyright (C) 2020 - 2024 Hiero
*
* 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.
*
*/
// SPDX-License-Identifier: Apache-2.0
#include "AddressBookQuery.h"
#include "Client.h"
#include "FileId.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
/*-
*
* Hiero C++ SDK
*
* Copyright (C) 2020 - 2024 Hiero
*
* 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.
*
*/
// SPDX-License-Identifier: Apache-2.0
#include "AccountCreateTransaction.h"
#include "Client.h"
#include "ED25519PrivateKey.h"
Expand Down
169 changes: 169 additions & 0 deletions src/sdk/examples/LongTermScheduledTransactionExample.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// SPDX-License-Identifier: Apache-2.0
#include "AccountBalance.h"
#include "AccountBalanceQuery.h"
#include "AccountCreateTransaction.h"
#include "AccountUpdateTransaction.h"
#include "Client.h"
#include "ED25519PrivateKey.h"
#include "PrivateKey.h"
#include "ScheduleCreateTransaction.h"
#include "ScheduleInfo.h"
#include "ScheduleInfoQuery.h"
#include "TransactionReceipt.h"
#include "TransactionResponse.h"
#include "TransferTransaction.h"
#include "WrappedTransaction.h"
#include "exceptions/ReceiptStatusException.h"
#include "impl/Utilities.h"

#include <dotenv.h>
#include <iostream>
#include <thread>

using namespace Hiero;

int main(int argc, char** argv)
{
// Step 0: Create and configure the SDK Client.
dotenv::init();
const AccountId operatorAccountId = AccountId::fromString(std::getenv("OPERATOR_ID"));
const std::shared_ptr<PrivateKey> operatorPrivateKey = ED25519PrivateKey::fromString(std::getenv("OPERATOR_KEY"));

// Get a client for the Hiero 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(operatorAccountId, operatorPrivateKey);

// Step 1: Create key pairs
std::cout << "Creating a Key List...(with threshold, requiring 2 of 2 keys to sign)." << std::endl;

// Generate three ED25519 private keys.
const std::vector<std::shared_ptr<PrivateKey>> privateKeys = {
ED25519PrivateKey::generatePrivateKey(),
ED25519PrivateKey::generatePrivateKey(),
};

// Create a Keylist from the list of generated private keys that require 2 of the 3 keys to sign.
auto keys = std::make_shared<KeyList>(KeyList::of({ privateKeys.at(0), privateKeys.at(1) }));
keys->setThreshold(2);

std::cout << "Created a Key List: " << keys->toString() << std::endl;

// Step 2: Create the account
std::cout << "Creating new account with the above Key List as an account key." << std::endl;

AccountId alice = AccountCreateTransaction()
.setKey(keys)
.setInitialBalance(Hbar(2LL))
.execute(client)
.getReceipt(client)
.mAccountId.value();

std::cout << "Created new account with ID: " << alice.toString() << std::endl;

// Step 3: Schedule a transfer transaction of 1 Hbar from the created account to the operator account
std::cout << "Creating new scheduled transaction with 1 day expiry." << std::endl;

const WrappedTransaction scheduledTransaction(
TransferTransaction().addHbarTransfer(alice, Hbar(-1LL)).addHbarTransfer(operatorAccountId, Hbar(1LL)));

TransactionReceipt txReceipt = ScheduleCreateTransaction()
.setScheduledTransaction(scheduledTransaction)
.setExpirationTime(std::chrono::system_clock::now() + std::chrono::hours(24))
.setWaitForExpiry(false)
.execute(client)
.getReceipt(client);

const ScheduleId scheduleId = txReceipt.mScheduleId.value();

// Step 4: Sign the transaction with one key and verify it is not executed
std::cout << "Signing the new scheduled transaction with 1 key" << std::endl;

txReceipt = ScheduleSignTransaction()
.setScheduleId(scheduleId)
.freezeWith(&client)
.sign(privateKeys[0])
.execute(client)
.getReceipt(client);

ScheduleInfo info = ScheduleInfoQuery().setScheduleId(scheduleId).execute(client);
std::cout << "Scheduled transaction is not yet executed. Is executed?: " << info.mExecutionTime.has_value()
<< std::endl;

// Step 5: Sign the transaction with the other key and verify the transaction executes
auto accountBalance = AccountBalanceQuery().setAccountId(alice).execute(client);
std::cout << "Alice's account balance before schedule transfer: " << accountBalance.mBalance.toString() << std::endl;

std::cout << "Signing the new scheduled transaction with the 2nd key" << std::endl;
txReceipt = ScheduleSignTransaction()
.setScheduleId(scheduleId)
.freezeWith(&client)
.sign(privateKeys[1])
.execute(client)
.getReceipt(client);

accountBalance = AccountBalanceQuery().setAccountId(alice).execute(client);
std::cout << "Alice's account balance after schedule transfer: " << accountBalance.mBalance.toString() << std::endl;

info = ScheduleInfoQuery().setScheduleId(scheduleId).execute(client);
std::cout << "Scheduled transaction is executed. Is executed?: " << info.mExecutionTime.has_value() << std::endl;

// Step 6: Schedule another transfer transaction with a 10-second expiration
std::cout << "Creating new scheduled transaction with 10 seconds expiry." << std::endl;

const WrappedTransaction scheduledTransactionShort(
TransferTransaction().addHbarTransfer(alice, Hbar(-1LL)).addHbarTransfer(operatorAccountId, Hbar(1LL)));

txReceipt = ScheduleCreateTransaction()
.setScheduledTransaction(scheduledTransactionShort)
.setExpirationTime(std::chrono::system_clock::now() + std::chrono::seconds(10))
.setWaitForExpiry(true)
.execute(client)
.getReceipt(client);

const ScheduleId scheduleId2 = txReceipt.mScheduleId.value();

auto expirationTime = std::chrono::system_clock::now() + std::chrono::seconds(10);

long startTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
long elapsedTime = 0;

// Step 7: Sign the transaction with one key and verify it is not executed
std::cout << "Signing the new scheduled transaction with 1 key" << std::endl;

txReceipt = ScheduleSignTransaction()
.setScheduleId(scheduleId2)
.freezeWith(&client)
.sign(privateKeys[1])
.execute(client)
.getReceipt(client);

info = ScheduleInfoQuery().setScheduleId(scheduleId2).execute(client);
std::cout << "Scheduled transaction is not yet executed. Is executed?: " << info.mExecutionTime.has_value()
<< std::endl;

// Step 8: Update the account’s key to be only the one key that has already signed the scheduled transfer.
std::cout << "Updating Alice's key to be the 1st key" << std::endl;

txReceipt = AccountUpdateTransaction()
.setAccountId(alice)
.setKey(privateKeys[0]->getPublicKey())
.freezeWith(&client)
.sign(privateKeys[0])
.sign(privateKeys[1])
.execute(client)
.getReceipt(client);

// Step 9: Verify the transfer executes roughly at the time of expiration.
accountBalance = AccountBalanceQuery().setAccountId(alice).execute(client);
std::cout << "Alice's account balance before schedule transfer: " << accountBalance.mBalance.toString() << std::endl;

std::cout << "Wait 10 seconds." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10000));

accountBalance = AccountBalanceQuery().setAccountId(alice).execute(client);
std::cout << "Alice's account balance after schedule transfer: " << accountBalance.mBalance.toString() << std::endl;

std::cout << "Long Term Scheduled Transaction Example Complete!" << std::endl;
return 0;
}
20 changes: 1 addition & 19 deletions src/sdk/main/include/Logger.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
/*-
*
* Hiero C++ SDK
*
* Copyright (C) 2020 - 2024 Hiero
*
* 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.
*
*/
// SPDX-License-Identifier: Apache-2.0
#ifndef HIERO_SDK_CPP_LOGGER_H_
#define HIERO_SDK_CPP_LOGGER_H_

Expand Down
20 changes: 1 addition & 19 deletions src/sdk/main/include/NftId.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
/*-
*
* Hiero C++ SDK
*
* Copyright (C) 2020 - 2024 Hiero
*
* 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.
*
*/
// SPDX-License-Identifier: Apache-2.0
#ifndef HIERO_SDK_CPP_NFT_ID_H_
#define HIERO_SDK_CPP_NFT_ID_H_

Expand Down
20 changes: 1 addition & 19 deletions src/sdk/main/include/ProxyStaker.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
/*-
*
* Hiero C++ SDK
*
* Copyright (C) 2020 - 2024 Hiero
*
* 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.
*
*/
// SPDX-License-Identifier: Apache-2.0
#ifndef HIERO_SDK_CPP_PROXY_STAKER_H_
#define HIERO_SDK_CPP_PROXY_STAKER_H_

Expand Down
Loading

0 comments on commit 168baef

Please sign in to comment.