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

stacks-network / stacks-core / 28180279429-1

25 Jun 2026 03:12PM UTC coverage: 86.051% (+0.3%) from 85.712%
28180279429-1

Pull #7349

github

60dd2f
web-flow
Merge 223323fdf into 7e8d141b5
Pull Request #7349: feat: add contract analysis max time guard-rails

209 of 219 new or added lines in 21 files covered. (95.43%)

8887 existing lines in 130 files now uncovered.

194988 of 226596 relevant lines covered (86.05%)

18771900.15 hits per line

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

92.02
/stackslib/src/net/codec.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::collections::HashSet;
18
use std::io;
19
use std::io::prelude::*;
20
use std::io::Read;
21

22
use clarity::vm::types::QualifiedContractIdentifier;
23
use clarity::vm::ContractName;
24
use rand::{self, Rng};
25
use sha2::{Digest, Sha512_256};
26
use stacks_common::bitvec::BitVec;
27
use stacks_common::codec::{
28
    read_next, read_next_at_most, read_next_exact, write_next, Error as codec_error,
29
    StacksMessageCodec, MAX_MESSAGE_LEN, MAX_RELAYERS_LEN, PREAMBLE_ENCODED_SIZE,
30
};
31
use stacks_common::types::chainstate::{BlockHeaderHash, BurnchainHeaderHash};
32
use stacks_common::types::net::PeerAddress;
33
use stacks_common::types::StacksPublicKeyBuffer;
34
use stacks_common::util::hash::{to_hex, Hash160};
35
use stacks_common::util::retry::BoundReader;
36
use stacks_common::util::secp256k1::{MessageSignature, Secp256k1PrivateKey, Secp256k1PublicKey};
37

38
use crate::burnchains::{BurnchainView, PrivateKey, PublicKey};
39
use crate::chainstate::burn::ConsensusHash;
40
use crate::chainstate::nakamoto::NakamotoBlock;
41
use crate::chainstate::stacks::{
42
    StacksBlock, StacksMicroblock, StacksPublicKey, StacksTransaction, MAX_BLOCK_LEN,
43
};
44
use crate::net::db::LocalPeer;
45
use crate::net::{Error as net_error, *};
46

47
pub fn bitvec_len(bitlen: u16) -> u16 {
2,796,257✔
48
    (bitlen / 8) + (if bitlen % 8 != 0 { 1 } else { 0 })
2,796,257✔
49
}
2,796,257✔
50

51
impl Preamble {
52
    /// Make an empty preamble with the given version and fork-set identifier, and payload length.
53
    pub fn new(
12,762,372✔
54
        peer_version: u32,
12,762,372✔
55
        network_id: u32,
12,762,372✔
56
        block_height: u64,
12,762,372✔
57
        burn_block_hash: &BurnchainHeaderHash,
12,762,372✔
58
        stable_block_height: u64,
12,762,372✔
59
        stable_burn_block_hash: &BurnchainHeaderHash,
12,762,372✔
60
        payload_len: u32,
12,762,372✔
61
    ) -> Preamble {
12,762,372✔
62
        Preamble {
12,762,372✔
63
            peer_version,
12,762,372✔
64
            network_id,
12,762,372✔
65
            seq: 0,
12,762,372✔
66
            burn_block_height: block_height,
12,762,372✔
67
            burn_block_hash: burn_block_hash.clone(),
12,762,372✔
68
            burn_stable_block_height: stable_block_height,
12,762,372✔
69
            burn_stable_block_hash: stable_burn_block_hash.clone(),
12,762,372✔
70
            additional_data: 0,
12,762,372✔
71
            signature: MessageSignature::empty(),
12,762,372✔
72
            payload_len,
12,762,372✔
73
        }
12,762,372✔
74
    }
12,762,372✔
75

76
    /// Given the serialized message type and bits, sign the resulting message and store the
77
    /// signature.  message_bits includes the relayers, payload type, and payload.
78
    pub fn sign(
12,761,927✔
79
        &mut self,
12,761,927✔
80
        message_bits: &[u8],
12,761,927✔
81
        privkey: &Secp256k1PrivateKey,
12,761,927✔
82
    ) -> Result<(), net_error> {
12,761,927✔
83
        let mut digest_bits = [0u8; 32];
12,761,927✔
84
        let mut sha2 = Sha512_256::new();
12,761,927✔
85

86
        // serialize the premable with a blank signature
87
        let old_signature = self.signature.clone();
12,761,927✔
88
        self.signature = MessageSignature::empty();
12,761,927✔
89

90
        let mut preamble_bits = vec![];
12,761,927✔
91
        self.consensus_serialize(&mut preamble_bits)?;
12,761,927✔
92
        self.signature = old_signature;
12,761,927✔
93

94
        sha2.update(&preamble_bits[..]);
12,761,927✔
95
        sha2.update(message_bits);
12,761,927✔
96

97
        digest_bits.copy_from_slice(sha2.finalize().as_slice());
12,761,927✔
98

99
        let sig = privkey
12,761,927✔
100
            .sign(&digest_bits)
12,761,927✔
101
            .map_err(|se| net_error::SigningError(se.to_string()))?;
12,761,927✔
102

103
        self.signature = sig;
12,761,927✔
104
        Ok(())
12,761,927✔
105
    }
12,761,927✔
106

107
    /// Given the serialized message type and bits, verify the signature.
108
    /// message_bits includes the relayers, payload type, and payload
109
    pub fn verify(
12,699,082✔
110
        &mut self,
12,699,082✔
111
        message_bits: &[u8],
12,699,082✔
112
        pubkey: &Secp256k1PublicKey,
12,699,082✔
113
    ) -> Result<(), net_error> {
12,699,082✔
114
        let mut digest_bits = [0u8; 32];
12,699,082✔
115
        let mut sha2 = Sha512_256::new();
12,699,082✔
116

117
        // serialize the preamble with a blank signature
118
        let sig_bits = self.signature.clone();
12,699,082✔
119
        self.signature = MessageSignature::empty();
12,699,082✔
120

121
        let mut preamble_bits = vec![];
12,699,082✔
122
        self.consensus_serialize(&mut preamble_bits)?;
12,699,082✔
123
        self.signature = sig_bits;
12,699,082✔
124

125
        sha2.update(&preamble_bits[..]);
12,699,082✔
126
        sha2.update(message_bits);
12,699,082✔
127

128
        digest_bits.copy_from_slice(sha2.finalize().as_slice());
12,699,082✔
129

130
        let res = pubkey
12,699,082✔
131
            .verify(&digest_bits, &self.signature)
12,699,082✔
132
            .map_err(|_ve| net_error::VerifyingError("Failed to verify signature".to_string()))?;
12,699,082✔
133

134
        if res {
12,699,082✔
135
            Ok(())
12,699,081✔
136
        } else {
137
            Err(net_error::VerifyingError(
1✔
138
                "Invalid message signature".to_string(),
1✔
139
            ))
1✔
140
        }
141
    }
12,699,082✔
142
}
143

144
impl StacksMessageCodec for Preamble {
145
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
38,223,003✔
146
        write_next(fd, &self.peer_version)?;
38,223,003✔
147
        write_next(fd, &self.network_id)?;
38,223,003✔
148
        write_next(fd, &self.seq)?;
38,223,003✔
149
        write_next(fd, &self.burn_block_height)?;
38,223,003✔
150
        write_next(fd, &self.burn_block_hash)?;
38,223,003✔
151
        write_next(fd, &self.burn_stable_block_height)?;
38,223,003✔
152
        write_next(fd, &self.burn_stable_block_hash)?;
38,223,003✔
153
        write_next(fd, &self.additional_data)?;
38,223,003✔
154
        write_next(fd, &self.signature)?;
38,223,003✔
155
        write_next(fd, &self.payload_len)?;
38,223,003✔
156
        Ok(())
38,223,003✔
157
    }
38,223,003✔
158

159
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Preamble, codec_error> {
12,744,359✔
160
        let peer_version: u32 = read_next(fd)?;
12,744,359✔
161
        let network_id: u32 = read_next(fd)?;
12,744,359✔
162
        let seq: u32 = read_next(fd)?;
12,744,359✔
163
        let burn_block_height: u64 = read_next(fd)?;
12,744,359✔
164
        let burn_block_hash: BurnchainHeaderHash = read_next(fd)?;
12,744,359✔
165
        let burn_stable_block_height: u64 = read_next(fd)?;
12,744,359✔
166
        let burn_stable_block_hash: BurnchainHeaderHash = read_next(fd)?;
12,744,359✔
167
        let additional_data: u32 = read_next(fd)?;
12,744,359✔
168
        let signature: MessageSignature = read_next(fd)?;
12,744,359✔
169
        let payload_len: u32 = read_next(fd)?;
12,744,359✔
170

171
        // minimum is 5 bytes -- a zero-length vector (4 bytes of 0) plus a type identifier (1 byte)
172
        if payload_len < 5 {
12,744,358✔
UNCOV
173
            test_debug!("Payload len is too small: {}", payload_len);
×
174
            return Err(codec_error::DeserializeError(format!(
×
175
                "Payload len is too small: {}",
×
176
                payload_len
×
177
            )));
×
178
        }
12,744,358✔
179

180
        if payload_len >= MAX_MESSAGE_LEN {
12,744,358✔
UNCOV
181
            test_debug!("Payload len is too big: {}", payload_len);
×
182
            return Err(codec_error::DeserializeError(format!(
×
183
                "Payload len is too big: {}",
×
184
                payload_len
×
185
            )));
×
186
        }
12,744,358✔
187

188
        if burn_block_height <= burn_stable_block_height {
12,744,358✔
UNCOV
189
            test_debug!(
×
190
                "burn block height {} <= burn stable block height {}",
191
                burn_block_height,
192
                burn_stable_block_height
193
            );
UNCOV
194
            return Err(codec_error::DeserializeError(format!(
×
195
                "Burn block height {} <= burn stable block height {}",
×
196
                burn_block_height, burn_stable_block_height
×
197
            )));
×
198
        }
12,744,358✔
199

200
        Ok(Preamble {
12,744,358✔
201
            peer_version,
12,744,358✔
202
            network_id,
12,744,358✔
203
            seq,
12,744,358✔
204
            burn_block_height,
12,744,358✔
205
            burn_block_hash,
12,744,358✔
206
            burn_stable_block_height,
12,744,358✔
207
            burn_stable_block_hash,
12,744,358✔
208
            additional_data,
12,744,358✔
209
            signature,
12,744,358✔
210
            payload_len,
12,744,358✔
211
        })
12,744,358✔
212
    }
12,744,359✔
213
}
214

215
impl StacksMessageCodec for GetBlocksInv {
216
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
1,307,616✔
217
        write_next(fd, &self.consensus_hash)?;
1,307,616✔
218
        write_next(fd, &self.num_blocks)?;
1,307,616✔
219
        Ok(())
1,307,616✔
220
    }
1,307,616✔
221

222
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<GetBlocksInv, codec_error> {
653,804✔
223
        let consensus_hash: ConsensusHash = read_next(fd)?;
653,804✔
224
        let num_blocks: u16 = read_next(fd)?;
653,804✔
225
        if num_blocks == 0 {
653,802✔
UNCOV
226
            return Err(codec_error::DeserializeError(
×
227
                "GetBlocksInv must request at least one block".to_string(),
×
228
            ));
×
229
        }
653,802✔
230

231
        Ok(GetBlocksInv {
653,802✔
232
            consensus_hash,
653,802✔
233
            num_blocks,
653,802✔
234
        })
653,802✔
235
    }
653,804✔
236
}
237

238
impl StacksMessageCodec for BlocksInvData {
239
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
1,296,859✔
240
        write_next(fd, &self.bitlen)?;
1,296,859✔
241
        write_next(fd, &self.block_bitvec)?;
1,296,859✔
242
        write_next(fd, &self.microblocks_bitvec)?;
1,296,859✔
243
        Ok(())
1,296,859✔
244
    }
1,296,859✔
245

246
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<BlocksInvData, codec_error> {
648,271✔
247
        let bitlen: u16 = read_next(fd)?;
648,271✔
248
        if bitlen == 0 {
648,271✔
249
            return Err(codec_error::DeserializeError(
1✔
250
                "BlocksInv must contain at least one block/microblock bit".to_string(),
1✔
251
            ));
1✔
252
        }
648,270✔
253

254
        let block_bitvec: Vec<u8> = read_next_exact::<_, u8>(fd, bitvec_len(bitlen).into())?;
648,270✔
255
        let microblocks_bitvec: Vec<u8> = read_next_exact::<_, u8>(fd, bitvec_len(bitlen).into())?;
648,268✔
256

257
        Ok(BlocksInvData {
648,266✔
258
            bitlen,
648,266✔
259
            block_bitvec,
648,266✔
260
            microblocks_bitvec,
648,266✔
261
        })
648,266✔
262
    }
648,271✔
263
}
264

265
impl BlocksInvData {
UNCOV
266
    pub fn empty() -> BlocksInvData {
×
267
        BlocksInvData {
×
268
            bitlen: 0,
×
269
            block_bitvec: vec![],
×
270
            microblocks_bitvec: vec![],
×
271
        }
×
272
    }
×
273

274
    #[allow(clippy::indexing_slicing)]
275
    pub fn compress_bools(bits: &[bool]) -> Vec<u8> {
1,302,986✔
276
        let bvl: u16 = bits
1,302,986✔
277
            .len()
1,302,986✔
278
            .try_into()
1,302,986✔
279
            .expect("FATAL: tried to compress more than u16::MAX bools");
1,302,986✔
280
        let mut bitvec = vec![0u8; bitvec_len(bvl) as usize];
1,302,986✔
281
        for (i, bit) in bits.iter().enumerate() {
21,341,154✔
282
            if *bit {
21,341,154✔
283
                bitvec[i / 8] |= 1u8 << (i % 8);
1,308,700✔
284
            }
20,034,788✔
285
        }
286
        bitvec
1,302,986✔
287
    }
1,302,986✔
288

289
    pub fn has_ith_block(&self, block_index: u16) -> bool {
39,496✔
290
        if block_index >= self.bitlen {
39,496✔
291
            return false;
2,817✔
292
        }
36,679✔
293

294
        let idx = block_index / 8;
36,679✔
295
        let bit = block_index % 8;
36,679✔
296
        let Some(bitvec_entry) = self.block_bitvec.get(idx as usize) else {
36,679✔
UNCOV
297
            return false;
×
298
        };
299
        (bitvec_entry & (1 << bit)) != 0
36,679✔
300
    }
39,496✔
301

302
    pub fn has_ith_microblock_stream(&self, block_index: u16) -> bool {
39,477✔
303
        if block_index >= self.bitlen {
39,477✔
304
            return false;
2,818✔
305
        }
36,659✔
306

307
        let idx = block_index / 8;
36,659✔
308
        let bit = block_index % 8;
36,659✔
309
        let Some(bitvec_entry) = self.microblocks_bitvec.get(idx as usize) else {
36,659✔
UNCOV
310
            return false;
×
311
        };
312
        bitvec_entry & (1 << bit) != 0
36,659✔
313
    }
39,477✔
314
}
315

316
impl StacksMessageCodec for GetNakamotoInvData {
317
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
474,314✔
318
        write_next(fd, &self.consensus_hash)?;
474,314✔
319
        Ok(())
474,314✔
320
    }
474,314✔
321

322
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Self, codec_error> {
236,765✔
323
        let consensus_hash: ConsensusHash = read_next(fd)?;
236,765✔
324
        Ok(Self { consensus_hash })
236,763✔
325
    }
236,765✔
326
}
327

328
impl StacksMessageCodec for NakamotoInvData {
329
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
460,514✔
330
        write_next(fd, &self.tenures)?;
460,514✔
331
        Ok(())
460,514✔
332
    }
460,514✔
333

334
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Self, codec_error> {
229,660✔
335
        Ok(Self {
336
            tenures: read_next(fd)?,
229,660✔
337
        })
338
    }
229,660✔
339
}
340

341
impl NakamotoInvData {
342
    pub fn try_from(bits: &[bool]) -> Result<Self, codec_error> {
230,288✔
343
        Ok(Self {
344
            tenures: BitVec::<2100>::try_from(bits).map_err(|e| {
230,288✔
UNCOV
345
                codec_error::SerializeError(format!(
×
346
                    "Could not serialize vec of {} bools: {}",
×
347
                    bits.len(),
×
348
                    e
×
349
                ))
×
350
            })?,
×
351
        })
352
    }
230,288✔
353

UNCOV
354
    pub fn has_ith_tenure(&self, tenure_index: u16) -> bool {
×
355
        self.tenures.get(tenure_index).unwrap_or(false)
×
356
    }
×
357
}
358

359
impl StacksMessageCodec for NakamotoBlocksData {
360
    #[cfg_attr(test, mutants::skip)]
361
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
15,524✔
362
        write_next(fd, &self.blocks)?;
15,524✔
363
        Ok(())
15,524✔
364
    }
15,524✔
365

