v0.3.10-pre.002

This commit is contained in:
2026-09-06 09:58:31 +02:00
parent 6b434750c5
commit d0da907c00
17 changed files with 1453 additions and 29 deletions

View File

@@ -0,0 +1,67 @@
// file: crates/ksp-raw-transaction-lib/src/signature.rs
// version: 1
/// Maximum UTF-8 byte length admitted for one textual Base58 Solana transaction signature.
pub const MAX_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES: usize = 88;
/// Minimum UTF-8 byte length admitted for one textual Base58 Solana transaction signature.
pub const MIN_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES: usize = 64;
/// Parses one bounded Base58 Solana transaction signature to exactly 64 canonical bytes.
pub fn parse_raw_transaction_signature(value: &str) -> ksp_core_lib::Result<ksp_store_api::RawTransactionSignature> {
let text = value.as_bytes();
if text.len() < crate::MIN_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES || text.len() > crate::MAX_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES {
return std::result::Result::Err(
crate::signature_error()
.with_context("actual_len", text.len().to_string())
.with_context("minimum_len", crate::MIN_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES.to_string())
.with_context("maximum_len", crate::MAX_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES.to_string()),
);
}
let mut decoded = [0_u8; 64];
let mut leading_zeroes = 0_usize;
for byte in text {
if *byte != b'1' {
break;
}
leading_zeroes += 1;
}
for byte in text {
let digit = match base58_digit(*byte) {
std::option::Option::Some(digit) => digit,
std::option::Option::None => return std::result::Result::Err(crate::signature_error()),
};
let mut carry = u32::from(digit);
for output in decoded.iter_mut().rev() {
let expanded = (u32::from(*output) * 58) + carry;
*output = (expanded & 0xff) as u8;
carry = expanded >> 8;
}
if carry != 0 {
return std::result::Result::Err(crate::signature_error());
}
}
let significant_len = match decoded.iter().position(|byte| return *byte != 0) {
std::option::Option::Some(index) => decoded.len() - index,
std::option::Option::None => 0,
};
if leading_zeroes + significant_len != decoded.len() {
return std::result::Result::Err(crate::signature_error());
}
return std::result::Result::Ok(ksp_store_api::RawTransactionSignature::new(decoded));
}
fn base58_digit(byte: u8) -> std::option::Option<u8> {
return match byte {
b'1'..=b'9' => std::option::Option::Some(byte - b'1'),
b'A'..=b'H' => std::option::Option::Some((byte - b'A') + 9),
b'J'..=b'N' => std::option::Option::Some((byte - b'J') + 17),
b'P'..=b'Z' => std::option::Option::Some((byte - b'P') + 22),
b'a'..=b'k' => std::option::Option::Some((byte - b'a') + 33),
b'm'..=b'z' => std::option::Option::Some((byte - b'm') + 44),
_ => std::option::Option::None,
};
}
#[cfg(test)]
#[path = "../unit_tests/signature.rs"]
mod tests;