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

stacks-network / stacks-core / 26250451051-1

21 May 2026 08:11PM UTC coverage: 85.585% (-0.1%) from 85.712%
26250451051-1

Pull #7215

github

ec9d4c
web-flow
Merge 9487bf852 into af1280aac
Pull Request #7215: Chore: fix flake in non_blocking_minority_configured_to_favour_...

188844 of 220651 relevant lines covered (85.58%)

18975267.44 hits per line

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

84.13
/stacks-common/src/codec/mod.rs
1
// Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation
2
// Copyright (C) 2020-2026 Stacks Open Internet Foundation
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

17
use std::io::{Read, Write};
18
use std::{error, fmt, io, mem};
19

20
use crate::types::chainstate::SortitionId;
21

22
#[macro_use]
23
pub mod macros;
24

25
#[derive(Debug)]
26
pub enum Error {
27
    /// Failed to encode
28
    SerializeError(String),
29
    /// Failed to read
30
    ReadError(io::Error),
31
    /// Failed to decode
32
    DeserializeError(String),
33
    /// Failed to write
34
    WriteError(io::Error),
35
    /// Underflow -- not enough bytes to form the message
36
    UnderflowError(String),
37
    /// Overflow -- message too big
38
    OverflowError(String),
39
    /// Array is too big
40
    ArrayTooLong,
41
    /// Failed to sign
42
    SigningError(String),
43
    /// Generic error
44
    GenericError(String),
45
}
46

47
impl fmt::Display for Error {
48
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3,220✔
49
        match *self {
3,220✔
50
            Error::SerializeError(ref s) => fmt::Display::fmt(s, f),
14✔
51
            Error::DeserializeError(ref s) => fmt::Display::fmt(s, f),
826✔
52
            Error::ReadError(ref io) => fmt::Display::fmt(io, f),
2,310✔
53
            Error::WriteError(ref io) => fmt::Display::fmt(io, f),
×
54
            Error::UnderflowError(ref s) => fmt::Display::fmt(s, f),
70✔
55
            Error::OverflowError(ref s) => fmt::Display::fmt(s, f),
×
56
            Error::ArrayTooLong => write!(f, "Array too long"),
×
57
            Error::SigningError(ref s) => fmt::Display::fmt(s, f),
×
58
            Error::GenericError(ref s) => fmt::Display::fmt(s, f),
×
59
        }
60
    }
3,220✔
61
}
62

63
impl error::Error for Error {
64
    fn cause(&self) -> Option<&dyn error::Error> {
×
65
        match *self {
×
66
            Error::SerializeError(ref _s) => None,
×
67
            Error::ReadError(ref io) => Some(io),
×
68
            Error::DeserializeError(ref _s) => None,
×
69
            Error::WriteError(ref io) => Some(io),
×
70
            Error::UnderflowError(ref _s) => None,
×
71
            Error::OverflowError(ref _s) => None,
×
72
            Error::ArrayTooLong => None,
×
73
            Error::SigningError(ref _s) => None,
×
74
            Error::GenericError(ref _s) => None,
×
75
        }
76
    }
×
77
}
78

79
/// Helper trait for various primitive types that make up Stacks messages
80
pub trait StacksMessageCodec {
81
    /// serialize implementors _should never_ error unless there is an underlying
82
    ///   failure in writing to the `fd`
83
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), Error>
84
    where
85
        Self: Sized;
86
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Self, Error>
87
    where
88
        Self: Sized;
89
    /// Convenience for serialization to a vec.
90
    ///  this function unwraps any underlying serialization error
91
    fn serialize_to_vec(&self) -> Vec<u8>
17,891,956✔
92
    where
17,891,956✔
93
        Self: Sized,
17,891,956✔
94
    {
95
        let mut bytes = vec![];
17,891,956✔
96
        self.consensus_serialize(&mut bytes)
17,891,956✔
97
            .expect("BUG: serialization to buffer failed.");
17,891,956✔
98
        bytes
17,891,956✔
99
    }
17,891,956✔
100
}
101

