mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-06-04 08:09:33 +00:00
fix(wallet_ffi): suggestions fix 2
This commit is contained in:
parent
e82c0f3658
commit
7c0701bb7d
@ -22,8 +22,8 @@ const MAX_NUM_CYCLES_PUBLIC_EXECUTION: u64 = 1024 * 1024 * 32; // 32M cycles
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
|
||||
pub struct Program {
|
||||
pub id: ProgramId,
|
||||
pub elf: Vec<u8>,
|
||||
id: ProgramId,
|
||||
elf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Program {
|
||||
|
||||
@ -14,13 +14,13 @@ use crate::{
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SerializationHelperResult {
|
||||
pub struct FfiInstructionWords {
|
||||
pub instruction_words: *mut u32,
|
||||
pub instruction_words_size: usize,
|
||||
pub error: WalletFfiError,
|
||||
}
|
||||
|
||||
impl SerializationHelperResult {
|
||||
impl FfiInstructionWords {
|
||||
const fn from_err(error: WalletFfiError) -> Self {
|
||||
Self {
|
||||
instruction_words: std::ptr::null_mut(),
|
||||
@ -57,8 +57,9 @@ impl TryFrom<&FfiProgram> for Program {
|
||||
|
||||
impl From<Program> for FfiProgram {
|
||||
fn from(value: Program) -> Self {
|
||||
let elf_size = value.elf.len();
|
||||
let elf_data = Box::into_raw(value.elf.into_boxed_slice()) as *const u8;
|
||||
let elf_clone = value.elf().to_vec();
|
||||
let elf_size = elf_clone.len();
|
||||
let elf_data = Box::into_raw(elf_clone.into_boxed_slice()) as *const u8;
|
||||
|
||||
Self { elf_data, elf_size }
|
||||
}
|
||||
@ -157,10 +158,10 @@ impl Default for FfiTransactionResult {
|
||||
pub unsafe extern "C" fn wallet_ffi_serialization_helper(
|
||||
input_instruction_data: *const u8,
|
||||
input_instruction_data_size: usize,
|
||||
) -> SerializationHelperResult {
|
||||
) -> FfiInstructionWords {
|
||||
if input_instruction_data.is_null() {
|
||||
print_error("Null input pointer for instruction_data");
|
||||
return SerializationHelperResult::from_err(WalletFfiError::NullPointer);
|
||||
return FfiInstructionWords::from_err(WalletFfiError::NullPointer);
|
||||
}
|
||||
|
||||
let input_slice =
|
||||
@ -172,7 +173,7 @@ pub unsafe extern "C" fn wallet_ffi_serialization_helper(
|
||||
WalletFfiError::SerializationError
|
||||
}) {
|
||||
Ok(res) => res,
|
||||
Err(err) => return SerializationHelperResult::from_err(err),
|
||||
Err(err) => return FfiInstructionWords::from_err(err),
|
||||
};
|
||||
|
||||
// The resulting vec contains len as prefix
|
||||
@ -182,7 +183,7 @@ pub unsafe extern "C" fn wallet_ffi_serialization_helper(
|
||||
let res_boxed = res_vec_u32.into_boxed_slice();
|
||||
let res_ptr = Box::into_raw(res_boxed).cast::<u32>();
|
||||
|
||||
SerializationHelperResult {
|
||||
FfiInstructionWords {
|
||||
instruction_words: res_ptr,
|
||||
instruction_words_size: res_len,
|
||||
error: WalletFfiError::Success,
|
||||
@ -418,3 +419,51 @@ pub unsafe extern "C" fn wallet_ffi_free_transaction_result(result: *mut FfiTran
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Free a instruction words returned by `wallet_ffi_serialization_helper`.
|
||||
///
|
||||
/// # Safety
|
||||
/// The result must be either null or a valid result from a serialization helper function.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_free_instruction_words(words: *mut FfiInstructionWords) {
|
||||
if words.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let words = &*words;
|
||||
|
||||
if !words.instruction_words.is_null() {
|
||||
let words = std::slice::from_raw_parts_mut(
|
||||
words.instruction_words,
|
||||
words.instruction_words_size,
|
||||
);
|
||||
drop(Box::from_raw(std::ptr::from_mut::<[u32]>(words)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nssa::program::Program;
|
||||
|
||||
use crate::generic_transaction::FfiProgram;
|
||||
|
||||
#[test]
|
||||
fn program_cast_consistency() {
|
||||
let prog = Program::amm();
|
||||
|
||||
let first_5_bytes = prog.elf()[..5].to_vec();
|
||||
|
||||
let ffi_prog: FfiProgram = prog.into();
|
||||
|
||||
assert!(!ffi_prog.elf_data.is_null());
|
||||
|
||||
let mut ffi_first_5_bytes = vec![];
|
||||
for i in 0..5 {
|
||||
ffi_first_5_bytes.push(unsafe { *ffi_prog.elf_data.add(i) });
|
||||
}
|
||||
|
||||
assert_eq!(ffi_first_5_bytes, first_5_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,3 +376,23 @@ pub unsafe extern "C" fn wallet_ffi_free_account_identity(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nssa::AccountId;
|
||||
use wallet::AccountIdentity;
|
||||
|
||||
use crate::{keys::wallet_ffi_free_account_identity, FfiAccountIdentity};
|
||||
|
||||
#[test]
|
||||
fn acc_identity_correct_free() {
|
||||
let acc_identity = AccountIdentity::Public(AccountId::new([42; 32]));
|
||||
let mut ffi_acc_identity: FfiAccountIdentity = acc_identity.into();
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_account_identity(&raw mut ffi_acc_identity);
|
||||
}
|
||||
|
||||
assert!(ffi_acc_identity.viewing_public_key.is_null());
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,11 +218,11 @@ typedef struct FfiAccount {
|
||||
struct FfiU128 nonce;
|
||||
} FfiAccount;
|
||||
|
||||
typedef struct SerializationHelperResult {
|
||||
typedef struct FfiInstructionWords {
|
||||
uint32_t *instruction_words;
|
||||
uintptr_t instruction_words_size;
|
||||
enum WalletFfiError error;
|
||||
} SerializationHelperResult;
|
||||
} FfiInstructionWords;
|
||||
|
||||
/**
|
||||
* Struct representing an account identity, given to `AccountManager` at intialization.
|
||||
@ -541,8 +541,8 @@ enum WalletFfiError wallet_ffi_import_private_account(struct WalletHandle *handl
|
||||
* # Safety
|
||||
* - `input_instruction_data` must be a valid pointer
|
||||
*/
|
||||
struct SerializationHelperResult wallet_ffi_serialization_helper(const uint8_t *input_instruction_data,
|
||||
uintptr_t input_instruction_data_size);
|
||||
struct FfiInstructionWords wallet_ffi_serialization_helper(const uint8_t *input_instruction_data,
|
||||
uintptr_t input_instruction_data_size);
|
||||
|
||||
/**
|
||||
* Send generic public transaction.
|
||||
@ -607,6 +607,14 @@ enum WalletFfiError wallet_ffi_send_generic_private_transaction(struct WalletHan
|
||||
*/
|
||||
void wallet_ffi_free_transaction_result(struct FfiTransactionResult *result);
|
||||
|
||||
/**
|
||||
* Free a instruction words returned by `wallet_ffi_serialization_helper`.
|
||||
*
|
||||
* # Safety
|
||||
* The result must be either null or a valid result from a serialization helper function.
|
||||
*/
|
||||
void wallet_ffi_free_instruction_words(struct FfiInstructionWords *words);
|
||||
|
||||
/**
|
||||
* Get the public key for a public account.
|
||||
*
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use core::fmt;
|
||||
|
||||
use anyhow::Result;
|
||||
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||
use nssa::{AccountId, PrivateKey};
|
||||
@ -10,7 +12,7 @@ use nssa_core::{
|
||||
|
||||
use crate::{ExecutionFailureKind, WalletCore};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum AccountIdentity {
|
||||
Public(AccountId),
|
||||
/// A public account without signing. Would not try to sign, even if account is owned.
|
||||
@ -52,6 +54,65 @@ pub enum AccountIdentity {
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Debug for AccountIdentity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Public(id) => f.debug_tuple("Public").field(id).finish(),
|
||||
Self::PublicNoSign(id) => f.debug_tuple("PublicNoSign").field(id).finish(),
|
||||
Self::PrivateOwned(id) => f.debug_tuple("PrivateOwned").field(id).finish(),
|
||||
Self::PrivateForeign {
|
||||
npk,
|
||||
vpk,
|
||||
identifier,
|
||||
} => f
|
||||
.debug_struct("PrivateForeign")
|
||||
.field("npk", npk)
|
||||
.field("vpk", vpk)
|
||||
.field("identifier", identifier)
|
||||
.finish(),
|
||||
Self::PrivatePdaOwned(id) => f.debug_tuple("PrivatePdaOwned").field(id).finish(),
|
||||
Self::PrivatePdaForeign {
|
||||
account_id,
|
||||
npk,
|
||||
vpk,
|
||||
identifier,
|
||||
} => f
|
||||
.debug_struct("PrivatePdaForeign")
|
||||
.field("account_id", account_id)
|
||||
.field("npk", npk)
|
||||
.field("vpk", vpk)
|
||||
.field("identifier", identifier)
|
||||
.finish(),
|
||||
Self::PrivateShared {
|
||||
npk,
|
||||
vpk,
|
||||
identifier,
|
||||
..
|
||||
} => f
|
||||
.debug_struct("PrivateShared")
|
||||
.field("nsk", &"<redacted>")
|
||||
.field("npk", npk)
|
||||
.field("vpk", vpk)
|
||||
.field("identifier", identifier)
|
||||
.finish(),
|
||||
Self::PrivatePdaShared {
|
||||
account_id,
|
||||
npk,
|
||||
vpk,
|
||||
identifier,
|
||||
..
|
||||
} => f
|
||||
.debug_struct("PrivatePdaShared")
|
||||
.field("account_id", account_id)
|
||||
.field("nsk", &"<redacted>")
|
||||
.field("npk", npk)
|
||||
.field("vpk", vpk)
|
||||
.field("identifier", identifier)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AccountIdentity {
|
||||
#[must_use]
|
||||
/// Note: `PublicNoSign` still counts as public, the variant just suppresses the signing-key
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user