366
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Self, codec_error> {
7,688✔
367
        let blocks: Vec<NakamotoBlock> = {
7,688✔
368
            // loose upper-bound
369
            let mut bound_read = BoundReader::from_reader(fd, MAX_MESSAGE_LEN as u64);
7,688✔
370
            read_next_at_most::<_, NakamotoBlock>(&mut bound_read, NAKAMOTO_BLOCKS_PUSHED_MAX)
7,688✔
UNCOV
371
        }?;
×
372

373
        // only valid if there are no dups
374
        let mut present = HashSet::new();
7,688✔
375
        for block in blocks.iter() {
8,019✔
376
            if present.contains(&block.block_id()) {
8,019✔
377
                // no dups allowed
UNCOV
378
                return Err(codec_error::DeserializeError(
×
379
                    "Invalid NakamotoBlocksData: duplicate block".to_string(),
×
380
                ));
×
381
            }
8,019✔
382

383
            present.insert(block.block_id());
8,019✔
384
        }
385

386
        Ok(NakamotoBlocksData { blocks })
7,688✔
387
    }
7,688✔
388
}
389

390
impl StacksMessageCodec for GetPoxInv {
391
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
393,575✔
392
        write_next(fd, &self.consensus_hash)?;
393,575✔
393
        write_next(fd, &self.num_cycles)?;
393,575✔
394
        Ok(())
393,575✔
395
    }
393,575✔
396

397
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<GetPoxInv, codec_error> {
196,789✔
398
        let ch: ConsensusHash = read_next(fd)?;
196,789✔
399
        let num_rcs: u16 = read_next(fd)?;
196,789✔
400
        if num_rcs == 0 || num_rcs as u64 > GETPOXINV_MAX_BITLEN {
196,787✔
401
            return Err(codec_error::DeserializeError(
1✔
402
                "Invalid GetPoxInv bitlen".to_string(),
1✔
403
            ));
1✔
404
        }
196,786✔
405
        Ok(GetPoxInv {
196,786✔
406
            consensus_hash: ch,
196,786✔
407
            num_cycles: num_rcs,
196,786✔
408
        })
196,786✔
409
    }
196,789✔
410
}
411

412
impl PoxInvData {
413
    pub fn has_ith_reward_cycle(&self, index: u16) -> bool {
1,503,229✔
414
        if index >= self.bitlen {
1,503,229✔
UNCOV
415
            return false;
×
416
        }
1,503,229✔
417

418
        let idx = index / 8;
1,503,229✔
419
        let bit = index % 8;
1,503,229✔
420
        let Some(bitvec_entry) = self.pox_bitvec.get(idx as usize) else {
1,503,229✔
UNCOV
421
            return false;
×
422
        };
423
        bitvec_entry & (1 << bit) != 0
1,503,229✔
424
    }
1,503,229✔
425
}
426

427
impl StacksMessageCodec for PoxInvData {
428
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
393,558✔
429
        write_next(fd, &self.bitlen)?;
393,558✔
430
        write_next(fd, &self.pox_bitvec)?;
393,558✔
431
        Ok(())
393,558✔
432
    }
393,558✔
433

434
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<PoxInvData, codec_error> {
196,735✔
435
        let bitlen: u16 = read_next(fd)?;
196,735✔
436
        if bitlen == 0 || (bitlen as u64) > GETPOXINV_MAX_BITLEN {
196,735✔
437
            return Err(codec_error::DeserializeError(
2✔
438
                "Invalid PoxInvData bitlen".to_string(),
2✔
439
            ));
2✔
440
        }
196,733✔
441

442
        let pox_bitvec: Vec<u8> = read_next_exact::<_, u8>(fd, bitvec_len(bitlen).into())?;
196,733✔
443
        Ok(PoxInvData { bitlen, pox_bitvec })
196,729✔
444
    }
196,735✔
445
}
446

447
impl StacksMessageCodec for BlocksAvailableData {
448
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
7,135✔
449
        write_next(fd, &self.available)?;
7,135✔
450
        Ok(())
7,135✔
451
    }
7,135✔
452

453
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<BlocksAvailableData, codec_error> {
3,570✔
454
        let available: Vec<(ConsensusHash, BurnchainHeaderHash)> =
3,567✔
455
            read_next_at_most::<_, (ConsensusHash, BurnchainHeaderHash)>(
3,570✔
456
                fd,
3,570✔
457
                BLOCKS_AVAILABLE_MAX_LEN,
458
            )?;
3✔
459
        Ok(BlocksAvailableData { available })
3,567✔
460
    }
3,570✔
461
}
462

463
impl BlocksAvailableData {
UNCOV
464
    pub fn new() -> BlocksAvailableData {
×
465
        BlocksAvailableData { available: vec![] }
×
466
    }
×
467

UNCOV
468
    pub fn try_push(
×
469
        &mut self,
×
470
        ch: ConsensusHash,
×
471
        bhh: BurnchainHeaderHash,
×
472
    ) -> Result<(), net_error> {
×
473
        if self.available.len() < BLOCKS_AVAILABLE_MAX_LEN as usize {
×
474
            self.available.push((ch, bhh));
×
475
            return Ok(());
×
476
        } else {
UNCOV
477
            return Err(net_error::InvalidMessage);
×
478
        }
UNCOV
479
    }
×
480
}
481

482
impl StacksMessageCodec for BlocksDatum {
483
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
54,216✔
484
        write_next(fd, &self.0)?;
54,216✔
485
        write_next(fd, &self.1)?;
54,216✔
486
        Ok(())
54,216✔
487
    }
54,216✔
488

489
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<BlocksDatum, codec_error> {
27,108✔
490
        let ch: ConsensusHash = read_next(fd)?;
27,108✔
491
        let block = {
27,108✔
492
            let mut bound_read = BoundReader::from_reader(fd, MAX_BLOCK_LEN as u64);
27,108✔
493
            read_next(&mut bound_read)
27,108✔
UNCOV
494
        }?;
×
495

496
        Ok(BlocksDatum(ch, block))
27,108✔
497
    }
27,108✔
498
}
499

500
impl BlocksData {
UNCOV
501
    pub fn new() -> BlocksData {
×
502
        BlocksData { blocks: vec![] }
×
503
    }
×
504

UNCOV
505
    pub fn push(&mut self, ch: ConsensusHash, block: StacksBlock) {
×
506
        self.blocks.push(BlocksDatum(ch, block))
×
507
    }
×
508
}
509

510
impl StacksMessageCodec for BlocksData {
511
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
54,018✔
512
        write_next(fd, &self.blocks)?;
54,018✔
513
        Ok(())
54,018✔
514
    }
54,018✔
515

516
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<BlocksData, codec_error> {
27,009✔
517
        let blocks: Vec<BlocksDatum> = {
27,009✔
518
            // loose upper-bound
519
            let mut bound_read = BoundReader::from_reader(fd, MAX_MESSAGE_LEN as u64);
27,009✔
520
            read_next_at_most::<_, BlocksDatum>(&mut bound_read, BLOCKS_PUSHED_MAX)
27,009✔
UNCOV
521
        }?;
×
522

523
        // only valid if there are no dups
524
        let mut present = HashSet::new();
27,009✔
525
        for BlocksDatum(consensus_hash, _block) in blocks.iter() {
27,108✔
526
            if present.contains(consensus_hash) {
27,108✔
527
                // no dups allowed
UNCOV
528
                return Err(codec_error::DeserializeError(
×
529
                    "Invalid BlocksData: duplicate block".to_string(),
×
530
                ));
×
531
            }
27,108✔
532

533
            present.insert(consensus_hash.clone());
27,108✔
534
        }
535

536
        Ok(BlocksData { blocks })
27,009✔
537
    }
27,009✔
538
}
539

540
impl StacksMessageCodec for MicroblocksData {
UNCOV
541
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
×
542
        write_next(fd, &self.index_anchor_block)?;
×
543
        write_next(fd, &self.microblocks)?;
×
544
        Ok(())
×
545
    }
×
546

UNCOV
547
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<MicroblocksData, codec_error> {
×
548
        let index_anchor_block = read_next(fd)?;
×
549
        let microblocks: Vec<StacksMicroblock> = {
×
550
            // loose upper-bound
UNCOV
551
            let mut bound_read = BoundReader::from_reader(fd, MAX_MESSAGE_LEN as u64);
×
552
            read_next(&mut bound_read)
×
553
        }?;
×
554

UNCOV
555
        Ok(MicroblocksData {
×
556
            index_anchor_block,
×
557
            microblocks,
×
558
        })
×
559
    }
×
560
}
561

562
impl NeighborAddress {
563
    pub fn from_neighbor(n: &Neighbor) -> NeighborAddress {
9,730,219✔
564
        NeighborAddress {
9,730,219✔
565
            addrbytes: n.addr.addrbytes.clone(),
9,730,219✔
566
            port: n.addr.port,
9,730,219✔
567
            public_key_hash: Hash160::from_node_public_key(&n.public_key),
9,730,219✔
568
        }
9,730,219✔
569
    }
9,730,219✔
570
}
571

572
impl StacksMessageCodec for NeighborAddress {
573
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
1,175,313✔
574
        write_next(fd, &self.addrbytes)?;
1,175,313✔
575
        write_next(fd, &self.port)?;
1,175,313✔
576
        write_next(fd, &self.public_key_hash)?;
1,175,313✔
577
        Ok(())
1,175,313✔
578
    }
1,175,313✔
579

580
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<NeighborAddress, codec_error> {
587,205✔
581
        let addrbytes: PeerAddress = read_next(fd)?;
587,205✔
582
        let port: u16 = read_next(fd)?;
587,205✔
583
        let public_key_hash: Hash160 = read_next(fd)?;
587,205✔
584

585
        Ok(NeighborAddress {
587,202✔
586
            addrbytes,
587,202✔
587
            port,
587,202✔
588
            public_key_hash,
587,202✔
589
        })
587,202✔
590
    }
587,205✔
591
}
592

593
impl StacksMessageCodec for NeighborsData {
594
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
671,768✔
595
        write_next(fd, &self.neighbors)?;
671,768✔
596
        Ok(())
671,768✔
597
    }
671,768✔
598

599
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<NeighborsData, codec_error> {
335,744✔
600
        // don't allow list of more than the pre-set number of neighbors
601
        let neighbors: Vec<NeighborAddress> =
335,742✔
602
            read_next_at_most::<_, NeighborAddress>(fd, MAX_NEIGHBORS_DATA_LEN)?;
335,744✔
603
        Ok(NeighborsData { neighbors })
335,742✔
604
    }
335,744✔
605
}
606

607
impl HandshakeData {
608
    pub fn from_local_peer(local_peer: &LocalPeer) -> HandshakeData {
814,020✔
609
        let (addrbytes, port) = match local_peer.public_ip_address {
814,020✔
610
            Some((ref public_addrbytes, ref port)) => (public_addrbytes.clone(), *port),
411,896✔
611
            None => (local_peer.addrbytes.clone(), local_peer.port),
402,124✔
612
        };
613

614
        // transmit the empty string if our data URL compels us to bind to the anynet address
615
        let data_url = if local_peer.data_url.has_routable_host() {
814,020✔
616
            local_peer.data_url.clone()
814,020✔
UNCOV
617
        } else if let Some(data_port) = local_peer.data_url.get_port() {
×
618
            // deduce from public IP
UNCOV
619
            UrlString::try_from(format!("http://{}", addrbytes.to_socketaddr(data_port))).unwrap()
×
620
        } else {
621
            // unroutable, so don't bother
UNCOV
622
            UrlString::try_from("").unwrap()
×
623
        };
624

625
        HandshakeData {
814,020✔
626
            addrbytes,
814,020✔
627
            port,
814,020✔
628
            services: local_peer.services,
814,020✔
629
            node_public_key: StacksPublicKeyBuffer::from_public_key(
814,020✔
630
                &Secp256k1PublicKey::from_private(&local_peer.private_key),
814,020✔
631
            ),
814,020✔
632
            expire_block_height: local_peer.private_key_expire,
814,020✔
633
            data_url,
814,020✔
634
        }
814,020✔
635
    }
814,020✔
636
}
637

638
impl StacksMessageCodec for HandshakeData {
639
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
1,642,493✔
640
        write_next(fd, &self.addrbytes)?;
1,642,493✔
641
        write_next(fd, &self.port)?;
1,642,493✔
642
        write_next(fd, &self.services)?;
1,642,493✔
643
        write_next(fd, &self.node_public_key)?;
1,642,493✔
644
        write_next(fd, &self.expire_block_height)?;
1,642,493✔
645
        write_next(fd, &self.data_url)?;
1,642,493✔
646
        Ok(())
1,642,493✔
647
    }
1,642,493✔
648

649
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<HandshakeData, codec_error> {
813,592✔
650
        let addrbytes: PeerAddress = read_next(fd)?;
813,592✔
651
        let port: u16 = read_next(fd)?;
813,592✔
652
        if port == 0 {
813,592✔
UNCOV
653
            return Err(codec_error::DeserializeError(
×
UNCOV
654
                "Invalid handshake data: port is 0".to_string(),
×
655
            ));
×
656
        }
813,592✔
657

658
        let services: u16 = read_next(fd)?;
813,592✔
659
        let node_public_key: StacksPublicKeyBuffer = read_next(fd)?;
813,592✔
660
        let expire_block_height: u64 = read_next(fd)?;
813,592✔
661
        let data_url: UrlString = read_next(fd)?;
813,592✔
662
        Ok(HandshakeData {
813,590✔
663
            addrbytes,
813,590✔
664
            port,
813,590✔
665
            services,
813,590✔
666
            node_public_key,
813,590✔
667
            expire_block_height,
813,590✔
668
            data_url,
813,590✔
669
        })
813,590✔
670
    }
813,592✔
671
}
672

673
impl HandshakeAcceptData {
674
    pub fn new(local_peer: &LocalPeer, heartbeat_interval: u32) -> HandshakeAcceptData {
406,625✔
675
        HandshakeAcceptData {
406,625✔
676
            handshake: HandshakeData::from_local_peer(local_peer),
406,625✔
677
            heartbeat_interval,
406,625✔
678
        }
406,625✔
679
    }
406,625✔
680
}
681

682
impl StacksMessageCodec for HandshakeAcceptData {
683
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
813,259✔
684
        write_next(fd, &self.handshake)?;
813,259✔
685
        write_next(fd, &self.heartbeat_interval)?;
813,259✔
686
        Ok(())
813,259✔
687
    }
813,259✔
688

689
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<HandshakeAcceptData, codec_error> {
406,330✔
690
        let handshake: HandshakeData = read_next(fd)?;
406,330✔
691
        let heartbeat_interval: u32 = read_next(fd)?;
406,330✔
692
        Ok(HandshakeAcceptData {
406,328✔
693
            handshake,
406,328✔
694
            heartbeat_interval,
406,328✔
695
        })
406,328✔
696
    }
406,330✔
697
}
698

699
impl NackData {
700
    pub fn new(error_code: u32) -> NackData {
383,687✔
701
        NackData { error_code }
383,687✔
702
    }
383,687✔
703
}
704

705
impl StacksMessageCodec for NackData {
706
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
738,864✔
707
        write_next(fd, &self.error_code)?;
738,864✔
708
        Ok(())
738,864✔
709
    }
738,864✔
710

711
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<NackData, codec_error> {
369,181✔
712
        let error_code: u32 = read_next(fd)?;
369,181✔
713
        Ok(NackData { error_code })
369,179✔
714
    }
369,181✔
715
}
716

717
impl PingData {
718
    pub fn new() -> PingData {
15✔
719
        let mut rng = rand::thread_rng();
15✔
720
        let n = rng.gen();
15✔
721
        PingData { nonce: n }
15✔
722
    }
15✔
723
}
724

725
impl StacksMessageCodec for PingData {
726
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
20,072✔
727
        write_next(fd, &self.nonce)?;
20,072✔
728
        Ok(())
20,072✔
729
    }
20,072✔
730

731
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<PingData, codec_error> {
10,020✔
732
        let nonce: u32 = read_next(fd)?;
10,020✔
733
        Ok(PingData { nonce })
10,019✔
734
    }
10,020✔
735
}
736

737
impl PongData {
738
    pub fn from_ping(p: &PingData) -> PongData {
6✔
739
        PongData { nonce: p.nonce }
6✔
740
    }
6✔
741
}
742

743
impl StacksMessageCodec for PongData {
744
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
15✔
745
        write_next(fd, &self.nonce)?;
15✔
746
        Ok(())
15✔
747
    }
15✔
748

749
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<PongData, codec_error> {
8✔
750
        let nonce: u32 = read_next(fd)?;
8✔
751
        Ok(PongData { nonce })
7✔
752
    }
8✔
753
}
754

755
impl StacksMessageCodec for NatPunchData {
756
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
1,372✔
757
        write_next(fd, &self.addrbytes)?;
1,372✔
758
        write_next(fd, &self.port)?;
1,372✔
759
        write_next(fd, &self.nonce)?;
1,372✔
760
        Ok(())
1,372✔
761
    }
1,372✔
762

763
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<NatPunchData, codec_error> {
688✔
764
        let addrbytes: PeerAddress = read_next(fd)?;
688✔
765
        let port: u16 = read_next(fd)?;
688✔
766
        let nonce: u32 = read_next(fd)?;
688✔
767
        Ok(NatPunchData {
686✔
768
            addrbytes,
686✔
769
            port,
686✔
770
            nonce,
686✔
771
        })
686✔
772
    }
688✔
773
}
774

775
fn contract_id_consensus_serialize<W: Write>(
18,935,757✔
776
    fd: &mut W,
18,935,757✔
777
    cid: &QualifiedContractIdentifier,
18,935,757✔
778
) -> Result<(), codec_error> {
18,935,757✔
779
    let addr = &cid.issuer;
18,935,757✔
780
    let name = &cid.name;
18,935,757✔
781
    write_next(fd, &addr.version())?;
18,935,757✔
782
    write_next(fd, &addr.1)?;
18,935,757✔
783
    write_next(fd, name)?;
18,935,757✔
784
    Ok(())
18,935,757✔
785
}
18,935,757✔
786

787
fn contract_id_consensus_deserialize<R: Read>(
9,455,345✔
788
    fd: &mut R,
9,455,345✔
789
) -> Result<QualifiedContractIdentifier, codec_error> {
9,455,345✔
790
    let version: u8 = read_next(fd)?;
9,455,345✔
791
    let bytes: [u8; 20] = read_next(fd)?;
9,455,345✔
792
    let name: ContractName = read_next(fd)?;
9,455,345✔
793
    let qn = QualifiedContractIdentifier::new(
9,455,343✔
794
        StacksAddress::new(version, Hash160(bytes))
9,455,343✔
795
            .map_err(|_| {
9,455,343✔
UNCOV
796
                codec_error::DeserializeError(
×
UNCOV
797
                    "Failed to make StacksAddress with given version".into(),
×
798
                )
×
799
            })?
×
800
            .into(),
9,455,343✔
801
        name,
9,455,343✔
802
    );
803
    Ok(qn)
9,455,343✔
804
}
9,455,345✔
805

806
impl StacksMessageCodec for StackerDBHandshakeData {
807
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
776,402✔
808
        if self.smart_contracts.len() > 256 {
776,402✔
UNCOV
809
            return Err(codec_error::ArrayTooLong);
×
810
        }
776,402✔
811
        // force no more than 256 names in the protocol
812
        let len_u8: u8 = self.smart_contracts.len().try_into().expect("Unreachable");
776,402✔
813
        write_next(fd, &self.rc_consensus_hash)?;
776,402✔
814
        write_next(fd, &len_u8)?;
776,402✔
815
        for cid in self.smart_contracts.iter() {
10,229,850✔
816
            contract_id_consensus_serialize(fd, cid)?;
9,862,230✔
817
        }
818
        Ok(())
776,402✔
819
    }
776,402✔
820

821
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StackerDBHandshakeData, codec_error> {
388,010✔
822
        let rc_consensus_hash = read_next(fd)?;
388,010✔
823
        let len_u8: u8 = read_next(fd)?;
388,010✔
824
        let mut smart_contracts = Vec::with_capacity(len_u8 as usize);
388,010✔
825
        for _ in 0..len_u8 {
388,010✔
826
            let cid: QualifiedContractIdentifier = contract_id_consensus_deserialize(fd)?;
4,927,894✔
827
            smart_contracts.push(cid);
4,927,892✔
828
        }
829
        Ok(StackerDBHandshakeData {
388,008✔
830
            rc_consensus_hash,
388,008✔
831
            smart_contracts,
388,008✔
832
        })
388,008✔
833
    }
388,010✔
834
}
835

836
impl StacksMessageCodec for StackerDBGetChunkInvData {
837
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
7,864,800✔
838
        contract_id_consensus_serialize(fd, &self.contract_id)?;
7,864,800✔
839
        write_next(fd, &self.rc_consensus_hash)?;
7,864,800✔
840
        Ok(())
7,864,800✔
841
    }
7,864,800✔
842

843
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StackerDBGetChunkInvData, codec_error> {
3,923,618✔
844
        let contract_id: QualifiedContractIdentifier = contract_id_consensus_deserialize(fd)?;
3,923,618✔
845
        let rc_consensus_hash: ConsensusHash = read_next(fd)?;
3,923,618✔
846
        Ok(StackerDBGetChunkInvData {
3,923,616✔
847
            contract_id,
3,923,616✔
848
            rc_consensus_hash,
3,923,616✔
849
        })
3,923,616✔
850
    }
3,923,618✔
851
}
852

853
impl StacksMessageCodec for StackerDBChunkInvData {
854
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
8,129,882✔
855
        if self.slot_versions.len() > (stackerdb::STACKERDB_INV_MAX as usize) {
8,129,882✔
UNCOV
856
            return Err(codec_error::ArrayTooLong);
×
857
        }
8,129,882✔
858
        write_next(fd, &self.slot_versions)?;
8,129,882✔
859
        write_next(fd, &self.num_outbound_replicas)?;
8,129,882✔
860
        Ok(())
8,129,882✔
861
    }
8,129,882✔
862

863
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StackerDBChunkInvData, codec_error> {
4,058,890✔
864
        let slot_versions: Vec<u32> = read_next_at_most(fd, stackerdb::STACKERDB_INV_MAX)?;
4,058,890✔
865
        let num_outbound_replicas: u32 = read_next(fd)?;
4,058,890✔
866
        Ok(StackerDBChunkInvData {
4,058,888✔
867
            slot_versions,
4,058,888✔
868
            num_outbound_replicas,
4,058,888✔
869
        })
4,058,888✔
870
    }
4,058,890✔
871
}
872

873
impl StacksMessageCodec for StackerDBGetChunkData {
874
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
174,898✔
875
        contract_id_consensus_serialize(fd, &self.contract_id)?;
174,898✔
876
        write_next(fd, &self.rc_consensus_hash)?;
174,898✔
877
        write_next(fd, &self.slot_id)?;
174,898✔
878
        write_next(fd, &self.slot_version)?;
174,898✔
879
        Ok(())
174,898✔
880
    }
174,898✔
881

882
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StackerDBGetChunkData, codec_error> {
87,423✔
883
        let contract_id: QualifiedContractIdentifier = contract_id_consensus_deserialize(fd)?;
87,423✔
884
        let rc_consensus_hash: ConsensusHash = read_next(fd)?;
87,423✔
885
        let slot_id: u32 = read_next(fd)?;
87,423✔
886
        let slot_version: u32 = read_next(fd)?;
87,423✔
887
        Ok(StackerDBGetChunkData {
87,421✔
888
            contract_id,
87,421✔
889
            rc_consensus_hash,
87,421✔
890
            slot_id,
87,421✔
891
            slot_version,
87,421✔
892
        })
87,421✔
893
    }
87,423✔
894
}
895

896
impl StacksMessageCodec for StackerDBPushChunkData {
897
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
1,033,856✔
898
        contract_id_consensus_serialize(fd, &self.contract_id)?;
1,033,856✔
899
        write_next(fd, &self.rc_consensus_hash)?;
1,033,856✔
900
        write_next(fd, &self.chunk_data)?;
1,033,856✔
901
        Ok(())
1,033,856✔
902
    }
1,033,856✔
903

904
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StackerDBPushChunkData, codec_error> {
516,410✔
905
        let contract_id: QualifiedContractIdentifier = contract_id_consensus_deserialize(fd)?;
516,410✔
906
        let rc_consensus_hash: ConsensusHash = read_next(fd)?;
516,410✔
907
        let chunk_data: StackerDBChunkData = read_next(fd)?;
516,410✔
908
        Ok(StackerDBPushChunkData {
516,408✔
909
            contract_id,
516,408✔
910
            rc_consensus_hash,
516,408✔
911
            chunk_data,
516,408✔
912
        })
516,408✔
913
    }
516,410✔
914
}
915

916
impl StacksMessageCodec for RelayData {
917
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
838,260✔
918
        write_next(fd, &self.peer)?;
838,260✔
919
        write_next(fd, &self.seq)?;
838,260✔
920
        Ok(())
838,260✔
921
    }
838,260✔
922

923
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<RelayData, codec_error> {
419,003✔
924
        let peer: NeighborAddress = read_next(fd)?;
419,003✔
925
        let seq: u32 = read_next(fd)?;
419,003✔
926
        Ok(RelayData { peer, seq })
419,002✔
927
    }
419,003✔
928
}
929

930
impl StacksMessageType {
931
    pub fn get_message_id(&self) -> StacksMessageID {
38,257,975✔
932
        match *self {
38,257,975✔
933
            StacksMessageType::Handshake(ref _m) => StacksMessageID::Handshake,
1,222,010✔
934
            StacksMessageType::HandshakeAccept(ref _m) => StacksMessageID::HandshakeAccept,
55,174✔
935
            StacksMessageType::HandshakeReject => StacksMessageID::HandshakeReject,
1,779✔
936
            StacksMessageType::GetNeighbors => StacksMessageID::GetNeighbors,
1,007,813✔
937
            StacksMessageType::Neighbors(ref _m) => StacksMessageID::Neighbors,
1,007,507✔
938
            StacksMessageType::GetPoxInv(ref _m) => StacksMessageID::GetPoxInv,
590,348✔
939
            StacksMessageType::PoxInv(ref _m) => StacksMessageID::PoxInv,
590,279✔
940
            StacksMessageType::GetBlocksInv(ref _m) => StacksMessageID::GetBlocksInv,
1,961,415✔
941
            StacksMessageType::BlocksInv(ref _m) => StacksMessageID::BlocksInv,
1,945,119✔
942
            StacksMessageType::BlocksAvailable(ref _m) => StacksMessageID::BlocksAvailable,
10,695✔
943
            StacksMessageType::MicroblocksAvailable(ref _m) => {
3✔
944
                StacksMessageID::MicroblocksAvailable
3✔
945
            }
946
            StacksMessageType::Blocks(ref _m) => StacksMessageID::Blocks,
81,027✔
UNCOV
947
            StacksMessageType::Microblocks(ref _m) => StacksMessageID::Microblocks,
×
948
            StacksMessageType::Transaction(ref _m) => StacksMessageID::Transaction,
13,959✔
949
            StacksMessageType::Nack(ref _m) => StacksMessageID::Nack,
1,108,040✔
950
            StacksMessageType::Ping(ref _m) => StacksMessageID::Ping,
20,078✔
951
            StacksMessageType::Pong(ref _m) => StacksMessageID::Pong,
21✔
952
            StacksMessageType::NatPunchRequest(ref _m) => StacksMessageID::NatPunchRequest,
2,056✔
953
            StacksMessageType::NatPunchReply(ref _m) => StacksMessageID::NatPunchReply,
2,055✔
954
            StacksMessageType::StackerDBHandshakeAccept(ref _h, ref _m) => {
1,164,371✔
955
                StacksMessageID::StackerDBHandshakeAccept
1,164,371✔
956
            }
957
            StacksMessageType::StackerDBGetChunkInv(ref _m) => {
11,788,413✔
958
                StacksMessageID::StackerDBGetChunkInv
11,788,413✔
959
            }
960
            StacksMessageType::StackerDBChunkInv(ref _m) => StacksMessageID::StackerDBChunkInv,
12,188,767✔
961
            StacksMessageType::StackerDBGetChunk(ref _m) => StacksMessageID::StackerDBGetChunk,
262,316✔
962
            StacksMessageType::StackerDBChunk(ref _m) => StacksMessageID::StackerDBChunk,
260,145✔
963
            StacksMessageType::StackerDBPushChunk(ref _m) => StacksMessageID::StackerDBPushChunk,
1,550,261✔
964
            StacksMessageType::GetNakamotoInv(ref _m) => StacksMessageID::GetNakamotoInv,
711,074✔
965
            StacksMessageType::NakamotoInv(ref _m) => StacksMessageID::NakamotoInv,
690,038✔
966
            StacksMessageType::NakamotoBlocks(ref _m) => StacksMessageID::NakamotoBlocks,
23,212✔
967
        }
968
    }
38,257,975✔
969

970
    pub fn get_message_name(&self) -> &'static str {
17,968,385✔
971
        match *self {
17,968,385✔
972
            StacksMessageType::Handshake(ref _m) => "Handshake",
407,379✔
973
            StacksMessageType::HandshakeAccept(ref _m) => "HandshakeAccept",
18,318✔
974
            StacksMessageType::HandshakeReject => "HandshakeReject",
592✔
975
            StacksMessageType::GetNeighbors => "GetNeighbors",
335,964✔
976
            StacksMessageType::Neighbors(ref _m) => "Neighbors",
335,740✔
977
            StacksMessageType::GetPoxInv(ref _m) => "GetPoxInv",
196,785✔
978
            StacksMessageType::PoxInv(ref _m) => "PoxInv",
393,501✔
979
            StacksMessageType::GetBlocksInv(ref _m) => "GetBlocksInv",
653,806✔
980
            StacksMessageType::BlocksInv(ref _m) => "BlocksInv",
1,296,690✔
981
            StacksMessageType::BlocksAvailable(ref _m) => "BlocksAvailable",
3,564✔
UNCOV
982
            StacksMessageType::MicroblocksAvailable(ref _m) => "MicroblocksAvailable",
×
983
            StacksMessageType::Blocks(ref _m) => "Blocks",
27,009✔
984
            StacksMessageType::Microblocks(ref _m) => "Microblocks",
×
985
            StacksMessageType::Transaction(ref _m) => "Transaction",
4,653✔
986
            StacksMessageType::Nack(ref _m) => "Nack",
738,602✔
987
            StacksMessageType::Ping(ref _m) => "Ping",
5,007✔
988
            StacksMessageType::Pong(ref _m) => "Pong",
6✔
989
            StacksMessageType::NatPunchRequest(ref _m) => "NatPunchRequest",
685✔
990
            StacksMessageType::NatPunchReply(ref _m) => "NatPunchReply",
684✔
991
            StacksMessageType::StackerDBHandshakeAccept(ref _h, ref _m) => {
387,971✔
992
                "StackerDBHandshakeAccept"
387,971✔
993
            }
994
            StacksMessageType::StackerDBGetChunkInv(ref _m) => "StackerDBGetChunkInv",
3,932,398✔
995
            StacksMessageType::StackerDBChunkInv(ref _m) => "StackerDBChunkInv",
7,746,674✔
996
            StacksMessageType::StackerDBGetChunk(ref _m) => "StackerDBGetChunk",
87,447✔
997
            StacksMessageType::StackerDBChunk(ref _m) => "StackerDBChunk",
173,416✔
998
            StacksMessageType::StackerDBPushChunk(ref _m) => "StackerDBPushChunk",
516,926✔
999
            StacksMessageType::GetNakamotoInv(ref _m) => "GetNakamotoInv",
237,026✔
1000
            StacksMessageType::NakamotoInv(ref _m) => "NakamotoInv",
459,780✔
1001
            StacksMessageType::NakamotoBlocks(ref _m) => "NakamotoBlocks",
7,762✔
1002
        }
1003
    }
17,968,385✔
1004

