mirror of
https://github.com/logos-blockchain/logos-execution-zone-module.git
synced 2026-06-14 07:49:32 +00:00
334 lines
13 KiB
C++
334 lines
13 KiB
C++
|
|
// Mock implementation of the wallet_ffi C functions.
|
||
|
|
// Replaces the real lssa wallet library at link time during unit tests.
|
||
|
|
// Return codes and out-parameter contents are controlled via LogosCMockStore.
|
||
|
|
//
|
||
|
|
// Conventions:
|
||
|
|
// - Functions returning WalletFfiError use LOGOS_CMOCK_RETURN(int, "<fn>"); an
|
||
|
|
// unset mock defaults to 0 (SUCCESS), so the happy path needs no setup.
|
||
|
|
// - Out-parameters are filled with deterministic bytes only on success so tests
|
||
|
|
// can assert on the resulting hex/JSON.
|
||
|
|
|
||
|
|
#include <logos_clib_mock.h>
|
||
|
|
|
||
|
|
extern "C" {
|
||
|
|
#include <wallet_ffi.h>
|
||
|
|
}
|
||
|
|
|
||
|
|
#include <cstdlib>
|
||
|
|
#include <cstring>
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
// A single non-null sentinel handle handed back by create_new / open.
|
||
|
|
char g_fakeWallet = 0;
|
||
|
|
|
||
|
|
// Backing storage for list_accounts (returned by pointer to the caller).
|
||
|
|
FfiAccountListEntry g_accountEntries[8];
|
||
|
|
|
||
|
|
// Fill a transfer result based on the mocked error code for `key`.
|
||
|
|
WalletFfiError fillTransferResult(const char* key, FfiTransferResult* 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("transfer_tx_hash");
|
||
|
|
// getReturnString yields "" (non-null) when unset; fall back to a default.
|
||
|
|
out_result->tx_hash = strdup((tx && *tx) ? tx : "0xmocktxhash");
|
||
|
|
} else {
|
||
|
|
out_result->tx_hash = nullptr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
extern "C" {
|
||
|
|
|
||
|
|
// === Lifecycle ===
|
||
|
|
|
||
|
|
WalletHandle* 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;
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletHandle* wallet_ffi_open(const char*, const char*) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_open");
|
||
|
|
const int ok = LOGOS_CMOCK_RETURN(int, "wallet_ffi_open");
|
||
|
|
return ok ? reinterpret_cast<WalletHandle*>(&g_fakeWallet) : nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
int wallet_ffi_save(WalletHandle*) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_save");
|
||
|
|
return LOGOS_CMOCK_RETURN(int, "wallet_ffi_save");
|
||
|
|
}
|
||
|
|
|
||
|
|
void wallet_ffi_destroy(WalletHandle*) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_destroy");
|
||
|
|
}
|
||
|
|
|
||
|
|
// === Account management ===
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_create_account_public(WalletHandle*, FfiBytes32* out_id) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_create_account_public");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_create_account_public");
|
||
|
|
if (err == 0 && out_id) {
|
||
|
|
memset(out_id->data, 0xAB, sizeof(out_id->data));
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_create_account_private(WalletHandle*, FfiBytes32* out_id) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_create_account_private");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_create_account_private");
|
||
|
|
if (err == 0 && out_id) {
|
||
|
|
memset(out_id->data, 0xCD, sizeof(out_id->data));
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_list_accounts(WalletHandle*, FfiAccountList* out_list) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_list_accounts");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_list_accounts");
|
||
|
|
if (!out_list) {
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
if (err == 0) {
|
||
|
|
int count = LOGOS_CMOCK_RETURN(int, "list_accounts_count");
|
||
|
|
if (count < 0) count = 0;
|
||
|
|
if (count > 8) count = 8;
|
||
|
|
for (int i = 0; i < count; ++i) {
|
||
|
|
memset(g_accountEntries[i].account_id.data, 0x10 + i, sizeof(g_accountEntries[i].account_id.data));
|
||
|
|
g_accountEntries[i].is_public = (i % 2 == 0);
|
||
|
|
}
|
||
|
|
out_list->entries = g_accountEntries;
|
||
|
|
out_list->count = static_cast<uintptr_t>(count);
|
||
|
|
} else {
|
||
|
|
out_list->entries = nullptr;
|
||
|
|
out_list->count = 0;
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
void wallet_ffi_free_account_list(FfiAccountList* list) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_free_account_list");
|
||
|
|
if (list) {
|
||
|
|
list->entries = nullptr;
|
||
|
|
list->count = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// === Account queries ===
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_get_balance(WalletHandle*, const FfiBytes32*, bool, uint8_t (*out_balance)[16]) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_get_balance");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_get_balance");
|
||
|
|
if (err == 0 && out_balance) {
|
||
|
|
const uint64_t value = static_cast<uint64_t>(LOGOS_CMOCK_RETURN(int, "get_balance_value"));
|
||
|
|
memset(*out_balance, 0, 16);
|
||
|
|
for (int i = 0; i < 8; ++i) {
|
||
|
|
(*out_balance)[i] = static_cast<uint8_t>((value >> (i * 8)) & 0xFF);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
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) {
|
||
|
|
memset(out_account->program_owner.data, 0xAA, sizeof(out_account->program_owner.data));
|
||
|
|
memset(out_account->balance.data, 0, sizeof(out_account->balance.data));
|
||
|
|
out_account->balance.data[0] = 0x07;
|
||
|
|
memset(out_account->nonce.data, 0, sizeof(out_account->nonce.data));
|
||
|
|
out_account->nonce.data[0] = 0x01;
|
||
|
|
out_account->data = nullptr;
|
||
|
|
out_account->data_len = 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);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_get_account_private(WalletHandle*, const FfiBytes32*, FfiAccount* out_account) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_get_account_private");
|
||
|
|
return fillAccount("wallet_ffi_get_account_private", out_account);
|
||
|
|
}
|
||
|
|
|
||
|
|
void wallet_ffi_free_account_data(FfiAccount* account) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_free_account_data");
|
||
|
|
if (account && account->data) {
|
||
|
|
free(account->data);
|
||
|
|
account->data = nullptr;
|
||
|
|
account->data_len = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_get_public_account_key(WalletHandle*, const FfiBytes32*, FfiPublicAccountKey* out_key) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_get_public_account_key");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_get_public_account_key");
|
||
|
|
if (err == 0 && out_key) {
|
||
|
|
memset(out_key->public_key.data, 0xBE, sizeof(out_key->public_key.data));
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_get_private_account_keys(WalletHandle*, const FfiBytes32*, FfiPrivateAccountKeys* out_keys) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_get_private_account_keys");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_get_private_account_keys");
|
||
|
|
if (err == 0 && out_keys) {
|
||
|
|
memset(out_keys->nullifier_public_key.data, 0xEF, sizeof(out_keys->nullifier_public_key.data));
|
||
|
|
out_keys->viewing_public_key = nullptr;
|
||
|
|
out_keys->viewing_public_key_len = 0;
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
void wallet_ffi_free_private_account_keys(FfiPrivateAccountKeys* keys) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_free_private_account_keys");
|
||
|
|
if (keys && keys->viewing_public_key) {
|
||
|
|
free(keys->viewing_public_key);
|
||
|
|
keys->viewing_public_key = nullptr;
|
||
|
|
keys->viewing_public_key_len = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// === Account encoding ===
|
||
|
|
|
||
|
|
char* wallet_ffi_account_id_to_base58(const FfiBytes32*) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_account_id_to_base58");
|
||
|
|
const char* str = LOGOS_CMOCK_RETURN_STRING("wallet_ffi_account_id_to_base58");
|
||
|
|
return strdup((str && *str) ? str : "MockBase58Address");
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_account_id_from_base58(const char*, FfiBytes32* out_id) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_account_id_from_base58");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_account_id_from_base58");
|
||
|
|
if (err == 0 && out_id) {
|
||
|
|
memset(out_id->data, 0x5A, sizeof(out_id->data));
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
void wallet_ffi_free_string(char* s) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_free_string");
|
||
|
|
if (s) {
|
||
|
|
free(s);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// === Blockchain synchronisation ===
|
||
|
|
|
||
|
|
int wallet_ffi_sync_to_block(WalletHandle*, uint64_t) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_sync_to_block");
|
||
|
|
return LOGOS_CMOCK_RETURN(int, "wallet_ffi_sync_to_block");
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_get_last_synced_block(WalletHandle*, uint64_t* out_block_id) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_get_last_synced_block");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_get_last_synced_block");
|
||
|
|
if (err == 0 && out_block_id) {
|
||
|
|
*out_block_id = static_cast<uint64_t>(LOGOS_CMOCK_RETURN(int, "last_synced_block_value"));
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_get_current_block_height(WalletHandle*, uint64_t* out_block_height) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_get_current_block_height");
|
||
|
|
const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_get_current_block_height");
|
||
|
|
if (err == 0 && out_block_height) {
|
||
|
|
*out_block_height = static_cast<uint64_t>(LOGOS_CMOCK_RETURN(int, "current_block_height_value"));
|
||
|
|
}
|
||
|
|
return static_cast<WalletFfiError>(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
// === Pinata claiming ===
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_claim_pinata(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_claim_pinata");
|
||
|
|
return fillTransferResult("wallet_ffi_claim_pinata", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_claim_pinata_private_owned_already_initialized(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16],
|
||
|
|
uintptr_t, const uint8_t (*)[32], uintptr_t, FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_claim_pinata_private_owned_already_initialized");
|
||
|
|
return fillTransferResult("wallet_ffi_claim_pinata_private_owned_already_initialized", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_claim_pinata_private_owned_not_initialized(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_claim_pinata_private_owned_not_initialized");
|
||
|
|
return fillTransferResult("wallet_ffi_claim_pinata_private_owned_not_initialized", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
// === Transfers / registration ===
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_transfer_public(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_public");
|
||
|
|
return fillTransferResult("wallet_ffi_transfer_public", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_transfer_shielded(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiPrivateAccountKeys*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_shielded");
|
||
|
|
return fillTransferResult("wallet_ffi_transfer_shielded", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_transfer_deshielded(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_deshielded");
|
||
|
|
return fillTransferResult("wallet_ffi_transfer_deshielded", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_transfer_private(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiPrivateAccountKeys*, 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) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_shielded_owned");
|
||
|
|
return fillTransferResult("wallet_ffi_transfer_shielded_owned", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_transfer_private_owned(
|
||
|
|
WalletHandle*, const FfiBytes32*, const FfiBytes32*, const uint8_t (*)[16], FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_transfer_private_owned");
|
||
|
|
return fillTransferResult("wallet_ffi_transfer_private_owned", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_register_public_account(WalletHandle*, const FfiBytes32*, FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_register_public_account");
|
||
|
|
return fillTransferResult("wallet_ffi_register_public_account", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
WalletFfiError wallet_ffi_register_private_account(WalletHandle*, const FfiBytes32*, FfiTransferResult* out_result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_register_private_account");
|
||
|
|
return fillTransferResult("wallet_ffi_register_private_account", out_result);
|
||
|
|
}
|
||
|
|
|
||
|
|
void wallet_ffi_free_transfer_result(FfiTransferResult* result) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_free_transfer_result");
|
||
|
|
if (result && result->tx_hash) {
|
||
|
|
free(result->tx_hash);
|
||
|
|
result->tx_hash = nullptr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// === Configuration ===
|
||
|
|
|
||
|
|
char* wallet_ffi_get_sequencer_addr(WalletHandle*) {
|
||
|
|
LOGOS_CMOCK_RECORD("wallet_ffi_get_sequencer_addr");
|
||
|
|
const char* addr = LOGOS_CMOCK_RETURN_STRING("wallet_ffi_get_sequencer_addr");
|
||
|
|
return strdup((addr && *addr) ? addr : "127.0.0.1:3000");
|
||
|
|
}
|
||
|
|
|
||
|
|
} // extern "C"
|