mirror of
https://github.com/logos-blockchain/logos-execution-zone-module.git
synced 2026-07-08 19:49:26 +00:00
Merge pull request #31 from logos-blockchain/Pravdyvy/mnemonic-updates
Mnemonic updates
This commit is contained in:
commit
5537c0065e
11277
flake.lock
generated
11277
flake.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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=cf3639d8252040d13b3d4e933feb19b42c76e14a"; # v0.1.2
|
||||
logos-execution-zone.url = "github:logos-blockchain/lssa?rev=4d055c71a77d4b3aa147dfe8e1673afb3217840b"; # latest mnemonic updates, to be replaced after merging
|
||||
};
|
||||
|
||||
outputs = inputs@{ logos-module-builder, ... }:
|
||||
|
||||
@ -55,6 +55,7 @@ constexpr auto NullifierPublicKey = "nullifier_public_key";
|
||||
constexpr auto ViewingPublicKey = "viewing_public_key";
|
||||
constexpr auto AccountId = "account_id";
|
||||
constexpr auto IsPublic = "is_public";
|
||||
constexpr auto Secrets = "secrets";
|
||||
} // namespace JsonKeys
|
||||
|
||||
bool hexToBytes(const std::string& hex, std::vector<uint8_t>& output_bytes, int expectedLength = -1) {
|
||||
@ -127,6 +128,23 @@ std::string transferResultToJson(const FfiTransferResult* result, const std::str
|
||||
return obj.dump();
|
||||
}
|
||||
|
||||
// Builds JSON { success, tx_hash, secrets, error } for both success (result + empty error) and failure (nullptr + errorMessage) in case of generic transaction.
|
||||
std::string genericTransactionResultToJson(const FfiTransactionResult* result, const std::string& errorMessage) {
|
||||
nlohmann::json obj = nlohmann::json::object();
|
||||
const bool isError = !errorMessage.empty();
|
||||
obj[JsonKeys::Success] = !isError && result && result->success;
|
||||
obj[JsonKeys::TxHash] = (!isError && result && result->tx_hash) ? std::string(result->tx_hash) : std::string();
|
||||
std::vector<std::string> secrets;
|
||||
if (!isError && result && result->secrets_data) {
|
||||
for (uintptr_t i = 0; i < result->secrets_size; ++i) {
|
||||
secrets.push_back(bytes32ToHex(result->secrets_data[i]));
|
||||
}
|
||||
}
|
||||
obj[JsonKeys::Secrets] = secrets;
|
||||
obj[JsonKeys::Error] = errorMessage;
|
||||
return obj.dump();
|
||||
}
|
||||
|
||||
std::string ffiAccountToJson(const FfiAccount& account) {
|
||||
nlohmann::json obj = nlohmann::json::object();
|
||||
obj[JsonKeys::ProgramOwner] = bytesToHex(reinterpret_cast<const uint8_t*>(account.program_owner.data), 32);
|
||||
@ -573,8 +591,13 @@ std::string LogosExecutionZoneWalletModule::transfer_shielded(
|
||||
return transferResultToJson(nullptr, "transfer_shielded: amount_le16_hex must be 32 hex characters (16 bytes)");
|
||||
}
|
||||
|
||||
// ToDo: Bandaid, I am not sure, how exactly identifiers should be used.
|
||||
FfiU128 identifier {};
|
||||
// ToDo: Add keycard support
|
||||
const char *key_path = nullptr;
|
||||
|
||||
FfiTransferResult result{};
|
||||
const WalletFfiError error = wallet_ffi_transfer_shielded(walletHandle, &fromId, &toKeys, &amount, &result);
|
||||
const WalletFfiError error = wallet_ffi_transfer_shielded(walletHandle, &fromId, &toKeys, &identifier, &amount, key_path, &result);
|
||||
free(const_cast<uint8_t*>(toKeys.viewing_public_key));
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "transfer_shielded: wallet FFI error %d\n", error);
|
||||
@ -637,8 +660,11 @@ std::string LogosExecutionZoneWalletModule::transfer_private(
|
||||
return transferResultToJson(nullptr, "transfer_private: amount_le16_hex must be 32 hex characters (16 bytes)");
|
||||
}
|
||||
|
||||
// ToDo: Bandaid, I am not sure, how exactly identifiers should be used.
|
||||
FfiU128 identifier {};
|
||||
|
||||
FfiTransferResult result{};
|
||||
const WalletFfiError error = wallet_ffi_transfer_private(walletHandle, &fromId, &toKeys, &amount, &result);
|
||||
const WalletFfiError error = wallet_ffi_transfer_private(walletHandle, &fromId, &toKeys, &identifier, &amount, &result);
|
||||
free(const_cast<uint8_t*>(toKeys.viewing_public_key));
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "transfer_private: wallet FFI error %d\n", error);
|
||||
@ -666,8 +692,11 @@ std::string LogosExecutionZoneWalletModule::transfer_shielded_owned(
|
||||
return transferResultToJson(nullptr, "transfer_shielded_owned: amount_le16_hex must be 32 hex characters (16 bytes)");
|
||||
}
|
||||
|
||||
// ToDo: Add keycard support
|
||||
const char *key_path = nullptr;
|
||||
|
||||
FfiTransferResult result{};
|
||||
const WalletFfiError error = wallet_ffi_transfer_shielded_owned(walletHandle, &fromId, &toId, &amount, &result);
|
||||
const WalletFfiError error = wallet_ffi_transfer_shielded_owned(walletHandle, &fromId, &toId, &amount, key_path, &result);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "transfer_shielded_owned: wallet FFI error %d\n", error);
|
||||
return transferResultToJson(nullptr, "transfer_shielded_owned: wallet FFI error " + std::to_string(error));
|
||||
@ -739,22 +768,300 @@ std::string LogosExecutionZoneWalletModule::register_private_account(const std::
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> LogosExecutionZoneWalletModule::token_elf() {
|
||||
FfiProgram ffi_program{};
|
||||
WalletFfiError error = wallet_ffi_token_elf(&ffi_program);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "token_elf: wallet FFI error %d\n", error);
|
||||
return std::vector<uint8_t>{};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> result(ffi_program.elf_data,
|
||||
ffi_program.elf_data + ffi_program.elf_size);
|
||||
|
||||
wallet_ffi_free_ffi_program(&ffi_program);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> LogosExecutionZoneWalletModule::amm_elf() {
|
||||
FfiProgram ffi_program{};
|
||||
WalletFfiError error = wallet_ffi_token_elf(&ffi_program);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "amm_elf: wallet FFI error %d\n", error);
|
||||
return std::vector<uint8_t>{};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> result(ffi_program.elf_data,
|
||||
ffi_program.elf_data + ffi_program.elf_size);
|
||||
|
||||
wallet_ffi_free_ffi_program(&ffi_program);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> LogosExecutionZoneWalletModule::ata_elf() {
|
||||
FfiProgram ffi_program{};
|
||||
WalletFfiError error = wallet_ffi_token_elf(&ffi_program);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "ata_elf: wallet FFI error %d\n", error);
|
||||
return std::vector<uint8_t>{};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> result(ffi_program.elf_data,
|
||||
ffi_program.elf_data + ffi_program.elf_size);
|
||||
|
||||
wallet_ffi_free_ffi_program(&ffi_program);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> LogosExecutionZoneWalletModule::authenticated_transfer_elf() {
|
||||
FfiProgram ffi_program{};
|
||||
WalletFfiError error = wallet_ffi_token_elf(&ffi_program);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "authenticated_transfer_elf: wallet FFI error %d\n", error);
|
||||
return std::vector<uint8_t>{};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> result(ffi_program.elf_data,
|
||||
ffi_program.elf_data + ffi_program.elf_size);
|
||||
|
||||
wallet_ffi_free_ffi_program(&ffi_program);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string LogosExecutionZoneWalletModule::send_generic_public_transaction(
|
||||
const std::vector<std::string>& account_ids,
|
||||
const std::vector<bool>& signing_requirements,
|
||||
const std::vector<uint32_t>& instruction,
|
||||
const std::vector<uint8_t>& program_elf,
|
||||
const std::vector<std::vector<uint8_t>>& program_dependencies
|
||||
) {
|
||||
std::vector<FfiAccountIdentity> identities_resolved;
|
||||
identities_resolved.reserve(account_ids.size());
|
||||
|
||||
for (int i = 0; i < account_ids.size(); ++i) {
|
||||
FfiAccountIdentity acc_identity{};
|
||||
|
||||
FfiBytes32 id{};
|
||||
if (!hexToBytes32(account_ids[i], &id)) {
|
||||
fprintf(stderr, "wallet_ffi_resolve_public_account: invalid account_id_hex");
|
||||
return transferResultToJson(nullptr, std::string("wallet_ffi_resolve_public_account: invalid account_id_hex"));
|
||||
}
|
||||
|
||||
WalletFfiError error = wallet_ffi_resolve_public_account(id, signing_requirements[i], &acc_identity);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "wallet_ffi_resolve_public_account failed for index %d: wallet FFI error %d\n", i, error);
|
||||
return transferResultToJson(nullptr, std::string("wallet_ffi_resolve_public_account: wallet FFI error ") + std::to_string(error));
|
||||
}
|
||||
identities_resolved.push_back(acc_identity);
|
||||
}
|
||||
|
||||
const FfiAccountIdentity *account_identities = identities_resolved.data();
|
||||
uintptr_t account_identities_size = static_cast<uintptr_t>(identities_resolved.size());
|
||||
|
||||
const uint32_t* input_instruction_data = instruction.data();
|
||||
uintptr_t input_instruction_data_size = static_cast<uintptr_t>(instruction.size());
|
||||
|
||||
FfiProgram main_program {};
|
||||
|
||||
const uint8_t *program_elf_data = program_elf.data();
|
||||
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;
|
||||
|
||||
std::vector<FfiProgram> ffi_program_dependencies;
|
||||
ffi_program_dependencies.reserve(program_dependencies.size());
|
||||
|
||||
for (int i = 0; i < program_dependencies.size(); ++i) {
|
||||
FfiProgram program{};
|
||||
|
||||
const uint8_t *program_elf_data = program_dependencies[i].data();
|
||||
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.push_back(program);
|
||||
}
|
||||
|
||||
const FfiProgram *dependencies_data = ffi_program_dependencies.data();
|
||||
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,
|
||||
input_instruction_data,
|
||||
input_instruction_data_size,
|
||||
&program_with_dependencies,
|
||||
&result
|
||||
);
|
||||
|
||||
for (FfiAccountIdentity& acc_identity : identities_resolved) {
|
||||
wallet_ffi_free_account_identity(&acc_identity);
|
||||
}
|
||||
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "send_generic_public_transaction: wallet FFI error %d\n", error);
|
||||
return transferResultToJson(nullptr, std::string("send_generic_public_transaction: wallet FFI error ") + std::to_string(error));
|
||||
}
|
||||
std::string resultJson = genericTransactionResultToJson(&result, std::string());
|
||||
wallet_ffi_free_transaction_result(&result);
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
std::string LogosExecutionZoneWalletModule::send_generic_private_transaction(
|
||||
const std::vector<std::string>& account_ids,
|
||||
const std::vector<uint32_t>& instruction,
|
||||
const std::vector<uint8_t>& program_elf,
|
||||
const std::vector<std::vector<uint8_t>>& program_dependencies
|
||||
) {
|
||||
std::vector<FfiAccountIdentity> identities_resolved;
|
||||
identities_resolved.reserve(account_ids.size());
|
||||
|
||||
for (int i = 0; i < account_ids.size(); ++i) {
|
||||
FfiAccountIdentity acc_identity{};
|
||||
|
||||
FfiBytes32 id{};
|
||||
if (!hexToBytes32(account_ids[i], &id)) {
|
||||
fprintf(stderr, "wallet_ffi_resolve_private_account: invalid account_id_hex");
|
||||
return transferResultToJson(nullptr, std::string("wallet_ffi_resolve_private_account: invalid account_id_hex"));
|
||||
}
|
||||
|
||||
WalletFfiError error = wallet_ffi_resolve_private_account(walletHandle, id, &acc_identity);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "wallet_ffi_resolve_private_account failed for index %d: wallet FFI error %d\n", i, error);
|
||||
return transferResultToJson(nullptr, std::string("wallet_ffi_resolve_private_account: wallet FFI error ") + std::to_string(error));
|
||||
}
|
||||
identities_resolved.push_back(acc_identity);
|
||||
}
|
||||
|
||||
const FfiAccountIdentity *account_identities = identities_resolved.data();
|
||||
uintptr_t account_identities_size = static_cast<uintptr_t>(identities_resolved.size());
|
||||
|
||||
const uint32_t* input_instruction_data = instruction.data();
|
||||
uintptr_t input_instruction_data_size = static_cast<uintptr_t>(instruction.size());
|
||||
|
||||
FfiProgram main_program {};
|
||||
|
||||
const uint8_t *program_elf_data = program_elf.data();
|
||||
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;
|
||||
|
||||
std::vector<FfiProgram> ffi_program_dependencies;
|
||||
ffi_program_dependencies.reserve(program_dependencies.size());
|
||||
|
||||
for (int i = 0; i < program_dependencies.size(); ++i) {
|
||||
FfiProgram program{};
|
||||
|
||||
const uint8_t *program_elf_data = program_dependencies[i].data();
|
||||
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.push_back(program);
|
||||
}
|
||||
|
||||
const FfiProgram *dependencies_data = ffi_program_dependencies.data();
|
||||
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_private_transaction(
|
||||
walletHandle,
|
||||
account_identities,
|
||||
account_identities_size,
|
||||
input_instruction_data,
|
||||
input_instruction_data_size,
|
||||
&program_with_dependencies,
|
||||
&result
|
||||
);
|
||||
|
||||
for (FfiAccountIdentity& acc_identity : identities_resolved) {
|
||||
wallet_ffi_free_account_identity(&acc_identity);
|
||||
}
|
||||
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "send_generic_private_transaction: wallet FFI error %d\n", error);
|
||||
return transferResultToJson(nullptr, std::string("send_generic_private_transaction: wallet FFI error ") + std::to_string(error));
|
||||
}
|
||||
std::string resultJson = genericTransactionResultToJson(&result, std::string());
|
||||
wallet_ffi_free_transaction_result(&result);
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
std::string LogosExecutionZoneWalletModule::send_program_deployment_transaction(
|
||||
const std::vector<uint8_t>& program_elf
|
||||
) {
|
||||
FfiTransactionResult result {};
|
||||
|
||||
const uint8_t *program_elf_data = program_elf.data();
|
||||
uintptr_t program_elf_size = static_cast<uintptr_t>(program_elf.size());
|
||||
|
||||
const WalletFfiError error = wallet_ffi_program_deployment(
|
||||
walletHandle,
|
||||
program_elf_data,
|
||||
program_elf_size,
|
||||
&result
|
||||
);
|
||||
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "send_program_deployment_transaction: wallet FFI error %d\n", error);
|
||||
return transferResultToJson(nullptr, std::string("send_program_deployment_transaction: wallet FFI error ") + std::to_string(error));
|
||||
}
|
||||
std::string resultJson = genericTransactionResultToJson(&result, std::string());
|
||||
wallet_ffi_free_transaction_result(&result);
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
// === Wallet Lifecycle ===
|
||||
|
||||
int64_t LogosExecutionZoneWalletModule::create_new(
|
||||
std::string LogosExecutionZoneWalletModule::create_new(
|
||||
const std::string& config_path,
|
||||
const std::string& storage_path,
|
||||
const std::string& password
|
||||
) {
|
||||
if (walletHandle) {
|
||||
fprintf(stderr, "create_new: wallet is already open\n");
|
||||
return INTERNAL_ERROR;
|
||||
return {};
|
||||
}
|
||||
|
||||
walletHandle = wallet_ffi_create_new(config_path.c_str(), storage_path.c_str(), password.c_str());
|
||||
if (!walletHandle) {
|
||||
FfiCreateWalletOutput create_output = wallet_ffi_create_new(config_path.c_str(), storage_path.c_str(), password.c_str());
|
||||
if (!create_output.wallet) {
|
||||
fprintf(stderr, "create_new: wallet_ffi_create_new returned null\n");
|
||||
return INTERNAL_ERROR;
|
||||
return {};
|
||||
}
|
||||
|
||||
walletHandle = create_output.wallet;
|
||||
std::string mnemonic(create_output.mnemonic);
|
||||
|
||||
wallet_ffi_free_string(create_output.mnemonic);
|
||||
|
||||
return mnemonic;
|
||||
}
|
||||
|
||||
int64_t LogosExecutionZoneWalletModule::restore_storage(const std::string& mnemonic, const std::string password, uint32_t depth) {
|
||||
const WalletFfiError error = wallet_ffi_restore_data(walletHandle, mnemonic.c_str(), password.c_str(), depth);
|
||||
if (error != SUCCESS) {
|
||||
fprintf(stderr, "restore_storage: wallet FFI error %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -791,4 +1098,4 @@ std::string LogosExecutionZoneWalletModule::get_sequencer_addr() {
|
||||
std::string value(addr);
|
||||
wallet_ffi_free_string(addr);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@ -30,10 +30,12 @@ public:
|
||||
std::string version() const;
|
||||
|
||||
// === Wallet Lifecycle ===
|
||||
int64_t create_new(const std::string& config_path, const std::string& storage_path, const std::string& password);
|
||||
std::string create_new(const std::string& config_path, const std::string& storage_path, const std::string& password);
|
||||
int64_t open(const std::string& config_path, const std::string& storage_path);
|
||||
int64_t save();
|
||||
|
||||
int64_t restore_storage(const std::string& mnemonic, const std::string password, uint32_t depth);
|
||||
|
||||
// === Account Management ===
|
||||
std::string create_account_public();
|
||||
std::string create_account_private();
|
||||
@ -70,6 +72,28 @@ public:
|
||||
std::string register_public_account(const std::string& account_id_hex);
|
||||
std::string register_private_account(const std::string& account_id_hex);
|
||||
|
||||
std::vector<uint8_t> authenticated_transfer_elf();
|
||||
std::vector<uint8_t> token_elf();
|
||||
std::vector<uint8_t> amm_elf();
|
||||
std::vector<uint8_t> ata_elf();
|
||||
|
||||
std::string send_generic_public_transaction(
|
||||
const std::vector<std::string>& account_ids,
|
||||
const std::vector<bool>& signing_requirements,
|
||||
const std::vector<uint32_t>& instruction,
|
||||
const std::vector<uint8_t>& program_elf,
|
||||
const std::vector<std::vector<uint8_t>>& program_dependencies
|
||||
);
|
||||
std::string send_generic_private_transaction(
|
||||
const std::vector<std::string>& account_ids,
|
||||
const std::vector<uint32_t>& instruction,
|
||||
const std::vector<uint8_t>& program_elf,
|
||||
const std::vector<std::vector<uint8_t>>& program_dependencies
|
||||
);
|
||||
std::string send_program_deployment_transaction(
|
||||
const std::vector<uint8_t>& program_elf
|
||||
);
|
||||
|
||||
// === Configuration ===
|
||||
std::string get_sequencer_addr();
|
||||
|
||||
|
||||
@ -47,10 +47,15 @@ extern "C" {
|
||||
|
||||
// === Lifecycle ===
|
||||
|
||||
WalletHandle* wallet_ffi_create_new(const char*, const char*, const char*) {
|
||||
FfiCreateWalletOutput wallet_ffi_create_new(const char*, const char*, const char*) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_create_new");
|
||||
const int ok = LOGOS_CMOCK_RETURN(int, "wallet_ffi_create_new");
|
||||
return ok ? reinterpret_cast<WalletHandle*>(&g_fakeWallet) : nullptr;
|
||||
const char* mnemonic_ok = LOGOS_CMOCK_RETURN_STRING("wallet_ffi_create_new");
|
||||
FfiCreateWalletOutput output;
|
||||
char* mn_char = strdup((mnemonic_ok && *mnemonic_ok) ? mnemonic_ok : "word word");
|
||||
output.mnemonic = mn_char;
|
||||
output.wallet = ok ? reinterpret_cast<WalletHandle*>(&g_fakeWallet) : nullptr;
|
||||
return output;
|
||||
}
|
||||
|
||||
WalletHandle* wallet_ffi_open(const char*, const char*) {
|
||||
@ -68,6 +73,12 @@ void wallet_ffi_destroy(WalletHandle*) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_destroy");
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_restore_data(WalletHandle*, const char*, const char*, uint32_t) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_restore_data");
|
||||
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_restore_data");
|
||||
return static_cast<WalletFfiError>(err);
|
||||
}
|
||||
|
||||
// === Account management ===
|
||||
|
||||
WalletFfiError wallet_ffi_create_account_public(WalletHandle*, FfiBytes32* out_id) {
|
||||
@ -134,6 +145,15 @@ WalletFfiError wallet_ffi_get_balance(WalletHandle*, const FfiBytes32*, bool, ui
|
||||
return static_cast<WalletFfiError>(err);
|
||||
}
|
||||
|
||||
static WalletFfiError fillProgram(const char* key, FfiProgram *ffi_program) {
|
||||
const int err = LogosCMockStore::instance().getReturn<int>(key);
|
||||
if (err == 0 && ffi_program) {
|
||||
memset(const_cast<uint8_t*>(ffi_program->elf_data), 0xAA, 100);
|
||||
ffi_program->elf_size = 100;
|
||||
}
|
||||
return static_cast<WalletFfiError>(err);
|
||||
}
|
||||
|
||||
static WalletFfiError fillAccount(const char* key, FfiAccount* out_account) {
|
||||
const int err = LogosCMockStore::instance().getReturn<int>(key);
|
||||
if (err == 0 && out_account) {
|
||||
@ -148,6 +168,53 @@ static WalletFfiError fillAccount(const char* key, FfiAccount* out_account) {
|
||||
return static_cast<WalletFfiError>(err);
|
||||
}
|
||||
|
||||
static WalletFfiError fillPublicAccountIdentity(const char* key, FfiAccountIdentity *out_account_identity) {
|
||||
const int err = LogosCMockStore::instance().getReturn<int>(key);
|
||||
if (err == 0 && out_account_identity) {
|
||||
out_account_identity->kind = FfiAccountIdentityKind::PUBLIC;
|
||||
memset(out_account_identity->account_id.data, 0xAA, sizeof(out_account_identity->account_id));
|
||||
out_account_identity->key_path = nullptr;
|
||||
memset(out_account_identity->nullifier_secret_key.data, 0x00, sizeof(out_account_identity->nullifier_secret_key));
|
||||
memset(out_account_identity->nullifier_public_key.data, 0x00, sizeof(out_account_identity->nullifier_public_key));
|
||||
out_account_identity->viewing_public_key = nullptr;
|
||||
out_account_identity->viewing_public_key_len = 0;
|
||||
memset(out_account_identity->identifier.data, 0x01, sizeof(out_account_identity->identifier));
|
||||
}
|
||||
return static_cast<WalletFfiError>(err);
|
||||
}
|
||||
|
||||
static WalletFfiError fillPrivateAccountIdentity(const char* key, FfiAccountIdentity *out_account_identity) {
|
||||
const int err = LogosCMockStore::instance().getReturn<int>(key);
|
||||
if (err == 0 && out_account_identity) {
|
||||
out_account_identity->kind = FfiAccountIdentityKind::PRIVATE_OWNED;
|
||||
memset(out_account_identity->account_id.data, 0xAB, sizeof(out_account_identity->account_id));
|
||||
out_account_identity->key_path = nullptr;
|
||||
memset(out_account_identity->nullifier_secret_key.data, 0x11, sizeof(out_account_identity->nullifier_secret_key));
|
||||
memset(out_account_identity->nullifier_public_key.data, 0x22, sizeof(out_account_identity->nullifier_public_key));
|
||||
out_account_identity->viewing_public_key = nullptr;
|
||||
out_account_identity->viewing_public_key_len = 0;
|
||||
memset(out_account_identity->identifier.data, 0x01, sizeof(out_account_identity->identifier));
|
||||
}
|
||||
return static_cast<WalletFfiError>(err);
|
||||
}
|
||||
|
||||
static WalletFfiError fillTransactionResult(const char* key, FfiTransactionResult *out_result) {
|
||||
const int err = LogosCMockStore::instance().getReturn<int>(key);
|
||||
if (out_result) {
|
||||
out_result->success = (err == 0);
|
||||
if (err == 0) {
|
||||
const char* tx = LogosCMockStore::instance().getReturnString("transaction_tx_hash");
|
||||
// getReturnString yields "" (non-null) when unset; fall back to a default.
|
||||
out_result->tx_hash = strdup((tx && *tx) ? tx : "0xmocktxhash2");
|
||||
} else {
|
||||
out_result->tx_hash = nullptr;
|
||||
}
|
||||
out_result->secrets_data = nullptr;
|
||||
out_result->secrets_size = 0;
|
||||
}
|
||||
return static_cast<WalletFfiError>(err);
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_get_account_public(WalletHandle*, const FfiBytes32*, FfiAccount* out_account) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_get_account_public");
|
||||
return fillAccount("wallet_ffi_get_account_public", out_account);
|
||||
@ -275,7 +342,10 @@ WalletFfiError wallet_ffi_transfer_public(
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_transfer_shielded(
|
||||
WalletHandle*, const FfiBytes32*, const FfiPrivateAccountKeys*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||||
WalletHandle*, const FfiBytes32*, const FfiPrivateAccountKeys*, const FfiU128*,
|
||||
const uint8_t (*)[16],
|
||||
const char*,
|
||||
FfiTransferResult* out_result) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_shielded");
|
||||
return fillTransferResult("wallet_ffi_transfer_shielded", out_result);
|
||||
}
|
||||
@ -287,13 +357,16 @@ WalletFfiError wallet_ffi_transfer_deshielded(
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_transfer_private(
|
||||
WalletHandle*, const FfiBytes32*, const FfiPrivateAccountKeys*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||||
WalletHandle*, const FfiBytes32*, const FfiPrivateAccountKeys*, const FfiU128*,
|
||||
const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_private");
|
||||
return fillTransferResult("wallet_ffi_transfer_private", out_result);
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_transfer_shielded_owned(
|
||||
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||||
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16],
|
||||
const char *,
|
||||
FfiTransferResult* out_result) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_shielded_owned");
|
||||
return fillTransferResult("wallet_ffi_transfer_shielded_owned", out_result);
|
||||
}
|
||||
@ -322,6 +395,88 @@ void wallet_ffi_free_transfer_result(FfiTransferResult* result) {
|
||||
}
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_transfer_elf(FfiProgram *ffi_program) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_elf");
|
||||
return fillProgram("wallet_ffi_transfer_elf", ffi_program);
|
||||
}
|
||||
WalletFfiError wallet_ffi_token_elf(FfiProgram *ffi_program) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_token_elf");
|
||||
return fillProgram("wallet_ffi_token_elf", ffi_program);
|
||||
}
|
||||
WalletFfiError wallet_ffi_ata_elf(FfiProgram *ffi_program) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_ata_elf");
|
||||
return fillProgram("wallet_ffi_ata_elf", ffi_program);
|
||||
}
|
||||
WalletFfiError wallet_ffi_amm_elf(FfiProgram *ffi_program) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_amm_elf");
|
||||
return fillProgram("wallet_ffi_amm_elf", ffi_program);
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_resolve_public_account(FfiBytes32 account_id, bool needs_sign, FfiAccountIdentity *out_account_identity) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_resolve_public_account");
|
||||
return fillPublicAccountIdentity("wallet_ffi_resolve_public_account", out_account_identity);
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_resolve_private_account(WalletHandle *handle, FfiBytes32 account_id, FfiAccountIdentity *out_account_identity){
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_resolve_private_account");
|
||||
return fillPrivateAccountIdentity("wallet_ffi_resolve_private_account", out_account_identity);
|
||||
}
|
||||
|
||||
void wallet_ffi_free_instruction_words(FfiInstructionWords *words){
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_free_instruction_words");
|
||||
if (words && words->instruction_words) {
|
||||
free(words->instruction_words);
|
||||
words->instruction_words = nullptr;
|
||||
words->instruction_words_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wallet_ffi_free_account_identity(FfiAccountIdentity *account_identity){
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_free_account_identity");
|
||||
if (account_identity && account_identity->viewing_public_key) {
|
||||
free(const_cast<uint8_t*>(account_identity->viewing_public_key));
|
||||
account_identity->viewing_public_key = nullptr;
|
||||
account_identity->viewing_public_key_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wallet_ffi_free_transaction_result(FfiTransactionResult *result) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_free_transaction_result");
|
||||
if (result && result->tx_hash) {
|
||||
free(const_cast<char*>(result->tx_hash));
|
||||
result->tx_hash = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void wallet_ffi_free_ffi_program(FfiProgram *ffi_program) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_free_ffi_program");
|
||||
if (ffi_program && ffi_program->elf_data) {
|
||||
free(const_cast<uint8_t*>(ffi_program->elf_data));
|
||||
ffi_program->elf_data = nullptr;
|
||||
ffi_program->elf_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_send_generic_public_transaction(WalletHandle *handle, const FfiAccountIdentity *account_identities,
|
||||
uintptr_t account_identities_size, const uint32_t *instruction_words, uintptr_t instruction_words_size,
|
||||
const FfiProgramWithDependencies *program_with_dependencies, FfiTransactionResult *out_result) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_send_generic_public_transaction");
|
||||
return fillTransactionResult("wallet_ffi_send_generic_public_transaction", out_result);
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_send_generic_private_transaction(WalletHandle *handle, const FfiAccountIdentity *account_identities,
|
||||
uintptr_t account_identities_size, const uint32_t *instruction_words, uintptr_t instruction_words_size,
|
||||
const FfiProgramWithDependencies *program_with_dependencies, FfiTransactionResult *out_result){
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_send_generic_private_transaction");
|
||||
return fillTransactionResult("wallet_ffi_send_generic_private_transaction", out_result);
|
||||
}
|
||||
|
||||
WalletFfiError wallet_ffi_program_deployment(WalletHandle *handle, const uint8_t *elf_data, uintptr_t elf_size,
|
||||
FfiTransactionResult *out_result) {
|
||||
LOGOS_CMOCK_RECORD("wallet_ffi_program_deployment");
|
||||
return fillTransactionResult("wallet_ffi_program_deployment", out_result);
|
||||
}
|
||||
|
||||
// === Configuration ===
|
||||
|
||||
char* wallet_ffi_get_sequencer_addr(WalletHandle*) {
|
||||
|
||||
@ -75,13 +75,104 @@ typedef struct FfiTransferResult {
|
||||
char* tx_hash;
|
||||
} FfiTransferResult;
|
||||
|
||||
/**
|
||||
* Enumeration to represent kinds of `FfiAccountIdentity`.
|
||||
*/
|
||||
typedef enum FfiAccountIdentityKind {
|
||||
PUBLIC = 0,
|
||||
PUBLIC_NO_SIGN = 1,
|
||||
PUBLIC_KEYCARD = 2,
|
||||
PRIVATE_OWNED = 3,
|
||||
PRIVATE_FOREIGN = 4,
|
||||
PRIVATE_PDA_OWNED = 5,
|
||||
PRIVATE_PDA_FOREIGN = 6,
|
||||
PRIVATE_SHARED = 7,
|
||||
PRIVATE_PDA_SHARED = 8,
|
||||
} FfiAccountIdentityKind;
|
||||
|
||||
/**
|
||||
* U128 - 16 bytes little endian.
|
||||
*/
|
||||
typedef struct FfiU128 {
|
||||
uint8_t data[16];
|
||||
} FfiU128;
|
||||
|
||||
typedef struct FfiInstructionWords {
|
||||
uint32_t *instruction_words;
|
||||
uintptr_t instruction_words_size;
|
||||
enum WalletFfiError error;
|
||||
} FfiInstructionWords;
|
||||
|
||||
/**
|
||||
* Struct representing an account identity, given to `AccountManager` at intialization.
|
||||
*/
|
||||
typedef struct FfiAccountIdentity {
|
||||
enum FfiAccountIdentityKind kind;
|
||||
struct FfiBytes32 account_id;
|
||||
/**
|
||||
* C-compatible string.
|
||||
*/
|
||||
char *key_path;
|
||||
struct FfiBytes32 nullifier_secret_key;
|
||||
struct FfiBytes32 nullifier_public_key;
|
||||
const uint8_t *viewing_public_key;
|
||||
uintptr_t viewing_public_key_len;
|
||||
struct FfiU128 identifier;
|
||||
} FfiAccountIdentity;
|
||||
|
||||
/**
|
||||
* Intended to be created manually.
|
||||
*/
|
||||
typedef struct FfiProgram {
|
||||
const uint8_t *elf_data;
|
||||
uintptr_t elf_size;
|
||||
} FfiProgram;
|
||||
|
||||
/**
|
||||
* Intended to be created manually.
|
||||
*/
|
||||
typedef struct FfiProgramWithDependencies {
|
||||
struct FfiProgram program;
|
||||
const struct FfiProgram *deps;
|
||||
uintptr_t deps_size;
|
||||
} FfiProgramWithDependencies;
|
||||
|
||||
/**
|
||||
* Result of a generic transaction operation.
|
||||
*/
|
||||
typedef struct FfiTransactionResult {
|
||||
/**
|
||||
* Transaction hash (null-terminated string, or null on failure).
|
||||
*/
|
||||
char *tx_hash;
|
||||
/**
|
||||
* Whether the transaction succeeded.
|
||||
*/
|
||||
bool success;
|
||||
const struct FfiBytes32 *secrets_data;
|
||||
/**
|
||||
* Public transactions have 0 secrets.
|
||||
*/
|
||||
uintptr_t secrets_size;
|
||||
} FfiTransactionResult;
|
||||
|
||||
typedef struct FfiCreateWalletOutput {
|
||||
struct WalletHandle *wallet;
|
||||
/**
|
||||
* C compatible(null terminated) string.
|
||||
*/
|
||||
char *mnemonic;
|
||||
} FfiCreateWalletOutput;
|
||||
|
||||
// === Lifecycle ===
|
||||
|
||||
WalletHandle* wallet_ffi_create_new(const char* config_path, const char* storage_path, const char* password);
|
||||
FfiCreateWalletOutput wallet_ffi_create_new(const char* config_path, const char* storage_path, const char* password);
|
||||
WalletHandle* wallet_ffi_open(const char* config_path, const char* storage_path);
|
||||
int wallet_ffi_save(WalletHandle* handle);
|
||||
void wallet_ffi_destroy(WalletHandle* handle);
|
||||
|
||||
WalletFfiError wallet_ffi_restore_data(WalletHandle *handle, const char *mnemonic, const char *password, uint32_t depth);
|
||||
|
||||
// === Account management ===
|
||||
|
||||
WalletFfiError wallet_ffi_create_account_public(WalletHandle* handle, FfiBytes32* out_id);
|
||||
@ -144,16 +235,22 @@ WalletFfiError wallet_ffi_transfer_public(
|
||||
const uint8_t (*amount)[16], FfiTransferResult* out_result);
|
||||
WalletFfiError wallet_ffi_transfer_shielded(
|
||||
WalletHandle* handle, const FfiBytes32* from, const FfiPrivateAccountKeys* to_keys,
|
||||
const uint8_t (*amount)[16], FfiTransferResult* out_result);
|
||||
const FfiU128 *to_identifier,
|
||||
const uint8_t (*amount)[16],
|
||||
const char *key_path,
|
||||
FfiTransferResult* out_result);
|
||||
WalletFfiError wallet_ffi_transfer_deshielded(
|
||||
WalletHandle* handle, const FfiBytes32* from, const FfiBytes32* to,
|
||||
const uint8_t (*amount)[16], FfiTransferResult* out_result);
|
||||
WalletFfiError wallet_ffi_transfer_private(
|
||||
WalletHandle* handle, const FfiBytes32* from, const FfiPrivateAccountKeys* to_keys,
|
||||
const FfiU128 *to_identifier,
|
||||
const uint8_t (*amount)[16], FfiTransferResult* out_result);
|
||||
WalletFfiError wallet_ffi_transfer_shielded_owned(
|
||||
WalletHandle* handle, const FfiBytes32* from, const FfiBytes32* to,
|
||||
const uint8_t (*amount)[16], FfiTransferResult* out_result);
|
||||
const uint8_t (*amount)[16],
|
||||
const char *key_path,
|
||||
FfiTransferResult* out_result);
|
||||
WalletFfiError wallet_ffi_transfer_private_owned(
|
||||
WalletHandle* handle, const FfiBytes32* from, const FfiBytes32* to,
|
||||
const uint8_t (*amount)[16], FfiTransferResult* out_result);
|
||||
@ -161,7 +258,43 @@ WalletFfiError wallet_ffi_transfer_private_owned(
|
||||
WalletFfiError wallet_ffi_register_public_account(WalletHandle* handle, const FfiBytes32* account_id, FfiTransferResult* out_result);
|
||||
WalletFfiError wallet_ffi_register_private_account(WalletHandle* handle, const FfiBytes32* account_id, FfiTransferResult* out_result);
|
||||
|
||||
WalletFfiError wallet_ffi_transfer_elf(FfiProgram *ffi_program);
|
||||
WalletFfiError wallet_ffi_token_elf(FfiProgram *ffi_program);
|
||||
WalletFfiError wallet_ffi_ata_elf(FfiProgram *ffi_program);
|
||||
WalletFfiError wallet_ffi_amm_elf(FfiProgram *ffi_program);
|
||||
|
||||
WalletFfiError wallet_ffi_send_generic_public_transaction(WalletHandle *handle,
|
||||
const FfiAccountIdentity *account_identities,
|
||||
uintptr_t account_identities_size,
|
||||
const uint32_t *instruction_words,
|
||||
uintptr_t instruction_words_size,
|
||||
const FfiProgramWithDependencies *program_with_dependencies,
|
||||
FfiTransactionResult *out_result);
|
||||
|
||||
WalletFfiError wallet_ffi_send_generic_private_transaction(WalletHandle *handle,
|
||||
const FfiAccountIdentity *account_identities,
|
||||
uintptr_t account_identities_size,
|
||||
const uint32_t *instruction_words,
|
||||
uintptr_t instruction_words_size,
|
||||
const FfiProgramWithDependencies *program_with_dependencies,
|
||||
FfiTransactionResult *out_result);
|
||||
|
||||
WalletFfiError wallet_ffi_program_deployment(WalletHandle *handle,
|
||||
const uint8_t *elf_data,
|
||||
uintptr_t elf_size,
|
||||
FfiTransactionResult *out_result);
|
||||
|
||||
WalletFfiError wallet_ffi_resolve_public_account(FfiBytes32 account_id,
|
||||
bool needs_sign,
|
||||
FfiAccountIdentity *out_account_identity);
|
||||
WalletFfiError wallet_ffi_resolve_private_account(WalletHandle *handle,
|
||||
FfiBytes32 account_id,
|
||||
FfiAccountIdentity *out_account_identity);
|
||||
void wallet_ffi_free_instruction_words(FfiInstructionWords *words);
|
||||
void wallet_ffi_free_account_identity(FfiAccountIdentity *account_identity);
|
||||
void wallet_ffi_free_transfer_result(FfiTransferResult* result);
|
||||
void wallet_ffi_free_transaction_result(FfiTransactionResult *result);
|
||||
void wallet_ffi_free_ffi_program(FfiProgram *ffi_program);
|
||||
|
||||
// === Configuration ===
|
||||
|
||||
|
||||
@ -374,10 +374,10 @@ LOGOS_TEST(create_new_success_then_double_open_fails) {
|
||||
t.mockCFunction("wallet_ffi_create_new").returns(1); // non-null handle
|
||||
LogosExecutionZoneWalletModule module;
|
||||
|
||||
LOGOS_ASSERT_EQ(module.create_new("/cfg", "/store", "pw"), static_cast<int64_t>(SUCCESS));
|
||||
LOGOS_ASSERT_TRUE(!module.create_new("/cfg", "/store", "pw").empty());
|
||||
LOGOS_ASSERT(t.cFunctionCalled("wallet_ffi_create_new"));
|
||||
// Second attempt: already open.
|
||||
LOGOS_ASSERT_EQ(module.create_new("/cfg", "/store", "pw"), static_cast<int64_t>(INTERNAL_ERROR));
|
||||
LOGOS_ASSERT_EQ(module.create_new("/cfg", "/store", "pw"), "");
|
||||
}
|
||||
|
||||
LOGOS_TEST(create_new_null_handle_returns_internal_error) {
|
||||
@ -385,7 +385,7 @@ LOGOS_TEST(create_new_null_handle_returns_internal_error) {
|
||||
t.mockCFunction("wallet_ffi_create_new").returns(0); // null handle
|
||||
LogosExecutionZoneWalletModule module;
|
||||
|
||||
LOGOS_ASSERT_EQ(module.create_new("/cfg", "/store", "pw"), static_cast<int64_t>(INTERNAL_ERROR));
|
||||
LOGOS_ASSERT_EQ(module.create_new("/cfg", "/store", "pw"), "");
|
||||
}
|
||||
|
||||
LOGOS_TEST(open_success) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user