1005
    pub fn get_message_description(&self) -> String {
19,705,094✔
1006
        match *self {
19,705,094✔
1007
            StacksMessageType::Handshake(ref m) => {
407,216✔
1008
                format!("Handshake({})", &to_hex(&m.node_public_key.to_bytes()))
407,216✔
1009
            }
1010
            StacksMessageType::HandshakeAccept(ref m) => format!(
36,744✔
1011
                "HandshakeAccept({},{})",
1012
                &to_hex(&m.handshake.node_public_key.to_bytes()),
36,744✔
1013
                m.heartbeat_interval
1014
            ),
1015
            StacksMessageType::HandshakeReject => "HandshakeReject".to_string(),
1,184✔
1016
            StacksMessageType::GetNeighbors => "GetNeighbors".to_string(),
335,882✔
1017
            StacksMessageType::Neighbors(ref m) => format!("Neighbors({:?})", m.neighbors),
671,622✔
1018
            StacksMessageType::GetPoxInv(ref m) => {
196,775✔
1019
                format!("GetPoxInv({},{}))", &m.consensus_hash, m.num_cycles)
196,775✔
1020
            }
1021
            StacksMessageType::PoxInv(ref m) => {
393,501✔
1022
                format!("PoxInv({},{:?})", &m.bitlen, &m.pox_bitvec)
393,501✔
1023
            }
1024
            StacksMessageType::GetBlocksInv(ref m) => {
653,800✔
1025
                format!("GetBlocksInv({},{})", &m.consensus_hash, m.num_blocks)
653,800✔
1026
            }
1027
            StacksMessageType::BlocksInv(ref m) => format!(
1,296,690✔
1028
                "BlocksInv({},{:?},{:?})",
1029
                m.bitlen, &m.block_bitvec, &m.microblocks_bitvec
1,296,690✔
1030
            ),
1031
            StacksMessageType::BlocksAvailable(ref m) => {
7,128✔
1032
                format!("BlocksAvailable({:?})", &m.available)
7,128✔
1033
            }
UNCOV
1034
            StacksMessageType::MicroblocksAvailable(ref m) => {
×
UNCOV
1035
                format!("MicroblocksAvailable({:?})", &m.available)
×
1036
            }
1037
            StacksMessageType::Blocks(ref m) => format!(
54,019✔
1038
                "Blocks({:?})",
1039
                m.blocks
54,019✔
1040
                    .iter()
54,019✔
1041
                    .map(|BlocksDatum(ch, blk)| (ch.clone(), blk.block_hash()))
54,217✔
1042
                    .collect::<Vec<(ConsensusHash, BlockHeaderHash)>>()
54,019✔
1043
            ),
1044
            StacksMessageType::Microblocks(ref m) => format!(
10✔
1045
                "Microblocks({},{:?})",
1046
                &m.index_anchor_block,
10✔
1047
                m.microblocks
10✔
1048
                    .iter()
10✔
1049
                    .map(|mblk| mblk.block_hash())
10✔
1050
                    .collect::<Vec<BlockHeaderHash>>()
10✔
1051
            ),
1052
            StacksMessageType::Transaction(ref m) => format!("Transaction({})", m.txid()),
41,636✔
1053
            StacksMessageType::Nack(ref m) => format!("Nack({})", m.error_code),
738,604✔
1054
            StacksMessageType::Ping(ref m) => format!("Ping({})", m.nonce),
9✔
1055
            StacksMessageType::Pong(ref m) => format!("Pong({})", m.nonce),
12✔
1056
            StacksMessageType::NatPunchRequest(ref m) => format!("NatPunchRequest({})", m),
684✔
1057
            StacksMessageType::NatPunchReply(ref m) => {
1,368✔
1058
                format!("NatPunchReply({},{}:{})", m.nonce, &m.addrbytes, m.port)
1,368✔
1059
            }
1060
            StacksMessageType::StackerDBHandshakeAccept(ref h, ref m) => {
776,169✔
1061
                format!(
776,169✔
1062
                    "StackerDBHandshakeAccept({},{},{:?})",
1063
                    &to_hex(&h.handshake.node_public_key.to_bytes()),
776,169✔
1064
                    &m.rc_consensus_hash,
776,169✔
1065
                    &m.smart_contracts
776,169✔
1066
                )
1067
            }
1068
            StacksMessageType::StackerDBGetChunkInv(ref m) => {
3,923,614✔
1069
                format!(
3,923,614✔
1070
                    "StackerDBGetChunkInv({}.{})",
1071
                    &m.contract_id, &m.rc_consensus_hash
3,923,614✔
1072
                )
1073
            }
1074
            StacksMessageType::StackerDBChunkInv(ref m) => {
7,625,654✔
1075
                format!("StackerDBChunkInv({:?})", &m.slot_versions)
7,625,654✔
1076
            }
1077
            StacksMessageType::StackerDBGetChunk(ref m) => {
87,419✔
1078
                format!(
87,419✔
1079
                    "StackerDBGetChunk({},{},{},{})",
1080
                    &m.contract_id, &m.rc_consensus_hash, m.slot_id, m.slot_version
87,419✔
1081
                )
1082
            }
1083
            StacksMessageType::StackerDBChunk(ref m) => {
173,416✔
1084
                format!(
173,416✔
1085
                    "StackerDBChunk({},{},{},sz={})",
1086
                    m.slot_id,
1087
                    m.slot_version,
1088
                    &m.sig,
173,416✔
1089
                    m.data.len()
173,416✔
1090
                )
1091
            }
1092
            StacksMessageType::StackerDBPushChunk(ref m) => {
1,489,709✔
1093
                format!(
1,489,709✔
1094
                    "StackerDBPushChunk({},{},{},{},{},sz={})",
1095
                    &m.contract_id,
1,489,709✔
1096
                    &m.rc_consensus_hash,
1,489,709✔
1097
                    m.chunk_data.slot_id,
1098
                    m.chunk_data.slot_version,
1099
                    &m.chunk_data.sig,
1,489,709✔
1100
                    m.chunk_data.data.len()
1,489,709✔
1101
                )
1102
            }
1103
            StacksMessageType::GetNakamotoInv(ref m) => {
236,761✔
1104
                format!("GetNakamotoInv({})", &m.consensus_hash,)
236,761✔
1105
            }
1106
            StacksMessageType::NakamotoInv(ref m) => {
459,780✔
1107
                format!("NakamotoInv({:?})", &m.tenures)
459,780✔
1108
            }
1109
            StacksMessageType::NakamotoBlocks(ref m) => {
95,688✔
1110
                format!(
95,688✔
1111
                    "NakamotoBlocks({:?})",
1112
                    m.blocks
95,688✔
1113
                        .iter()
95,688✔
1114
                        .map(|block| block.block_id())
96,353✔
1115
                        .collect::<Vec<_>>()
95,688✔
1116
                )
1117
            }
1118
        }
1119
    }
19,705,094✔
1120
}
1121

1122
impl StacksMessageCodec for StacksMessageID {
UNCOV
1123
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
×
UNCOV
1124
        write_next(fd, &(*self as u8))
×
1125
    }
×
1126

1127
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StacksMessageID, codec_error> {
12,744,333✔
1128
        let as_u8: u8 = read_next(fd)?;
12,744,333✔
1129
        let id = match as_u8 {
12,744,331✔
1130
            x if x == StacksMessageID::Handshake as u8 => StacksMessageID::Handshake,
12,744,331✔
1131
            x if x == StacksMessageID::HandshakeAccept as u8 => StacksMessageID::HandshakeAccept,
12,337,071✔
1132
            x if x == StacksMessageID::HandshakeReject as u8 => StacksMessageID::HandshakeReject,
12,318,751✔
1133
            x if x == StacksMessageID::GetNeighbors as u8 => StacksMessageID::GetNeighbors,
12,318,158✔
1134
            x if x == StacksMessageID::Neighbors as u8 => StacksMessageID::Neighbors,
11,982,274✔
1135
            x if x == StacksMessageID::GetPoxInv as u8 => StacksMessageID::GetPoxInv,
11,646,532✔
1136
            x if x == StacksMessageID::PoxInv as u8 => StacksMessageID::PoxInv,
11,449,746✔
1137
            x if x == StacksMessageID::GetBlocksInv as u8 => StacksMessageID::GetBlocksInv,
11,253,018✔
1138
            x if x == StacksMessageID::BlocksInv as u8 => StacksMessageID::BlocksInv,
10,599,216✔
1139
            x if x == StacksMessageID::BlocksAvailable as u8 => StacksMessageID::BlocksAvailable,
9,950,950✔
1140
            x if x == StacksMessageID::MicroblocksAvailable as u8 => {
9,947,384✔
1141
                StacksMessageID::MicroblocksAvailable
2✔
1142
            }
1143
            x if x == StacksMessageID::Blocks as u8 => StacksMessageID::Blocks,
9,947,382✔
1144
            x if x == StacksMessageID::Microblocks as u8 => StacksMessageID::Microblocks,
9,920,373✔
1145
            x if x == StacksMessageID::Transaction as u8 => StacksMessageID::Transaction,
9,920,373✔
1146
            x if x == StacksMessageID::Nack as u8 => StacksMessageID::Nack,
9,915,720✔
1147
            x if x == StacksMessageID::Ping as u8 => StacksMessageID::Ping,
9,546,541✔
1148
            x if x == StacksMessageID::Pong as u8 => StacksMessageID::Pong,
9,536,521✔
1149
            x if x == StacksMessageID::NatPunchRequest as u8 => StacksMessageID::NatPunchRequest,
9,536,513✔
1150
            x if x == StacksMessageID::NatPunchReply as u8 => StacksMessageID::NatPunchReply,
9,535,826✔
1151
            x if x == StacksMessageID::StackerDBHandshakeAccept as u8 => {
9,535,140✔
1152
                StacksMessageID::StackerDBHandshakeAccept
388,008✔
1153
            }
1154
            x if x == StacksMessageID::StackerDBGetChunkInv as u8 => {
9,147,132✔
1155
                StacksMessageID::StackerDBGetChunkInv
3,923,616✔
1156
            }
1157
            x if x == StacksMessageID::StackerDBChunkInv as u8 => {
5,223,516✔
1158
                StacksMessageID::StackerDBChunkInv
4,058,888✔
1159
            }
1160
            x if x == StacksMessageID::StackerDBGetChunk as u8 => {
1,164,628✔
1161
                StacksMessageID::StackerDBGetChunk
87,421✔
1162
            }
1163
            x if x == StacksMessageID::StackerDBChunk as u8 => StacksMessageID::StackerDBChunk,
1,077,207✔
1164
            x if x == StacksMessageID::StackerDBPushChunk as u8 => {
990,515✔
1165
                StacksMessageID::StackerDBPushChunk
516,408✔
1166
            }
1167
            x if x == StacksMessageID::GetNakamotoInv as u8 => StacksMessageID::GetNakamotoInv,
474,107✔
1168
            x if x == StacksMessageID::NakamotoInv as u8 => StacksMessageID::NakamotoInv,
237,344✔
1169
            x if x == StacksMessageID::NakamotoBlocks as u8 => StacksMessageID::NakamotoBlocks,
7,688✔
1170
            _ => {
UNCOV
1171
                return Err(codec_error::DeserializeError(
×
UNCOV
1172
                    "Unknown message ID".to_string(),
×
1173
                ));
×
1174
            }
1175
        };
1176
        Ok(id)
12,744,331✔
1177
    }
12,744,333✔
1178
}
1179

1180
impl StacksMessageCodec for StacksMessageType {
1181
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
25,538,352✔
1182
        write_next(fd, &(self.get_message_id() as u8))?;
25,538,352✔
1183
        match *self {
25,538,352✔
1184
            StacksMessageType::Handshake(ref m) => write_next(fd, m)?,
829,233✔
1185
            StacksMessageType::HandshakeAccept(ref m) => write_next(fd, m)?,
36,857✔
1186
            StacksMessageType::HandshakeReject => {}
1,187✔
1187
            StacksMessageType::GetNeighbors => {}
671,931✔
1188
            StacksMessageType::Neighbors(ref m) => write_next(fd, m)?,
671,767✔
1189
            StacksMessageType::GetPoxInv(ref m) => write_next(fd, m)?,
393,573✔
1190
            StacksMessageType::PoxInv(ref m) => write_next(fd, m)?,
393,553✔
1191
            StacksMessageType::GetBlocksInv(ref m) => write_next(fd, m)?,
1,307,615✔
1192
            StacksMessageType::BlocksInv(ref m) => write_next(fd, m)?,
1,296,855✔
1193
            StacksMessageType::BlocksAvailable(ref m) => write_next(fd, m)?,
7,131✔
1194
            StacksMessageType::MicroblocksAvailable(ref m) => write_next(fd, m)?,
3✔
1195
            StacksMessageType::Blocks(ref m) => write_next(fd, m)?,
54,018✔
UNCOV
1196
            StacksMessageType::Microblocks(ref m) => write_next(fd, m)?,
×
1197
            StacksMessageType::Transaction(ref m) => write_next(fd, m)?,
9,306✔
1198
            StacksMessageType::Nack(ref m) => write_next(fd, m)?,
738,863✔
1199
            StacksMessageType::Ping(ref m) => write_next(fd, m)?,
20,072✔
1200
            StacksMessageType::Pong(ref m) => write_next(fd, m)?,
15✔
1201
            StacksMessageType::NatPunchRequest(ref nonce) => write_next(fd, nonce)?,
1,373✔
1202
            StacksMessageType::NatPunchReply(ref m) => write_next(fd, m)?,
1,371✔
1203
            StacksMessageType::StackerDBHandshakeAccept(ref h, ref m) => {
776,401✔
1204
                write_next(fd, h)?;
776,401✔
1205
                write_next(fd, m)?
776,401✔
1206
            }
1207
            StacksMessageType::StackerDBGetChunkInv(ref m) => write_next(fd, m)?,
7,864,790✔
1208
            StacksMessageType::StackerDBChunkInv(ref m) => write_next(fd, m)?,
8,129,881✔
1209
            StacksMessageType::StackerDBGetChunk(ref m) => write_next(fd, m)?,
174,897✔
1210
            StacksMessageType::StackerDBChunk(ref m) => write_next(fd, m)?,
173,455✔
1211
            StacksMessageType::StackerDBPushChunk(ref m) => write_next(fd, m)?,
1,033,855✔
1212
            StacksMessageType::GetNakamotoInv(ref m) => write_next(fd, m)?,
474,313✔
1213
            StacksMessageType::NakamotoInv(ref m) => write_next(fd, m)?,
460,513✔
1214
            StacksMessageType::NakamotoBlocks(ref m) => write_next(fd, m)?,
15,524✔
1215
        }
1216
        Ok(())
25,538,352✔
1217
    }
25,538,352✔
1218

1219
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StacksMessageType, codec_error> {
12,744,333✔
1220
        let message_id: StacksMessageID = read_next(fd)?;
12,744,333✔
1221
        let message = match message_id {
12,744,331✔
1222
            StacksMessageID::Handshake => {
1223
                let m: HandshakeData = read_next(fd)?;
407,260✔
1224
                StacksMessageType::Handshake(m)
407,259✔
1225
            }
1226
            StacksMessageID::HandshakeAccept => {
1227
                let m: HandshakeAcceptData = read_next(fd)?;
18,320✔
1228
                StacksMessageType::HandshakeAccept(m)
18,319✔
1229
            }
1230
            StacksMessageID::HandshakeReject => StacksMessageType::HandshakeReject,
593✔
1231
            StacksMessageID::GetNeighbors => StacksMessageType::GetNeighbors,
335,884✔
1232
            StacksMessageID::Neighbors => {
1233
                let m: NeighborsData = read_next(fd)?;
335,742✔
1234
                StacksMessageType::Neighbors(m)
335,741✔
1235
            }
1236
            StacksMessageID::GetPoxInv => {
1237
                let m: GetPoxInv = read_next(fd)?;
196,786✔
1238
                StacksMessageType::GetPoxInv(m)
196,785✔
1239
            }
1240
            StacksMessageID::PoxInv => {
1241
                let m: PoxInvData = read_next(fd)?;
196,728✔
1242
                StacksMessageType::PoxInv(m)
196,727✔
1243
            }
1244
            StacksMessageID::GetBlocksInv => {
1245
                let m: GetBlocksInv = read_next(fd)?;
653,802✔
1246
                StacksMessageType::GetBlocksInv(m)
653,801✔
1247
            }
1248
            StacksMessageID::BlocksInv => {
1249
                let m: BlocksInvData = read_next(fd)?;
648,266✔
1250
                StacksMessageType::BlocksInv(m)
648,265✔
1251
            }
1252
            StacksMessageID::BlocksAvailable => {
1253
                let m: BlocksAvailableData = read_next(fd)?;
3,566✔
1254
                StacksMessageType::BlocksAvailable(m)
3,565✔
1255
            }
1256
            StacksMessageID::MicroblocksAvailable => {
1257
                let m: BlocksAvailableData = read_next(fd)?;
2✔
1258
                StacksMessageType::MicroblocksAvailable(m)
1✔
1259
            }
1260
            StacksMessageID::Blocks => {
1261
                let m: BlocksData = read_next(fd)?;
27,009✔
1262
                StacksMessageType::Blocks(m)
27,009✔
1263
            }
1264
            StacksMessageID::Microblocks => {
UNCOV
1265
                let m: MicroblocksData = read_next(fd)?;
×
UNCOV
1266
                StacksMessageType::Microblocks(m)
×
1267
            }
1268
            StacksMessageID::Transaction => {
1269
                let m: StacksTransaction = read_next(fd)?;
4,653✔
1270
                StacksMessageType::Transaction(m)
4,653✔
1271
            }
1272
            StacksMessageID::Nack => {
1273
                let m: NackData = read_next(fd)?;
369,179✔
1274
                StacksMessageType::Nack(m)
369,178✔
1275
            }
1276
            StacksMessageID::Ping => {
1277
                let m: PingData = read_next(fd)?;
10,020✔
1278
                StacksMessageType::Ping(m)
10,019✔
1279
            }
1280
            StacksMessageID::Pong => {
1281
                let m: PongData = read_next(fd)?;
8✔
1282
                StacksMessageType::Pong(m)
7✔
1283
            }
1284
            StacksMessageID::NatPunchRequest => {
1285
                let nonce: u32 = read_next(fd)?;
687✔
1286
                StacksMessageType::NatPunchRequest(nonce)
686✔
1287
            }
1288
            StacksMessageID::NatPunchReply => {
1289
                let m: NatPunchData = read_next(fd)?;
686✔
1290
                StacksMessageType::NatPunchReply(m)
685✔
1291
            }
1292
            StacksMessageID::StackerDBHandshakeAccept => {
1293
                let h: HandshakeAcceptData = read_next(fd)?;
388,008✔
1294
                let m: StackerDBHandshakeData = read_next(fd)?;
388,008✔
1295
                StacksMessageType::StackerDBHandshakeAccept(h, m)
388,007✔
1296
            }
1297
            StacksMessageID::StackerDBGetChunkInv => {
1298
                let m: StackerDBGetChunkInvData = read_next(fd)?;
3,923,616✔
1299
                StacksMessageType::StackerDBGetChunkInv(m)
3,923,615✔
1300
            }
1301
            StacksMessageID::StackerDBChunkInv => {
1302
                let m: StackerDBChunkInvData = read_next(fd)?;
4,058,888✔
1303
                StacksMessageType::StackerDBChunkInv(m)
4,058,887✔
1304
            }
1305
            StacksMessageID::StackerDBGetChunk => {
1306
                let m: StackerDBGetChunkData = read_next(fd)?;
87,421✔
1307
                StacksMessageType::StackerDBGetChunk(m)
87,420✔
1308
            }
1309
            StacksMessageID::StackerDBChunk => {
1310
                let m: StackerDBChunkData = read_next(fd)?;
86,692✔
1311
                StacksMessageType::StackerDBChunk(m)
86,691✔
1312
            }
1313
            StacksMessageID::StackerDBPushChunk => {
1314
                let m: StackerDBPushChunkData = read_next(fd)?;
516,408✔
1315
                StacksMessageType::StackerDBPushChunk(m)
516,407✔
1316
            }
1317
            StacksMessageID::GetNakamotoInv => {
1318
                let m: GetNakamotoInvData = read_next(fd)?;
236,763✔
1319
                StacksMessageType::GetNakamotoInv(m)
236,762✔
1320
            }
1321
            StacksMessageID::NakamotoInv => {
1322
                let m: NakamotoInvData = read_next(fd)?;
229,656✔
1323
                StacksMessageType::NakamotoInv(m)
229,655✔
1324
            }
1325
            StacksMessageID::NakamotoBlocks => {
1326
                let m: NakamotoBlocksData = read_next(fd)?;
7,688✔
1327
                StacksMessageType::NakamotoBlocks(m)
7,688✔
1328
            }
1329
            StacksMessageID::Reserved => {
UNCOV
1330
                return Err(codec_error::DeserializeError(
×
UNCOV
1331
                    "Unsupported message ID 'reserved'".to_string(),
×
1332
                ));
×
1333
            }
1334
        };
1335
        Ok(message)
12,744,309✔
1336
    }
