mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-06-26 00:49:27 +00:00
Merge branch 'main' into Pravdyvy/ffi-mnemonic
This commit is contained in:
commit
ca64789a90
@ -60,7 +60,7 @@ allow-git = [
|
||||
"https://github.com/logos-blockchain/logos-blockchain.git",
|
||||
"https://github.com/logos-blockchain/logos-blockchain-circuits.git",
|
||||
"https://github.com/logos-blockchain/logos-blockchain-rust-rapidsnark.git",
|
||||
"https://github.com/arkworks-rs/spongefish.git"
|
||||
"https://github.com/arkworks-rs/spongefish.git",
|
||||
]
|
||||
unknown-git = "deny"
|
||||
unknown-registry = "deny"
|
||||
|
||||
@ -166,6 +166,14 @@ unsafe extern "C" {
|
||||
|
||||
fn wallet_ffi_free_transfer_result(result: *mut FfiTransferResult);
|
||||
|
||||
fn wallet_ffi_bridge_withdraw(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
amount: u64,
|
||||
bedrock_account_pk: *const FfiBytes32,
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_register_public_account(
|
||||
handle: *mut WalletHandle,
|
||||
account_id: *const FfiBytes32,
|
||||
@ -1452,6 +1460,69 @@ fn restore_keys_from_seed_ffi() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_bridge_withdraw() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
let home = tempfile::tempdir()?;
|
||||
let FfiCreateWalletResult {
|
||||
wallet: wallet_ffi_handle,
|
||||
mnemonic: _,
|
||||
} = new_wallet_ffi_with_test_context_config(&ctx, home.path())?;
|
||||
let from: FfiBytes32 = ctx.ctx().existing_public_accounts()[0].into();
|
||||
let bridge_account: FfiBytes32 = lee::system_bridge_account_id().into();
|
||||
let bedrock_account_pk = FfiBytes32::from_bytes([0x42; 32]);
|
||||
let amount = 100_u64;
|
||||
|
||||
let mut transfer_result = FfiTransferResult::default();
|
||||
unsafe {
|
||||
wallet_ffi_bridge_withdraw(
|
||||
wallet_ffi_handle,
|
||||
&raw const from,
|
||||
amount,
|
||||
&raw const bedrock_account_pk,
|
||||
&raw mut transfer_result,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
let from_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
&raw const from,
|
||||
true,
|
||||
&raw mut out_balance,
|
||||
)
|
||||
.unwrap();
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
let bridge_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
&raw const bridge_account,
|
||||
true,
|
||||
&raw mut out_balance,
|
||||
)
|
||||
.unwrap();
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
assert_eq!(from_balance, 9900);
|
||||
assert_eq!(bridge_balance, 1_000_100);
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_transfer_result(&raw mut transfer_result);
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_transfer_generic_public() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
|
||||
91
lez/wallet-ffi/src/bridge.rs
Normal file
91
lez/wallet-ffi/src/bridge.rs
Normal file
@ -0,0 +1,91 @@
|
||||
//! Bridge program functions (deposit/withdraw between L1 Bedrock and L2).
|
||||
|
||||
use std::{ffi::CString, ptr};
|
||||
|
||||
use lee::AccountId;
|
||||
use wallet::program_facades::bridge::Bridge;
|
||||
|
||||
use crate::{
|
||||
block_on,
|
||||
error::{print_error, WalletFfiError},
|
||||
map_execution_error,
|
||||
types::{FfiBytes32, FfiTransferResult, WalletHandle},
|
||||
wallet::get_wallet,
|
||||
};
|
||||
|
||||
/// Withdraw native tokens from a public account to Bedrock (L1) through the bridge.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `handle`: Valid wallet handle
|
||||
/// - `from`: Source public account ID (must be owned by this wallet). Bridge withdrawals only
|
||||
/// support public sender accounts.
|
||||
/// - `amount`: Amount of native tokens to withdraw
|
||||
/// - `bedrock_account_pk`: Recipient's Bedrock (L1) public key, 32 bytes
|
||||
/// - `out_result`: Output pointer for the withdraw result
|
||||
///
|
||||
/// # Returns
|
||||
/// - `Success` if the withdraw transaction was submitted successfully
|
||||
/// - `InsufficientFunds` if the source account doesn't have enough balance
|
||||
/// - `KeyNotFound` if the source account's signing key is not in this wallet
|
||||
/// - Error code on other failures
|
||||
///
|
||||
/// # Memory
|
||||
/// The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||
///
|
||||
/// # Safety
|
||||
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||
/// - `from` must be a valid pointer to a `FfiBytes32` struct
|
||||
/// - `bedrock_account_pk` must be a valid pointer to a `FfiBytes32` struct
|
||||
/// - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_bridge_withdraw(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
amount: u64,
|
||||
bedrock_account_pk: *const FfiBytes32,
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> WalletFfiError {
|
||||
let wrapper = match get_wallet(handle) {
|
||||
Ok(w) => w,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
if from.is_null() || bedrock_account_pk.is_null() || out_result.is_null() {
|
||||
print_error("Null pointer argument");
|
||||
return WalletFfiError::NullPointer;
|
||||
}
|
||||
|
||||
let wallet = match wrapper.core.lock() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to lock wallet: {e}"));
|
||||
return WalletFfiError::InternalError;
|
||||
}
|
||||
};
|
||||
|
||||
let from_id = AccountId::new(unsafe { (*from).data });
|
||||
let bedrock_account_pk = unsafe { (*bedrock_account_pk).data };
|
||||
|
||||
let bridge = Bridge(&wallet);
|
||||
|
||||
match block_on(bridge.send_withdraw(from_id, amount, bedrock_account_pk)) {
|
||||
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!("Bridge withdraw failed: {e:?}"));
|
||||
unsafe {
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
map_execution_error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,6 +42,7 @@ pub use types::*;
|
||||
use crate::error::print_error;
|
||||
|
||||
pub mod account;
|
||||
pub mod bridge;
|
||||
pub mod error;
|
||||
pub mod generic_transaction;
|
||||
pub mod keys;
|
||||
|
||||
@ -219,6 +219,20 @@ typedef struct FfiAccount {
|
||||
struct FfiU128 nonce;
|
||||
} FfiAccount;
|
||||
|
||||
/**
|
||||
* Result of a transfer operation.
|
||||
*/
|
||||
typedef struct FfiTransferResult {
|
||||
/**
|
||||
* Transaction hash (null-terminated string, or null on failure).
|
||||
*/
|
||||
char *tx_hash;
|
||||
/**
|
||||
* Whether the transfer succeeded.
|
||||
*/
|
||||
bool success;
|
||||
} FfiTransferResult;
|
||||
|
||||
typedef struct FfiInstructionWords {
|
||||
uint32_t *instruction_words;
|
||||
uintptr_t instruction_words_size;
|
||||
@ -285,20 +299,6 @@ typedef struct FfiPublicAccountKey {
|
||||
struct FfiBytes32 public_key;
|
||||
} FfiPublicAccountKey;
|
||||
|
||||
/**
|
||||
* Result of a transfer operation.
|
||||
*/
|
||||
typedef struct FfiTransferResult {
|
||||
/**
|
||||
* Transaction hash (null-terminated string, or null on failure).
|
||||
*/
|
||||
char *tx_hash;
|
||||
/**
|
||||
* Whether the transfer succeeded.
|
||||
*/
|
||||
bool success;
|
||||
} FfiTransferResult;
|
||||
|
||||
typedef struct FfiCreateWalletResult {
|
||||
struct WalletHandle *wallet;
|
||||
/**
|
||||
@ -540,6 +540,38 @@ enum WalletFfiError wallet_ffi_import_private_account(struct WalletHandle *handl
|
||||
const struct FfiU128 *identifier,
|
||||
const char *account_state_json);
|
||||
|
||||
/**
|
||||
* Withdraw native tokens from a public account to Bedrock (L1) through the bridge.
|
||||
*
|
||||
* # Parameters
|
||||
* - `handle`: Valid wallet handle
|
||||
* - `from`: Source public account ID (must be owned by this wallet). Bridge withdrawals only
|
||||
* support public sender accounts.
|
||||
* - `amount`: Amount of native tokens to withdraw
|
||||
* - `bedrock_account_pk`: Recipient's Bedrock (L1) public key, 32 bytes
|
||||
* - `out_result`: Output pointer for the withdraw result
|
||||
*
|
||||
* # Returns
|
||||
* - `Success` if the withdraw transaction was submitted successfully
|
||||
* - `InsufficientFunds` if the source account doesn't have enough balance
|
||||
* - `KeyNotFound` if the source account's signing key is not in this wallet
|
||||
* - Error code on other failures
|
||||
*
|
||||
* # Memory
|
||||
* The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||
*
|
||||
* # Safety
|
||||
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||
* - `from` must be a valid pointer to a `FfiBytes32` struct
|
||||
* - `bedrock_account_pk` must be a valid pointer to a `FfiBytes32` struct
|
||||
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||
*/
|
||||
enum WalletFfiError wallet_ffi_bridge_withdraw(struct WalletHandle *handle,
|
||||
const struct FfiBytes32 *from,
|
||||
uint64_t amount,
|
||||
const struct FfiBytes32 *bedrock_account_pk,
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Serialize sequence of bytes into RISC0 readable words.
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user