Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/header/aura.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2019-2022  Parity Technologies (UK) Ltd.
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
use super::Error;
19
use crate::util;
20
21
use alloc::vec::Vec;
22
use core::{cmp, fmt, iter, slice};
23
24
/// A consensus log item for AURA.
25
#[derive(Debug, Clone, PartialEq, Eq)]
26
pub enum AuraConsensusLogRef<'a> {
27
    /// List of authorities has changed.
28
    AuthoritiesChange(AuraAuthoritiesIter<'a>),
29
    /// Disable the authority with given index.
30
    OnDisabled(u32),
31
}
32
33
impl<'a> AuraConsensusLogRef<'a> {
34
    /// Decodes a [`AuraConsensusLogRef`] from a slice of bytes.
35
1
    pub fn from_slice(slice: &'a [u8]) -> Result<Self, Error> {
36
1
        Ok(match slice.first() {
37
            Some(1) => {
38
1
                AuraConsensusLogRef::AuthoritiesChange(AuraAuthoritiesIter::decode(&slice[1..])?)
39
            }
40
            Some(2) => {
41
0
                let n = u32::from_le_bytes(
42
0
                    <[u8; 4]>::try_from(&slice[1..]).map_err(|_| Error::DigestItemDecodeError)?,
Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot6header4auraNtB4_19AuraConsensusLogRef10from_slice0B8_
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6header4auraNtB4_19AuraConsensusLogRef10from_slice0B8_
43
                );
44
0
                AuraConsensusLogRef::OnDisabled(n)
45
            }
46
0
            Some(_) => return Err(Error::BadAuraConsensusRefType),
47
0
            None => return Err(Error::TooShort),
48
        })
49
1
    }
_RNvMNtNtCsN16ciHI6Qf_7smoldot6header4auraNtB2_19AuraConsensusLogRef10from_slice
Line
Count
Source
35
1
    pub fn from_slice(slice: &'a [u8]) -> Result<Self, Error> {
36
1
        Ok(match slice.first() {
37
            Some(1) => {
38
1
                AuraConsensusLogRef::AuthoritiesChange(AuraAuthoritiesIter::decode(&slice[1..])?)
39
            }
40
            Some(2) => {
41
0
                let n = u32::from_le_bytes(
42
0
                    <[u8; 4]>::try_from(&slice[1..]).map_err(|_| Error::DigestItemDecodeError)?,
43
                );
44
0
                AuraConsensusLogRef::OnDisabled(n)
45
            }
46
0
            Some(_) => return Err(Error::BadAuraConsensusRefType),
47
0
            None => return Err(Error::TooShort),
48
        })
49
1
    }
Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot6header4auraNtB2_19AuraConsensusLogRef10from_slice
50
51
    /// Returns an iterator to list of buffers which, when concatenated, produces the SCALE
52
    /// encoding of that object.
53
0
    pub fn scale_encoding(
54
0
        &self,
55
0
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
56
0
        let index = iter::once(match self {
57
0
            AuraConsensusLogRef::AuthoritiesChange(_) => [1],
58
0
            AuraConsensusLogRef::OnDisabled(_) => [2],
59
        });
60
61
0
        let body = match self {
62
0
            AuraConsensusLogRef::AuthoritiesChange(list) => {
63
0
                let len = util::encode_scale_compact_usize(list.len());
64
0
                either::Left(
65
0
                    iter::once(len)
66
0
                        .map(either::Left)
67
0
                        .chain(
68
0
                            list.clone()
69
0
                                .flat_map(|l| l.scale_encoding().map(either::Right)),
Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot6header4auraNtB4_19AuraConsensusLogRef14scale_encoding0B8_
Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot6header4auraNtB4_19AuraConsensusLogRef14scale_encoding0B8_
70
0
                        )
71
0
                        .map(either::Left),
72
0
                )
73
            }
74
0
            AuraConsensusLogRef::OnDisabled(digest) => {
75
0
                either::Right(iter::once(digest.to_le_bytes()).map(either::Right))
76
            }
77
        };
78
79
0
        index.map(either::Left).chain(body.map(either::Right))
80
0
    }
Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot6header4auraNtB2_19AuraConsensusLogRef14scale_encoding
Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot6header4auraNtB2_19AuraConsensusLogRef14scale_encoding
81
}
82
83
impl<'a> From<&'a AuraConsensusLog> for AuraConsensusLogRef<'a> {
84
0
    fn from(a: &'a AuraConsensusLog) -> Self {
85
0
        match a {
86
0
            AuraConsensusLog::AuthoritiesChange(v) => AuraConsensusLogRef::AuthoritiesChange(
87
0
                AuraAuthoritiesIter(AuraAuthoritiesIterInner::List(v.iter())),
88
0
            ),
89
0
            AuraConsensusLog::OnDisabled(v) => AuraConsensusLogRef::OnDisabled(*v),
90
        }
91
0
    }
