use crate::types::{CheckCount, FuelAmount, LogSize};
#[derive(Debug, Clone, Copy)]
pub struct SecurityLimits {
pub max_fuel: FuelAmount,
pub max_checks: CheckCount,
pub max_log_size: LogSize,
pub max_memory_size: usize,
pub max_instances: usize,
pub max_memories: usize,
pub max_tables: usize,
}
impl SecurityLimits {
pub const PRODUCTION: Self = Self {
max_fuel: FuelAmount::new(FuelAmount::DEFAULT),
max_checks: CheckCount::new(CheckCount::MAX),
max_log_size: LogSize::new(LogSize::MAX),
max_memory_size: 4 * 1024 * 1024, max_instances: 1,
max_memories: 1,
max_tables: 0,
};
pub const DEVELOPMENT: Self = Self {
max_fuel: FuelAmount::new(10 * FuelAmount::DEFAULT),
max_checks: CheckCount::new(CheckCount::MAX),
max_log_size: LogSize::new(LogSize::MAX),
max_memory_size: 16 * 1024 * 1024, max_instances: 2,
max_memories: 2,
max_tables: 1,
};
pub const STRICT: Self = Self {
max_fuel: FuelAmount::new(100_000),
max_checks: CheckCount::new(16), max_log_size: LogSize::new(4 * 1024), max_memory_size: 1024 * 1024, max_instances: 1,
max_memories: 1,
max_tables: 0,
};
}
impl Default for SecurityLimits {
fn default() -> Self {
Self::PRODUCTION
}
}
pub mod allowed_algorithms {
pub const ALLOWED_HASH_CODECS: &[u64] = &[
0x12, 0x13, 0x20, 0x14, 0x15, 0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0xb220, 0xb240, 0xb260, ];
#[must_use]
pub fn is_hash_allowed(codec: u64) -> bool {
ALLOWED_HASH_CODECS.contains(&codec)
}
#[must_use]
pub const fn hash_name(codec: u64) -> &'static str {
match codec {
0x11 => "SHA-1 (deprecated)",
0xd4 => "MD4 (broken)",
0xd5 => "MD5 (broken)",
0x12 => "SHA2-256",
0x13 => "SHA2-512",
0x1013 => "SHA2-224",
0x20 => "SHA2-384",
0x14 => "SHA3-512",
0x15 => "SHA3-384",
0x16 => "SHA3-256",
0x17 => "SHA3-224",
0x1a => "Keccak-224",
0x1b => "Keccak-256",
0x1c => "Keccak-384",
0x1d => "Keccak-512",
0x1e => "Blake3",
0xb220 => "Blake2b-256",
0xb240 => "Blake2b-512",
0xb260 => "Blake2s-256",
_ => "unknown",
}
}
pub const ALLOWED_SIG_CODECS: &[u64] = &[
0xed, 0xe7, 0x1200, 0xea, ];
#[must_use]
pub fn is_sig_allowed(codec: u64) -> bool {
ALLOWED_SIG_CODECS.contains(&codec)
}
}
pub mod stack_limits {
pub const MAX_PSTACK_DEPTH: usize = 256;
pub const MAX_RSTACK_DEPTH: usize = 256;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_security_limits_default() {
let limits = SecurityLimits::default();
assert_eq!(limits.max_fuel.as_u64(), FuelAmount::DEFAULT);
assert_eq!(limits.max_checks.as_usize(), CheckCount::MAX);
}
#[test]
fn test_production_vs_strict() {
let prod = SecurityLimits::PRODUCTION;
let strict = SecurityLimits::STRICT;
assert!(prod.max_fuel.as_u64() > strict.max_fuel.as_u64());
assert!(prod.max_checks.as_usize() > strict.max_checks.as_usize());
assert!(prod.max_memory_size > strict.max_memory_size);
}
#[test]
fn test_hash_whitelist() {
use allowed_algorithms::is_hash_allowed;
assert!(is_hash_allowed(0x12)); assert!(is_hash_allowed(0x13)); assert!(is_hash_allowed(0x1e)); assert!(is_hash_allowed(0xb220));
assert!(!is_hash_allowed(0x11)); assert!(!is_hash_allowed(0xd5)); assert!(!is_hash_allowed(0x9999)); }
#[test]
fn test_sig_whitelist() {
use allowed_algorithms::is_sig_allowed;
assert!(is_sig_allowed(0xed)); assert!(is_sig_allowed(0x1200)); assert!(is_sig_allowed(0xea));
assert!(!is_sig_allowed(0x9999)); }
}