102
impl_stacks_message_codec_for_int!(u8; [0; 1]);
103
impl_stacks_message_codec_for_int!(u16; [0; 2]);
104
impl_stacks_message_codec_for_int!(u32; [0; 4]);
105
impl_stacks_message_codec_for_int!(u64; [0; 8]);
106
impl_stacks_message_codec_for_int!(i64; [0; 8]);
107

108
impl StacksMessageCodec for [u8; 4] {
109
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), Error> {
×
110
        fd.write_all(self).map_err(Error::WriteError)
×
111
    }
×
112

113
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<[u8; 4], Error> {
2,147,483,647✔
114
        let mut buf = [0u8; 4];
2,147,483,647✔
115
        fd.read_exact(&mut buf).map_err(Error::ReadError)?;
2,147,483,647✔
116
        Ok(buf)
2,147,483,647✔
117
    }
2,147,483,647✔
118
}
119

120
impl StacksMessageCodec for [u8; 20] {
121
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), Error> {
18,547,590✔
122
        fd.write_all(self).map_err(Error::WriteError)
18,547,590✔
123
    }
18,547,590✔
124

125
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<[u8; 20], Error> {
9,255,995✔
126
        let mut buf = [0u8; 20];
9,255,995✔
127
        fd.read_exact(&mut buf).map_err(Error::ReadError)?;
9,255,995✔
128
        Ok(buf)
9,255,995✔
129
    }
9,255,995✔
130
}
131

132
impl StacksMessageCodec for [u8; 32] {
133
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), Error> {
18,474✔
134
        fd.write_all(self).map_err(Error::WriteError)
18,474✔
135
    }
18,474✔
136

137
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<[u8; 32], Error> {
2,311,481✔
138
        let mut buf = [0u8; 32];
2,311,481✔
139
        fd.read_exact(&mut buf).map_err(Error::ReadError)?;
2,311,481✔
140
        Ok(buf)
2,311,481✔
141
    }
2,311,481✔
142
}
143

144
pub fn write_next<T: StacksMessageCodec, W: Write>(fd: &mut W, item: &T) -> Result<(), Error> {
2,147,483,647✔
145
    item.consensus_serialize(fd)
2,147,483,647✔
146
}
2,147,483,647✔
147

148
pub fn read_next<T: StacksMessageCodec, R: Read>(fd: &mut R) -> Result<T, Error> {
2,147,483,647✔
149
    let item: T = T::consensus_deserialize(fd)?;
2,147,483,647✔
150
    Ok(item)
2,147,483,647✔
151
}
2,147,483,647✔
152

153
fn read_next_vec<T: StacksMessageCodec + Sized, R: Read>(
110,877,532✔
154
    fd: &mut R,
110,877,532✔
155
    num_items: u32,
110,877,532✔
156
    max_items: u32,
110,877,532✔
157
) -> Result<Vec<T>, Error> {
110,877,532✔
158
    let len = u32::consensus_deserialize(fd)?;
110,877,532✔
159

160
    if max_items > 0 {
110,877,454✔
161
        if len > max_items {
95,973,075✔
162
            // too many items
163
            return Err(Error::DeserializeError(format!(
24✔
164
                "Array has too many items ({len} > {max_items})"
24✔
165
            )));
24✔
166
        }
95,973,051✔
167
    } else if len != num_items {
14,904,379✔
168
        // inexact item count
169
        return Err(Error::DeserializeError(format!(
5✔
170
            "Array has incorrect number of items ({len} != {num_items})"
5✔
171
        )));
5✔
172
    }
14,904,374✔
173

174
    if (mem::size_of::<T>() as u128) * (len as u128) > MAX_MESSAGE_LEN as u128 {
110,877,425✔
175
        return Err(Error::DeserializeError(format!(
870✔
176
            "Message occupies too many bytes (tried to allocate {}*{}={})",
870✔
177
            mem::size_of::<T>() as u128,
870✔
178
            len,
870✔
179
            (mem::size_of::<T>() as u128) * (len as u128)
870✔
180
        )));
870✔
181
    }
110,876,555✔
182

183
    let mut ret = Vec::with_capacity(len as usize);
110,876,555✔
184
    for _i in 0..len {
2,147,483,647✔
185
        let next_item = T::consensus_deserialize(fd)?;
2,147,483,647✔
186
        ret.push(next_item);
2,147,483,647✔
187
    }
188

189
    Ok(ret)
110,865,295✔
190
}
110,877,532✔
191

