• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

oasisprotocol / oasis-core / #6530

09 Oct 2025 09:53AM UTC coverage: 47.818% (-0.01%) from 47.829%
#6530

Pull #6351

peternose
go/consensus/cometbft/full: Error if light block cannot be constructed

Returning an error instead of an empty light block when block results
for the requested height are unavailable will cause the runtime host
handler to fetch the light block from other nodes in the network.
Pull Request #6351: go/consensus/cometbft/full: Error if light block cannot be constructed

4581 of 9580 relevant lines covered (47.82%)

1.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.68
/runtime/src/common/key_format.rs
1
use std::{convert::TryInto, mem::size_of};
2

3
use impl_trait_for_tuples::impl_for_tuples;
4

5
/// Size of the KeyFormat prefix.
6
const KEY_FORMAT_PREFIX_SIZE: usize = size_of::<u8>();
7

8
/// A key formatting helper trait to be used together with key-value
9
/// backends for constructing keys.
10
pub trait KeyFormat {
11
    /// The prefix that identifies the key format.
12
    fn prefix() -> u8;
13

14
    /// The minimum size of the encoded key.
15
    fn size() -> usize;
16

17
    /// Encode the given key format into a set of atoms.
18
    fn encode_atoms(self, atoms: &mut Vec<Vec<u8>>);
19

20
    /// Decode the given key format from data (without prefix).
21
    ///
22
    /// The caller must ensure that the size of the passed data is at
23
    /// least the minimum size returned by `size`.
24
    fn decode_atoms(data: &[u8]) -> Self
25
    where
26
        Self: Sized;
27

28
    /// Encode the first few atoms in the key format.
29
    ///
30
    /// This method can be used to construct key prefixes for iteration.
31
    /// Specifying a zero count will only generate the prefix.
32
    fn encode_partial(self, count: usize) -> Vec<u8>
21✔
33
    where
34
        Self: Sized,
35
    {
36
        let mut v = Vec::with_capacity(KEY_FORMAT_PREFIX_SIZE + Self::size());
42✔
37
        v.push(Self::prefix());
42✔
38

39
        if count == 0 {
21✔
40
            return v;
6✔
41
        }
42

43
        let mut atoms = Vec::new();
21✔
44
        self.encode_atoms(&mut atoms);
21✔
45
        for (included, mut atom) in atoms.into_iter().enumerate() {
63✔
46
            if included >= count {
21✔
47
                break;
×
48
            }
49
            v.append(&mut atom);
21✔
50
        }
51

52
        v
21✔
53
    }
54

55
    /// Encode the given key format.
56
    fn encode(self) -> Vec<u8>
21✔
57
    where
58
        Self: Sized,
59
    {
60
        self.encode_partial(usize::MAX)
21✔
61
    }
62

63
    /// Decode the given key format from data.
64
    ///
65
    /// The method may return `None` in case the key is of a different
66
    /// type as indicated by the prefix byte.
67
    fn decode(data: &[u8]) -> Option<Self>
8✔
68
    where
69
        Self: Sized,
70
    {
71
        assert!(!data.is_empty(), "key format: malformed input (empty data)");
8✔
72
        if data[0] != Self::prefix() {
16✔
73
            return None;
7✔
74
        }
75
        assert!(
×
76
            data.len() >= Self::size() + KEY_FORMAT_PREFIX_SIZE,
×
77
            "key format: malformed input"
×
78
        );
79

80
        Some(Self::decode_atoms(&data[1..]))
8✔
81
    }
82
}
83

84
/// Part of the KeyFormat to be used with key-value backends for constructing keys.
85
pub trait KeyFormatAtom {
86
    fn size() -> usize;
87

88
    fn encode_atom(self) -> Vec<u8>;
89

90
    fn decode_atom(data: &[u8]) -> Self
91
    where
92
        Self: Sized;
93
}
94

95
impl KeyFormatAtom for u64 {
96
    fn size() -> usize {
97
        8
98
    }
99

100
    fn encode_atom(self) -> Vec<u8> {
1✔
101
        self.to_be_bytes().to_vec()
1✔
102
    }
103

104
    fn decode_atom(data: &[u8]) -> Self
1✔
105
    where
106
        Self: Sized,
107
    {
108
        u64::from_be_bytes(data.try_into().expect("key_format: malformed u64 input"))
1✔
109
    }
110
}
111

112
impl KeyFormatAtom for u8 {
113
    fn size() -> usize {
114
        1
115
    }
116

117
    fn encode_atom(self) -> Vec<u8> {
1✔
118
        vec![self]
1✔
119
    }
120

121
    fn decode_atom(data: &[u8]) -> Self
1✔
122
    where
123
        Self: Sized,
124
    {
125
        assert!(!data.is_empty(), "key_format: malformed: u8 input");
1✔
126
        data[0]
2✔
127
    }
128
}
129

