2026-06-22 16:37:46 +00:00
|
|
|
use crate::common::skein::skein_256_hash_bytes;
|
|
|
|
|
use crate::decode;
|
2026-05-24 17:56:57 +00:00
|
|
|
use crate::wallets::structures::Wallet;
|
|
|
|
|
|
|
|
|
|
impl Wallet {
|
2026-06-04 16:18:55 +00:00
|
|
|
pub fn has_valid_public_key_bytes(public_key_bytes: &[u8]) -> bool {
|
2026-05-24 17:56:57 +00:00
|
|
|
// Public keys must match the FN-DSA public key byte length exactly.
|
|
|
|
|
if public_key_bytes.len() != Self::PUBLIC_KEY_LENGTH {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FN-DSA encoded public keys carry the security parameter in the first byte.
|
2026-06-22 06:24:44 +00:00
|
|
|
if public_key_bytes[0] != Self::FN_DSA_LOGN as u8 {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-22 16:37:46 +00:00
|
|
|
// The encoded Falcon key body is bit-packed and some raw byte values
|
|
|
|
|
// cannot occur at every position. Apply the chain-specific key rule to
|
|
|
|
|
// a public-key hash byte instead so the target remains reachable.
|
|
|
|
|
let public_key_hash = match decode(skein_256_hash_bytes(public_key_bytes)) {
|
|
|
|
|
Ok(hash) => hash,
|
|
|
|
|
Err(_) => return false,
|
|
|
|
|
};
|
|
|
|
|
public_key_hash
|
|
|
|
|
.first()
|
|
|
|
|
.is_some_and(|byte| *byte == Self::REQUIRED_PUBLIC_KEY_HASH_BYTE)
|
2026-05-24 17:56:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn short_address_validation(short_address: &str) -> bool {
|
|
|
|
|
// Accept either canonical short-address bytes or vanity-address bytes.
|
|
|
|
|
let short_address_bytes = match Self::short_address_to_bytes(short_address)
|
|
|
|
|
.or_else(|| Self::vanity_address_to_bytes(short_address))
|
|
|
|
|
{
|
|
|
|
|
Some(bytes) => bytes,
|
|
|
|
|
None => return false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// The final byte must match the currently compiled network.
|
|
|
|
|
short_address_bytes[Self::SHORT_ADDRESS_BYTES_LENGTH - 1] == Self::current_network_byte()
|
|
|
|
|
}
|
|
|
|
|
}
|