62 lines
2.4 KiB
Rust
62 lines
2.4 KiB
Rust
|
|
use crate::wallets::structures::Wallet;
|
||
|
|
|
||
|
|
impl Wallet {
|
||
|
|
fn has_valid_public_key_bytes(public_key_bytes: &[u8]) -> bool {
|
||
|
|
// 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.
|
||
|
|
public_key_bytes[0] == Self::FN_DSA_LOGN as u8
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate a long wallet address for the active network and FN-DSA key layout.
|
||
|
|
pub async fn wallet_validation(wallet: &str) -> bool {
|
||
|
|
// Split the visible network prefix from the encoded key body.
|
||
|
|
let (network_prefix, encoded_key) = if let Some(rest) = wallet.strip_prefix("CLTC") {
|
||
|
|
("CLTC", rest)
|
||
|
|
} else if let Some(rest) = wallet.strip_prefix("CLC") {
|
||
|
|
("CLC", rest)
|
||
|
|
} else {
|
||
|
|
return false;
|
||
|
|
};
|
||
|
|
|
||
|
|
// Compare the wallet prefix against the currently compiled network.
|
||
|
|
let expected_byte = Self::current_network_byte();
|
||
|
|
|
||
|
|
if Wallet::map_wallet_to_byte(network_prefix) != expected_byte {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Long wallet address bodies must be the exact encoded public key length.
|
||
|
|
if encoded_key.len() != Self::ADDRESS_HEX_LENGTH {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// The public key body is stored as hex text.
|
||
|
|
if !encoded_key.chars().all(|ch| ch.is_ascii_hexdigit()) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Decode the address and verify the network byte and public key payload.
|
||
|
|
let wallet_bytes = Self::long_address_to_bytes(wallet.to_string());
|
||
|
|
wallet_bytes.len() == Self::ADDRESS_BYTES_LENGTH
|
||
|
|
&& wallet_bytes[0] == expected_byte
|
||
|
|
&& Self::has_valid_public_key_bytes(&wallet_bytes[1..])
|
||
|
|
}
|
||
|
|
|
||
|
|
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()
|
||
|
|
}
|
||
|
|
}
|