130
impl KeyFormatAtom for () {
131
    fn size() -> usize {
132
        0
133
    }
134

135
    fn encode_atom(self) -> Vec<u8> {
1✔
136
        Vec::new()
1✔
137
    }
138

139
    fn decode_atom(_: &[u8]) {}
×
140
}
141

142
#[impl_for_tuples(2, 10)]
143
impl KeyFormatAtom for Tuple {
144
    fn size() -> usize {
5✔
145
        for_tuples!( #( Tuple::size() )+* );
146
    }
147

148
    fn encode_atom(self) -> Vec<u8> {
5✔
149
        let mut atoms: Vec<Vec<u8>> = [for_tuples!( #( self.Tuple.encode_atom() ),* )].to_vec();
18✔
150

151
        atoms.into_iter().flatten().collect()
5✔
152
    }
153

154
    fn decode_atom(data: &[u8]) -> for_tuples!( ( #( Tuple ),* ) ) {
4✔
155
        assert!(
×
156
            data.len() >= Self::size(),
157
            "key format atom: malformed input"
158
        );
159

160
        let mut sizes: Vec<usize> = [for_tuples!( #( Tuple::size() ),* )].to_vec();
4✔
161
        sizes.reverse();
8✔
162
        let mut data = data.to_vec();
4✔
163

164
        /*
165
            (
166
                {
167
                    let x = T1::decode_atom(data.drain(0..T1::size()));
168
                    x
169
                },
170
                {
171
                    let x = T2::decode_atom(data.drain(0..T2::size()));
172
                    x
173
                }
174
                ...
175
            )
176
        */
177
        for_tuples!(
178
            (
179
                #(
180
                    {
181
                        let x = Tuple::decode_atom(data.drain(0..sizes.pop().unwrap()).as_slice());
36✔
182
                        x
5✔
183
                    }
184
                ),*
185
            )
186
        )
187
    }
188
}
189

190
/// Define a KeyFormat from KeyFormatAtom and a prefix.
191
///
192
/// # Examples
193
///
194
/// ```rust,ignore
195
/// key_format!(NewKeyFormatName, 0x01, InnerType);
196
/// ```
197
#[macro_export]
198
macro_rules! key_format {
199
    ($name:ident, $prefix:expr, $inner:ty) => {
200
        #[derive(Debug, Default, PartialEq, Eq, Clone)]
14✔
201
        struct $name($inner);
7✔
202

203
        impl KeyFormat for $name {
204
            fn prefix() -> u8 {
205
                $prefix
206
            }
207

208
            fn size() -> usize {
18✔
209
                <$inner>::size()
18✔
210
            }
211

212
            fn encode_atoms(self, atoms: &mut Vec<Vec<u8>>) {
18✔
213
                atoms.push(self.0.encode_atom());
18✔
214
            }
215

216
            fn decode_atoms(data: &[u8]) -> Self {
7✔
217
                Self(<$inner>::decode_atom(data))
7✔
218
            }
219
        }
220
    };
221
}
222

223
#[cfg(test)]
224
mod test {
225
    use rustc_hex::ToHex;
226

227
    use crate::common::crypto::hash::Hash;
228

229
    use super::*;
230

231
    #[derive(Debug, PartialEq)]
232
    struct Test1KeyFormat {
233
        h: Hash,
234
    }
235

236
    impl KeyFormat for Test1KeyFormat {
237
        fn prefix() -> u8 {
238
            b'T'
239
        }
240

241
        fn size() -> usize {
242
            32
243
        }
244

245
        fn encode_atoms(self, atoms: &mut Vec<Vec<u8>>) {
246
            atoms.push(self.h.as_ref().to_vec());
247
        }
248

249
        fn decode_atoms(data: &[u8]) -> Self {
250
            Self { h: data.into() }
251
        }
252
    }
253

254
    #[test]
255
    fn test_key_format() {
256
        let mut enc = Test1KeyFormat {
257
            h: Hash::empty_hash(),
258
        }
259
        .encode();
260
        assert_eq!(
261
            enc.to_hex::<String>(),
262
            "54c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"
263
        );
264

265
        let dec = Test1KeyFormat::decode(&enc);
266
        assert_eq!(
267
            dec,
268
            Some(Test1KeyFormat {
269
                h: Hash::empty_hash()
270
            })
271
        );
272

273
        // Clear type.
274
        enc[0] = 0x00;
275
        let dec = Test1KeyFormat::decode(&enc);
276
        assert_eq!(dec, None);
277

278
        // Partial encoding.
279
        let enc = Test1KeyFormat {
280
            h: Hash::empty_hash(),
281
        }
282
        .encode_partial(0);
283
        assert_eq!(enc.to_hex::<String>(), "54");
284
    }
285

286
    #[test]
287
    fn test_key_format_atom() {
288
        key_format!(TestKeyFormat, 0x01, (u8, u64, u8, u64, u64));
289

290
        let key = TestKeyFormat((1, 2, 3, 4, 5));
291
        let enc = key.clone().encode();
292
        let dec = TestKeyFormat::decode(&enc);
293

294
        assert_eq!(dec, Some(key),)
295
    }
296
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc