feat: generic public executions

This commit is contained in:
Pravdyvy 2026-06-03 16:38:58 +03:00
parent f555a8edae
commit 15135d8477
5 changed files with 167 additions and 17 deletions

32
flake.lock generated
View File

@ -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": {

View File

@ -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, ... }:

View File

@ -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<uint32_t> serialization_helper(const QList<uint8_t>& input_data) = 0;
virtual QString send_generic_public_transaction(
const QList<QString>& account_ids,
const QList<bool>& signing_requirements,
const QList<uint8_t>& instruction,
const QList<uint8_t>& program_elf,
const QList<QList<uint8_t>>& program_dependencies,
) = 0;
virtual QString send_generic_private_transaction(
const QList<QString>& account_ids,
const QList<uint8_t>& instruction,
const QList<uint8_t>& program_elf,
const QList<QList<uint8_t>>& program_dependencies,
) = 0;
// Wallet Lifecycle
virtual int create_new(
const QString& config_path,

View File

@ -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<const uint8_t*>(account.program_owner.data), 32);
@ -726,6 +743,106 @@ QString LogosExecutionZoneWalletModule::register_private_account(const QString&
return resultJson;
}
QList<uint32_t> LogosExecutionZoneWalletModule::serialization_helper(const QList<uint8_t>& input_data) {
const uint8_t *input_instruction_data = input_data.constData();
uintptr_t input_instruction_data_size = static_cast<uintptr_t>(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<uint32_t> {};
}
QList<uint32_t> 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<FfiBytes32>& account_ids,
const QList<bool>& signing_requirements,
const QList<uint8_t>& instruction,
const QList<uint8_t>& program_elf,
const QList<QList<uint8_t>>& program_dependencies,
) {
QList<FfiAccountIdentity> 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<uintptr_t>(resolved.size());
const uint8_t *input_instruction_data = instruction.constData();
uintptr_t input_instruction_data_size = static_cast<uintptr_t>(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<uintptr_t>(program_elf.size());
main_program.elf_data = program_elf_data;
main_program.elf_size = program_elf_size;
QList<FfiProgram> 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<uintptr_t>(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<uintptr_t>(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(

View File

@ -15,6 +15,7 @@ extern "C" {
#include <QObject>
#include <QString>
#include <QVariantList>
#include <QList>
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<uint32_t> serialization_helper(const QList<uint8_t>& input_data) override;
Q_INVOKABLE QString send_generic_public_transaction(
const QList<FfiBytes32>& account_ids,
const QList<bool>& signing_requirements,
const QList<uint8_t>& instruction,
const QList<uint8_t>& program_elf,
const QList<QList<uint8_t>>& program_dependencies,
) override;
Q_INVOKABLE QString send_generic_private_transaction(
const QList<FfiBytes32>& account_ids,
const QList<uint8_t>& instruction,
const QList<uint8_t>& program_elf,
const QList<QList<uint8_t>>& 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;