sonicapi/util/
sigs.rs

1// SONIC: Toolchain for formally-verifiable distributed contracts
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Designed in 2019-2025 by Dr Maxim Orlovsky <orlovsky@ubideco.org>
6// Written in 2024-2025 by Dr Maxim Orlovsky <orlovsky@ubideco.org>
7//
8// Copyright (C) 2019-2024 LNP/BP Standards Association, Switzerland.
9// Copyright (C) 2024-2025 Laboratories for Ubiquitous Deterministic Computing (UBIDECO),
10//                         Institute for Distributed and Cognitive Systems (InDCS), Switzerland.
11// Copyright (C) 2019-2025 Dr Maxim Orlovsky.
12// All rights under the above copyrights are reserved.
13//
14// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
15// in compliance with the License. You may obtain a copy of the License at
16//
17//        http://www.apache.org/licenses/LICENSE-2.0
18//
19// Unless required by applicable law or agreed to in writing, software distributed under the License
20// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
21// or implied. See the License for the specific language governing permissions and limitations under
22// the License.
23
24use 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            // TODO: Validate sigs
99            // If we have signatures in excess, we just ignore it
100            if let Ok(None) = self.insert(identity, sig) {
101                count += 1;
102            }
103        }
104        count
105    }
106}