1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::bls::BlsPubkey;
use crate::error::{Error, check};
use crate::ffi;
/// `AnchorSet` is a collection of trusted BLS anchor public keys with a signature threshold.
///
/// `AnchorSet` is `Send + Sync` and may be shared across threads. The threshold is set at
/// construction time and governs how many anchor signatures are required for
/// [`Checkpoint::verify`](crate::checkpoint::Checkpoint::verify) to succeed.
pub struct AnchorSet {
ptr: *mut ffi::nwep_anchor_set,
}
unsafe impl Send for AnchorSet {}
unsafe impl Sync for AnchorSet {}
impl AnchorSet {
/// `new` creates an empty `AnchorSet` with the given signature threshold.
///
/// `threshold` is the minimum number of anchor signatures required to validate a
/// checkpoint. A threshold of 0 means no signatures are required (not recommended).
///
/// # Errors
///
/// Returns `Err` if the underlying C allocation fails.
pub fn new(threshold: usize) -> Result<Self, Error> {
let mut ptr: *mut ffi::nwep_anchor_set = std::ptr::null_mut();
check(unsafe { ffi::nwep_anchor_set_new(&mut ptr, threshold) })?;
Ok(AnchorSet { ptr })
}
/// `add` adds a BLS public key to the anchor set.
///
/// `builtin` should be `true` for keys that are part of the initial hardcoded
/// trust configuration, and `false` for dynamically added anchors. The distinction
/// is used by the C library when persisting the anchor set.
///
/// # Errors
///
/// Returns `Err` if `pk` is already present or if the C call fails.
pub fn add(&mut self, pk: &BlsPubkey, builtin: bool) -> Result<(), Error> {
let ffi_pk = ffi::nwep_bls_pubkey { data: pk.0 };
check(unsafe { ffi::nwep_anchor_set_add(self.ptr, &ffi_pk, builtin as i32) })
}
/// `remove` removes a BLS public key from the anchor set.
///
/// # Errors
///
/// Returns `Err` if `pk` is not present or if the C call fails.
pub fn remove(&mut self, pk: &BlsPubkey) -> Result<(), Error> {
let ffi_pk = ffi::nwep_bls_pubkey { data: pk.0 };
check(unsafe { ffi::nwep_anchor_set_remove(self.ptr, &ffi_pk) })
}
/// `size` returns the number of anchor keys currently in the set.
pub fn size(&self) -> usize {
unsafe { ffi::nwep_anchor_set_size(self.ptr) }
}
/// `threshold` returns the minimum number of signatures required to validate a checkpoint.
pub fn threshold(&self) -> usize {
unsafe { ffi::nwep_anchor_set_threshold(self.ptr) }
}
/// `get` returns the BLS public key and `builtin` flag at position `idx`.
///
/// # Errors
///
/// Returns `Err` if `idx >= size()`.
pub fn get(&self, idx: usize) -> Result<(BlsPubkey, bool), Error> {
let mut pk = ffi::nwep_bls_pubkey { data: [0u8; 48] };
let mut builtin = 0i32;
check(unsafe { ffi::nwep_anchor_set_get(self.ptr, idx, &mut pk, &mut builtin) })?;
Ok((BlsPubkey(pk.data), builtin != 0))
}
/// `contains` returns `true` if the given BLS public key is in the anchor set.
pub fn contains(&self, pk: &BlsPubkey) -> bool {
let ffi_pk = ffi::nwep_bls_pubkey { data: pk.0 };
unsafe { ffi::nwep_anchor_set_contains(self.ptr, &ffi_pk) != 0 }
}
/// `iter` returns an iterator over all `(BlsPubkey, builtin)` pairs in the set.
pub fn iter(&self) -> impl Iterator<Item = (BlsPubkey, bool)> + '_ {
(0..self.size()).filter_map(|i| self.get(i).ok())
}
pub(crate) fn as_ptr(&self) -> *const ffi::nwep_anchor_set {
self.ptr
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut ffi::nwep_anchor_set {
self.ptr
}
}
impl Drop for AnchorSet {
fn drop(&mut self) {
if !self.ptr.is_null() {
unsafe { ffi::nwep_anchor_set_free(self.ptr) }
}
}
}