Compare commits

...

5 Commits

Author SHA1 Message Date
Kris Nuttycombe d34c2a3667
Merge 764da27e30 into 5d9a58930c 2024-04-17 18:42:29 +01:00
str4d 5d9a58930c
Merge pull request #132 from nuttycom/avoid_missing_account_panic
Return an error instead of a panic in the case of data corruption.
2024-04-17 18:42:19 +01:00
Kris Nuttycombe 764da27e30 Rename `is_valid_shielded_address` => `is_valid_sapling_address`
Fixing this incorrect name was previously deferred, but since we have a
breaking API change with the addition of the `output_pool` argument to
`zcashlc_get_memo`, we can now fix this.
2024-04-16 13:49:36 -06:00
Kris Nuttycombe 22d80883c9 Require a shielded pool identifier for memo retrieval. 2024-04-16 13:48:36 -06:00
Kris Nuttycombe df52aa844d Return an error instead of a panic in the case of data corruption.
This removes an `expect` call that risked crashing the app in the case of
database corruption, potentially hiding other bugs.
2024-04-01 11:33:48 -06:00
1 changed files with 39 additions and 13 deletions

View File

@ -144,15 +144,27 @@ fn account_id_from_ffi<P: Parameters>(
.filter_map(|account_id| {
db_data
.get_account(account_id)
.transpose()
.expect("account_id exists")
.map(|account| match account.source() {
AccountSource::Derived { account_index, .. }
if account_index == requested_account_index =>
{
Some(account)
}
_ => None,
.map_err(|e| {
anyhow!(
"Database error encountered retrieving account {:?}: {}",
account_id,
e
)
})
.and_then(|acct_opt| {
acct_opt
.ok_or(anyhow!(
"Wallet data corrupted: unable to retrieve account data for account {:?}",
account_id
))
.map(|account| match account.source() {
AccountSource::Derived { account_index, .. }
if account_index == requested_account_index =>
{
Some(account)
}
_ => None,
})
})
.transpose()
});
@ -1012,19 +1024,19 @@ pub unsafe extern "C" fn zcashlc_get_sapling_receiver_for_unified_address(
/// - `address` must be non-null and must point to a null-terminated UTF-8 string.
/// - The memory referenced by `address` must not be mutated for the duration of the function call.
#[no_mangle]
pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(
pub unsafe extern "C" fn zcashlc_is_valid_sapling_address(
address: *const c_char,
network_id: u32,
) -> bool {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let addr = unsafe { CStr::from_ptr(address).to_str()? };
Ok(is_valid_shielded_address(addr, &network))
Ok(is_valid_sapling_address(addr, &network))
});
unwrap_exc_or(res, false)
}
fn is_valid_shielded_address(address: &str, network: &Network) -> bool {
fn is_valid_sapling_address(address: &str, network: &Network) -> bool {
match Address::decode(network, address) {
Some(addr) => match addr {
Address::Sapling(_) => true,
@ -1511,6 +1523,14 @@ pub unsafe extern "C" fn zcashlc_get_total_transparent_balance_for_account(
unwrap_exc_or(res, -1)
}
fn parse_protocol(code: u32) -> Option<ShieldedProtocol> {
match code {
2 => Some(ShieldedProtocol::Sapling),
3 => Some(ShieldedProtocol::Orchard),
_ => None,
}
}
/// Returns the memo for a note by copying the corresponding bytes to the received
/// pointer in `memo_bytes_ret`.
///
@ -1530,6 +1550,7 @@ pub unsafe extern "C" fn zcashlc_get_memo(
db_data: *const u8,
db_data_len: usize,
txid_bytes: *const u8,
output_pool: u32,
output_index: u16,
memo_bytes_ret: *mut u8,
network_id: u32,
@ -1541,8 +1562,13 @@ pub unsafe extern "C" fn zcashlc_get_memo(
let txid_bytes = unsafe { slice::from_raw_parts(txid_bytes, 32) };
let txid = TxId::read(&txid_bytes[..])?;
let protocol = parse_protocol(output_pool).ok_or(anyhow!(
"Shielded protocol not recognized for code: {}",
output_pool
))?;
let memo_bytes = db_data
.get_memo(NoteId::new(txid, ShieldedProtocol::Sapling, output_index))
.get_memo(NoteId::new(txid, protocol, output_index))
.map_err(|e| anyhow!("An error occurred retrieving the memo: {}", e))
.and_then(|memo| memo.ok_or(anyhow!("Memo not available")))
.map(|memo| memo.encode())?;