192
pub fn read_next_at_most<R: Read, T: StacksMessageCodec + Sized>(
95,973,153✔
193
    fd: &mut R,
95,973,153✔
194
    max_items: u32,
95,973,153✔
195
) -> Result<Vec<T>, Error> {
95,973,153✔
196
    read_next_vec::<T, R>(fd, 0, max_items)
95,973,153✔
197
}
95,973,153✔
198

199
pub fn read_next_exact<R: Read, T: StacksMessageCodec + Sized>(
14,904,379✔
200
    fd: &mut R,
14,904,379✔
201
    num_items: u32,
14,904,379✔
202
) -> Result<Vec<T>, Error> {
14,904,379✔
203
    read_next_vec::<T, R>(fd, num_items, 0)
14,904,379✔
204
}
14,904,379✔
205

206
impl<A, B> StacksMessageCodec for (A, B)
207
where
208
    A: StacksMessageCodec + Sized,
209
    B: StacksMessageCodec + Sized,
210
{
211
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), Error> {
20,282✔
212
        write_next(fd, &self.0)?;
20,282✔
213
        write_next(fd, &self.1)?;
20,282✔
214
        Ok(())
20,282✔
215
    }
20,282✔
216

217
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<(A, B), Error> {
10,146✔
218
        let a: A = read_next(fd)?;
10,146✔
219
        let b: B = read_next(fd)?;
10,146✔
220
        Ok((a, b))
10,143✔
221
    }
10,146✔
222
}
223

224
impl<T> StacksMessageCodec for Vec<T>
225
where
226
    T: StacksMessageCodec + Sized,
227
{
228
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), Error> {
247,890,814✔
229
        let len = self.len() as u32;
247,890,814✔
230
        write_next(fd, &len)?;
247,890,814✔
231
        for item in self {
2,147,483,647✔
232
            write_next(fd, item)?;
2,147,483,647✔
233
        }
234
        Ok(())
247,890,814✔
235
    }
247,890,814✔
236

237
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Vec<T>, Error> {
77,614,220✔
238
        read_next_at_most::<R, T>(fd, u32::MAX)
77,614,220✔
239
    }
77,614,220✔
240
}
241

242
// messages can't be bigger than 16MB plus the preamble and relayers
243
pub const MAX_PAYLOAD_LEN: u32 = 1 + 16 * 1024 * 1024;
244
pub const MAX_MESSAGE_LEN: u32 =
245
    MAX_PAYLOAD_LEN + (PREAMBLE_ENCODED_SIZE + MAX_RELAYERS_LEN * RELAY_DATA_ENCODED_SIZE);
246

247
/// P2P preamble length (addands correspond to fields above)
248
pub const PREAMBLE_ENCODED_SIZE: u32 = 4
249
    + 4
250
    + 4
251
    + 8
252
    + BURNCHAIN_HEADER_HASH_ENCODED_SIZE
253
    + 8
254
    + BURNCHAIN_HEADER_HASH_ENCODED_SIZE
255
    + 4
256
    + MESSAGE_SIGNATURE_ENCODED_SIZE
257
    + 4;
258

259
pub const BURNCHAIN_HEADER_HASH_ENCODED_SIZE: u32 = 32;
260

261
// maximum number of relayers that can be included in a message
262
pub const MAX_RELAYERS_LEN: u32 = 16;
263

264
pub const RELAY_DATA_ENCODED_SIZE: u32 = NEIGHBOR_ADDRESS_ENCODED_SIZE + 4;
265

266
pub const NEIGHBOR_ADDRESS_ENCODED_SIZE: u32 = PEER_ADDRESS_ENCODED_SIZE + 2 + HASH160_ENCODED_SIZE;
267
pub const PEER_ADDRESS_ENCODED_SIZE: u32 = 16;
268

269
pub const HASH160_ENCODED_SIZE: u32 = 20;
270
pub const MESSAGE_SIGNATURE_ENCODED_SIZE: u32 = 65;
271

272
// Stacks-specific codec impls that depend on types defined in this crate.
273
impl_byte_array_message_codec!(SortitionId, 32);
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