Unexecuted instantiation: _RNvXs_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB4_19AuraConsensusLogRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB4_16AuraConsensusLogE4from
Unexecuted instantiation: _RNvXs_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB4_19AuraConsensusLogRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB4_16AuraConsensusLogE4from
92
}
93
94
/// A consensus log item for AURA.
95
#[derive(Debug, Clone, PartialEq, Eq)]
96
pub enum AuraConsensusLog {
97
    /// List of authorities has changed.
98
    AuthoritiesChange(Vec<AuraAuthority>),
99
    /// Disable the authority with given index.
100
    OnDisabled(u32),
101
}
102
103
impl<'a> From<AuraConsensusLogRef<'a>> for AuraConsensusLog {
104
0
    fn from(a: AuraConsensusLogRef<'a>) -> Self {
105
0
        match a {
106
0
            AuraConsensusLogRef::AuthoritiesChange(v) => {
107
0
                AuraConsensusLog::AuthoritiesChange(v.map(|a| a.into()).collect())
Unexecuted instantiation: _RNCNvXs0_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB7_16AuraConsensusLogINtNtCsaYZPK01V26L_4core7convert4FromNtB7_19AuraConsensusLogRefE4from0Bb_
Unexecuted instantiation: _RNCNvXs0_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB7_16AuraConsensusLogINtNtCsaYZPK01V26L_4core7convert4FromNtB7_19AuraConsensusLogRefE4from0Bb_
108
            }
109
0
            AuraConsensusLogRef::OnDisabled(v) => AuraConsensusLog::OnDisabled(v),
110
        }
111
0
    }
Unexecuted instantiation: _RNvXs0_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_16AuraConsensusLogINtNtCsaYZPK01V26L_4core7convert4FromNtB5_19AuraConsensusLogRefE4from
Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_16AuraConsensusLogINtNtCsaYZPK01V26L_4core7convert4FromNtB5_19AuraConsensusLogRefE4from
112
}
113
114
/// List of authorities in an AURA context.
115
#[derive(Clone)]
116
pub struct AuraAuthoritiesIter<'a>(AuraAuthoritiesIterInner<'a>);
117
118
#[derive(Clone)]
119
enum AuraAuthoritiesIterInner<'a> {
120
    List(slice::Iter<'a, AuraAuthority>),
121
    Raw(slice::Chunks<'a, u8>),
122
}
123
124
impl<'a> AuraAuthoritiesIter<'a> {
125
    /// Decodes a list of authorities from a SCALE-encoded blob of data.
126
43
    pub fn decode(data: &'a [u8]) -> Result<Self, Error> {
127
43
        let (data, num_items) = util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(data)
128
43
            .map_err(|_| 
Error::TooShort0
)
?0
;
Unexecuted instantiation: _RNCNvMs1_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB7_19AuraAuthoritiesIter6decode0Bb_
Unexecuted instantiation: _RNCNvMs1_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB7_19AuraAuthoritiesIter6decode0Bb_
129
130
43
        if data.len()
131
43
            != num_items
132
43
                .checked_mul(32)
133
43
                .ok_or(Error::BadAuraAuthoritiesListLen)
?1
134
        {
135
0
            return Err(Error::BadAuraAuthoritiesListLen);
136
42
        }
137
42
138
42
        Ok(AuraAuthoritiesIter(AuraAuthoritiesIterInner::Raw(
139
42
            data.chunks(32),
140
42
        )))
141
43
    }
_RNvMs1_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_19AuraAuthoritiesIter6decode
Line
Count
Source
126
1
    pub fn decode(data: &'a [u8]) -> Result<Self, Error> {
127
1
        let (data, num_items) = util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(data)
128
1
            .map_err(|_| Error::TooShort)
?0
;
129
130
1
        if data.len()
131
1
            != num_items
132
1
                .checked_mul(32)
133
1
                .ok_or(Error::BadAuraAuthoritiesListLen)?
134
        {
135
0
            return Err(Error::BadAuraAuthoritiesListLen);
136
0
        }
137
0
138
0
        Ok(AuraAuthoritiesIter(AuraAuthoritiesIterInner::Raw(
139
0
            data.chunks(32),
140
0
        )))
141
1
    }
_RNvMs1_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_19AuraAuthoritiesIter6decode
Line
Count
Source
126
42
    pub fn decode(data: &'a [u8]) -> Result<Self, Error> {
127
42
        let (data, num_items) = util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(data)
128
42
            .map_err(|_| Error::TooShort)
?0
;
129
130
42
        if data.len()
131
42
            != num_items
132
42
                .checked_mul(32)
133
42
                .ok_or(Error::BadAuraAuthoritiesListLen)
?0
134
        {
135
0
            return Err(Error::BadAuraAuthoritiesListLen);
136
42
        }
137
42
138
42
        Ok(AuraAuthoritiesIter(AuraAuthoritiesIterInner::Raw(
139
42
            data.chunks(32),
140
42
        )))
141
42
    }
142
143
    /// Builds an iterator corresponding to the given slice.
144
315
    pub fn from_slice(slice: &'a [AuraAuthority]) -> Self {
145
315
        AuraAuthoritiesIter(AuraAuthoritiesIterInner::List(slice.iter()))
146
315
    }
Unexecuted instantiation: _RNvMs1_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_19AuraAuthoritiesIter10from_slice
_RNvMs1_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_19AuraAuthoritiesIter10from_slice
Line
Count
Source
144
315
    pub fn from_slice(slice: &'a [AuraAuthority]) -> Self {
145
315
        AuraAuthoritiesIter(AuraAuthoritiesIterInner::List(slice.iter()))
146
315
    }
147
}
148
149
impl<'a> Iterator for AuraAuthoritiesIter<'a> {
150
    type Item = AuraAuthorityRef<'a>;
151
152
126
    fn next(&mut self) -> Option<Self::Item> {
153
126
        match &mut self.0 {
154
0
            AuraAuthoritiesIterInner::List(l) => l.next().map(Into::into),
155
126
            AuraAuthoritiesIterInner::Raw(l) => {
156
126
                let 
item84
= l.next()
?42
;
157
84
                assert_eq!(item.len(), 32);
158
84
                Some(AuraAuthorityRef {
159
84
                    public_key: <&[u8; 32]>::try_from(item).unwrap(),
160
84
                })
161
            }
162
        }
163
126
    }
Unexecuted instantiation: _RNvXs2_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4next
_RNvXs2_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
152
126
    fn next(&mut self) -> Option<Self::Item> {
153
126
        match &mut self.0 {
154
0
            AuraAuthoritiesIterInner::List(l) => l.next().map(Into::into),
155
126
            AuraAuthoritiesIterInner::Raw(l) => {
156
126
                let 
item84
= l.next()
?42
;
157
84
                assert_eq!(item.len(), 32);
158
84
                Some(AuraAuthorityRef {
159
84
                    public_key: <&[u8; 32]>::try_from(item).unwrap(),
160
84
                })
161
            }
162
        }
163
126
    }
164
165
42
    fn size_hint(&self) -> (usize, Option<usize>) {
166
42
        match &self.0 {
167
0
            AuraAuthoritiesIterInner::List(l) => l.size_hint(),
168
42
            AuraAuthoritiesIterInner::Raw(l) => l.size_hint(),
169
        }
170
42
    }
Unexecuted instantiation: _RNvXs2_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hint
_RNvXs2_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hint
Line
Count
Source
165
42
    fn size_hint(&self) -> (usize, Option<usize>) {
166
42
        match &self.0 {
167
0
            AuraAuthoritiesIterInner::List(l) => l.size_hint(),
168
42
            AuraAuthoritiesIterInner::Raw(l) => l.size_hint(),
169
        }
170
42
    }
171
}
172
173
impl<'a> ExactSizeIterator for AuraAuthoritiesIter<'a> {}
174
175
impl<'a> cmp::PartialEq<AuraAuthoritiesIter<'a>> for AuraAuthoritiesIter<'a> {
176
0
    fn eq(&self, other: &AuraAuthoritiesIter<'a>) -> bool {
177
0
        let mut a = self.clone();
178
0
        let mut b = other.clone();
179
        loop {
180
0
            match (a.next(), b.next()) {
181
0
                (Some(a), Some(b)) if a == b => {}
182
0
                (None, None) => return true,
183
0
                _ => return false,
184
            }
185
        }
186
0
    }
Unexecuted instantiation: _RNvXs4_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtCsaYZPK01V26L_4core3cmp9PartialEq2eq
Unexecuted instantiation: _RNvXs4_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtCsaYZPK01V26L_4core3cmp9PartialEq2eq
187
}
188
189
impl<'a> cmp::Eq for AuraAuthoritiesIter<'a> {}
190
191
impl<'a> fmt::Debug for AuraAuthoritiesIter<'a> {
192
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
193
0
        f.debug_list().entries(self.clone()).finish()
194
0
    }