12,744,333✔
1337
}
1338

1339
impl StacksMessageCodec for StacksMessage {
1340
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
12,761,969✔
1341
        write_next(fd, &self.preamble)?;
12,761,969✔
1342
        write_next(fd, &self.relayers)?;
12,761,969✔
1343
        write_next(fd, &self.payload)?;
12,761,969✔
1344
        Ok(())
12,761,969✔
1345
    }
12,761,969✔
1346

1347
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StacksMessage, codec_error> {
234✔
1348
        let preamble: Preamble = read_next(fd)?;
234✔
1349
        if preamble.payload_len > MAX_MESSAGE_LEN - PREAMBLE_ENCODED_SIZE {
234✔
UNCOV
1350
            return Err(codec_error::DeserializeError(
×
UNCOV
1351
                "Message would be too big".to_string(),
×
1352
            ));
×
1353
        }
234✔
1354

1355
        let relayers: Vec<RelayData> = read_next_at_most::<_, RelayData>(fd, MAX_RELAYERS_LEN)?;
234✔
1356
        let payload: StacksMessageType = read_next(fd)?;
210✔
1357

1358
        let message = StacksMessage {
186✔
1359
            preamble,
186✔
1360
            relayers,
186✔
1361
            payload,
186✔
1362
        };
186✔
1363
        Ok(message)
186✔
1364
    }
234✔
1365
}
1366

1367
impl StacksMessage {
1368
    /// Create an unsigned Stacks p2p message
1369
    pub fn new(
12,762,372✔
1370
        peer_version: u32,
12,762,372✔
1371
        network_id: u32,
12,762,372✔
1372
        block_height: u64,
12,762,372✔
1373
        burn_header_hash: &BurnchainHeaderHash,
12,762,372✔
1374
        stable_block_height: u64,
12,762,372✔
1375
        stable_burn_header_hash: &BurnchainHeaderHash,
12,762,372✔
1376
        message: StacksMessageType,
12,762,372✔
1377
    ) -> StacksMessage {
12,762,372✔
1378
        let preamble = Preamble::new(
12,762,372✔
1379
            peer_version,
12,762,372✔
1380
            network_id,
12,762,372✔
1381
            block_height,
12,762,372✔
1382
            burn_header_hash,
12,762,372✔
1383
            stable_block_height,
12,762,372✔
1384
            stable_burn_header_hash,
12,762,372✔
1385
            0,
1386
        );
1387
        StacksMessage {
12,762,372✔
1388
            preamble,
12,762,372✔
1389
            relayers: vec![],
12,762,372✔
1390
            payload: message,
12,762,372✔
1391
        }
12,762,372✔
1392
    }
12,762,372✔
1393

1394
    /// Create an unsigned Stacks message
1395
    pub fn from_chain_view(
12,752,356✔
1396
        peer_version: u32,
12,752,356✔
1397
        network_id: u32,
12,752,356✔
1398
        chain_view: &BurnchainView,
12,752,356✔
1399
        message: StacksMessageType,
12,752,356✔
1400
    ) -> StacksMessage {
12,752,356✔
1401
        StacksMessage::new(
12,752,356✔
1402
            peer_version,
12,752,356✔
1403
            network_id,
12,752,356✔
1404
            chain_view.burn_block_height,
12,752,356✔
1405
            &chain_view.burn_block_hash,
12,752,356✔
1406
            chain_view.burn_stable_block_height,
12,752,356✔
1407
            &chain_view.burn_stable_block_hash,
12,752,356✔
1408
            message,
12,752,356✔
1409
        )
1410
    }
12,752,356✔
1411

1412
    /// represent as neighbor key
1413
    pub fn to_neighbor_key(&self, addrbytes: &PeerAddress, port: u16) -> NeighborKey {
4,179✔
1414
        NeighborKey {
4,179✔
1415
            peer_version: self.preamble.peer_version,
4,179✔
1416
            network_id: self.preamble.network_id,
4,179✔
1417
            addrbytes: addrbytes.clone(),
4,179✔
1418
            port,
4,179✔
1419
        }
4,179✔
1420
    }
4,179✔
1421

1422
    /// Sign the stacks message
1423
    fn do_sign(&mut self, private_key: &Secp256k1PrivateKey) -> Result<(), net_error> {
12,761,927✔
1424
        let mut message_bits = vec![];
12,761,927✔
1425
        self.relayers.consensus_serialize(&mut message_bits)?;
12,761,927✔
1426
        self.payload.consensus_serialize(&mut message_bits)?;
12,761,927✔
1427

1428
        self.preamble.payload_len = message_bits.len() as u32;
12,761,927✔
1429
        self.preamble.sign(&message_bits[..], private_key)
12,761,927✔
1430
    }
12,761,927✔
1431

1432
    /// Sign the StacksMessage.  The StacksMessage must _not_ have any relayers (i.e. we're
1433
    /// originating this messsage).
1434
    pub fn sign(&mut self, seq: u32, private_key: &Secp256k1PrivateKey) -> Result<(), net_error> {
12,343,210✔
1435
        if !self.relayers.is_empty() {
12,343,210✔
UNCOV
1436
            return Err(net_error::InvalidMessage);
×
1437
        }
12,343,210✔
1438
        self.preamble.seq = seq;
12,343,210✔
1439
        self.do_sign(private_key)
12,343,210✔
1440
    }
12,343,210✔
1441

1442
    /// Sign the StacksMessage and add ourselves as a relayer.
1443
    pub fn sign_relay(
418,719✔
1444
        &mut self,
418,719✔
1445
        private_key: &Secp256k1PrivateKey,
418,719✔
1446
        our_seq: u32,
418,719✔
1447
        our_addr: &NeighborAddress,
418,719✔
1448
    ) -> Result<(), net_error> {
418,719✔
1449
        if self.relayers.len() >= MAX_RELAYERS_LEN as usize {
418,719✔
UNCOV
1450
            warn!(
×
1451
                "Message {:?} has too many relayers; will not sign",
1452
                self.payload.get_message_description()
×
1453
            );
1454
            return Err(net_error::InvalidMessage);
×
1455
        }
418,719✔
1456

1457
        // don't sign if signed more than once
1458
        for relayer in &self.relayers {
418,721✔
1459
            if relayer.peer.public_key_hash == our_addr.public_key_hash {
13✔
1460
                warn!(
2✔
1461
                    "Message {:?} already signed by {}",
1462
                    self.payload.get_message_description(),
2✔
1463
                    &our_addr.public_key_hash
2✔
1464
                );
1465
                return Err(net_error::InvalidMessage);
2✔
1466
            }
11✔
1467
        }
1468

1469
        // save relayer state
1470
        let our_relay = RelayData {
418,717✔
1471
            peer: our_addr.clone(),
418,717✔
1472
            seq: self.preamble.seq,
418,717✔
1473
        };
418,717✔
1474

1475
        self.relayers.push(our_relay);
418,717✔
1476
        self.preamble.seq = our_seq;
418,717✔
1477
        self.do_sign(private_key)
418,717✔
1478
    }
418,719✔
1479

1480
    pub fn deserialize_body<R: Read>(
12,744,123✔
1481
        fd: &mut R,
12,744,123✔
1482
    ) -> Result<(Vec<RelayData>, StacksMessageType), net_error> {
12,744,123✔
1483
        let relayers: Vec<RelayData> = read_next_at_most::<_, RelayData>(fd, MAX_RELAYERS_LEN)?;
12,744,123✔
1484
        let payload: StacksMessageType = read_next(fd)?;
12,744,123✔
1485
        Ok((relayers, payload))
12,744,123✔
1486
    }
12,744,123✔
1487

1488
    /// Verify this message by treating the public key buffer as a secp256k1 public key.
1489
    /// Fails if:
1490
    /// * the signature doesn't match
1491
    /// * the buffer doesn't encode a secp256k1 public key
1492
    pub fn verify_secp256k1(&self, public_key: &StacksPublicKeyBuffer) -> Result<(), net_error> {
14,441✔
1493
        let secp256k1_pubkey = public_key
14,441✔
1494
            .to_public_key()
14,441✔
1495
            .map_err(|e| net_error::DeserializeError(e.into()))?;
14,441✔
1496

1497
        let mut message_bits = vec![];
14,441✔
1498
        self.relayers.consensus_serialize(&mut message_bits)?;
14,441✔
1499
        self.payload.consensus_serialize(&mut message_bits)?;
14,441✔
1500

1501
        let mut p = self.preamble.clone();
14,441✔
1502
        p.verify(&message_bits, &secp256k1_pubkey).map(|_m| ())
14,441✔
1503
    }
14,441✔
1504
}
1505

1506
impl MessageSequence for StacksMessage {
1507
    fn request_id(&self) -> u32 {
575,927,289✔
1508
        self.preamble.seq
575,927,289✔
1509
    }
575,927,289✔
1510

1511
    fn get_message_name(&self) -> &'static str {
12,451,303✔
1512
        self.payload.get_message_name()
12,451,303✔
1513
    }
12,451,303✔
1514
}
1515

1516
impl StacksP2P {
1517
    pub fn new() -> StacksP2P {
28,211✔
1518
        StacksP2P {}
28,211✔
1519
    }
28,211✔
1520
}
1521

1522
impl ProtocolFamily for StacksP2P {
1523
    type Preamble = Preamble;
1524
    type Message = StacksMessage;
1525

1526
    /// How big can a P2P preamble get?
1527
    fn preamble_size_hint(&mut self) -> usize {
12,745,513✔
1528
        PREAMBLE_ENCODED_SIZE as usize
12,745,513✔
1529
    }
12,745,513✔
1530

1531
    /// How long is an encoded message payload going to be, if we can tell at all?
1532
    fn payload_len(&mut self, preamble: &Preamble) -> Option<usize> {
38,246,857✔
1533
        Some(preamble.payload_len as usize)
38,246,857✔
1534
    }
38,246,857✔
1535

1536
    /// StacksP2P deals with Preambles
1537
    fn read_preamble(&mut self, buf: &[u8]) -> Result<(Preamble, usize), net_error> {
12,745,513✔
1538
        let mut preamble_bytes = buf.get(..PREAMBLE_ENCODED_SIZE as usize).ok_or_else(|| {
12,745,513✔
1539
            Error::UnderflowError("Not enough bytes to form a P2P preamble".to_string())
1,390✔
1540
        })?;
1,390✔
1541

1542
        let preamble: Preamble = read_next(&mut preamble_bytes)?;
12,744,123✔
1543
        Ok((preamble, PREAMBLE_ENCODED_SIZE as usize))
12,744,123✔
1544
    }
12,745,513✔
1545

1546
    /// StacksP2P messages are never streamed, since we always know how long they are.
1547
    /// This should be unreachable, since payload_len() always returns Some(...)
UNCOV
1548
    fn stream_payload<R: Read>(
×
UNCOV
1549
        &mut self,
×
1550
        _preamble: &Preamble,
×
1551
        _fd: &mut R,
×
1552
    ) -> Result<(Option<(StacksMessage, usize)>, usize), net_error> {
×
1553
        panic!(
×
1554
            "BUG: tried to stream a StacksP2P message, even though their lengths are always known"
1555
        )
1556
    }
1557

1558
    /// StacksP2P deals with StacksMessages
1559
    fn read_payload(
12,744,123✔
1560
        &mut self,
12,744,123✔
1561
        preamble: &Preamble,
12,744,123✔
1562
        bytes: &[u8],
12,744,123✔
1563
    ) -> Result<(StacksMessage, usize), net_error> {
12,744,123✔
1564
        let preamble_bytes = bytes.get(..preamble.payload_len as usize).ok_or_else(|| {
12,744,123✔
UNCOV
1565
            Error::UnderflowError("Not enough bytes to form a StacksMessage".to_string())
×
UNCOV
1566
        })?;
×
1567

1568
        let mut cursor = io::Cursor::new(preamble_bytes);
12,744,123✔
1569
        let (relayers, payload) = StacksMessage::deserialize_body(&mut cursor)?;
12,744,123✔
1570
        let message = StacksMessage {
12,744,123✔
1571
            preamble: preamble.clone(),
12,744,123✔
1572
            relayers,
12,744,123✔
1573
            payload,
12,744,123✔
1574
        };
12,744,123✔
1575
        Ok((message, cursor.position() as usize))
12,744,123✔
1576
    }
12,744,123✔
1577

1578
    fn verify_payload_bytes(
12,684,641✔
1579
        &mut self,
12,684,641✔
1580
        key: &StacksPublicKey,
12,684,641✔
1581
        preamble: &Preamble,
12,684,641✔
1582
        bytes: &[u8],
12,684,641✔
1583
    ) -> Result<(), Error> {
12,684,641✔
1584
        let preamble_bytes = bytes.get(..preamble.payload_len as usize).ok_or_else(|| {
12,684,641✔
UNCOV
1585
            Error::UnderflowError("Not enough bytes to form a StacksMessage".to_string())
×
UNCOV
1586
        })?;
×
1587
        preamble.clone().verify(preamble_bytes, key).map(|_m| ())
12,684,641✔
1588
    }
12,684,641✔
1589

1590
    fn write_message<W: Write>(
10,000✔
1591
        &mut self,
10,000✔
1592
        fd: &mut W,
10,000✔
1593
        message: &StacksMessage,
10,000✔
1594
    ) -> Result<(), net_error> {
10,000✔
1595
        message.consensus_serialize(fd).map_err(|e| e.into())
10,000✔
1596
    }
10,000✔
1597
}
1598

