1use alloc::collections::btree_map;
25
26use amplify::confinement::{ConfinedOrdMap, NonEmptyBlob};
27use commit_verify::StrictHash;
28use ultrasonic::Identity;
29
30use crate::LIB_NAME_SONIC;
31
32pub trait SigValidator {
33 fn validate_sig(&self, identity: &Identity, sig: SigBlob) -> bool;
34}
35
36pub struct DumbValidator;
37impl SigValidator for DumbValidator {
38 fn validate_sig(&self, _: &Identity, _: SigBlob) -> bool { false }
39}
40
41#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Default)]
42#[display(lowercase)]
43#[derive(StrictType, StrictEncode, StrictDecode)]
44#[strict_type(lib = LIB_NAME_SONIC, tags = repr, into_u8, try_from_u8)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
46#[repr(u8)]
47pub enum TrustLevel {
48 Malicious = 0x10,
49 #[default]
50 Unknown = 0x20,
51 Untrusted = 0x40,
52 Trusted = 0x80,
53 Ultimate = 0xC0,
54}
55
56impl TrustLevel {
57 pub fn should_accept(self) -> bool { self >= Self::Unknown }
58 pub fn should_use(self) -> bool { self >= Self::Trusted }
59 pub fn must_use(self) -> bool { self >= Self::Ultimate }
60}
61
62#[derive(Wrapper, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From, Display)]
63#[wrapper(Deref, AsSlice, BorrowSlice, Hex)]
64#[display(LowerHex)]
65#[derive(StrictType, StrictEncode, StrictDecode)]
66#[strict_type(lib = LIB_NAME_SONIC)]
67#[derive(CommitEncode)]
68#[commit_encode(strategy = strict, id = StrictHash)]
69#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
70pub struct SigBlob(NonEmptyBlob<4096>);
71
72impl Default for SigBlob {
73 fn default() -> Self { SigBlob(NonEmptyBlob::with(0)) }
74}
75
76#[derive(Wrapper, WrapperMut, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Debug, Default, From)]
77#[wrapper(Deref)]
78#[wrapper_mut(DerefMut)]
79#[derive(StrictType, StrictEncode, StrictDecode)]
80#[strict_type(lib = LIB_NAME_SONIC)]
81#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
82pub struct ContentSigs(ConfinedOrdMap<Identity, SigBlob, 0, 10>);
83
84impl IntoIterator for ContentSigs {
85 type Item = (Identity, SigBlob);
86 type IntoIter = btree_map::IntoIter<Identity, SigBlob>;
87
88 fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
89}
90
91impl ContentSigs {
92 pub fn merge(&mut self, other: ContentSigs) -> usize {
93 let mut count = 0;
94 for (identity, sig) in other {
95 if self.contains_key(&identity) {
96 continue;
97 }
98 if let Ok(None) = self.insert(identity, sig) {
101 count += 1;
102 }
103 }
104 count
105 }
106}