Unexecuted instantiation: _RNvXs6_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs6_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_19AuraAuthoritiesIterNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
195
}
196
197
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
198
pub struct AuraAuthorityRef<'a> {
199
    /// Sr25519 public key.
200
    pub public_key: &'a [u8; 32],
201
}
202
203
impl<'a> AuraAuthorityRef<'a> {
204
    /// Returns an iterator to list of buffers which, when concatenated, produces the SCALE
205
    /// encoding of that object.
206
0
    pub fn scale_encoding(
207
0
        &self,
208
0
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
209
0
        iter::once(self.public_key)
210
0
    }
Unexecuted instantiation: _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_16AuraAuthorityRef14scale_encoding
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_16AuraAuthorityRef14scale_encoding
211
}
212
213
impl<'a> From<&'a AuraAuthority> for AuraAuthorityRef<'a> {
214
0
    fn from(a: &'a AuraAuthority) -> Self {
215
0
        AuraAuthorityRef {
216
0
            public_key: &a.public_key,
217
0
        }
218
0
    }
Unexecuted instantiation: _RNvXs8_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_16AuraAuthorityRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_13AuraAuthorityE4from
Unexecuted instantiation: _RNvXs8_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_16AuraAuthorityRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_13AuraAuthorityE4from
219
}
220
221
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
222
pub struct AuraAuthority {
223
    /// Sr25519 public key.
224
    pub public_key: [u8; 32],
225
}
226
227
impl<'a> From<AuraAuthorityRef<'a>> for AuraAuthority {
228
84
    fn from(a: AuraAuthorityRef<'a>) -> Self {
229
84
        AuraAuthority {
230
84
            public_key: *a.public_key,
231
84
        }
232
84
    }
Unexecuted instantiation: _RNvXs9_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_13AuraAuthorityINtNtCsaYZPK01V26L_4core7convert4FromNtB5_16AuraAuthorityRefE4from
_RNvXs9_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_13AuraAuthorityINtNtCsaYZPK01V26L_4core7convert4FromNtB5_16AuraAuthorityRefE4from
Line
Count
Source
228
84
    fn from(a: AuraAuthorityRef<'a>) -> Self {
229
84
        AuraAuthority {
230
84
            public_key: *a.public_key,
231
84
        }
232
84
    }
233
}
234
235
/// AURA slot number pre-digest.
236
#[derive(Debug, Clone, PartialEq, Eq)]
237
pub struct AuraPreDigest {
238
    /// Slot number when the block was produced.
239
    pub slot_number: u64,
240
}
241
242
impl AuraPreDigest {
243
    /// Decodes a [`AuraPreDigest`] from a slice of bytes.
244
1
    pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
245
1
        if slice.len() != 8 {
246
0
            return Err(Error::TooShort);
247
1
        }
248
1
249
1
        Ok(AuraPreDigest {
250
1
            slot_number: u64::from_le_bytes(<[u8; 8]>::try_from(slice).unwrap()),
251
1
        })
252
1
    }