1599
#[cfg(test)]
1600
pub mod test {
1601
    use clarity::consts::PEER_VERSION_TESTNET;
1602
    use stacks_common::bitvec::BitVec;
1603
    use stacks_common::codec::NEIGHBOR_ADDRESS_ENCODED_SIZE;
1604
    use stacks_common::util::hash::hex_bytes;
1605
    use stacks_common::util::secp256k1::*;
1606

1607
    use super::*;
1608
    use crate::net::{GetNakamotoInvData, NakamotoInvData};
1609

UNCOV
1610
    fn check_overflow<T>(r: Result<T, net_error>) -> bool {
×
UNCOV
1611
        match r {
×
1612
            Ok(_) => {
1613
                test_debug!("did not get an overflow error, or any error");
×
UNCOV
1614
                false
×
1615
            }
1616
            Err(e) => match e {
×
UNCOV
1617
                net_error::OverflowError(_) => true,
×
1618
                _ => {
1619
                    test_debug!("did not get an overflow error, but got {:?}", &e);
×
UNCOV
1620
                    false
×
1621
                }
1622
            },
1623
        }
UNCOV
1624
    }
×
1625

1626
    fn check_underflow<T>(r: Result<T, net_error>) -> bool {
×
UNCOV
1627
        match r {
×
1628
            Ok(_) => {
1629
                test_debug!("did not get an underflow error, or any error");
×
UNCOV
1630
                false
×
1631
            }
1632
            Err(e) => match e {
×
UNCOV
1633
                net_error::UnderflowError(_) => true,
×
1634
                _ => {
1635
                    test_debug!("did not get an underflow error, but got {:?}", &e);
×
UNCOV
1636
                    false
×
1637
                }
1638
            },
1639
        }
UNCOV
1640
    }
×
1641

1642
    fn check_deserialize<T: std::fmt::Debug>(r: Result<T, codec_error>) -> bool {
31✔
1643
        match r {
31✔
UNCOV
1644
            Ok(m) => {
×
UNCOV
1645
                test_debug!("deserialized {m:?}");
×
1646
                false
×
1647
            }
1648
            Err(e) => matches!(e, codec_error::DeserializeError(_)),
31✔
1649
        }
1650
    }
31✔
1651

1652
    fn check_deserialize_failure<T: StacksMessageCodec + fmt::Debug + Clone + PartialEq>(
31✔
1653
        obj: &T,
31✔
1654
    ) -> bool {
31✔
1655
        let mut bytes: Vec<u8> = vec![];
31✔
1656
        obj.consensus_serialize(&mut bytes).unwrap();
31✔
1657
        check_deserialize(T::consensus_deserialize(&mut &bytes[..]))
31✔
1658
    }
31✔
1659

1660
    // Canonical implementation lives in `stacks_common::codec::testing`.
1661
    pub use stacks_common::codec::testing::check_codec_and_corruption;
1662

1663
    #[test]
1664
    fn codec_primitive_types() {
1✔
1665
        check_codec_and_corruption::<u8>(&0x01, &[0x01]);
1✔
1666
        check_codec_and_corruption::<u16>(&0x0203, &[0x02, 0x03]);
1✔
1667
        check_codec_and_corruption::<u32>(&0x04050607, &[0x04, 0x05, 0x06, 0x07]);
1✔
1668
        check_codec_and_corruption::<u64>(
1✔
1669
            &0x08090a0b0c0d0e0f,
1✔
1670
            &[0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
1✔
1671
        );
1672
    }
1✔
1673

1674
    #[test]
1675
    fn codec_primitive_vector() {
1✔
1676
        check_codec_and_corruption::<Vec<u8>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1677
        check_codec_and_corruption::<Vec<u8>>(
1✔
1678
            &vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09],
1✔
1679
            &[
1✔
1680
                0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
1✔
1681
            ],
1✔
1682
        );
1683

1684
        check_codec_and_corruption::<Vec<u16>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1685
        check_codec_and_corruption::<Vec<u16>>(
1✔
1686
            &vec![
1✔
1687
                0xf000, 0xf101, 0xf202, 0xf303, 0xf404, 0xf505, 0xf606, 0xf707, 0xf808, 0xf909,
1✔
1688
            ],
1✔
1689
            &[
1✔
1690
                0x00, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0xf1, 0x01, 0xf2, 0x02, 0xf3, 0x03, 0xf4, 0x04,
1✔
1691
                0xf5, 0x05, 0xf6, 0x06, 0xf7, 0x07, 0xf8, 0x08, 0xf9, 0x09,
1✔
1692
            ],
1✔
1693
        );
1694

1695
        check_codec_and_corruption::<Vec<u32>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1696
        check_codec_and_corruption::<Vec<u32>>(
1✔
1697
            &vec![
1✔
1698
                0xa0b0f000, 0xa1b1f101, 0xa2b2f202, 0xa3b3f303, 0xa4b4f404, 0xa5b5f505, 0xa6b6f606,
1✔
1699
                0xa7b7f707, 0xa8b8f808, 0xa9b9f909,
1✔
1700
            ],
1✔
1701
            &[
1✔
1702
                0x00, 0x00, 0x00, 0x0a, 0xa0, 0xb0, 0xf0, 0x00, 0xa1, 0xb1, 0xf1, 0x01, 0xa2, 0xb2,
1✔
1703
                0xf2, 0x02, 0xa3, 0xb3, 0xf3, 0x03, 0xa4, 0xb4, 0xf4, 0x04, 0xa5, 0xb5, 0xf5, 0x05,
1✔
1704
                0xa6, 0xb6, 0xf6, 0x06, 0xa7, 0xb7, 0xf7, 0x07, 0xa8, 0xb8, 0xf8, 0x08, 0xa9, 0xb9,
1✔
1705
                0xf9, 0x09,
1✔
1706
            ],
1✔
1707
        );
1708

1709
        check_codec_and_corruption::<Vec<u64>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1710
        check_codec_and_corruption::<Vec<u64>>(
1✔
1711
            &vec![
1✔
1712
                0x1020304050607080,
1✔
1713
                0x1121314151617181,
1✔
1714
                0x1222324252627282,
1✔
1715
                0x1323334353637383,
1✔
1716
                0x1424344454647484,
1✔
1717
                0x1525354555657585,
1✔
1718
                0x1626364656667686,
1✔
1719
                0x1727374757677787,
1✔
1720
                0x1828384858687888,
1✔
1721
            ],
1✔
1722
            &[
1✔
1723
                0x00, 0x00, 0x00, 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x11, 0x21,
1✔
1724
                0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x82,
1✔
1725
                0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64,
1✔
1726
                0x74, 0x84, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x16, 0x26, 0x36, 0x46,
1✔
1727
                0x56, 0x66, 0x76, 0x86, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 0x87, 0x18, 0x28,
1✔
1728
                0x38, 0x48, 0x58, 0x68, 0x78, 0x88,
1✔
1729
            ],
1✔
1730
        );
1731
    }
1✔
1732

1733
    #[test]
1734
    fn codec_Preamble() {
1✔
1735
        let preamble = Preamble {
1✔
1736
            peer_version: 0x01020304,
1✔
1737
            network_id: 0x05060708,
1✔
1738
            seq: 0x090a0b0c,
1✔
1739
            burn_block_height: 0x00001122,
1✔
1740
            burn_block_hash: BurnchainHeaderHash([0x11; 32]),
1✔
1741
            burn_stable_block_height: 0x00001111,
1✔
1742
            burn_stable_block_hash: BurnchainHeaderHash([0x22; 32]),
1✔
1743
            additional_data: 0x33333333,
1✔
1744
            signature: MessageSignature::from_raw(&[0x44; 65]),
1✔
1745
            payload_len: 0x000007ff,
1✔
1746
        };
1✔
1747
        let preamble_bytes: Vec<u8> = vec![
1✔
1748
            // peer_version
1749
            0x01, 0x02, 0x03, 0x04, // network_id
1750
            0x05, 0x06, 0x07, 0x08, // seq
1751
            0x09, 0x0a, 0x0b, 0x0c, // burn_block_height
1752
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, // burn_block_hash
1753
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1754
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1755
            0x11, 0x11, 0x11, 0x11, // stable_burn_block_height
1756
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, // stable_burn_block_hash
1757
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
1758
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
1759
            0x22, 0x22, 0x22, 0x22, // additional_data
1760
            0x33, 0x33, 0x33, 0x33, // signature
1761
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1762
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1763
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1764
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1765
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, // payload_len
1766
            0x00, 0x00, 0x07, 0xff,
1767
        ];
1768

1769
        assert_eq!(preamble_bytes.len() as u32, PREAMBLE_ENCODED_SIZE);
1✔
1770
        check_codec_and_corruption::<Preamble>(&preamble, &preamble_bytes);
1✔
1771
    }
1✔
1772

1773
    #[test]
1774
    fn codec_GetPoxInv() {
1✔
1775
        let getpoxinv = GetPoxInv {
1✔
1776
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
1777
            num_cycles: GETPOXINV_MAX_BITLEN as u16,
1✔
1778
        };
1✔
1779

1780
        let getpoxinv_bytes: Vec<u8> = vec![
1✔
1781
            // consensus hash
1782
            0x55,
1783
            0x55,
1784
            0x55,
1785
            0x55,
1786
            0x55,
1787
            0x55,
1788
            0x55,
1789
            0x55,
1790
            0x55,
1791
            0x55,
1792
            0x55,
1793
            0x55,
1794
            0x55,
1795
            0x55,
1796
            0x55,
1797
            0x55,
1798
            0x55,
1799
            0x55,
1800
            0x55,
1801
            0x55,
1802
            // num reward cycles
1803
            0x00,
1804
            GETPOXINV_MAX_BITLEN as u8,
1✔
1805
        ];
1806

1807
        check_codec_and_corruption::<GetPoxInv>(&getpoxinv, &getpoxinv_bytes);
1✔
1808

1809
        // should fail to decode if the block range is too big
1810
        let getpoxinv_range_too_big = GetPoxInv {
1✔
1811
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
1812
            num_cycles: (GETPOXINV_MAX_BITLEN + 1) as u16,
1✔
1813
        };
1✔
1814

1815
        assert!(check_deserialize_failure::<GetPoxInv>(
1✔
1816
            &getpoxinv_range_too_big
1✔
1817
        ));
1818
    }
1✔
1819

1820
    #[test]
1821
    fn codec_PoxInvData() {
1✔
1822
        // maximially big PoxInvData
1823
        let maximal_bitvec = vec![0xffu8; (GETPOXINV_MAX_BITLEN / 8) as usize];
1✔
1824
        let mut too_big_bitvec: Vec<u8> = vec![];
1✔
1825
        for i in 0..GETPOXINV_MAX_BITLEN + 1 {
9✔
1826
            too_big_bitvec.push(0xff);
9✔
1827
        }
9✔
1828

1829
        let maximal_poxinvdata = PoxInvData {
1✔
1830
            bitlen: GETPOXINV_MAX_BITLEN as u16,
1✔
1831
            pox_bitvec: maximal_bitvec.clone(),
1✔
1832
        };
1✔
1833

1834
        let mut maximal_poxinvdata_bytes: Vec<u8> = vec![];
1✔
1835
        // bitlen
1836
        maximal_poxinvdata_bytes.append(&mut (GETPOXINV_MAX_BITLEN as u16).to_be_bytes().to_vec());
1✔
1837
        // pox bitvec
1838
        maximal_poxinvdata_bytes
1✔
1839
            .append(&mut ((GETPOXINV_MAX_BITLEN / 8) as u32).to_be_bytes().to_vec());
1✔
1840
        maximal_poxinvdata_bytes.extend_from_slice(&maximal_bitvec);
1✔
1841

1842
        assert!((maximal_poxinvdata_bytes.len() as u32) < MAX_MESSAGE_LEN);
1✔
1843

1844
        check_codec_and_corruption::<PoxInvData>(&maximal_poxinvdata, &maximal_poxinvdata_bytes);
1✔
1845

1846
        // should fail to decode if the bitlen is too big
1847
        let too_big_poxinvdata = PoxInvData {
1✔
1848
            bitlen: (GETPOXINV_MAX_BITLEN + 1) as u16,
1✔
1849
            pox_bitvec: too_big_bitvec.clone(),
1✔
1850
        };
1✔
1851
        assert!(check_deserialize_failure::<PoxInvData>(&too_big_poxinvdata));
1✔
1852

1853
        // should fail to decode if the bitlen doesn't match the bitvec
1854
        let long_bitlen = PoxInvData {
1✔
1855
            bitlen: 1,
1✔
1856
            pox_bitvec: vec![0xff, 0x01],
1✔
1857
        };
1✔
1858
        assert!(check_deserialize_failure::<PoxInvData>(&long_bitlen));
1✔
1859

1860
        let short_bitlen = PoxInvData {
1✔
1861
            bitlen: 9,
1✔
1862
            pox_bitvec: vec![0xff],
1✔
1863
        };
1✔
1864
        assert!(check_deserialize_failure::<PoxInvData>(&short_bitlen));
1✔
1865

1866
        // empty
1867
        let empty_inv = PoxInvData {
1✔
1868
            bitlen: 0,
1✔
1869
            pox_bitvec: vec![],
1✔
1870
        };
1✔
1871
        let empty_inv_bytes = [
1✔
1872
            // bitlen
1✔
1873
            0x00, 0x00, 0x00, 0x00, // bitvec
1✔
1874
            0x00, 0x00, 0x00, 0x00,
1✔
1875
        ];
1✔
1876

1877
        check_codec_and_corruption::<PoxInvData>(&maximal_poxinvdata, &maximal_poxinvdata_bytes);
1✔
1878
    }
1✔
1879

1880
    #[test]
1881
    fn codec_GetBlocksInv() {
1✔
1882
        let getblocksdata = GetBlocksInv {
1✔
1883
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
1884
            num_blocks: 32,
1✔
1885
        };
1✔
1886

1887
        let getblocksdata_bytes: Vec<u8> = vec![
1✔
1888
            // consensus hash
1889
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1890
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // num blocks
1891
            0x00, 0x20,
1892
        ];
1893

1894
        check_codec_and_corruption::<GetBlocksInv>(&getblocksdata, &getblocksdata_bytes);
1✔
1895
    }
1✔
1896

1897
    #[test]
1898
    fn codec_BlocksInvData() {
1✔
1899
        let blocks_bitlen: u32 = 32;
1✔
1900

1901
        let maximal_bitvec = vec![0xffu8; (blocks_bitlen / 8) as usize];
1✔
1902
        let maximal_blocksinvdata = BlocksInvData {
1✔
1903
            bitlen: blocks_bitlen as u16,
1✔
1904
            block_bitvec: maximal_bitvec.clone(),
1✔
1905
            microblocks_bitvec: maximal_bitvec.clone(),
1✔
1906
        };
1✔
1907

1908
        let mut maximal_blocksinvdata_bytes: Vec<u8> = vec![];
1✔
1909
        // bitlen
1910
        maximal_blocksinvdata_bytes.append(&mut (blocks_bitlen as u16).to_be_bytes().to_vec());
1✔
1911
        // block bitvec
1912
        maximal_blocksinvdata_bytes.append(&mut (blocks_bitlen / 8).to_be_bytes().to_vec());
1✔
1913
        maximal_blocksinvdata_bytes.extend_from_slice(&maximal_bitvec);
1✔
1914
        // microblock bitvec
1915
        maximal_blocksinvdata_bytes.append(&mut (blocks_bitlen / 8).to_be_bytes().to_vec());
1✔
1916
        maximal_blocksinvdata_bytes.extend_from_slice(&maximal_bitvec);
1✔
1917

1918
        assert!((maximal_blocksinvdata_bytes.len() as u32) < MAX_MESSAGE_LEN);
1✔
1919

1920
        check_codec_and_corruption::<BlocksInvData>(
1✔
1921
            &maximal_blocksinvdata,
1✔
1922
            &maximal_blocksinvdata_bytes,
1✔
1923
        );
1924

1925
        // should fail to decode if the bitlen doesn't match the bitvec
1926
        let long_bitlen = BlocksInvData {
1✔
1927
            bitlen: 1,
1✔
1928
            block_bitvec: vec![0xff, 0x01],
1✔
1929
            microblocks_bitvec: vec![0xff, 0x01],
1✔
1930
        };
1✔
1931
        assert!(check_deserialize_failure::<BlocksInvData>(&long_bitlen));
1✔
1932

1933
        let short_bitlen = BlocksInvData {
1✔
1934
            bitlen: 9,
1✔
1935
            block_bitvec: vec![0xff],
1✔
1936
            microblocks_bitvec: vec![0xff],
1✔
1937
        };
1✔
1938
        assert!(check_deserialize_failure::<BlocksInvData>(&short_bitlen));
1✔
1939

1940
        // empty
1941
        let empty_inv = BlocksInvData {
1✔
1942
            bitlen: 0,
1✔
1943
            block_bitvec: vec![],
1✔
1944
            microblocks_bitvec: vec![],
1✔
1945
        };
1✔
1946
        let empty_inv_bytes = [
1✔
1947
            // bitlen
1✔
1948
            0x00, 0x00, 0x00, 0x00, // bitvec
1✔
1949
            0x00, 0x00, 0x00, 0x00, // microblock bitvec
1✔
1950
            0x00, 0x00, 0x00, 0x00,
1✔
1951
        ];
1✔
1952

1953
        assert!(check_deserialize_failure::<BlocksInvData>(&empty_inv));
1✔
1954
    }
1✔
1955

1956
    #[test]
1957
    fn codec_NeighborAddress() {
1✔
1958
        let data = NeighborAddress {
1✔
1959
            addrbytes: PeerAddress([
1✔
1960
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
1✔
1961
                0x0e, 0x0f,
1✔
1962
            ]),
1✔
1963
            port: 12345,
1✔
1964
            public_key_hash: Hash160::from_bytes(
1✔
1965
                &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
1966
            )
1✔
1967
            .unwrap(),
1✔
1968
        };
1✔
1969
        let bytes = vec![
1✔
1970
            // addrbytes
1971
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
1972
            0x0e, 0x0f, // port
1973
            0x30, 0x39, // public key hash
1974
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1975
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1976
        ];
1977

1978
        assert_eq!(bytes.len() as u32, NEIGHBOR_ADDRESS_ENCODED_SIZE);
1✔
1979
        check_codec_and_corruption::<NeighborAddress>(&data, &bytes);
1✔
1980
    }
1✔
1981

1982
    #[test]
1983
    fn codec_NeighborsData() {
1✔
1984
        let data = NeighborsData {
1✔
1985
            neighbors: vec![
1✔
1986
                NeighborAddress {
1✔
1987
                    addrbytes: PeerAddress([
1✔
1988
                        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
1989
                        0x0c, 0x0d, 0x0e, 0x0f,
1✔
1990
                    ]),
1✔
1991
                    port: 12345,
1✔
1992
                    public_key_hash: Hash160::from_bytes(
1✔
1993
                        &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
1994
                    )
1✔
1995
                    .unwrap(),
1✔
1996
                },
1✔
1997
                NeighborAddress {
1✔
1998
                    addrbytes: PeerAddress([
1✔
1999
                        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
1✔
2000
                        0x1c, 0x1d, 0x1e, 0x1f,
1✔
2001
                    ]),
1✔
2002
                    port: 23456,
1✔
2003
                    public_key_hash: Hash160::from_bytes(
1✔
2004
                        &hex_bytes("2222222222222222222222222222222222222222").unwrap(),
1✔
2005
                    )
1✔
2006
                    .unwrap(),
1✔
2007
                },
1✔
2008
            ],
1✔
2009
        };
1✔
2010
        let bytes = vec![
1✔
2011
            // length
2012
            0x00, 0x00, 0x00, 0x02, // addrbytes
2013
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2014
            0x0e, 0x0f, // port
2015
            0x30, 0x39, // public key hash
2016
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2017
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // addrbytes
2018
            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
2019
            0x1e, 0x1f, // port
2020
            0x5b, 0xa0, // public key hash
2021
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2022
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2023
        ];
2024

2025
        check_codec_and_corruption::<NeighborsData>(&data, &bytes);
1✔
2026
    }
1✔
2027

2028
    #[test]
2029
    fn codec_HandshakeData() {
1✔
2030
        let data = HandshakeData {
1✔
2031
            addrbytes: PeerAddress([
1✔
2032
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
1✔
2033
                0x0e, 0x0f,
1✔
2034
            ]),
1✔
2035
            port: 12345,
1✔
2036
            services: 0x0001,
1✔
2037
            node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2038
                &hex_bytes("034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb")
1✔
2039
                    .unwrap(),
1✔
2040
            )
1✔
2041
            .unwrap(),
1✔
2042
            expire_block_height: 0x0102030405060708,
1✔
2043
            data_url: UrlString::try_from("https://the-new-interwebs.com/data").unwrap(),
1✔
2044
        };
1✔
2045
        let mut bytes = vec![
1✔
2046
            // addrbytes
2047
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2048
            0x0e, 0x0f, // port
2049
            0x30, 0x39, // services
2050
            0x00, 0x01, // public key
2051
            0x03, 0x4e, 0x31, 0x6b, 0xe0, 0x48, 0x70, 0xce, 0xf1, 0x79, 0x5f, 0xba, 0x64, 0xd5,
2052
            0x81, 0xcf, 0x64, 0xba, 0xd0, 0xc8, 0x94, 0xb0, 0x1a, 0x06, 0x8f, 0xb9, 0xed, 0xf8,
2053
            0x53, 0x21, 0xdc, 0xd9, 0xbb, // expire block height
2054
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
2055
        ];
2056
        // data URL
2057
        bytes.push(data.data_url.len() as u8);
1✔
2058
        bytes.extend_from_slice(data.data_url.as_bytes());
1✔
2059

2060
        check_codec_and_corruption::<HandshakeData>(&data, &bytes);
1✔
2061
    }
