mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-25 17:39:27 +00:00
Merge 6721d8d96e71566f072bab2ededcf56d29b002b0 into cf9177a0954fa4d9796fc8086b87a03380602fff
This commit is contained in:
commit
94a67ebb50
@ -41,6 +41,8 @@ pub enum WalletFfiError {
|
|||||||
InvalidTypeConversion = 15,
|
InvalidTypeConversion = 15,
|
||||||
/// Invalid Key value.
|
/// Invalid Key value.
|
||||||
InvalidKeyValue = 16,
|
InvalidKeyValue = 16,
|
||||||
|
/// Invalid argument value.
|
||||||
|
InvalidArgument = 17,
|
||||||
/// Internal error (catch-all).
|
/// Internal error (catch-all).
|
||||||
InternalError = 99,
|
InternalError = 99,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,6 +106,107 @@ pub unsafe extern "C" fn wallet_ffi_transfer_public(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send an arbitrary public transaction to a program.
|
||||||
|
///
|
||||||
|
/// Builds a `PublicTransaction` from the given program, accounts, and instruction data,
|
||||||
|
/// signs it with the signer's key, and submits to the sequencer.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
/// - `handle`: Valid wallet handle
|
||||||
|
/// - `program_id`: 32-byte program ID
|
||||||
|
/// - `accounts`: Pointer to array of 32-byte account IDs
|
||||||
|
/// - `num_accounts`: Number of accounts in the array
|
||||||
|
/// - `instruction_data`: Pointer to raw instruction bytes (Vec<u32> serialized as LE bytes)
|
||||||
|
/// - `instruction_len`: Length of instruction data in bytes (must be multiple of 4)
|
||||||
|
/// - `signer`: Signer account ID (must be owned by this wallet)
|
||||||
|
/// - `out_result`: Output pointer for transfer result
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// All pointers must be valid. `instruction_len` must be a multiple of 4.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wallet_ffi_send_public_transaction(
|
||||||
|
handle: *mut WalletHandle,
|
||||||
|
program_id: *const FfiBytes32,
|
||||||
|
accounts: *const FfiBytes32,
|
||||||
|
num_accounts: usize,
|
||||||
|
instruction_data: *const u8,
|
||||||
|
instruction_len: usize,
|
||||||
|
signer: *const FfiBytes32,
|
||||||
|
out_result: *mut FfiTransferResult,
|
||||||
|
) -> WalletFfiError {
|
||||||
|
let wrapper = match get_wallet(handle) {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => return e,
|
||||||
|
};
|
||||||
|
|
||||||
|
if program_id.is_null()
|
||||||
|
|| accounts.is_null()
|
||||||
|
|| instruction_data.is_null()
|
||||||
|
|| signer.is_null()
|
||||||
|
|| out_result.is_null()
|
||||||
|
{
|
||||||
|
print_error("Null pointer argument");
|
||||||
|
return WalletFfiError::NullPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if instruction_len % 4 != 0 {
|
||||||
|
print_error("instruction_len must be a multiple of 4");
|
||||||
|
return WalletFfiError::InvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wallet = match wrapper.core.lock() {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => {
|
||||||
|
print_error(format!("Failed to lock wallet: {e}"));
|
||||||
|
return WalletFfiError::InternalError;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let pid_bytes = unsafe { (*program_id).data };
|
||||||
|
let mut pid: nssa_core::program::ProgramId = [0u32; 8];
|
||||||
|
for i in 0..8 {
|
||||||
|
pid[i] = u32::from_le_bytes([
|
||||||
|
pid_bytes[i * 4],
|
||||||
|
pid_bytes[i * 4 + 1],
|
||||||
|
pid_bytes[i * 4 + 2],
|
||||||
|
pid_bytes[i * 4 + 3],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
let signer_id = AccountId::new(unsafe { (*signer).data });
|
||||||
|
|
||||||
|
let account_ids: Vec<AccountId> = (0..num_accounts)
|
||||||
|
.map(|i| AccountId::new(unsafe { (*accounts.add(i)).data }))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Convert raw bytes to Vec<u32> (LE)
|
||||||
|
let instr_slice = unsafe { std::slice::from_raw_parts(instruction_data, instruction_len) };
|
||||||
|
let instr_u32: Vec<u32> = instr_slice
|
||||||
|
.chunks_exact(4)
|
||||||
|
.map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]]))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
match block_on(wallet.send_public_transaction(pid, account_ids, instr_u32, signer_id)) {
|
||||||
|
Ok(tx_hash) => {
|
||||||
|
let tx_hash = CString::new(tx_hash.to_string())
|
||||||
|
.map_or(ptr::null_mut(), std::ffi::CString::into_raw);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = tx_hash;
|
||||||
|
(*out_result).success = true;
|
||||||
|
}
|
||||||
|
WalletFfiError::Success
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
print_error(format!("Transaction failed: {e:?}"));
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = ptr::null_mut();
|
||||||
|
(*out_result).success = false;
|
||||||
|
}
|
||||||
|
map_execution_error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Send a shielded token transfer.
|
/// Send a shielded token transfer.
|
||||||
///
|
///
|
||||||
/// Transfers tokens from a public account to a private account.
|
/// Transfers tokens from a public account to a private account.
|
||||||
|
|||||||
@ -103,6 +103,10 @@ typedef enum WalletFfiError {
|
|||||||
* Invalid Key value.
|
* Invalid Key value.
|
||||||
*/
|
*/
|
||||||
INVALID_KEY_VALUE = 16,
|
INVALID_KEY_VALUE = 16,
|
||||||
|
/**
|
||||||
|
* Invalid argument value.
|
||||||
|
*/
|
||||||
|
INVALID_ARGUMENT = 17,
|
||||||
/**
|
/**
|
||||||
* Internal error (catch-all).
|
* Internal error (catch-all).
|
||||||
*/
|
*/
|
||||||
@ -753,6 +757,34 @@ enum WalletFfiError wallet_ffi_transfer_public(struct WalletHandle *handle,
|
|||||||
const uint8_t (*amount)[16],
|
const uint8_t (*amount)[16],
|
||||||
struct FfiTransferResult *out_result);
|
struct FfiTransferResult *out_result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an arbitrary public transaction to a program.
|
||||||
|
*
|
||||||
|
* Builds a `PublicTransaction` from the given program, accounts, and instruction data,
|
||||||
|
* signs it with the signer's key, and submits to the sequencer.
|
||||||
|
*
|
||||||
|
* # Parameters
|
||||||
|
* - `handle`: Valid wallet handle
|
||||||
|
* - `program_id`: 32-byte program ID
|
||||||
|
* - `accounts`: Pointer to array of 32-byte account IDs
|
||||||
|
* - `num_accounts`: Number of accounts in the array
|
||||||
|
* - `instruction_data`: Pointer to raw instruction bytes (Vec<u32> serialized as LE bytes)
|
||||||
|
* - `instruction_len`: Length of instruction data in bytes (must be multiple of 4)
|
||||||
|
* - `signer`: Signer account ID (must be owned by this wallet)
|
||||||
|
* - `out_result`: Output pointer for transfer result
|
||||||
|
*
|
||||||
|
* # Safety
|
||||||
|
* All pointers must be valid. `instruction_len` must be a multiple of 4.
|
||||||
|
*/
|
||||||
|
enum WalletFfiError wallet_ffi_send_public_transaction(struct WalletHandle *handle,
|
||||||
|
const struct FfiBytes32 *program_id,
|
||||||
|
const struct FfiBytes32 *accounts,
|
||||||
|
uintptr_t num_accounts,
|
||||||
|
const uint8_t *instruction_data,
|
||||||
|
uintptr_t instruction_len,
|
||||||
|
const struct FfiBytes32 *signer,
|
||||||
|
struct FfiTransferResult *out_result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a shielded token transfer.
|
* Send a shielded token transfer.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -463,6 +463,41 @@ impl WalletCore {
|
|||||||
self.storage.key_chain().pub_account_signing_key(account_id)
|
self.storage.key_chain().pub_account_signing_key(account_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send an arbitrary public transaction to a program.
|
||||||
|
pub async fn send_public_transaction(
|
||||||
|
&self,
|
||||||
|
program_id: nssa_core::program::ProgramId,
|
||||||
|
account_ids: Vec<AccountId>,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
signer: AccountId,
|
||||||
|
) -> Result<HashType, ExecutionFailureKind> {
|
||||||
|
let nonces = self
|
||||||
|
.get_accounts_nonces(vec![signer])
|
||||||
|
.await
|
||||||
|
.map_err(ExecutionFailureKind::SequencerError)?;
|
||||||
|
|
||||||
|
let message = nssa::public_transaction::Message::new_preserialized(
|
||||||
|
program_id,
|
||||||
|
account_ids,
|
||||||
|
nonces,
|
||||||
|
instruction_data,
|
||||||
|
);
|
||||||
|
|
||||||
|
let signing_key = self.storage.user_data.get_pub_account_signing_key(signer);
|
||||||
|
let Some(signing_key) = signing_key else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let witness_set =
|
||||||
|
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
||||||
|
let tx = nssa::PublicTransaction::new(message, witness_set);
|
||||||
|
|
||||||
|
Ok(self
|
||||||
|
.sequencer_client
|
||||||
|
.send_transaction(NSSATransaction::Public(tx))
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_account_private(&self, account_id: AccountId) -> Option<Account> {
|
pub fn get_account_private(&self, account_id: AccountId) -> Option<Account> {
|
||||||
self.storage
|
self.storage
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user