_RNvMsa_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_13AuraPreDigest10from_slice
Line
Count
Source
244
1
    pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
245
1
        if slice.len() != 8 {
246
0
            return Err(Error::TooShort);
247
1
        }
248
1
249
1
        Ok(AuraPreDigest {
250
1
            slot_number: u64::from_le_bytes(<[u8; 8]>::try_from(slice).unwrap()),
251
1
        })
252
1
    }
Unexecuted instantiation: _RNvMsa_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_13AuraPreDigest10from_slice
253
254
    /// Returns an iterator to list of buffers which, when concatenated, produces the SCALE
255
    /// encoding of that object.
256
2
    pub fn scale_encoding(&self) -> impl Iterator<Item = impl AsRef<[u8]> + Clone> + Clone {
257
2
        iter::once(self.slot_number.to_le_bytes())
258
2
    }
_RNvMsa_NtNtCsN16ciHI6Qf_7smoldot6header4auraNtB5_13AuraPreDigest14scale_encoding
Line
Count
Source
256
2
    pub fn scale_encoding(&self) -> impl Iterator<Item = impl AsRef<[u8]> + Clone> + Clone {
257
2
        iter::once(self.slot_number.to_le_bytes())
258
2
    }
Unexecuted instantiation: _RNvMsa_NtNtCseuYC0Zibziv_7smoldot6header4auraNtB5_13AuraPreDigest14scale_encoding
259
}