From 15135d84775f75396f3fa8ca95d3a254584020c8 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Wed, 3 Jun 2026 16:38:58 +0300 Subject: [PATCH] feat: generic public executions --- flake.lock | 32 +++--- flake.nix | 2 +- src/i_logos_execution_zone_wallet_module.h | 16 +++ src/logos_execution_zone_wallet_module.cpp | 117 +++++++++++++++++++++ src/logos_execution_zone_wallet_module.h | 17 +++ 5 files changed, 167 insertions(+), 17 deletions(-) diff --git a/flake.lock b/flake.lock index 55b4621..d25c482 100644 --- a/flake.lock +++ b/flake.lock @@ -670,11 +670,11 @@ ] }, "locked": { - "lastModified": 1779716125, - "narHash": "sha256-PfpmvkXyDnQRW0dcnIthGKE17rm5bwm8KLbEqJcm9kM=", + "lastModified": 1780426494, + "narHash": "sha256-u4S2n1wTpLMcWjJKIEYvFcesu8W7bkz3713bap9+phs=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "d77c3dd616384addfcc8c5607860466850fdfcf2", + "rev": "c71089abe9cb4ad169bccfb7cdb8d0d42523a148", "type": "github" }, "original": { @@ -891,17 +891,17 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1780313412, - "narHash": "sha256-2Tpoxwl1yc9ctvMPiDh42Jfld1iUBI3SF3sv8V6VJf0=", + "lastModified": 1780488595, + "narHash": "sha256-OCGxIR0yq07OcTCxLSEb8WR/5Hrtv51L0g1Utdjp4fw=", "owner": "logos-blockchain", "repo": "lssa", - "rev": "18e1bea512ab0c74e7ee701871628c93168b80ce", + "rev": "a999563a2d27325ecada318746f1a0dc083d187f", "type": "github" }, "original": { "owner": "logos-blockchain", "repo": "lssa", - "rev": "18e1bea512ab0c74e7ee701871628c93168b80ce", + "rev": "a999563a2d27325ecada318746f1a0dc083d187f", "type": "github" } }, @@ -921,11 +921,11 @@ "process-stats": "process-stats_2" }, "locked": { - "lastModified": 1779724404, - "narHash": "sha256-HKgY1cbcm1BgFau0KBJba0pKGNZ/7oJMcqJMhPDQ20Q=", + "lastModified": 1780324383, + "narHash": "sha256-cArQVYE2U50Dyj3Nm78qTYJNemBiAH8WxRzysceAYIc=", "owner": "logos-co", "repo": "logos-liblogos", - "rev": "be7c8fd8e89e9c7506421735e18dc85bde0c1cb2", + "rev": "51313eb58f2566efaa6ece82071a34e3bc4f7f61", "type": "github" }, "original": { @@ -1140,11 +1140,11 @@ ] }, "locked": { - "lastModified": 1780067269, - "narHash": "sha256-t8rzOR1H+q4PLrJnr+umNyJ7YsYYTWLoUZ3IeUH++4M=", + "lastModified": 1780432590, + "narHash": "sha256-Cv1PfovEI+I5eV2A7HAa8ii1MD4JdsrZz3Ltp4/sMK4=", "owner": "logos-co", "repo": "logos-module-builder", - "rev": "131faf1522947416cbbe3faffcac6191d5147c0d", + "rev": "5557c3b0e4848e3b0481e2386ab0ea9cf1b8bdc5", "type": "github" }, "original": { @@ -6465,11 +6465,11 @@ ] }, "locked": { - "lastModified": 1778168561, - "narHash": "sha256-BINVw7hztdrDkoDSdmnKZes7A15g1SmXKjIHpjZv/3I=", + "lastModified": 1780432542, + "narHash": "sha256-LcZnXuNTCyFQS7rhOHF3sy+oF6PNq/H1MLPHch08XrU=", "owner": "logos-co", "repo": "logos-test-framework", - "rev": "44816073a437fde4203e140b896e70a387c0678a", + "rev": "ee081954096f602b47308c6dc7d00fb71d5dcdc7", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 1ddf6d7..2913bd9 100644 --- a/flake.nix +++ b/flake.nix @@ -4,7 +4,7 @@ inputs = { logos-module-builder.url = "github:logos-co/logos-module-builder"; nix-bundle-lgx.url = "github:logos-co/nix-bundle-lgx"; - logos-execution-zone.url = "github:logos-blockchain/lssa?rev=18e1bea512ab0c74e7ee701871628c93168b80ce"; # branch with the latest functionality + logos-execution-zone.url = "github:logos-blockchain/lssa?rev=a999563a2d27325ecada318746f1a0dc083d187f"; # branch with the latest functionality }; outputs = inputs@{ logos-module-builder, ... }: diff --git a/src/i_logos_execution_zone_wallet_module.h b/src/i_logos_execution_zone_wallet_module.h index def8a41..4037277 100644 --- a/src/i_logos_execution_zone_wallet_module.h +++ b/src/i_logos_execution_zone_wallet_module.h @@ -88,6 +88,22 @@ public: virtual QString register_public_account(const QString& account_id_hex) = 0; virtual QString register_private_account(const QString& account_id_hex) = 0; + virtual QList serialization_helper(const QList& input_data) = 0; + + virtual QString send_generic_public_transaction( + const QList& account_ids, + const QList& signing_requirements, + const QList& instruction, + const QList& program_elf, + const QList>& program_dependencies, + ) = 0; + virtual QString send_generic_private_transaction( + const QList& account_ids, + const QList& instruction, + const QList& program_elf, + const QList>& program_dependencies, + ) = 0; + // Wallet Lifecycle virtual int create_new( const QString& config_path, diff --git a/src/logos_execution_zone_wallet_module.cpp b/src/logos_execution_zone_wallet_module.cpp index aed6c09..09e763a 100644 --- a/src/logos_execution_zone_wallet_module.cpp +++ b/src/logos_execution_zone_wallet_module.cpp @@ -93,6 +93,23 @@ static QString transferResultToJson(const FfiTransferResult* result, const QStri return QJsonDocument(QJsonObject::fromVariantMap(map)).toJson(QJsonDocument::Compact); } +// Builds JSON { success, tx_hash, secrets, error } for both success (result + empty error) and failure (nullptr + errorMessage) in case of generic transaction. +static QString genericTransactionResultToJson(const FfiTransactionResult* result, const QString& errorMessage) { + QVariantMap map; + const bool isError = !errorMessage.isEmpty(); + map[JsonKeys::Success] = !isError && result && result->success; + map[JsonKeys::TxHash] = (!isError && result && result->tx_hash) ? QString::fromUtf8(result->tx_hash) : QString(); + QVariantList secrets; + if (!isError && result && result->secrets_data) { + for (uintptr_t i = 0; i < result->secrets_size; ++i) { + secrets.append(bytes32ToHex(result->secrets_data[i])); + } + } + map[JsonKeys::Secrets] = secrets; + map[JsonKeys::Error] = errorMessage; + return QJsonDocument(QJsonObject::fromVariantMap(map)).toJson(QJsonDocument::Compact); +} + static QString ffiAccountToJson(const FfiAccount& account) { QVariantMap map; map[JsonKeys::ProgramOwner] = bytesToHex(reinterpret_cast(account.program_owner.data), 32); @@ -726,6 +743,106 @@ QString LogosExecutionZoneWalletModule::register_private_account(const QString& return resultJson; } +QList LogosExecutionZoneWalletModule::serialization_helper(const QList& input_data) { + const uint8_t *input_instruction_data = input_data.constData(); + uintptr_t input_instruction_data_size = static_cast(input_data.size()); + FfiInstructionWords raw_words = wallet_ffi_serialization_helper(input_instruction_data, input_instruction_data_size); + if (raw_words.error != SUCCESS) { + qWarning() << "serialization_helper: wallet FFI error" << raw_words.error; + return QList {}; + } + QList result(raw_words.instruction_words, raw_words.instruction_words + raw_words.instruction_words_size); + wallet_ffi_free_instruction_words(&raw_words); + return result; +} + +QString send_generic_public_transaction( + const QList& account_ids, + const QList& signing_requirements, + const QList& instruction, + const QList& program_elf, + const QList>& program_dependencies, +) { + QList identities_resolved; + identities_resolved.reserve(account_ids.size()); + + for (int i = 0; i < account_ids.size(); ++i) { + FfiAccountIdentity acc_identity{}; + WalletFfiError error = wallet_ffi_resolve_public_account(account_ids[i], signing_requirements[i], &acc_identity); + if (error != SUCCESS) { + qWarning() << "wallet_ffi_resolve_public_account failed for index" << i << " : wallet FFI error" << error; + return transferResultToJson(nullptr, QStringLiteral("wallet_ffi_resolve_public_account: wallet FFI error ") + QString::number(error)); + } + resolved.append(acc_identity); + } + + const FfiAccountIdentity *account_identities = resolved.constData(); + uintptr_t account_identities_size = static_cast(resolved.size()); + + const uint8_t *input_instruction_data = instruction.constData(); + uintptr_t input_instruction_data_size = static_cast(instruction.size()); + FfiInstructionWords raw_words = wallet_ffi_serialization_helper(input_instruction_data, input_instruction_data_size); + if (raw_words.error != SUCCESS) { + qWarning() << "wallet_ffi_resolve_public_account failed at instruction serialization: wallet FFI error" << raw_words.error; + return transferResultToJson(nullptr, QStringLiteral("wallet_ffi_resolve_public_account: wallet FFI error ") + QString::number(error)); + } + + FfiProgram main_program {}; + + const uint8_t *program_elf_data = program_elf.constData(); + uintptr_t program_elf_size = static_cast(program_elf.size()); + + main_program.elf_data = program_elf_data; + main_program.elf_size = program_elf_size; + + QList ffi_program_dependencies; + + for (int i = 0; i < program_dependencies.size(); ++i) { + FfiProgram program{}; + + const uint8_t *program_elf_data = program_dependencies[i].constData(); + uintptr_t program_elf_size = static_cast(program_dependencies[i].size()); + + program.elf_data = program_elf_data; + program.elf_size = program_elf_size; + + ffi_program_dependencies.append(program); + } + + const FfiProgram *dependencies_data = ffi_program_dependencies.constData(); + uintptr_t dependencies_size = static_cast(ffi_program_dependencies.size()); + + FfiProgramWithDependencies program_with_dependencies {}; + + program_with_dependencies.program = main_program; + program_with_dependencies.deps = dependencies_data; + program_with_dependencies.deps_size = dependencies_size; + + FfiTransactionResult result {}; + + const WalletFfiError error = wallet_ffi_send_generic_public_transaction( + walletHandle, + account_identities, + account_identities_size, + raw_words.instruction_words, + raw_words.instruction_words_size, + &program_with_dependencies, + result, + ); + + for (FfiAccountIdentity& acc_identity : identities_resolved) { + wallet_ffi_free_account_identity(&acc_identity); + } + + if (error != SUCCESS) { + qWarning() << "send_generic_public_transaction: wallet FFI error" << error; + return transferResultToJson(nullptr, QStringLiteral("send_generic_public_transaction: wallet FFI error ") + QString::number(error)); + } + QString resultJson = genericTransactionResultToJson(&result, QString()); + wallet_ffi_free_transaction_result(&result); + return resultJson; +} + // === Wallet Lifecycle === int LogosExecutionZoneWalletModule::create_new( diff --git a/src/logos_execution_zone_wallet_module.h b/src/logos_execution_zone_wallet_module.h index bf30074..976e9e0 100644 --- a/src/logos_execution_zone_wallet_module.h +++ b/src/logos_execution_zone_wallet_module.h @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include class LogosExecutionZoneWalletModule : public QObject, public PluginInterface, public ILogosExecutionZoneWalletModule { Q_OBJECT @@ -115,6 +116,22 @@ public: Q_INVOKABLE QString register_public_account(const QString& account_id_hex) override; Q_INVOKABLE QString register_private_account(const QString& account_id_hex) override; + Q_INVOKABLE QList serialization_helper(const QList& input_data) override; + + Q_INVOKABLE QString send_generic_public_transaction( + const QList& account_ids, + const QList& signing_requirements, + const QList& instruction, + const QList& program_elf, + const QList>& program_dependencies, + ) override; + Q_INVOKABLE QString send_generic_private_transaction( + const QList& account_ids, + const QList& instruction, + const QList& program_elf, + const QList>& program_dependencies, + ) override; + // Wallet Lifecycle Q_INVOKABLE int create_new(const QString& config_path, const QString& storage_path, const QString& password) override; Q_INVOKABLE int open(const QString& config_path, const QString& storage_path) override;