1✔
2062

2063
    #[test]
2064
    fn codec_HandshakeAcceptData() {
1✔
2065
        let data = HandshakeAcceptData {
1✔
2066
            handshake: HandshakeData {
1✔
2067
                addrbytes: PeerAddress([
1✔
2068
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2069
                    0x0d, 0x0e, 0x0f,
1✔
2070
                ]),
1✔
2071
                port: 12345,
1✔
2072
                services: 0x0001,
1✔
2073
                node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2074
                    &hex_bytes(
1✔
2075
                        "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2076
                    )
1✔
2077
                    .unwrap(),
1✔
2078
                )
1✔
2079
                .unwrap(),
1✔
2080
                expire_block_height: 0x0102030405060708,
1✔
2081
                data_url: UrlString::try_from("https://the-new-interwebs.com/data").unwrap(),
1✔
2082
            },
1✔
2083
            heartbeat_interval: 0x01020304,
1✔
2084
        };
1✔
2085
        let mut bytes = vec![
1✔
2086
            // addrbytes
2087
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2088
            0x0e, 0x0f, // port
2089
            0x30, 0x39, // services
2090
            0x00, 0x01, // public key
2091
            0x03, 0x4e, 0x31, 0x6b, 0xe0, 0x48, 0x70, 0xce, 0xf1, 0x79, 0x5f, 0xba, 0x64, 0xd5,
2092
            0x81, 0xcf, 0x64, 0xba, 0xd0, 0xc8, 0x94, 0xb0, 0x1a, 0x06, 0x8f, 0xb9, 0xed, 0xf8,
2093
            0x53, 0x21, 0xdc, 0xd9, 0xbb, // expire block height
2094
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
2095
        ];
2096
        // data URL
2097
        bytes.push(data.handshake.data_url.len() as u8);
1✔
2098
        bytes.extend_from_slice(data.handshake.data_url.as_bytes());
1✔
2099

2100
        bytes.extend_from_slice(&[
1✔
2101
            // heartbeat
1✔
2102
            0x01, 0x02, 0x03, 0x04,
1✔
2103
        ]);
1✔
2104

2105
        check_codec_and_corruption::<HandshakeAcceptData>(&data, &bytes);
1✔
2106
    }
1✔
2107

2108
    #[test]
2109
    fn codec_NackData() {
1✔
2110
        let data = NackData {
1✔
2111
            error_code: 0x01020304,
1✔
2112
        };
1✔
2113
        let bytes = vec![
1✔
2114
            // error code
2115
            0x01, 0x02, 0x03, 0x04,
2116
        ];
2117

2118
        check_codec_and_corruption::<NackData>(&data, &bytes);
1✔
2119
    }
1✔
2120

2121
    #[test]
2122
    fn codec_RelayData() {
1✔
2123
        let data = RelayData {
1✔
2124
            peer: NeighborAddress {
1✔
2125
                addrbytes: PeerAddress([
1✔
2126
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2127
                    0x0d, 0x0e, 0x0f,
1✔
2128
                ]),
1✔
2129
                port: 12345,
1✔
2130
                public_key_hash: Hash160::from_bytes(
1✔
2131
                    &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2132
                )
1✔
2133
                .unwrap(),
1✔
2134
            },
1✔
2135
            seq: 0x01020304,
1✔
2136
        };
1✔
2137
        let bytes = vec![
1✔
2138
            // peer.addrbytes
2139
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2140
            0x0e, 0x0f, // peer.port
2141
            0x30, 0x39, // peer.public_key_hash
2142
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2143
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // seq
2144
            0x01, 0x02, 0x03, 0x04,
2145
        ];
2146

2147
        check_codec_and_corruption::<RelayData>(&data, &bytes);
1✔
2148
    }
1✔
2149

2150
    #[test]
2151
    fn codec_BlocksAvailable() {
1✔
2152
        let data = BlocksAvailableData {
1✔
2153
            available: vec![
1✔
2154
                (ConsensusHash([0x11; 20]), BurnchainHeaderHash([0x22; 32])),
1✔
2155
                (ConsensusHash([0x33; 20]), BurnchainHeaderHash([0x44; 32])),
1✔
2156
            ],
1✔
2157
        };
1✔
2158
        let bytes = vec![
1✔
2159
            // length
2160
            0x00, 0x00, 0x00, 0x02, // first tuple
2161
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2162
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2163
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2164
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // second tuple
2165
            0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
2166
            0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2167
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2168
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2169
        ];
2170

2171
        check_codec_and_corruption::<BlocksAvailableData>(&data, &bytes);
1✔
2172
    }
1✔
2173

2174
    #[test]
2175
    fn codec_NatPunch() {
1✔
2176
        let data = NatPunchData {
1✔
2177
            addrbytes: PeerAddress([0x1; 16]),
1✔
2178
            port: 0x1234,
1✔
2179
            nonce: 0x56789abc,
1✔
2180
        };
1✔
2181
        let bytes = vec![
1✔
2182
            // peer address
2183
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2184
            0x01, 0x01, // port
2185
            0x12, 0x34, // nonce
2186
            0x56, 0x78, 0x9a, 0xbc,
2187
        ];
2188

2189
        check_codec_and_corruption::<NatPunchData>(&data, &bytes);
1✔
2190
    }
1✔
2191

2192
    #[test]
2193
    fn codec_StackerDBHandshakeAccept() {
1✔
2194
        let data = StackerDBHandshakeData {
1✔
2195
            rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2196
            smart_contracts: vec![
1✔
2197
                QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo")
1✔
2198
                    .unwrap(),
1✔
2199
                QualifiedContractIdentifier::parse("SP28D54YKFCMRKXBR6BR0E4BPN57S62RSM4XEVPRP.bar")
1✔
2200
                    .unwrap(),
1✔
2201
            ],
1✔
2202
        };
1✔
2203
        let bytes = vec![
1✔
2204
            // rc consensus hash
2205
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2206
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // len(smart_contracts)
2207
            0x02, // SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN
2208
            0x16, 0x11, 0x7b, 0x59, 0x1a, 0xdf, 0x7c, 0xae, 0xe4, 0x3b, 0x7e, 0x5d, 0x88, 0x24,
2209
            0xe8, 0x51, 0xb9, 0x35, 0xbc, 0xa9, 0xae, // len(foo)
2210
            0x03, // foo
2211
            0x66, 0x6f, 0x6f, // SP28D54YKFCMRKXBR6BR0E4BPN57S62RSM4XEVPRP
2212
            0x16, 0x90, 0xd2, 0x93, 0xd3, 0x7b, 0x29, 0x89, 0xf5, 0x78, 0x32, 0xf0, 0x07, 0x11,
2213
            0x76, 0xa9, 0x4f, 0x93, 0x0b, 0x19, 0xa1, // len(bar)
2214
            0x03, // bar
2215
            0x62, 0x61, 0x72,
2216
        ];
2217

2218
        check_codec_and_corruption::<StackerDBHandshakeData>(&data, &bytes);
1✔
2219
    }
1✔
2220

2221
    #[test]
2222
    fn codec_StackerDBGetChunkInvData() {
1✔
2223
        let data = StackerDBGetChunkInvData {
1✔
2224
            contract_id: QualifiedContractIdentifier::parse(
1✔
2225
                "SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo",
1✔
2226
            )
1✔
2227
            .unwrap(),
1✔
2228
            rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2229
        };
1✔
2230

2231
        let bytes = vec![
1✔
2232
            // SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN
2233
            0x16, 0x11, 0x7b, 0x59, 0x1a, 0xdf, 0x7c, 0xae, 0xe4, 0x3b, 0x7e, 0x5d, 0x88, 0x24,
2234
            0xe8, 0x51, 0xb9, 0x35, 0xbc, 0xa9, 0xae, // len(foo)
2235
            0x03, // foo
2236
            0x66, 0x6f, 0x6f, // rc consensus hash
2237
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2238
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2239
        ];
2240

2241
        check_codec_and_corruption::<StackerDBGetChunkInvData>(&data, &bytes);
1✔
2242
    }
1✔
2243

2244
    #[test]
2245
    fn codec_StackerDBChunkInvData() {
1✔
2246
        let data = StackerDBChunkInvData {
1✔
2247
            slot_versions: vec![0, 1, 2, 3],
1✔
2248
            num_outbound_replicas: 4,
1✔
2249
        };
1✔
2250

2251
        let bytes = vec![
1✔
2252
            // len(slot_versions)
2253
            0x00, 0x00, 0x00, 0x04, // 0u32
2254
            0x00, 0x00, 0x00, 0x00, // 1u32
2255
            0x00, 0x00, 0x00, 0x01, // 2u32
2256
            0x00, 0x00, 0x00, 0x02, // 3u32
2257
            0x00, 0x00, 0x00, 0x03, // num_outbound_replicas
2258
            0x00, 0x00, 0x00, 0x04,
2259
        ];
2260

2261
        check_codec_and_corruption::<StackerDBChunkInvData>(&data, &bytes);
1✔
2262
    }
1✔
2263

2264
    #[test]
2265
    fn codec_StackerDBGetChunkData() {
1✔
2266
        let data = StackerDBGetChunkData {
1✔
2267
            contract_id: QualifiedContractIdentifier::parse(
1✔
2268
                "SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo",
1✔
2269
            )
1✔
2270
            .unwrap(),
1✔
2271
            rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2272
            slot_id: 2,
1✔
2273
            slot_version: 3,
1✔
2274
        };
1✔
2275

2276
        let bytes = vec![
1✔
2277
            // SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN
2278
            0x16, 0x11, 0x7b, 0x59, 0x1a, 0xdf, 0x7c, 0xae, 0xe4, 0x3b, 0x7e, 0x5d, 0x88, 0x24,
2279
            0xe8, 0x51, 0xb9, 0x35, 0xbc, 0xa9, 0xae, // len(foo)
2280
            0x03, // foo
2281
            0x66, 0x6f, 0x6f, // rc consensus hash
2282
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2283
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // slot id
2284
            0x00, 0x00, 0x00, 0x02, // slot version
2285
            0x00, 0x00, 0x00, 0x03,
2286
        ];
2287

2288
        check_codec_and_corruption::<StackerDBGetChunkData>(&data, &bytes);
1✔
2289
    }
1✔
2290

2291
    #[test]
2292
    fn codec_StackerDBChunkData() {
1✔
2293
        let data = StackerDBChunkData {
1✔
2294
            slot_id: 2,
1✔
2295
            slot_version: 3,
1✔
2296
            sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2297
            data: vec![
1✔
2298
                0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
1✔
2299
            ],
1✔
2300
        };
1✔
2301

2302
        let bytes = vec![
1✔
2303
            // slot id
2304
            0x00, 0x00, 0x00, 0x02, // slot version
2305
            0x00, 0x00, 0x00, 0x03, // signature
2306
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2307
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2308
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2309
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2310
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, // length
2311
            0x00, 0x00, 0x00, 0x0b, // data
2312
            0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
2313
        ];
2314

2315
        check_codec_and_corruption::<StackerDBChunkData>(&data, &bytes);
1✔
2316
    }
1✔
2317

2318
    #[test]
2319
    fn codec_StackerDBPushChunkData() {
1✔
2320
        let data = StackerDBChunkData {
1✔
2321
            slot_id: 2,
1✔
2322
            slot_version: 3,
1✔
2323
            sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2324
            data: vec![
1✔
2325
                0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
1✔
2326
            ],
1✔
2327
        };
1✔
2328

2329
        let push_data = StackerDBPushChunkData {
1✔
2330
            contract_id: QualifiedContractIdentifier::parse(
1✔
2331
                "SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo",
1✔
2332
            )
1✔
2333
            .unwrap(),
1✔
2334
            rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2335
            chunk_data: data,
1✔
2336
        };
1✔
2337

2338
        let bytes = vec![
1✔
2339
            // SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN
2340
            0x16, 0x11, 0x7b, 0x59, 0x1a, 0xdf, 0x7c, 0xae, 0xe4, 0x3b, 0x7e, 0x5d, 0x88, 0x24,
2341
            0xe8, 0x51, 0xb9, 0x35, 0xbc, 0xa9, 0xae, // len(foo)
2342
            0x03, // foo
2343
            0x66, 0x6f, 0x6f, // rc consensus hash
2344
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2345
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // slot id
2346
            0x00, 0x00, 0x00, 0x02, // slot version
2347
            0x00, 0x00, 0x00, 0x03, // signature
2348
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2349
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2350
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2351
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2352
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, // length
2353
            0x00, 0x00, 0x00, 0x0b, // data
2354
            0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
2355
        ];
2356

2357
        check_codec_and_corruption::<StackerDBPushChunkData>(&push_data, &bytes);
1✔
2358
    }
1✔
2359

2360
    #[test]
2361
    fn codec_GetNakamotoInv() {
1✔
2362
        let get_nakamoto_inv = GetNakamotoInvData {
1✔
2363
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
2364
        };
1✔
2365

2366
        let get_nakamoto_inv_bytes: Vec<u8> = vec![
1✔
2367
            // consensus hash
2368
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
2369
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
2370
        ];
2371

2372
        check_codec_and_corruption::<GetNakamotoInvData>(
1✔
2373
            &get_nakamoto_inv,
1✔
2374
            &get_nakamoto_inv_bytes,
1✔
2375
        );
2376
    }
1✔
2377

2378
    #[test]
2379
    fn codec_NakamotoInv() {
1✔
2380
        let nakamoto_inv = NakamotoInvData {
1✔
2381
            tenures: BitVec::<2100>::try_from(
1✔
2382
                // 0xdd
1✔
2383
                vec![
1✔
2384
                    true, false, true, true, true, false, true, true, // 0xee
1✔
2385
                    false, true, true, true, false, true, true, true, // 0xaa
1✔
2386
                    false, true, false, true, false, true, false, true, // 0xdd
1✔
2387
                    true, false, true, true, true, false, true, true, // 0xbb
1✔
2388
                    true, true, false, true, true, true, false, true, // 0xee
1✔
2389
                    false, true, true, true, false, true, true, true, // 0xee
1✔
2390
                    false, true, true, true, false, true, true, true, // 0xff
1✔
2391
                    true, true, true, true, true, true, true, true,
1✔
2392
                ]
1✔
2393
                .as_slice(),
1✔
2394
            )
1✔
2395
            .unwrap(),
1✔
2396
        };
1✔
2397

2398
        let nakamoto_inv_bytes = [
1✔
2399
            // bitlen
1✔
2400
            0x00, 0x40, // vec len
1✔
2401
            0x00, 0x00, 0x00, 0x08, // bits
1✔
2402
            0xdd, 0xee, 0xaa, 0xdd, 0xbb, 0xee, 0xee, 0xff,
1✔
2403
        ];
1✔
2404

2405
        check_codec_and_corruption::<NakamotoInvData>(&nakamoto_inv, &nakamoto_inv_bytes);
1✔
2406

2407
        // should fail
2408
        let nakamoto_inv_bytes = [
1✔
2409
            // bitlen
1✔
2410
            0x00, 0x20, // vec len
1✔
2411
            0x00, 0x00, 0x00, 0x05, // bits
1✔
2412
            0x00, 0x00, 0x00, 0x00,
1✔
2413
        ];
1✔
2414

2415
        let _ = NakamotoInvData::consensus_deserialize(&mut &nakamoto_inv_bytes[..]).unwrap_err();
1✔
2416

2417
        // should fail
2418
        let nakamoto_inv_bytes = [
1✔
2419
            // bitlen
1✔
2420
            0x00, 0x21, // vec len
1✔
2421
            0x00, 0x00, 0x00, 0x04, // bits
1✔
2422
            0x00, 0x00, 0x00, 0x00,
1✔
2423
        ];
1✔
2424

2425
        let _ = NakamotoInvData::consensus_deserialize(&mut &nakamoto_inv_bytes[..]).unwrap_err();
1✔
2426
    }
1✔
2427

2428
    #[test]
2429
    fn codec_StacksMessage() {
1✔
2430
        let payloads: Vec<StacksMessageType> = vec![
1✔
2431
            StacksMessageType::Handshake(HandshakeData {
1✔
2432
                addrbytes: PeerAddress([
1✔
2433
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2434
                    0x0d, 0x0e, 0x0f,
1✔
2435
                ]),
1✔
2436
                port: 12345,
1✔
2437
                services: 0x0001,
1✔
2438
                node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2439
                    &hex_bytes(
1✔
2440
                        "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2441
                    )
1✔
2442
                    .unwrap(),
1✔
2443
                )
1✔
2444
                .unwrap(),
1✔
2445
                expire_block_height: 0x0102030405060708,
1✔
2446
                data_url: UrlString::try_from("https://the-new-interwebs.com:4008/the-data")
1✔
2447
                    .unwrap(),
1✔
2448
            }),
1✔
2449
            StacksMessageType::HandshakeAccept(HandshakeAcceptData {
1✔
2450
                heartbeat_interval: 0x01020304,
1✔
2451
                handshake: HandshakeData {
1✔
2452
                    addrbytes: PeerAddress([
1✔
2453
                        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
2454
                        0x0c, 0x0d, 0x0e, 0x0f,
1✔
2455
                    ]),
1✔
2456
                    port: 12345,
1✔
2457
                    services: 0x0001,
1✔
2458
                    node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2459
                        &hex_bytes(
1✔
2460
                            "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2461
                        )
1✔
2462
                        .unwrap(),
1✔
2463
                    )
1✔
2464
                    .unwrap(),
1✔
2465
                    expire_block_height: 0x0102030405060708,
1✔
2466
                    data_url: UrlString::try_from("https://the-new-interwebs.com:4008/the-data")
1✔
2467
                        .unwrap(),
1✔
2468
                },
1✔
2469
            }),
1✔
2470
            StacksMessageType::HandshakeReject,
1✔
2471
            StacksMessageType::GetNeighbors,
1✔
2472
            StacksMessageType::Neighbors(NeighborsData {
1✔
2473
                neighbors: vec![
1✔
2474
                    NeighborAddress {
1✔
2475
                        addrbytes: PeerAddress([
1✔
2476
                            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
2477
                            0x0c, 0x0d, 0x0e, 0x0f,
1✔
2478
                        ]),
1✔
2479
                        port: 12345,
1✔
2480
                        public_key_hash: Hash160::from_bytes(
1✔
2481
                            &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2482
                        )
1✔
2483
                        .unwrap(),
1✔
2484
                    },
1✔
2485
                    NeighborAddress {
1✔
2486
                        addrbytes: PeerAddress([
1✔
2487
                            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
1✔
2488
                            0x1c, 0x1d, 0x1e, 0x1f,
1✔
2489
                        ]),
1✔
2490
                        port: 23456,
1✔
2491
                        public_key_hash: Hash160::from_bytes(
1✔
2492
                            &hex_bytes("2222222222222222222222222222222222222222").unwrap(),
1✔
2493
                        )
1✔
2494
                        .unwrap(),
1✔
2495
                    },
1✔
2496
                ],
1✔
2497
            }),
1✔
2498
            StacksMessageType::GetPoxInv(GetPoxInv {
1✔
2499
                consensus_hash: ConsensusHash([0x55; 20]),
1✔
2500
                num_cycles: GETPOXINV_MAX_BITLEN as u16,
1✔
2501
            }),
1✔
2502
            StacksMessageType::PoxInv(PoxInvData {
1✔
2503
                bitlen: 2,
1✔
2504
                pox_bitvec: vec![0x03],
1✔
2505
            }),
1✔
2506
            StacksMessageType::GetBlocksInv(GetBlocksInv {
1✔
2507
                consensus_hash: ConsensusHash([0x55; 20]),
1✔
2508
                num_blocks: 32,
1✔
2509
            }),
1✔
2510
            StacksMessageType::BlocksInv(BlocksInvData {
1✔
2511
                bitlen: 2,
1✔
2512
                block_bitvec: vec![0x03],
1✔
2513
                microblocks_bitvec: vec![0x03],
1✔
2514
            }),
1✔
2515
            StacksMessageType::BlocksAvailable(BlocksAvailableData {
1✔
2516
                available: vec![
1✔
2517
                    (ConsensusHash([0x11; 20]), BurnchainHeaderHash([0x22; 32])),
1✔
2518
                    (ConsensusHash([0x33; 20]), BurnchainHeaderHash([0x44; 32])),
1✔
2519
                ],
1✔
2520
            }),
1✔
2521
            StacksMessageType::MicroblocksAvailable(BlocksAvailableData {
1✔
2522
                available: vec![
1✔
2523
                    (ConsensusHash([0x11; 20]), BurnchainHeaderHash([0x22; 32])),
1✔
2524
                    (ConsensusHash([0x33; 20]), BurnchainHeaderHash([0x44; 32])),
1✔
2525
                ],
1✔
2526
            }),
1✔
2527
            // TODO: Blocks
2528
            // TODO: Microblocks
2529
            // TODO: Transaction
2530
            StacksMessageType::Nack(NackData {
1✔
2531
                error_code: 0x01020304,
1✔
2532
            }),
1✔
2533
            StacksMessageType::Ping(PingData { nonce: 0x01020304 }),
1✔
2534
            StacksMessageType::Pong(PongData { nonce: 0x01020304 }),
1✔
2535
            StacksMessageType::NatPunchRequest(0x12345678),
1✔
2536
            StacksMessageType::NatPunchReply(NatPunchData {
1✔
2537
                addrbytes: PeerAddress([
1✔
2538
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2539
                    0x0d, 0x0e, 0x0f,
1✔
2540
                ]),
1✔
2541
                port: 12345,
1✔
2542
                nonce: 0x12345678,
1✔
2543
            }),
1✔
2544
            StacksMessageType::StackerDBHandshakeAccept(
1✔
2545
                HandshakeAcceptData {
1✔
2546
                    heartbeat_interval: 0x01020304,
1✔
2547
                    handshake: HandshakeData {
1✔
2548
                        addrbytes: PeerAddress([
1✔
2549
                            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
2550
                            0x0c, 0x0d, 0x0e, 0x0f,
1✔
2551
                        ]),
1✔
2552
                        port: 12345,
1✔
2553
                        services: 0x0001,
1✔
2554
                        node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2555
                            &hex_bytes(
1✔
2556
                                "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2557
                            )
1✔
2558
                            .unwrap(),
1✔
2559
                        )
1✔
2560
                        .unwrap(),
1✔
2561
                        expire_block_height: 0x0102030405060708,
1✔
2562
                        data_url: UrlString::try_from("https://the-new-interwebs.com:4008/the-data")
1✔
2563
                            .unwrap(),
1✔
2564
                    },
1✔
2565
                },
1✔
2566
                StackerDBHandshakeData {
1✔
2567
                    rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2568
                    smart_contracts: vec![QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(), QualifiedContractIdentifier::parse("SP28D54YKFCMRKXBR6BR0E4BPN57S62RSM4XEVPRP.bar").unwrap()]
1✔
2569
                }
1✔
2570
            ),
1✔
2571
            StacksMessageType::StackerDBGetChunkInv(StackerDBGetChunkInvData {
1✔
2572
                contract_id: QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(),
1✔
2573
                rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2574
            }),
1✔
2575
            StacksMessageType::StackerDBChunkInv(StackerDBChunkInvData {
1✔
2576
                slot_versions: vec![0, 1, 2, 3],
1✔
2577
                num_outbound_replicas: 4,
1✔
2578
            }),
1✔
2579
            StacksMessageType::StackerDBGetChunk(StackerDBGetChunkData {
1✔
2580
                contract_id: QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(),
1✔
2581
                rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2582
                slot_id: 2,
1✔
2583
                slot_version: 3
1✔
2584
            }),
1✔
2585
            StacksMessageType::StackerDBChunk(StackerDBChunkData {
1✔
2586
                slot_id: 2,
1✔
2587
                slot_version: 3,
1✔
2588
                sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2589
                data: vec![0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
1✔
2590
            }),
1✔
2591
            StacksMessageType::StackerDBPushChunk(StackerDBPushChunkData {
1✔
2592
                contract_id: QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(),
1✔
2593
                rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2594
                chunk_data: StackerDBChunkData {
1✔
2595
                    slot_id: 2,
1✔
2596
                    slot_version: 3,
1✔
2597
                    sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2598
                    data: vec![0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
1✔
2599
                }
1✔
2600
            }),
1✔
2601
            StacksMessageType::GetNakamotoInv(GetNakamotoInvData {
1✔
2602
                consensus_hash: ConsensusHash([0x01; 20]),
1✔
2603
            }),
1✔
2604
            StacksMessageType::NakamotoInv(NakamotoInvData {
1✔
2605
                tenures: BitVec::<2100>::try_from(
1✔
2606
                    // 0xdd
1✔
2607
                    vec![true, true, false, true, true, true, false, true,
1✔
2608
                    // 0xee
1✔
2609
                    true, true, true, false, true, true, true, false,
1✔
2610
                    // 0xaa
1✔
2611
                    true, false, true, false, true, false, true, false,
1✔
2612
                    // 0xdd
1✔
2613
                    true, true, false, true, true, true, false, true,
1✔
2614
                    // 0xbb
1✔
2615
                    true, false, true, true, true, false, true, true,
1✔
2616
                    // 0xee
1✔
2617
                    true, true, true, false, true, true, true, false,
1✔
2618
                    // 0xee
1✔
2619
                    true, true, true, false, true, true, true, false,
1✔
2620
                    // 0xff
1✔
2621
                    true, true, true, true, true, true, true, true].as_slice()
1✔
2622
                ).unwrap()
1✔
2623
            }),
1✔
2624
        ];
2625

2626
        let mut maximal_relayers: Vec<RelayData> = vec![];
1✔
2627
        let mut too_many_relayers: Vec<RelayData> = vec![];
1✔
2628
        for i in 0..MAX_RELAYERS_LEN {
16✔
2629
            let next_relayer = RelayData {
16✔
2630
                peer: NeighborAddress {
16✔
2631
                    addrbytes: PeerAddress([
16✔
2632
                        i as u8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
16✔
2633
                        0x0c, 0x0d, 0x0e, 0x0f,
16✔
2634
                    ]),
16✔
2635
                    port: 12345 + (i as u16),
16✔
2636
                    public_key_hash: Hash160::from_bytes(
16✔
2637
                        &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
16✔
2638
                    )
16✔
2639
                    .unwrap(),
16✔
2640
                },
16✔
2641
                seq: 0x01020304 + i,
16✔
2642
            };
16✔
2643
            too_many_relayers.push(next_relayer.clone());
16✔
2644
            maximal_relayers.push(next_relayer);
16✔
2645
        }
16✔
2646
        too_many_relayers.push(RelayData {
1✔
2647
            peer: NeighborAddress {
1✔
2648
                addrbytes: PeerAddress([
1✔
2649
                    0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2650
                    0x0d, 0x0e, 0x0f,
1✔
2651
                ]),
1✔
2652
                port: 65535,
1✔
2653
                public_key_hash: Hash160::from_bytes(
1✔
2654
                    &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2655
                )
1✔
2656
                .unwrap(),
1✔
2657
            },
1✔
2658
            seq: 0x010203ff,
1✔
2659
        });
1✔
2660

2661
        let mut relayers_bytes: Vec<u8> = vec![];
1✔
2662
        maximal_relayers
1✔
2663
            .consensus_serialize(&mut relayers_bytes)
1✔
2664
            .unwrap();
1✔
2665

2666
        let mut too_many_relayer_bytes: Vec<u8> = vec![];
1✔
2667
        too_many_relayers
1✔
2668
            .consensus_serialize(&mut too_many_relayer_bytes)
1✔
2669
            .unwrap();
1✔
2670

2671
        for payload in &payloads {
24✔
2672
            // just testing codec; don't worry about signatures
2673
            // (only payload_len must be valid)
2674
            let mut payload_bytes: Vec<u8> = vec![];
24✔
2675
            payload.consensus_serialize(&mut payload_bytes).unwrap();
24✔
2676

2677
            let preamble = Preamble {
24✔
2678
                peer_version: 0x01020304,
24✔
2679
                network_id: 0x05060708,
24✔
2680
                seq: 0x090a0b0c,
24✔
2681
                burn_block_height: 0x00001122,
24✔
2682
                burn_block_hash: BurnchainHeaderHash([0x11; 32]),
24✔
2683
                burn_stable_block_height: 0x00001111,
24✔
2684
                burn_stable_block_hash: BurnchainHeaderHash([0x22; 32]),
24✔
2685
                additional_data: 0x33333333,
24✔
2686
                signature: MessageSignature::from_raw(&[0x44; 65]),
24✔
2687
                payload_len: (relayers_bytes.len() + payload_bytes.len()) as u32,
24✔
2688
            };
24✔
2689

2690
            let stacks_message = StacksMessage {
24✔
2691
                preamble: preamble.clone(),
24✔
2692
                relayers: maximal_relayers.clone(),
24✔
2693
                payload: payload.clone(),
24✔
2694
            };
24✔
2695

2696
            let mut stacks_message_bytes: Vec<u8> = vec![];
24✔
2697
            preamble
24✔
2698
                .consensus_serialize(&mut stacks_message_bytes)
24✔
2699
                .unwrap();
24✔
2700
            stacks_message_bytes.append(&mut relayers_bytes.clone());
24✔
2701
            stacks_message_bytes.append(&mut payload_bytes.clone());
24✔
2702

2703
            test_debug!(
24✔
2704
                "Test {}-byte relayer, {}-byte payload {:?}",
UNCOV
2705
                relayers_bytes.len(),
×
UNCOV
2706
                payload_bytes.len(),
×
UNCOV
2707
                &payload
×
2708
            );
2709
            check_codec_and_corruption::<StacksMessage>(&stacks_message, &stacks_message_bytes);
24✔
2710

2711
            // can't have too many relayers
2712
            let mut preamble_too_many_relayers = preamble.clone();
24✔
2713
            preamble_too_many_relayers.payload_len =
24✔
2714
                (too_many_relayer_bytes.len() + payload_bytes.len() + 1) as u32;
24✔
2715

2716
            let stacks_message_too_many_relayers = StacksMessage {
24✔
2717
                preamble: preamble_too_many_relayers.clone(),
24✔
2718
                relayers: too_many_relayers.clone(),
24✔
2719
                payload: payload.clone(),
24✔
2720
            };
24✔
2721
            assert!(check_deserialize_failure(&stacks_message_too_many_relayers));
24✔
2722
        }
2723
    }
1✔
2724

2725
    #[test]
2726
    fn codec_sign_and_verify() {
1✔
2727
        let privkey = Secp256k1PrivateKey::random();
1✔
2728
        let pubkey_buf =
1✔
2729
            StacksPublicKeyBuffer::from_public_key(&Secp256k1PublicKey::from_private(&privkey));
1✔
2730

2731
        let mut ping = StacksMessage::new(
1✔
2732
            PEER_VERSION_TESTNET,
2733
            0x9abcdef0,
2734
            12345,
2735
            &BurnchainHeaderHash([0x11; 32]),
1✔
2736
            12339,
2737
            &BurnchainHeaderHash([0x22; 32]),
1✔
2738
            StacksMessageType::Ping(PingData { nonce: 0x01020304 }),
1✔
2739
        );
2740

2741
        ping.sign(444, &privkey).unwrap();
1✔
2742
        ping.verify_secp256k1(&pubkey_buf).unwrap();
1✔
2743
    }
1✔
2744

2745
    #[test]
2746
    fn codec_stacks_public_key_roundtrip() {
1✔
2747
        for i in 0..100 {
100✔
2748
            let privkey = Secp256k1PrivateKey::random();
100✔
2749
            let pubkey = Secp256k1PublicKey::from_private(&privkey);
100✔
2750

2751
            let pubkey_buf = StacksPublicKeyBuffer::from_public_key(&pubkey);
100✔
2752
            let pubkey_2 = pubkey_buf.to_public_key().unwrap();
100✔
2753

2754
            assert_eq!(pubkey, pubkey_2);
100✔
2755
        }
2756
    }
1✔
2757

2758
    #[test]
2759
    fn blocks_inv_compress_bools() {
1✔
2760
        let block_flags = vec![
1✔
2761
            true, true, true, false, false, false, false, true, true, false, true,
2762
        ];
2763
        let block_bitvec = BlocksInvData::compress_bools(&block_flags);
1✔
2764
        assert_eq!(block_bitvec, vec![0x87, 0x05]);
1✔
2765

2766
        let short_block_flags = vec![true, false, true];
1✔
2767
        let short_block_bitvec = BlocksInvData::compress_bools(&short_block_flags);
1✔
2768
        assert_eq!(short_block_bitvec, vec![0x05]);
1✔
2769
    }
1✔
2770
}
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