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

stacks-network / stacks-core / 25801484257-1

13 May 2026 01:15PM UTC coverage: 85.648% (-0.06%) from 85.712%
25801484257-1

Pull #7183

github

2d7e6d
web-flow
Merge 420cb597a into 31276d071
Pull Request #7183: Fix problematic transaction handling

110 of 130 new or added lines in 7 files covered. (84.62%)

5464 existing lines in 98 files now uncovered.

188263 of 219809 relevant lines covered (85.65%)

18940648.33 hits per line

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

91.68
/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 {
3,019,752✔
48
    (bitlen / 8) + (if bitlen % 8 != 0 { 1 } else { 0 })
3,019,752✔
49
}
3,019,752✔
50

51
impl Preamble {
52
    /// Make an empty preamble with the given version and fork-set identifier, and payload length.
53
    pub fn new(
14,128,390✔
54
        peer_version: u32,
14,128,390✔
55
        network_id: u32,
14,128,390✔
56
        block_height: u64,
14,128,390✔
57
        burn_block_hash: &BurnchainHeaderHash,
14,128,390✔
58
        stable_block_height: u64,
14,128,390✔
59
        stable_burn_block_hash: &BurnchainHeaderHash,
14,128,390✔
60
        payload_len: u32,
14,128,390✔
61
    ) -> Preamble {
14,128,390✔
62
        Preamble {
14,128,390✔
63
            peer_version,
14,128,390✔
64
            network_id,
14,128,390✔
65
            seq: 0,
14,128,390✔
66
            burn_block_height: block_height,
14,128,390✔
67
            burn_block_hash: burn_block_hash.clone(),
14,128,390✔
68
            burn_stable_block_height: stable_block_height,
14,128,390✔
69
            burn_stable_block_hash: stable_burn_block_hash.clone(),
14,128,390✔
70
            additional_data: 0,
14,128,390✔
71
            signature: MessageSignature::empty(),
14,128,390✔
72
            payload_len,
14,128,390✔
73
        }
14,128,390✔
74
    }
14,128,390✔
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(
14,127,941✔
79
        &mut self,
14,127,941✔
80
        message_bits: &[u8],
14,127,941✔
81
        privkey: &Secp256k1PrivateKey,
14,127,941✔
82
    ) -> Result<(), net_error> {
14,127,941✔
83
        let mut digest_bits = [0u8; 32];
14,127,941✔
84
        let mut sha2 = Sha512_256::new();
14,127,941✔
85

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

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

94
        sha2.update(&preamble_bits[..]);
14,127,941✔
95
        sha2.update(message_bits);
14,127,941✔
96

97
        digest_bits.copy_from_slice(sha2.finalize().as_slice());
14,127,941✔
98

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

103
        self.signature = sig;
14,127,941✔
104
        Ok(())
14,127,941✔
105
    }
14,127,941✔
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(
14,057,192✔
110
        &mut self,
14,057,192✔
111
        message_bits: &[u8],
14,057,192✔
112
        pubkey: &Secp256k1PublicKey,
14,057,192✔
113
    ) -> Result<(), net_error> {
14,057,192✔
114
        let mut digest_bits = [0u8; 32];
14,057,192✔
115
        let mut sha2 = Sha512_256::new();
14,057,192✔
116

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

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

125
        sha2.update(&preamble_bits[..]);
14,057,192✔
126
        sha2.update(message_bits);
14,057,192✔
127

128
        digest_bits.copy_from_slice(sha2.finalize().as_slice());
14,057,192✔
129

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

134
        if res {
14,057,192✔
135
            Ok(())
14,057,191✔
136
        } else {
137
            Err(net_error::VerifyingError(
1✔
138
                "Invalid message signature".to_string(),
1✔
139
            ))
1✔
140
        }
141
    }
14,057,192✔
142
}
143

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

159
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Preamble, codec_error> {
14,109,274✔
160
        let peer_version: u32 = read_next(fd)?;
14,109,274✔
161
        let network_id: u32 = read_next(fd)?;
14,109,274✔
162
        let seq: u32 = read_next(fd)?;
14,109,274✔
163
        let burn_block_height: u64 = read_next(fd)?;
14,109,274✔
164
        let burn_block_hash: BurnchainHeaderHash = read_next(fd)?;
14,109,274✔
165
        let burn_stable_block_height: u64 = read_next(fd)?;
14,109,274✔
166
        let burn_stable_block_hash: BurnchainHeaderHash = read_next(fd)?;
14,109,274✔
167
        let additional_data: u32 = read_next(fd)?;
14,109,274✔
168
        let signature: MessageSignature = read_next(fd)?;
14,109,274✔
169
        let payload_len: u32 = read_next(fd)?;
14,109,274✔
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 {
14,109,273✔
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
        }
14,109,273✔
179

180
        if payload_len >= MAX_MESSAGE_LEN {
14,109,273✔
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
        }
14,109,273✔
187

188
        if burn_block_height <= burn_stable_block_height {
14,109,273✔
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
        }
14,109,273✔
199

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

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

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

231
        Ok(GetBlocksInv {
704,274✔
232
            consensus_hash,
704,274✔
233
            num_blocks,
704,274✔
234
        })
704,274✔
235
    }
704,276✔
236
}
237

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

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

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

257
        Ok(BlocksInvData {
693,603✔
258
            bitlen,
693,603✔
259
            block_bitvec,
693,603✔
260
            microblocks_bitvec,
693,603✔
261
        })
693,603✔
262
    }
693,608✔
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,414,380✔
276
        let bvl: u16 = bits
1,414,380✔
277
            .len()
1,414,380✔
278
            .try_into()
1,414,380✔
279
            .expect("FATAL: tried to compress more than u16::MAX bools");
1,414,380✔
280
        let mut bitvec = vec![0u8; bitvec_len(bvl) as usize];
1,414,380✔
281
        for (i, bit) in bits.iter().enumerate() {
23,829,474✔
282
            if *bit {
23,829,474✔
283
                bitvec[i / 8] |= 1u8 << (i % 8);
1,446,703✔
284
            }
22,384,113✔
285
        }
286
        bitvec
1,414,380✔
287
    }
1,414,380✔
288

289
    pub fn has_ith_block(&self, block_index: u16) -> bool {
52,316✔
290
        if block_index >= self.bitlen {
52,316✔
291
            return false;
3,650✔
292
        }
48,666✔
293

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

302
    pub fn has_ith_microblock_stream(&self, block_index: u16) -> bool {
52,296✔
303
        if block_index >= self.bitlen {
52,296✔
304
            return false;
3,651✔
305
        }
48,645✔
306

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

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

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

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

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

341
impl NakamotoInvData {
342
    pub fn try_from(bits: &[bool]) -> Result<Self, codec_error> {
263,471✔
343
        Ok(Self {
344
            tenures: BitVec::<2100>::try_from(bits).map_err(|e| {
263,471✔
UNCOV
345
                codec_error::SerializeError(format!(
×
346
                    "Could not serialize vec of {} bools: {}",
×
347
                    bits.len(),
×
348
                    e
×
349
                ))
×
350
            })?,
×
351
        })
352
    }
263,471✔
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> {
18,376✔
362
        write_next(fd, &self.blocks)?;
18,376✔
363
        Ok(())
18,376✔
364
    }
18,376✔
365

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

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

383
            present.insert(block.block_id());
9,456✔
384
        }
385

386
        Ok(NakamotoBlocksData { blocks })
9,096✔
387
    }
9,096✔
388
}
389

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

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

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

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

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

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

442
        let pox_bitvec: Vec<u8> = read_next_exact::<_, u8>(fd, bitvec_len(bitlen).into())?;
218,160✔
443
        Ok(PoxInvData { bitlen, pox_bitvec })
218,156✔
444
    }
218,162✔
445
}
446

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

453
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<BlocksAvailableData, codec_error> {
11,656✔
454
        let available: Vec<(ConsensusHash, BurnchainHeaderHash)> =
11,653✔
455
            read_next_at_most::<_, (ConsensusHash, BurnchainHeaderHash)>(
11,656✔
456
                fd,
11,656✔
457
                BLOCKS_AVAILABLE_MAX_LEN,
458
            )?;
3✔
459
        Ok(BlocksAvailableData { available })
11,653✔
460
    }
11,656✔
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> {
40,600✔
484
        write_next(fd, &self.0)?;
40,600✔
485
        write_next(fd, &self.1)?;
40,600✔
486
        Ok(())
40,600✔
487
    }
40,600✔
488

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

496
        Ok(BlocksDatum(ch, block))
20,300✔
497
    }
20,300✔
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> {
40,420✔
512
        write_next(fd, &self.blocks)?;
40,420✔
513
        Ok(())
40,420✔
514
    }
40,420✔
515

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

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

533
            present.insert(consensus_hash.clone());
20,300✔
534
        }
535

536
        Ok(BlocksData { blocks })
20,210✔
537
    }
20,210✔
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 {
10,962,140✔
564
        NeighborAddress {
10,962,140✔
565
            addrbytes: n.addr.addrbytes.clone(),
10,962,140✔
566
            port: n.addr.port,
10,962,140✔
567
            public_key_hash: Hash160::from_node_public_key(&n.public_key),
10,962,140✔
568
        }
10,962,140✔
569
    }
10,962,140✔
570
}
571

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

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

585
        Ok(NeighborAddress {
618,133✔
586
            addrbytes,
618,133✔
587
            port,
618,133✔
588
            public_key_hash,
618,133✔
589
        })
618,133✔
590
    }
618,136✔
591
}
592

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

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

607
impl HandshakeData {
608
    pub fn from_local_peer(local_peer: &LocalPeer) -> HandshakeData {
825,163✔
609
        let (addrbytes, port) = match local_peer.public_ip_address {
825,163✔
610
            Some((ref public_addrbytes, ref port)) => (public_addrbytes.clone(), *port),
419,331✔
611
            None => (local_peer.addrbytes.clone(), local_peer.port),
405,832✔
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() {
825,163✔
616
            local_peer.data_url.clone()
825,163✔
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 {
825,163✔
626
            addrbytes,
825,163✔
627
            port,
825,163✔
628
            services: local_peer.services,
825,163✔
629
            node_public_key: StacksPublicKeyBuffer::from_public_key(
825,163✔
630
                &Secp256k1PublicKey::from_private(&local_peer.private_key),
825,163✔
631
            ),
825,163✔
632
            expire_block_height: local_peer.private_key_expire,
825,163✔
633
            data_url,
825,163✔
634
        }
825,163✔
635
    }
825,163✔
636
}
637

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

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

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

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

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

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

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

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

711
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<NackData, codec_error> {
482,240✔
712
        let error_code: u32 = read_next(fd)?;
482,240✔
713
        Ok(NackData { error_code })
482,238✔
714
    }
482,240✔
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,442✔
757
        write_next(fd, &self.addrbytes)?;
1,442✔
758
        write_next(fd, &self.port)?;
1,442✔
759
        write_next(fd, &self.nonce)?;
1,442✔
760
        Ok(())
1,442✔
761
    }
1,442✔
762

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

930
impl StacksMessageType {
931
    pub fn get_message_id(&self) -> StacksMessageID {
42,354,527✔
932
        match *self {
42,354,527✔
933
            StacksMessageType::Handshake(ref _m) => StacksMessageID::Handshake,
1,239,324✔
934
            StacksMessageType::HandshakeAccept(ref _m) => StacksMessageID::HandshakeAccept,
52,076✔
935
            StacksMessageType::HandshakeReject => StacksMessageID::HandshakeReject,
2,499✔
936
            StacksMessageType::GetNeighbors => StacksMessageID::GetNeighbors,
1,014,073✔
937
            StacksMessageType::Neighbors(ref _m) => StacksMessageID::Neighbors,
1,013,803✔
938
            StacksMessageType::GetPoxInv(ref _m) => StacksMessageID::GetPoxInv,
654,725✔
939
            StacksMessageType::PoxInv(ref _m) => StacksMessageID::PoxInv,
654,608✔
940
            StacksMessageType::GetBlocksInv(ref _m) => StacksMessageID::GetBlocksInv,
2,112,827✔
941
            StacksMessageType::BlocksInv(ref _m) => StacksMessageID::BlocksInv,
2,080,946✔
942
            StacksMessageType::BlocksAvailable(ref _m) => StacksMessageID::BlocksAvailable,
34,953✔
943
            StacksMessageType::MicroblocksAvailable(ref _m) => {
3✔
944
                StacksMessageID::MicroblocksAvailable
3✔
945
            }
946
            StacksMessageType::Blocks(ref _m) => StacksMessageID::Blocks,
60,630✔
UNCOV
947
            StacksMessageType::Microblocks(ref _m) => StacksMessageID::Microblocks,
×
948
            StacksMessageType::Transaction(ref _m) => StacksMessageID::Transaction,
16,260✔
949
            StacksMessageType::Nack(ref _m) => StacksMessageID::Nack,
1,447,271✔
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,161✔
953
            StacksMessageType::NatPunchReply(ref _m) => StacksMessageID::NatPunchReply,
2,160✔
954
            StacksMessageType::StackerDBHandshakeAccept(ref _h, ref _m) => {
1,182,764✔
955
                StacksMessageID::StackerDBHandshakeAccept
1,182,764✔
956
            }
957
            StacksMessageType::StackerDBGetChunkInv(ref _m) => {
13,342,605✔
958
                StacksMessageID::StackerDBGetChunkInv
13,342,605✔
959
            }
960
            StacksMessageType::StackerDBChunkInv(ref _m) => StacksMessageID::StackerDBChunkInv,
13,539,388✔
961
            StacksMessageType::StackerDBGetChunk(ref _m) => StacksMessageID::StackerDBGetChunk,
292,538✔
962
            StacksMessageType::StackerDBChunk(ref _m) => StacksMessageID::StackerDBChunk,
288,982✔
963
            StacksMessageType::StackerDBPushChunk(ref _m) => StacksMessageID::StackerDBPushChunk,
1,664,234✔
964
            StacksMessageType::GetNakamotoInv(ref _m) => StacksMessageID::GetNakamotoInv,
818,642✔
965
            StacksMessageType::NakamotoInv(ref _m) => StacksMessageID::NakamotoInv,
789,484✔
966
            StacksMessageType::NakamotoBlocks(ref _m) => StacksMessageID::NakamotoBlocks,
27,472✔
967
        }
968
    }
42,354,527✔
969

970
    pub fn get_message_name(&self) -> &'static str {
19,973,456✔
971
        match *self {
19,973,456✔
972
            StacksMessageType::Handshake(ref _m) => "Handshake",
413,310✔
973
            StacksMessageType::HandshakeAccept(ref _m) => "HandshakeAccept",
17,264✔
974
            StacksMessageType::HandshakeReject => "HandshakeReject",
832✔
975
            StacksMessageType::GetNeighbors => "GetNeighbors",
338,048✔
976
            StacksMessageType::Neighbors(ref _m) => "Neighbors",
337,852✔
977
            StacksMessageType::GetPoxInv(ref _m) => "GetPoxInv",
218,248✔
978
            StacksMessageType::PoxInv(ref _m) => "PoxInv",
436,379✔
979
            StacksMessageType::GetBlocksInv(ref _m) => "GetBlocksInv",
704,276✔
980
            StacksMessageType::BlocksInv(ref _m) => "BlocksInv",
1,387,272✔
981
            StacksMessageType::BlocksAvailable(ref _m) => "BlocksAvailable",
11,650✔
UNCOV
982
            StacksMessageType::MicroblocksAvailable(ref _m) => "MicroblocksAvailable",
×
983
            StacksMessageType::Blocks(ref _m) => "Blocks",
20,210✔
984
            StacksMessageType::Microblocks(ref _m) => "Microblocks",
×
985
            StacksMessageType::Transaction(ref _m) => "Transaction",
5,420✔
986
            StacksMessageType::Nack(ref _m) => "Nack",
964,747✔
987
            StacksMessageType::Ping(ref _m) => "Ping",
5,007✔
988
            StacksMessageType::Pong(ref _m) => "Pong",
6✔
989
            StacksMessageType::NatPunchRequest(ref _m) => "NatPunchRequest",
720✔
990
            StacksMessageType::NatPunchReply(ref _m) => "NatPunchReply",
719✔
991
            StacksMessageType::StackerDBHandshakeAccept(ref _h, ref _m) => {
393,896✔
992
                "StackerDBHandshakeAccept"
393,896✔
993
            }
994
            StacksMessageType::StackerDBGetChunkInv(ref _m) => "StackerDBGetChunkInv",
4,450,384✔
995
            StacksMessageType::StackerDBChunkInv(ref _m) => "StackerDBChunkInv",
8,614,015✔
996
            StacksMessageType::StackerDBGetChunk(ref _m) => "StackerDBGetChunk",
97,526✔
997
            StacksMessageType::StackerDBChunk(ref _m) => "StackerDBChunk",
192,636✔
998
            StacksMessageType::StackerDBPushChunk(ref _m) => "StackerDBPushChunk",
554,916✔
999
            StacksMessageType::GetNakamotoInv(ref _m) => "GetNakamotoInv",
272,892✔
1000
            StacksMessageType::NakamotoInv(ref _m) => "NakamotoInv",
526,043✔
1001
            StacksMessageType::NakamotoBlocks(ref _m) => "NakamotoBlocks",
9,188✔
1002
        }
1003
    }
19,973,456✔
1004

1005
    pub fn get_message_description(&self) -> String {
21,773,498✔
1006
        match *self {
21,773,498✔
1007
            StacksMessageType::Handshake(ref m) => {
412,668✔
1008
                format!("Handshake({})", &to_hex(&m.node_public_key.to_bytes()))
412,668✔
1009
            }
1010
            StacksMessageType::HandshakeAccept(ref m) => format!(
34,668✔
1011
                "HandshakeAccept({},{})",
1012
                &to_hex(&m.handshake.node_public_key.to_bytes()),
34,668✔
1013
                m.heartbeat_interval
1014
            ),
1015
            StacksMessageType::HandshakeReject => "HandshakeReject".to_string(),
1,664✔
1016
            StacksMessageType::GetNeighbors => "GetNeighbors".to_string(),
337,974✔
1017
            StacksMessageType::Neighbors(ref m) => format!("Neighbors({:?})", m.neighbors),
675,826✔
1018
            StacksMessageType::GetPoxInv(ref m) => {
218,226✔
1019
                format!("GetPoxInv({},{}))", &m.consensus_hash, m.num_cycles)
218,226✔
1020
            }
1021
            StacksMessageType::PoxInv(ref m) => {
436,379✔
1022
                format!("PoxInv({},{:?})", &m.bitlen, &m.pox_bitvec)
436,379✔
1023
            }
1024
            StacksMessageType::GetBlocksInv(ref m) => {
704,272✔
1025
                format!("GetBlocksInv({},{})", &m.consensus_hash, m.num_blocks)
704,272✔
1026
            }
1027
            StacksMessageType::BlocksInv(ref m) => format!(
1,387,272✔
1028
                "BlocksInv({},{:?},{:?})",
1029
                m.bitlen, &m.block_bitvec, &m.microblocks_bitvec
1,387,272✔
1030
            ),
1031
            StacksMessageType::BlocksAvailable(ref m) => {
23,300✔
1032
                format!("BlocksAvailable({:?})", &m.available)
23,300✔
1033
            }
UNCOV
1034
            StacksMessageType::MicroblocksAvailable(ref m) => {
×
UNCOV
1035
                format!("MicroblocksAvailable({:?})", &m.available)
×
1036
            }
1037
            StacksMessageType::Blocks(ref m) => format!(
40,421✔
1038
                "Blocks({:?})",
1039
                m.blocks
40,421✔
1040
                    .iter()
40,421✔
1041
                    .map(|BlocksDatum(ch, blk)| (ch.clone(), blk.block_hash()))
40,601✔
1042
                    .collect::<Vec<(ConsensusHash, BlockHeaderHash)>>()
40,421✔
1043
            ),
1044
            StacksMessageType::Microblocks(ref m) => format!(
11✔
1045
                "Microblocks({},{:?})",
1046
                &m.index_anchor_block,
11✔
1047
                m.microblocks
11✔
1048
                    .iter()
11✔
1049
                    .map(|mblk| mblk.block_hash())
11✔
1050
                    .collect::<Vec<BlockHeaderHash>>()
11✔
1051
            ),
1052
            StacksMessageType::Transaction(ref m) => format!("Transaction({})", m.txid()),
46,872✔
1053
            StacksMessageType::Nack(ref m) => format!("Nack({})", m.error_code),
964,749✔
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),
719✔
1057
            StacksMessageType::NatPunchReply(ref m) => {
1,438✔
1058
                format!("NatPunchReply({},{}:{})", m.nonce, &m.addrbytes, m.port)
1,438✔
1059
            }
1060
            StacksMessageType::StackerDBHandshakeAccept(ref h, ref m) => {
788,328✔
1061
                format!(
788,328✔
1062
                    "StackerDBHandshakeAccept({},{},{:?})",
1063
                    &to_hex(&h.handshake.node_public_key.to_bytes()),
788,328✔
1064
                    &m.rc_consensus_hash,
788,328✔
1065
                    &m.smart_contracts
788,328✔
1066
                )
1067
            }
1068
            StacksMessageType::StackerDBGetChunkInv(ref m) => {
4,441,834✔
1069
                format!(
4,441,834✔
1070
                    "StackerDBGetChunkInv({}.{})",
1071
                    &m.contract_id, &m.rc_consensus_hash
4,441,834✔
1072
                )
1073
            }
1074
            StacksMessageType::StackerDBChunkInv(ref m) => {
8,488,788✔
1075
                format!("StackerDBChunkInv({:?})", &m.slot_versions)
8,488,788✔
1076
            }
1077
            StacksMessageType::StackerDBGetChunk(ref m) => {
97,483✔
1078
                format!(
97,483✔
1079
                    "StackerDBGetChunk({},{},{},{})",
1080
                    &m.contract_id, &m.rc_consensus_hash, m.slot_id, m.slot_version
97,483✔
1081
                )
1082
            }
1083
            StacksMessageType::StackerDBChunk(ref m) => {
192,636✔
1084
                format!(
192,636✔
1085
                    "StackerDBChunk({},{},{},sz={})",
1086
                    m.slot_id,
1087
                    m.slot_version,
1088
                    &m.sig,
192,636✔
1089
                    m.data.len()
192,636✔
1090
                )
1091
            }
1092
            StacksMessageType::StackerDBPushChunk(ref m) => {
1,569,543✔
1093
                format!(
1,569,543✔
1094
                    "StackerDBPushChunk({},{},{},{},{},sz={})",
1095
                    &m.contract_id,
1,569,543✔
1096
                    &m.rc_consensus_hash,
1,569,543✔
1097
                    m.chunk_data.slot_id,
1098
                    m.chunk_data.slot_version,
1099
                    &m.chunk_data.sig,
1,569,543✔
1100
                    m.chunk_data.data.len()
1,569,543✔
1101
                )
1102
            }
1103
            StacksMessageType::GetNakamotoInv(ref m) => {
272,597✔
1104
                format!("GetNakamotoInv({})", &m.consensus_hash,)
272,597✔
1105
            }
1106
            StacksMessageType::NakamotoInv(ref m) => {
526,043✔
1107
                format!("NakamotoInv({:?})", &m.tenures)
526,043✔
1108
            }
1109
            StacksMessageType::NakamotoBlocks(ref m) => {
109,766✔
1110
                format!(
109,766✔
1111
                    "NakamotoBlocks({:?})",
1112
                    m.blocks
109,766✔
1113
                        .iter()
109,766✔
1114
                        .map(|block| block.block_id())
110,491✔
1115
                        .collect::<Vec<_>>()
109,766✔
1116
                )
1117
            }
1118
        }
1119
    }
21,773,498✔
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> {
14,109,248✔
1128
        let as_u8: u8 = read_next(fd)?;
14,109,248✔
1129
        let id = match as_u8 {
14,109,246✔
1130
            x if x == StacksMessageID::Handshake as u8 => StacksMessageID::Handshake,
14,109,246✔
1131
            x if x == StacksMessageID::HandshakeAccept as u8 => StacksMessageID::HandshakeAccept,
13,696,284✔
1132
            x if x == StacksMessageID::HandshakeReject as u8 => StacksMessageID::HandshakeReject,
13,679,018✔
1133
            x if x == StacksMessageID::GetNeighbors as u8 => StacksMessageID::GetNeighbors,
13,678,185✔
1134
            x if x == StacksMessageID::Neighbors as u8 => StacksMessageID::Neighbors,
13,340,209✔
1135
            x if x == StacksMessageID::GetPoxInv as u8 => StacksMessageID::GetPoxInv,
13,002,355✔
1136
            x if x == StacksMessageID::PoxInv as u8 => StacksMessageID::PoxInv,
12,784,107✔
1137
            x if x == StacksMessageID::GetBlocksInv as u8 => StacksMessageID::GetBlocksInv,
12,565,952✔
1138
            x if x == StacksMessageID::BlocksInv as u8 => StacksMessageID::BlocksInv,
11,861,678✔
1139
            x if x == StacksMessageID::BlocksAvailable as u8 => StacksMessageID::BlocksAvailable,
11,168,075✔
1140
            x if x == StacksMessageID::MicroblocksAvailable as u8 => {
11,156,423✔
1141
                StacksMessageID::MicroblocksAvailable
2✔
1142
            }
1143
            x if x == StacksMessageID::Blocks as u8 => StacksMessageID::Blocks,
11,156,421✔
1144
            x if x == StacksMessageID::Microblocks as u8 => StacksMessageID::Microblocks,
11,136,211✔
1145
            x if x == StacksMessageID::Transaction as u8 => StacksMessageID::Transaction,
11,136,211✔
1146
            x if x == StacksMessageID::Nack as u8 => StacksMessageID::Nack,
11,130,791✔
1147
            x if x == StacksMessageID::Ping as u8 => StacksMessageID::Ping,
10,648,553✔
1148
            x if x == StacksMessageID::Pong as u8 => StacksMessageID::Pong,
10,638,533✔
1149
            x if x == StacksMessageID::NatPunchRequest as u8 => StacksMessageID::NatPunchRequest,
10,638,525✔
1150
            x if x == StacksMessageID::NatPunchReply as u8 => StacksMessageID::NatPunchReply,
10,637,803✔
1151
            x if x == StacksMessageID::StackerDBHandshakeAccept as u8 => {
10,637,082✔
1152
                StacksMessageID::StackerDBHandshakeAccept
394,043✔
1153
            }
1154
            x if x == StacksMessageID::StackerDBGetChunkInv as u8 => {
10,243,039✔
1155
                StacksMessageID::StackerDBGetChunkInv
4,441,836✔
1156
            }
1157
            x if x == StacksMessageID::StackerDBChunkInv as u8 => {
5,801,203✔
1158
                StacksMessageID::StackerDBChunkInv
4,508,571✔
1159
            }
1160
            x if x == StacksMessageID::StackerDBGetChunk as u8 => {
1,292,632✔
1161
                StacksMessageID::StackerDBGetChunk
97,485✔
1162
            }
1163
            x if x == StacksMessageID::StackerDBChunk as u8 => StacksMessageID::StackerDBChunk,
1,195,147✔
1164
            x if x == StacksMessageID::StackerDBPushChunk as u8 => {
1,098,852✔
1165
                StacksMessageID::StackerDBPushChunk
554,401✔
1166
            }
1167
            x if x == StacksMessageID::GetNakamotoInv as u8 => StacksMessageID::GetNakamotoInv,
544,451✔
1168
            x if x == StacksMessageID::NakamotoInv as u8 => StacksMessageID::NakamotoInv,
271,842✔
1169
            x if x == StacksMessageID::NakamotoBlocks as u8 => StacksMessageID::NakamotoBlocks,
9,096✔
1170
            _ => {
UNCOV
1171
                return Err(codec_error::DeserializeError(
×
UNCOV
1172
                    "Unknown message ID".to_string(),
×
1173
                ));
×
1174
            }
1175
        };
1176
        Ok(id)
14,109,246✔
1177
    }
14,109,248✔
1178
}
1179

1180
impl StacksMessageCodec for StacksMessageType {
1181
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
28,270,625✔
1182
        write_next(fd, &(self.get_message_id() as u8))?;
28,270,625✔
1183
        match *self {
28,270,625✔
1184
            StacksMessageType::Handshake(ref m) => write_next(fd, m)?,
841,331✔
1185
            StacksMessageType::HandshakeAccept(ref m) => write_next(fd, m)?,
34,813✔
1186
            StacksMessageType::HandshakeReject => {}
1,667✔
1187
            StacksMessageType::GetNeighbors => {}
676,099✔
1188
            StacksMessageType::Neighbors(ref m) => write_next(fd, m)?,
675,951✔
1189
            StacksMessageType::GetPoxInv(ref m) => write_next(fd, m)?,
436,499✔
1190
            StacksMessageType::PoxInv(ref m) => write_next(fd, m)?,
436,455✔
1191
            StacksMessageType::GetBlocksInv(ref m) => write_next(fd, m)?,
1,408,555✔
1192
            StacksMessageType::BlocksInv(ref m) => write_next(fd, m)?,
1,387,345✔
1193
            StacksMessageType::BlocksAvailable(ref m) => write_next(fd, m)?,
23,303✔
1194
            StacksMessageType::MicroblocksAvailable(ref m) => write_next(fd, m)?,
3✔
1195
            StacksMessageType::Blocks(ref m) => write_next(fd, m)?,
40,420✔
UNCOV
1196
            StacksMessageType::Microblocks(ref m) => write_next(fd, m)?,
×
1197
            StacksMessageType::Transaction(ref m) => write_next(fd, m)?,
10,840✔
1198
            StacksMessageType::Nack(ref m) => write_next(fd, m)?,
965,035✔
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,443✔
1202
            StacksMessageType::NatPunchReply(ref m) => write_next(fd, m)?,
1,441✔
1203
            StacksMessageType::StackerDBHandshakeAccept(ref h, ref m) => {
788,869✔
1204
                write_next(fd, h)?;
788,869✔
1205
                write_next(fd, m)?
788,869✔
1206
            }
1207
            StacksMessageType::StackerDBGetChunkInv(ref m) => write_next(fd, m)?,
8,900,771✔
1208
            StacksMessageType::StackerDBChunkInv(ref m) => write_next(fd, m)?,
9,030,819✔
1209
            StacksMessageType::StackerDBGetChunk(ref m) => write_next(fd, m)?,
195,055✔
1210
            StacksMessageType::StackerDBChunk(ref m) => write_next(fd, m)?,
192,689✔
1211
            StacksMessageType::StackerDBPushChunk(ref m) => write_next(fd, m)?,
1,109,835✔
1212
            StacksMessageType::GetNakamotoInv(ref m) => write_next(fd, m)?,
546,045✔
1213
            StacksMessageType::NakamotoInv(ref m) => write_next(fd, m)?,
526,879✔
1214
            StacksMessageType::NakamotoBlocks(ref m) => write_next(fd, m)?,
18,376✔
1215
        }
1216
        Ok(())
28,270,625✔
1217
    }
28,270,625✔
1218

1219
    fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<StacksMessageType, codec_error> {
14,109,248✔
1220
        let message_id: StacksMessageID = read_next(fd)?;
14,109,248✔
1221
        let message = match message_id {
14,109,246✔
1222
            StacksMessageID::Handshake => {
1223
                let m: HandshakeData = read_next(fd)?;
412,962✔
1224
                StacksMessageType::Handshake(m)
412,961✔
1225
            }
1226
            StacksMessageID::HandshakeAccept => {
1227
                let m: HandshakeAcceptData = read_next(fd)?;
17,266✔
1228
                StacksMessageType::HandshakeAccept(m)
17,265✔
1229
            }
1230
            StacksMessageID::HandshakeReject => StacksMessageType::HandshakeReject,
833✔
1231
            StacksMessageID::GetNeighbors => StacksMessageType::GetNeighbors,
337,976✔
1232
            StacksMessageID::Neighbors => {
1233
                let m: NeighborsData = read_next(fd)?;
337,854✔
1234
                StacksMessageType::Neighbors(m)
337,853✔
1235
            }
1236
            StacksMessageID::GetPoxInv => {
1237
                let m: GetPoxInv = read_next(fd)?;
218,248✔
1238
                StacksMessageType::GetPoxInv(m)
218,247✔
1239
            }
1240
            StacksMessageID::PoxInv => {
1241
                let m: PoxInvData = read_next(fd)?;
218,155✔
1242
                StacksMessageType::PoxInv(m)
218,154✔
1243
            }
1244
            StacksMessageID::GetBlocksInv => {
1245
                let m: GetBlocksInv = read_next(fd)?;
704,274✔
1246
                StacksMessageType::GetBlocksInv(m)
704,273✔
1247
            }
1248
            StacksMessageID::BlocksInv => {
1249
                let m: BlocksInvData = read_next(fd)?;
693,603✔
1250
                StacksMessageType::BlocksInv(m)
693,602✔
1251
            }
1252
            StacksMessageID::BlocksAvailable => {
1253
                let m: BlocksAvailableData = read_next(fd)?;
11,652✔
1254
                StacksMessageType::BlocksAvailable(m)
11,651✔
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)?;
20,210✔
1262
                StacksMessageType::Blocks(m)
20,210✔
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)?;
5,420✔
1270
                StacksMessageType::Transaction(m)
5,420✔
1271
            }
1272
            StacksMessageID::Nack => {
1273
                let m: NackData = read_next(fd)?;
482,238✔
1274
                StacksMessageType::Nack(m)
482,237✔
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)?;
722✔
1286
                StacksMessageType::NatPunchRequest(nonce)
721✔
1287
            }
1288
            StacksMessageID::NatPunchReply => {
1289
                let m: NatPunchData = read_next(fd)?;
721✔
1290
                StacksMessageType::NatPunchReply(m)
720✔
1291
            }
1292
            StacksMessageID::StackerDBHandshakeAccept => {
1293
                let h: HandshakeAcceptData = read_next(fd)?;
394,043✔
1294
                let m: StackerDBHandshakeData = read_next(fd)?;
394,043✔
1295
                StacksMessageType::StackerDBHandshakeAccept(h, m)
394,042✔
1296
            }
1297
            StacksMessageID::StackerDBGetChunkInv => {
1298
                let m: StackerDBGetChunkInvData = read_next(fd)?;
4,441,836✔
1299
                StacksMessageType::StackerDBGetChunkInv(m)
4,441,835✔
1300
            }
1301
            StacksMessageID::StackerDBChunkInv => {
1302
                let m: StackerDBChunkInvData = read_next(fd)?;
4,508,571✔
1303
                StacksMessageType::StackerDBChunkInv(m)
4,508,570✔
1304
            }
1305
            StacksMessageID::StackerDBGetChunk => {
1306
                let m: StackerDBGetChunkData = read_next(fd)?;
97,485✔
1307
                StacksMessageType::StackerDBGetChunk(m)
97,484✔
1308
            }
1309
            StacksMessageID::StackerDBChunk => {
1310
                let m: StackerDBChunkData = read_next(fd)?;
96,295✔
1311
                StacksMessageType::StackerDBChunk(m)
96,294✔
1312
            }
1313
            StacksMessageID::StackerDBPushChunk => {
1314
                let m: StackerDBPushChunkData = read_next(fd)?;
554,401✔
1315
                StacksMessageType::StackerDBPushChunk(m)
554,400✔
1316
            }
1317
            StacksMessageID::GetNakamotoInv => {
1318
                let m: GetNakamotoInvData = read_next(fd)?;
272,609✔
1319
                StacksMessageType::GetNakamotoInv(m)
272,608✔
1320
            }
1321
            StacksMessageID::NakamotoInv => {
1322
                let m: NakamotoInvData = read_next(fd)?;
262,746✔
1323
                StacksMessageType::NakamotoInv(m)
262,745✔
1324
            }
1325
            StacksMessageID::NakamotoBlocks => {
1326
                let m: NakamotoBlocksData = read_next(fd)?;
9,096✔
1327
                StacksMessageType::NakamotoBlocks(m)
9,096✔
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)
14,109,224✔
1336
    }
14,109,248✔
1337
}
1338

1339
impl StacksMessageCodec for StacksMessage {
1340
    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
14,127,983✔
1341
        write_next(fd, &self.preamble)?;
14,127,983✔
1342
        write_next(fd, &self.relayers)?;
14,127,983✔
1343
        write_next(fd, &self.payload)?;
14,127,983✔
1344
        Ok(())
14,127,983✔
1345
    }
14,127,983✔
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(
14,128,390✔
1370
        peer_version: u32,
14,128,390✔
1371
        network_id: u32,
14,128,390✔
1372
        block_height: u64,
14,128,390✔
1373
        burn_header_hash: &BurnchainHeaderHash,
14,128,390✔
1374
        stable_block_height: u64,
14,128,390✔
1375
        stable_burn_header_hash: &BurnchainHeaderHash,
14,128,390✔
1376
        message: StacksMessageType,
14,128,390✔
1377
    ) -> StacksMessage {
14,128,390✔
1378
        let preamble = Preamble::new(
14,128,390✔
1379
            peer_version,
14,128,390✔
1380
            network_id,
14,128,390✔
1381
            block_height,
14,128,390✔
1382
            burn_header_hash,
14,128,390✔
1383
            stable_block_height,
14,128,390✔
1384
            stable_burn_header_hash,
14,128,390✔
1385
            0,
1386
        );
1387
        StacksMessage {
14,128,390✔
1388
            preamble,
14,128,390✔
1389
            relayers: vec![],
14,128,390✔
1390
            payload: message,
14,128,390✔
1391
        }
14,128,390✔
1392
    }
14,128,390✔
1393

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

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

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

1428
        self.preamble.payload_len = message_bits.len() as u32;
14,127,941✔
1429
        self.preamble.sign(&message_bits[..], private_key)
14,127,941✔
1430
    }
14,127,941✔
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> {
13,672,011✔
1435
        if !self.relayers.is_empty() {
13,672,011✔
UNCOV
1436
            return Err(net_error::InvalidMessage);
×
1437
        }
13,672,011✔
1438
        self.preamble.seq = seq;
13,672,011✔
1439
        self.do_sign(private_key)
13,672,011✔
1440
    }
13,672,011✔
1441

1442
    /// Sign the StacksMessage and add ourselves as a relayer.
1443
    pub fn sign_relay(
455,932✔
1444
        &mut self,
455,932✔
1445
        private_key: &Secp256k1PrivateKey,
455,932✔
1446
        our_seq: u32,
455,932✔
1447
        our_addr: &NeighborAddress,
455,932✔
1448
    ) -> Result<(), net_error> {
455,932✔
1449
        if self.relayers.len() >= MAX_RELAYERS_LEN as usize {
455,932✔
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
        }
455,932✔
1456

1457
        // don't sign if signed more than once
1458
        for relayer in &self.relayers {
455,934✔
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 {
455,930✔
1471
            peer: our_addr.clone(),
455,930✔
1472
            seq: self.preamble.seq,
455,930✔
1473
        };
455,930✔
1474

1475
        self.relayers.push(our_relay);
455,930✔
1476
        self.preamble.seq = our_seq;
455,930✔
1477
        self.do_sign(private_key)
455,930✔
1478
    }
455,932✔
1479

1480
    pub fn deserialize_body<R: Read>(
14,109,038✔
1481
        fd: &mut R,
14,109,038✔
1482
    ) -> Result<(Vec<RelayData>, StacksMessageType), net_error> {
14,109,038✔
1483
        let relayers: Vec<RelayData> = read_next_at_most::<_, RelayData>(fd, MAX_RELAYERS_LEN)?;
14,109,038✔
1484
        let payload: StacksMessageType = read_next(fd)?;
14,109,038✔
1485
        Ok((relayers, payload))
14,109,038✔
1486
    }
14,109,038✔
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,677✔
1493
        let secp256k1_pubkey = public_key
14,677✔
1494
            .to_public_key()
14,677✔
1495
            .map_err(|e| net_error::DeserializeError(e.into()))?;
14,677✔
1496

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

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

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

1511
    fn get_message_name(&self) -> &'static str {
13,783,128✔
1512
        self.payload.get_message_name()
13,783,128✔
1513
    }
13,783,128✔
1514
}
1515

1516
impl StacksP2P {
1517
    pub fn new() -> StacksP2P {
28,187✔
1518
        StacksP2P {}
28,187✔
1519
    }
28,187✔
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 {
14,111,916✔
1528
        PREAMBLE_ENCODED_SIZE as usize
14,111,916✔
1529
    }
14,111,916✔
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> {
42,345,442✔
1533
        Some(preamble.payload_len as usize)
42,345,442✔
1534
    }
42,345,442✔
1535

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

1542
        let preamble: Preamble = read_next(&mut preamble_bytes)?;
14,109,038✔
1543
        Ok((preamble, PREAMBLE_ENCODED_SIZE as usize))
14,109,038✔
1544
    }
14,111,916✔
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(
14,109,038✔
1560
        &mut self,
14,109,038✔
1561
        preamble: &Preamble,
14,109,038✔
1562
        bytes: &[u8],
14,109,038✔
1563
    ) -> Result<(StacksMessage, usize), net_error> {
14,109,038✔
1564
        let preamble_bytes = bytes.get(..preamble.payload_len as usize).ok_or_else(|| {
14,109,038✔
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);
14,109,038✔
1569
        let (relayers, payload) = StacksMessage::deserialize_body(&mut cursor)?;
14,109,038✔
1570
        let message = StacksMessage {
14,109,038✔
1571
            preamble: preamble.clone(),
14,109,038✔
1572
            relayers,
14,109,038✔
1573
            payload,
14,109,038✔
1574
        };
14,109,038✔
1575
        Ok((message, cursor.position() as usize))
14,109,038✔
1576
    }
14,109,038✔
1577

1578
    fn verify_payload_bytes(
14,042,515✔
1579
        &mut self,
14,042,515✔
1580
        key: &StacksPublicKey,
14,042,515✔
1581
        preamble: &Preamble,
14,042,515✔
1582
        bytes: &[u8],
14,042,515✔
1583
    ) -> Result<(), Error> {
14,042,515✔
1584
        let preamble_bytes = bytes.get(..preamble.payload_len as usize).ok_or_else(|| {
14,042,515✔
UNCOV
1585
            Error::UnderflowError("Not enough bytes to form a StacksMessage".to_string())
×
UNCOV
1586
        })?;
×
1587
        preamble.clone().verify(preamble_bytes, key).map(|_m| ())
14,042,515✔
1588
    }
14,042,515✔
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
    pub fn check_codec_and_corruption<T: StacksMessageCodec + fmt::Debug + Clone + PartialEq>(
5,190✔
1661
        obj: &T,
5,190✔
1662
        bytes: &[u8],
5,190✔
1663
    ) {
5,190✔
1664
        // obj should serialize to bytes
1665
        let mut write_buf: Vec<u8> = Vec::with_capacity(bytes.len());
5,190✔
1666
        obj.consensus_serialize(&mut write_buf).unwrap();
5,190✔
1667
        assert_eq!(write_buf, *bytes);
5,190✔
1668

1669
        // bytes should deserialize to obj
1670
        let read_buf: Vec<u8> = write_buf.clone();
5,190✔
1671
        let res = T::consensus_deserialize(&mut &read_buf[..]);
5,190✔
1672
        match res {
5,190✔
1673
            Ok(out) => {
5,190✔
1674
                assert_eq!(out, *obj);
5,190✔
1675
            }
UNCOV
1676
            Err(e) => {
×
UNCOV
1677
                panic!("Failed to parse to {obj:?}: {bytes:?}\nerror: {e:?}");
×
1678
            }
1679
        }
1680

1681
        // short message shouldn't parse, but should EOF
1682
        if !write_buf.is_empty() {
5,190✔
1683
            let mut short_buf = write_buf.clone();
5,190✔
1684
            let short_len = short_buf.len() - 1;
5,190✔
1685
            short_buf.truncate(short_len);
5,190✔
1686

1687
            let underflow_res = T::consensus_deserialize(&mut &short_buf[..]);
5,190✔
1688
            match underflow_res {
5,190✔
UNCOV
1689
                Ok(oops) => {
×
UNCOV
1690
                    test_debug!(
×
1691
                        "\nMissing Underflow: Parsed {oops:?}\nFrom {:?}\n",
1692
                        &write_buf[0..short_len].to_vec()
×
1693
                    );
1694
                }
1695
                Err(codec_error::ReadError(io_error)) => match io_error.kind() {
5,190✔
1696
                    io::ErrorKind::UnexpectedEof => {}
5,190✔
1697
                    _ => {
UNCOV
1698
                        panic!("Got unexpected I/O error: {io_error:?}");
×
1699
                    }
1700
                },
UNCOV
1701
                Err(e) => {
×
UNCOV
1702
                    panic!("Got unexpected Net error: {e:?}");
×
1703
                }
1704
            };
UNCOV
1705
        }
×
1706
    }
5,190✔
1707

1708
    #[test]
1709
    fn codec_primitive_types() {
1✔
1710
        check_codec_and_corruption::<u8>(&0x01, &[0x01]);
1✔
1711
        check_codec_and_corruption::<u16>(&0x0203, &[0x02, 0x03]);
1✔
1712
        check_codec_and_corruption::<u32>(&0x04050607, &[0x04, 0x05, 0x06, 0x07]);
1✔
1713
        check_codec_and_corruption::<u64>(
1✔
1714
            &0x08090a0b0c0d0e0f,
1✔
1715
            &[0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
1✔
1716
        );
1717
    }
1✔
1718

1719
    #[test]
1720
    fn codec_primitive_vector() {
1✔
1721
        check_codec_and_corruption::<Vec<u8>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1722
        check_codec_and_corruption::<Vec<u8>>(
1✔
1723
            &vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09],
1✔
1724
            &[
1✔
1725
                0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
1✔
1726
            ],
1✔
1727
        );
1728

1729
        check_codec_and_corruption::<Vec<u16>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1730
        check_codec_and_corruption::<Vec<u16>>(
1✔
1731
            &vec![
1✔
1732
                0xf000, 0xf101, 0xf202, 0xf303, 0xf404, 0xf505, 0xf606, 0xf707, 0xf808, 0xf909,
1✔
1733
            ],
1✔
1734
            &[
1✔
1735
                0x00, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0xf1, 0x01, 0xf2, 0x02, 0xf3, 0x03, 0xf4, 0x04,
1✔
1736
                0xf5, 0x05, 0xf6, 0x06, 0xf7, 0x07, 0xf8, 0x08, 0xf9, 0x09,
1✔
1737
            ],
1✔
1738
        );
1739

1740
        check_codec_and_corruption::<Vec<u32>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1741
        check_codec_and_corruption::<Vec<u32>>(
1✔
1742
            &vec![
1✔
1743
                0xa0b0f000, 0xa1b1f101, 0xa2b2f202, 0xa3b3f303, 0xa4b4f404, 0xa5b5f505, 0xa6b6f606,
1✔
1744
                0xa7b7f707, 0xa8b8f808, 0xa9b9f909,
1✔
1745
            ],
1✔
1746
            &[
1✔
1747
                0x00, 0x00, 0x00, 0x0a, 0xa0, 0xb0, 0xf0, 0x00, 0xa1, 0xb1, 0xf1, 0x01, 0xa2, 0xb2,
1✔
1748
                0xf2, 0x02, 0xa3, 0xb3, 0xf3, 0x03, 0xa4, 0xb4, 0xf4, 0x04, 0xa5, 0xb5, 0xf5, 0x05,
1✔
1749
                0xa6, 0xb6, 0xf6, 0x06, 0xa7, 0xb7, 0xf7, 0x07, 0xa8, 0xb8, 0xf8, 0x08, 0xa9, 0xb9,
1✔
1750
                0xf9, 0x09,
1✔
1751
            ],
1✔
1752
        );
1753

1754
        check_codec_and_corruption::<Vec<u64>>(&vec![], &[0x00, 0x00, 0x00, 0x00]);
1✔
1755
        check_codec_and_corruption::<Vec<u64>>(
1✔
1756
            &vec![
1✔
1757
                0x1020304050607080,
1✔
1758
                0x1121314151617181,
1✔
1759
                0x1222324252627282,
1✔
1760
                0x1323334353637383,
1✔
1761
                0x1424344454647484,
1✔
1762
                0x1525354555657585,
1✔
1763
                0x1626364656667686,
1✔
1764
                0x1727374757677787,
1✔
1765
                0x1828384858687888,
1✔
1766
            ],
1✔
1767
            &[
1✔
1768
                0x00, 0x00, 0x00, 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x11, 0x21,
1✔
1769
                0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x82,
1✔
1770
                0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64,
1✔
1771
                0x74, 0x84, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x16, 0x26, 0x36, 0x46,
1✔
1772
                0x56, 0x66, 0x76, 0x86, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 0x87, 0x18, 0x28,
1✔
1773
                0x38, 0x48, 0x58, 0x68, 0x78, 0x88,
1✔
1774
            ],
1✔
1775
        );
1776
    }
1✔
1777

1778
    #[test]
1779
    fn codec_Preamble() {
1✔
1780
        let preamble = Preamble {
1✔
1781
            peer_version: 0x01020304,
1✔
1782
            network_id: 0x05060708,
1✔
1783
            seq: 0x090a0b0c,
1✔
1784
            burn_block_height: 0x00001122,
1✔
1785
            burn_block_hash: BurnchainHeaderHash([0x11; 32]),
1✔
1786
            burn_stable_block_height: 0x00001111,
1✔
1787
            burn_stable_block_hash: BurnchainHeaderHash([0x22; 32]),
1✔
1788
            additional_data: 0x33333333,
1✔
1789
            signature: MessageSignature::from_raw(&[0x44; 65]),
1✔
1790
            payload_len: 0x000007ff,
1✔
1791
        };
1✔
1792
        let preamble_bytes: Vec<u8> = vec![
1✔
1793
            // peer_version
1794
            0x01, 0x02, 0x03, 0x04, // network_id
1795
            0x05, 0x06, 0x07, 0x08, // seq
1796
            0x09, 0x0a, 0x0b, 0x0c, // burn_block_height
1797
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, // burn_block_hash
1798
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1799
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1800
            0x11, 0x11, 0x11, 0x11, // stable_burn_block_height
1801
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, // stable_burn_block_hash
1802
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
1803
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
1804
            0x22, 0x22, 0x22, 0x22, // additional_data
1805
            0x33, 0x33, 0x33, 0x33, // signature
1806
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1807
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1808
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1809
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1810
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, // payload_len
1811
            0x00, 0x00, 0x07, 0xff,
1812
        ];
1813

1814
        assert_eq!(preamble_bytes.len() as u32, PREAMBLE_ENCODED_SIZE);
1✔
1815
        check_codec_and_corruption::<Preamble>(&preamble, &preamble_bytes);
1✔
1816
    }
1✔
1817

1818
    #[test]
1819
    fn codec_GetPoxInv() {
1✔
1820
        let getpoxinv = GetPoxInv {
1✔
1821
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
1822
            num_cycles: GETPOXINV_MAX_BITLEN as u16,
1✔
1823
        };
1✔
1824

1825
        let getpoxinv_bytes: Vec<u8> = vec![
1✔
1826
            // consensus hash
1827
            0x55,
1828
            0x55,
1829
            0x55,
1830
            0x55,
1831
            0x55,
1832
            0x55,
1833
            0x55,
1834
            0x55,
1835
            0x55,
1836
            0x55,
1837
            0x55,
1838
            0x55,
1839
            0x55,
1840
            0x55,
1841
            0x55,
1842
            0x55,
1843
            0x55,
1844
            0x55,
1845
            0x55,
1846
            0x55,
1847
            // num reward cycles
1848
            0x00,
1849
            GETPOXINV_MAX_BITLEN as u8,
1✔
1850
        ];
1851

1852
        check_codec_and_corruption::<GetPoxInv>(&getpoxinv, &getpoxinv_bytes);
1✔
1853

1854
        // should fail to decode if the block range is too big
1855
        let getpoxinv_range_too_big = GetPoxInv {
1✔
1856
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
1857
            num_cycles: (GETPOXINV_MAX_BITLEN + 1) as u16,
1✔
1858
        };
1✔
1859

1860
        assert!(check_deserialize_failure::<GetPoxInv>(
1✔
1861
            &getpoxinv_range_too_big
1✔
1862
        ));
1863
    }
1✔
1864

1865
    #[test]
1866
    fn codec_PoxInvData() {
1✔
1867
        // maximially big PoxInvData
1868
        let maximal_bitvec = vec![0xffu8; (GETPOXINV_MAX_BITLEN / 8) as usize];
1✔
1869
        let mut too_big_bitvec: Vec<u8> = vec![];
1✔
1870
        for i in 0..GETPOXINV_MAX_BITLEN + 1 {
9✔
1871
            too_big_bitvec.push(0xff);
9✔
1872
        }
9✔
1873

1874
        let maximal_poxinvdata = PoxInvData {
1✔
1875
            bitlen: GETPOXINV_MAX_BITLEN as u16,
1✔
1876
            pox_bitvec: maximal_bitvec.clone(),
1✔
1877
        };
1✔
1878

1879
        let mut maximal_poxinvdata_bytes: Vec<u8> = vec![];
1✔
1880
        // bitlen
1881
        maximal_poxinvdata_bytes.append(&mut (GETPOXINV_MAX_BITLEN as u16).to_be_bytes().to_vec());
1✔
1882
        // pox bitvec
1883
        maximal_poxinvdata_bytes
1✔
1884
            .append(&mut ((GETPOXINV_MAX_BITLEN / 8) as u32).to_be_bytes().to_vec());
1✔
1885
        maximal_poxinvdata_bytes.extend_from_slice(&maximal_bitvec);
1✔
1886

1887
        assert!((maximal_poxinvdata_bytes.len() as u32) < MAX_MESSAGE_LEN);
1✔
1888

1889
        check_codec_and_corruption::<PoxInvData>(&maximal_poxinvdata, &maximal_poxinvdata_bytes);
1✔
1890

1891
        // should fail to decode if the bitlen is too big
1892
        let too_big_poxinvdata = PoxInvData {
1✔
1893
            bitlen: (GETPOXINV_MAX_BITLEN + 1) as u16,
1✔
1894
            pox_bitvec: too_big_bitvec.clone(),
1✔
1895
        };
1✔
1896
        assert!(check_deserialize_failure::<PoxInvData>(&too_big_poxinvdata));
1✔
1897

1898
        // should fail to decode if the bitlen doesn't match the bitvec
1899
        let long_bitlen = PoxInvData {
1✔
1900
            bitlen: 1,
1✔
1901
            pox_bitvec: vec![0xff, 0x01],
1✔
1902
        };
1✔
1903
        assert!(check_deserialize_failure::<PoxInvData>(&long_bitlen));
1✔
1904

1905
        let short_bitlen = PoxInvData {
1✔
1906
            bitlen: 9,
1✔
1907
            pox_bitvec: vec![0xff],
1✔
1908
        };
1✔
1909
        assert!(check_deserialize_failure::<PoxInvData>(&short_bitlen));
1✔
1910

1911
        // empty
1912
        let empty_inv = PoxInvData {
1✔
1913
            bitlen: 0,
1✔
1914
            pox_bitvec: vec![],
1✔
1915
        };
1✔
1916
        let empty_inv_bytes = [
1✔
1917
            // bitlen
1✔
1918
            0x00, 0x00, 0x00, 0x00, // bitvec
1✔
1919
            0x00, 0x00, 0x00, 0x00,
1✔
1920
        ];
1✔
1921

1922
        check_codec_and_corruption::<PoxInvData>(&maximal_poxinvdata, &maximal_poxinvdata_bytes);
1✔
1923
    }
1✔
1924

1925
    #[test]
1926
    fn codec_GetBlocksInv() {
1✔
1927
        let getblocksdata = GetBlocksInv {
1✔
1928
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
1929
            num_blocks: 32,
1✔
1930
        };
1✔
1931

1932
        let getblocksdata_bytes: Vec<u8> = vec![
1✔
1933
            // consensus hash
1934
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1935
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // num blocks
1936
            0x00, 0x20,
1937
        ];
1938

1939
        check_codec_and_corruption::<GetBlocksInv>(&getblocksdata, &getblocksdata_bytes);
1✔
1940
    }
1✔
1941

1942
    #[test]
1943
    fn codec_BlocksInvData() {
1✔
1944
        let blocks_bitlen: u32 = 32;
1✔
1945

1946
        let maximal_bitvec = vec![0xffu8; (blocks_bitlen / 8) as usize];
1✔
1947
        let maximal_blocksinvdata = BlocksInvData {
1✔
1948
            bitlen: blocks_bitlen as u16,
1✔
1949
            block_bitvec: maximal_bitvec.clone(),
1✔
1950
            microblocks_bitvec: maximal_bitvec.clone(),
1✔
1951
        };
1✔
1952

1953
        let mut maximal_blocksinvdata_bytes: Vec<u8> = vec![];
1✔
1954
        // bitlen
1955
        maximal_blocksinvdata_bytes.append(&mut (blocks_bitlen as u16).to_be_bytes().to_vec());
1✔
1956
        // block bitvec
1957
        maximal_blocksinvdata_bytes.append(&mut (blocks_bitlen / 8).to_be_bytes().to_vec());
1✔
1958
        maximal_blocksinvdata_bytes.extend_from_slice(&maximal_bitvec);
1✔
1959
        // microblock bitvec
1960
        maximal_blocksinvdata_bytes.append(&mut (blocks_bitlen / 8).to_be_bytes().to_vec());
1✔
1961
        maximal_blocksinvdata_bytes.extend_from_slice(&maximal_bitvec);
1✔
1962

1963
        assert!((maximal_blocksinvdata_bytes.len() as u32) < MAX_MESSAGE_LEN);
1✔
1964

1965
        check_codec_and_corruption::<BlocksInvData>(
1✔
1966
            &maximal_blocksinvdata,
1✔
1967
            &maximal_blocksinvdata_bytes,
1✔
1968
        );
1969

1970
        // should fail to decode if the bitlen doesn't match the bitvec
1971
        let long_bitlen = BlocksInvData {
1✔
1972
            bitlen: 1,
1✔
1973
            block_bitvec: vec![0xff, 0x01],
1✔
1974
            microblocks_bitvec: vec![0xff, 0x01],
1✔
1975
        };
1✔
1976
        assert!(check_deserialize_failure::<BlocksInvData>(&long_bitlen));
1✔
1977

1978
        let short_bitlen = BlocksInvData {
1✔
1979
            bitlen: 9,
1✔
1980
            block_bitvec: vec![0xff],
1✔
1981
            microblocks_bitvec: vec![0xff],
1✔
1982
        };
1✔
1983
        assert!(check_deserialize_failure::<BlocksInvData>(&short_bitlen));
1✔
1984

1985
        // empty
1986
        let empty_inv = BlocksInvData {
1✔
1987
            bitlen: 0,
1✔
1988
            block_bitvec: vec![],
1✔
1989
            microblocks_bitvec: vec![],
1✔
1990
        };
1✔
1991
        let empty_inv_bytes = [
1✔
1992
            // bitlen
1✔
1993
            0x00, 0x00, 0x00, 0x00, // bitvec
1✔
1994
            0x00, 0x00, 0x00, 0x00, // microblock bitvec
1✔
1995
            0x00, 0x00, 0x00, 0x00,
1✔
1996
        ];
1✔
1997

1998
        assert!(check_deserialize_failure::<BlocksInvData>(&empty_inv));
1✔
1999
    }
1✔
2000

2001
    #[test]
2002
    fn codec_NeighborAddress() {
1✔
2003
        let data = NeighborAddress {
1✔
2004
            addrbytes: PeerAddress([
1✔
2005
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
1✔
2006
                0x0e, 0x0f,
1✔
2007
            ]),
1✔
2008
            port: 12345,
1✔
2009
            public_key_hash: Hash160::from_bytes(
1✔
2010
                &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2011
            )
1✔
2012
            .unwrap(),
1✔
2013
        };
1✔
2014
        let bytes = vec![
1✔
2015
            // addrbytes
2016
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2017
            0x0e, 0x0f, // port
2018
            0x30, 0x39, // public key hash
2019
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2020
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2021
        ];
2022

2023
        assert_eq!(bytes.len() as u32, NEIGHBOR_ADDRESS_ENCODED_SIZE);
1✔
2024
        check_codec_and_corruption::<NeighborAddress>(&data, &bytes);
1✔
2025
    }
1✔
2026

2027
    #[test]
2028
    fn codec_NeighborsData() {
1✔
2029
        let data = NeighborsData {
1✔
2030
            neighbors: vec![
1✔
2031
                NeighborAddress {
1✔
2032
                    addrbytes: PeerAddress([
1✔
2033
                        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
2034
                        0x0c, 0x0d, 0x0e, 0x0f,
1✔
2035
                    ]),
1✔
2036
                    port: 12345,
1✔
2037
                    public_key_hash: Hash160::from_bytes(
1✔
2038
                        &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2039
                    )
1✔
2040
                    .unwrap(),
1✔
2041
                },
1✔
2042
                NeighborAddress {
1✔
2043
                    addrbytes: PeerAddress([
1✔
2044
                        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
1✔
2045
                        0x1c, 0x1d, 0x1e, 0x1f,
1✔
2046
                    ]),
1✔
2047
                    port: 23456,
1✔
2048
                    public_key_hash: Hash160::from_bytes(
1✔
2049
                        &hex_bytes("2222222222222222222222222222222222222222").unwrap(),
1✔
2050
                    )
1✔
2051
                    .unwrap(),
1✔
2052
                },
1✔
2053
            ],
1✔
2054
        };
1✔
2055
        let bytes = vec![
1✔
2056
            // length
2057
            0x00, 0x00, 0x00, 0x02, // addrbytes
2058
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2059
            0x0e, 0x0f, // port
2060
            0x30, 0x39, // public key hash
2061
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2062
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // addrbytes
2063
            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
2064
            0x1e, 0x1f, // port
2065
            0x5b, 0xa0, // public key hash
2066
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2067
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2068
        ];
2069

2070
        check_codec_and_corruption::<NeighborsData>(&data, &bytes);
1✔
2071
    }
1✔
2072

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

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

2108
    #[test]
2109
    fn codec_HandshakeAcceptData() {
1✔
2110
        let data = HandshakeAcceptData {
1✔
2111
            handshake: HandshakeData {
1✔
2112
                addrbytes: PeerAddress([
1✔
2113
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2114
                    0x0d, 0x0e, 0x0f,
1✔
2115
                ]),
1✔
2116
                port: 12345,
1✔
2117
                services: 0x0001,
1✔
2118
                node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2119
                    &hex_bytes(
1✔
2120
                        "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2121
                    )
1✔
2122
                    .unwrap(),
1✔
2123
                )
1✔
2124
                .unwrap(),
1✔
2125
                expire_block_height: 0x0102030405060708,
1✔
2126
                data_url: UrlString::try_from("https://the-new-interwebs.com/data").unwrap(),
1✔
2127
            },
1✔
2128
            heartbeat_interval: 0x01020304,
1✔
2129
        };
1✔
2130
        let mut bytes = vec![
1✔
2131
            // addrbytes
2132
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2133
            0x0e, 0x0f, // port
2134
            0x30, 0x39, // services
2135
            0x00, 0x01, // public key
2136
            0x03, 0x4e, 0x31, 0x6b, 0xe0, 0x48, 0x70, 0xce, 0xf1, 0x79, 0x5f, 0xba, 0x64, 0xd5,
2137
            0x81, 0xcf, 0x64, 0xba, 0xd0, 0xc8, 0x94, 0xb0, 0x1a, 0x06, 0x8f, 0xb9, 0xed, 0xf8,
2138
            0x53, 0x21, 0xdc, 0xd9, 0xbb, // expire block height
2139
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
2140
        ];
2141
        // data URL
2142
        bytes.push(data.handshake.data_url.len() as u8);
1✔
2143
        bytes.extend_from_slice(data.handshake.data_url.as_bytes());
1✔
2144

2145
        bytes.extend_from_slice(&[
1✔
2146
            // heartbeat
1✔
2147
            0x01, 0x02, 0x03, 0x04,
1✔
2148
        ]);
1✔
2149

2150
        check_codec_and_corruption::<HandshakeAcceptData>(&data, &bytes);
1✔
2151
    }
1✔
2152

2153
    #[test]
2154
    fn codec_NackData() {
1✔
2155
        let data = NackData {
1✔
2156
            error_code: 0x01020304,
1✔
2157
        };
1✔
2158
        let bytes = vec![
1✔
2159
            // error code
2160
            0x01, 0x02, 0x03, 0x04,
2161
        ];
2162

2163
        check_codec_and_corruption::<NackData>(&data, &bytes);
1✔
2164
    }
1✔
2165

2166
    #[test]
2167
    fn codec_RelayData() {
1✔
2168
        let data = RelayData {
1✔
2169
            peer: NeighborAddress {
1✔
2170
                addrbytes: PeerAddress([
1✔
2171
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2172
                    0x0d, 0x0e, 0x0f,
1✔
2173
                ]),
1✔
2174
                port: 12345,
1✔
2175
                public_key_hash: Hash160::from_bytes(
1✔
2176
                    &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2177
                )
1✔
2178
                .unwrap(),
1✔
2179
            },
1✔
2180
            seq: 0x01020304,
1✔
2181
        };
1✔
2182
        let bytes = vec![
1✔
2183
            // peer.addrbytes
2184
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2185
            0x0e, 0x0f, // peer.port
2186
            0x30, 0x39, // peer.public_key_hash
2187
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2188
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // seq
2189
            0x01, 0x02, 0x03, 0x04,
2190
        ];
2191

2192
        check_codec_and_corruption::<RelayData>(&data, &bytes);
1✔
2193
    }
1✔
2194

2195
    #[test]
2196
    fn codec_BlocksAvailable() {
1✔
2197
        let data = BlocksAvailableData {
1✔
2198
            available: vec![
1✔
2199
                (ConsensusHash([0x11; 20]), BurnchainHeaderHash([0x22; 32])),
1✔
2200
                (ConsensusHash([0x33; 20]), BurnchainHeaderHash([0x44; 32])),
1✔
2201
            ],
1✔
2202
        };
1✔
2203
        let bytes = vec![
1✔
2204
            // length
2205
            0x00, 0x00, 0x00, 0x02, // first tuple
2206
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2207
            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2208
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2209
            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // second tuple
2210
            0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
2211
            0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2212
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2213
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2214
        ];
2215

2216
        check_codec_and_corruption::<BlocksAvailableData>(&data, &bytes);
1✔
2217
    }
1✔
2218

2219
    #[test]
2220
    fn codec_NatPunch() {
1✔
2221
        let data = NatPunchData {
1✔
2222
            addrbytes: PeerAddress([0x1; 16]),
1✔
2223
            port: 0x1234,
1✔
2224
            nonce: 0x56789abc,
1✔
2225
        };
1✔
2226
        let bytes = vec![
1✔
2227
            // peer address
2228
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2229
            0x01, 0x01, // port
2230
            0x12, 0x34, // nonce
2231
            0x56, 0x78, 0x9a, 0xbc,
2232
        ];
2233

2234
        check_codec_and_corruption::<NatPunchData>(&data, &bytes);
1✔
2235
    }
1✔
2236

2237
    #[test]
2238
    fn codec_StackerDBHandshakeAccept() {
1✔
2239
        let data = StackerDBHandshakeData {
1✔
2240
            rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2241
            smart_contracts: vec![
1✔
2242
                QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo")
1✔
2243
                    .unwrap(),
1✔
2244
                QualifiedContractIdentifier::parse("SP28D54YKFCMRKXBR6BR0E4BPN57S62RSM4XEVPRP.bar")
1✔
2245
                    .unwrap(),
1✔
2246
            ],
1✔
2247
        };
1✔
2248
        let bytes = vec![
1✔
2249
            // rc consensus hash
2250
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2251
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // len(smart_contracts)
2252
            0x02, // SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN
2253
            0x16, 0x11, 0x7b, 0x59, 0x1a, 0xdf, 0x7c, 0xae, 0xe4, 0x3b, 0x7e, 0x5d, 0x88, 0x24,
2254
            0xe8, 0x51, 0xb9, 0x35, 0xbc, 0xa9, 0xae, // len(foo)
2255
            0x03, // foo
2256
            0x66, 0x6f, 0x6f, // SP28D54YKFCMRKXBR6BR0E4BPN57S62RSM4XEVPRP
2257
            0x16, 0x90, 0xd2, 0x93, 0xd3, 0x7b, 0x29, 0x89, 0xf5, 0x78, 0x32, 0xf0, 0x07, 0x11,
2258
            0x76, 0xa9, 0x4f, 0x93, 0x0b, 0x19, 0xa1, // len(bar)
2259
            0x03, // bar
2260
            0x62, 0x61, 0x72,
2261
        ];
2262

2263
        check_codec_and_corruption::<StackerDBHandshakeData>(&data, &bytes);
1✔
2264
    }
1✔
2265

2266
    #[test]
2267
    fn codec_StackerDBGetChunkInvData() {
1✔
2268
        let data = StackerDBGetChunkInvData {
1✔
2269
            contract_id: QualifiedContractIdentifier::parse(
1✔
2270
                "SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo",
1✔
2271
            )
1✔
2272
            .unwrap(),
1✔
2273
            rc_consensus_hash: ConsensusHash([0x01; 20]),
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,
2284
        ];
2285

2286
        check_codec_and_corruption::<StackerDBGetChunkInvData>(&data, &bytes);
1✔
2287
    }
1✔
2288

2289
    #[test]
2290
    fn codec_StackerDBChunkInvData() {
1✔
2291
        let data = StackerDBChunkInvData {
1✔
2292
            slot_versions: vec![0, 1, 2, 3],
1✔
2293
            num_outbound_replicas: 4,
1✔
2294
        };
1✔
2295

2296
        let bytes = vec![
1✔
2297
            // len(slot_versions)
2298
            0x00, 0x00, 0x00, 0x04, // 0u32
2299
            0x00, 0x00, 0x00, 0x00, // 1u32
2300
            0x00, 0x00, 0x00, 0x01, // 2u32
2301
            0x00, 0x00, 0x00, 0x02, // 3u32
2302
            0x00, 0x00, 0x00, 0x03, // num_outbound_replicas
2303
            0x00, 0x00, 0x00, 0x04,
2304
        ];
2305

2306
        check_codec_and_corruption::<StackerDBChunkInvData>(&data, &bytes);
1✔
2307
    }
1✔
2308

2309
    #[test]
2310
    fn codec_StackerDBGetChunkData() {
1✔
2311
        let data = StackerDBGetChunkData {
1✔
2312
            contract_id: QualifiedContractIdentifier::parse(
1✔
2313
                "SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo",
1✔
2314
            )
1✔
2315
            .unwrap(),
1✔
2316
            rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2317
            slot_id: 2,
1✔
2318
            slot_version: 3,
1✔
2319
        };
1✔
2320

2321
        let bytes = vec![
1✔
2322
            // SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN
2323
            0x16, 0x11, 0x7b, 0x59, 0x1a, 0xdf, 0x7c, 0xae, 0xe4, 0x3b, 0x7e, 0x5d, 0x88, 0x24,
2324
            0xe8, 0x51, 0xb9, 0x35, 0xbc, 0xa9, 0xae, // len(foo)
2325
            0x03, // foo
2326
            0x66, 0x6f, 0x6f, // rc consensus hash
2327
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2328
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // slot id
2329
            0x00, 0x00, 0x00, 0x02, // slot version
2330
            0x00, 0x00, 0x00, 0x03,
2331
        ];
2332

2333
        check_codec_and_corruption::<StackerDBGetChunkData>(&data, &bytes);
1✔
2334
    }
1✔
2335

2336
    #[test]
2337
    fn codec_StackerDBChunkData() {
1✔
2338
        let data = StackerDBChunkData {
1✔
2339
            slot_id: 2,
1✔
2340
            slot_version: 3,
1✔
2341
            sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2342
            data: vec![
1✔
2343
                0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
1✔
2344
            ],
1✔
2345
        };
1✔
2346

2347
        let bytes = vec![
1✔
2348
            // slot id
2349
            0x00, 0x00, 0x00, 0x02, // slot version
2350
            0x00, 0x00, 0x00, 0x03, // signature
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, 0x44, 0x44, 0x44, 0x44, 0x44,
2353
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2354
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2355
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, // length
2356
            0x00, 0x00, 0x00, 0x0b, // data
2357
            0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
2358
        ];
2359

2360
        check_codec_and_corruption::<StackerDBChunkData>(&data, &bytes);
1✔
2361
    }
1✔
2362

2363
    #[test]
2364
    fn codec_StackerDBPushChunkData() {
1✔
2365
        let data = StackerDBChunkData {
1✔
2366
            slot_id: 2,
1✔
2367
            slot_version: 3,
1✔
2368
            sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2369
            data: vec![
1✔
2370
                0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
1✔
2371
            ],
1✔
2372
        };
1✔
2373

2374
        let push_data = StackerDBPushChunkData {
1✔
2375
            contract_id: QualifiedContractIdentifier::parse(
1✔
2376
                "SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo",
1✔
2377
            )
1✔
2378
            .unwrap(),
1✔
2379
            rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2380
            chunk_data: data,
1✔
2381
        };
1✔
2382

2383
        let bytes = vec![
1✔
2384
            // SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN
2385
            0x16, 0x11, 0x7b, 0x59, 0x1a, 0xdf, 0x7c, 0xae, 0xe4, 0x3b, 0x7e, 0x5d, 0x88, 0x24,
2386
            0xe8, 0x51, 0xb9, 0x35, 0xbc, 0xa9, 0xae, // len(foo)
2387
            0x03, // foo
2388
            0x66, 0x6f, 0x6f, // rc consensus hash
2389
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2390
            0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // slot id
2391
            0x00, 0x00, 0x00, 0x02, // slot version
2392
            0x00, 0x00, 0x00, 0x03, // signature
2393
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2394
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2395
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2396
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2397
            0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, // length
2398
            0x00, 0x00, 0x00, 0x0b, // data
2399
            0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
2400
        ];
2401

2402
        check_codec_and_corruption::<StackerDBPushChunkData>(&push_data, &bytes);
1✔
2403
    }
1✔
2404

2405
    #[test]
2406
    fn codec_GetNakamotoInv() {
1✔
2407
        let get_nakamoto_inv = GetNakamotoInvData {
1✔
2408
            consensus_hash: ConsensusHash([0x55; 20]),
1✔
2409
        };
1✔
2410

2411
        let get_nakamoto_inv_bytes: Vec<u8> = vec![
1✔
2412
            // consensus hash
2413
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
2414
            0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
2415
        ];
2416

2417
        check_codec_and_corruption::<GetNakamotoInvData>(
1✔
2418
            &get_nakamoto_inv,
1✔
2419
            &get_nakamoto_inv_bytes,
1✔
2420
        );
2421
    }
1✔
2422

2423
    #[test]
2424
    fn codec_NakamotoInv() {
1✔
2425
        let nakamoto_inv = NakamotoInvData {
1✔
2426
            tenures: BitVec::<2100>::try_from(
1✔
2427
                // 0xdd
1✔
2428
                vec![
1✔
2429
                    true, false, true, true, true, false, true, true, // 0xee
1✔
2430
                    false, true, true, true, false, true, true, true, // 0xaa
1✔
2431
                    false, true, false, true, false, true, false, true, // 0xdd
1✔
2432
                    true, false, true, true, true, false, true, true, // 0xbb
1✔
2433
                    true, true, false, true, true, true, false, true, // 0xee
1✔
2434
                    false, true, true, true, false, true, true, true, // 0xee
1✔
2435
                    false, true, true, true, false, true, true, true, // 0xff
1✔
2436
                    true, true, true, true, true, true, true, true,
1✔
2437
                ]
1✔
2438
                .as_slice(),
1✔
2439
            )
1✔
2440
            .unwrap(),
1✔
2441
        };
1✔
2442

2443
        let nakamoto_inv_bytes = [
1✔
2444
            // bitlen
1✔
2445
            0x00, 0x40, // vec len
1✔
2446
            0x00, 0x00, 0x00, 0x08, // bits
1✔
2447
            0xdd, 0xee, 0xaa, 0xdd, 0xbb, 0xee, 0xee, 0xff,
1✔
2448
        ];
1✔
2449

2450
        check_codec_and_corruption::<NakamotoInvData>(&nakamoto_inv, &nakamoto_inv_bytes);
1✔
2451

2452
        // should fail
2453
        let nakamoto_inv_bytes = [
1✔
2454
            // bitlen
1✔
2455
            0x00, 0x20, // vec len
1✔
2456
            0x00, 0x00, 0x00, 0x05, // bits
1✔
2457
            0x00, 0x00, 0x00, 0x00,
1✔
2458
        ];
1✔
2459

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

2462
        // should fail
2463
        let nakamoto_inv_bytes = [
1✔
2464
            // bitlen
1✔
2465
            0x00, 0x21, // vec len
1✔
2466
            0x00, 0x00, 0x00, 0x04, // bits
1✔
2467
            0x00, 0x00, 0x00, 0x00,
1✔
2468
        ];
1✔
2469

2470
        let _ = NakamotoInvData::consensus_deserialize(&mut &nakamoto_inv_bytes[..]).unwrap_err();
1✔
2471
    }
1✔
2472

2473
    #[test]
2474
    fn codec_StacksMessage() {
1✔
2475
        let payloads: Vec<StacksMessageType> = vec![
1✔
2476
            StacksMessageType::Handshake(HandshakeData {
1✔
2477
                addrbytes: PeerAddress([
1✔
2478
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2479
                    0x0d, 0x0e, 0x0f,
1✔
2480
                ]),
1✔
2481
                port: 12345,
1✔
2482
                services: 0x0001,
1✔
2483
                node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2484
                    &hex_bytes(
1✔
2485
                        "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2486
                    )
1✔
2487
                    .unwrap(),
1✔
2488
                )
1✔
2489
                .unwrap(),
1✔
2490
                expire_block_height: 0x0102030405060708,
1✔
2491
                data_url: UrlString::try_from("https://the-new-interwebs.com:4008/the-data")
1✔
2492
                    .unwrap(),
1✔
2493
            }),
1✔
2494
            StacksMessageType::HandshakeAccept(HandshakeAcceptData {
1✔
2495
                heartbeat_interval: 0x01020304,
1✔
2496
                handshake: HandshakeData {
1✔
2497
                    addrbytes: PeerAddress([
1✔
2498
                        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
2499
                        0x0c, 0x0d, 0x0e, 0x0f,
1✔
2500
                    ]),
1✔
2501
                    port: 12345,
1✔
2502
                    services: 0x0001,
1✔
2503
                    node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2504
                        &hex_bytes(
1✔
2505
                            "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2506
                        )
1✔
2507
                        .unwrap(),
1✔
2508
                    )
1✔
2509
                    .unwrap(),
1✔
2510
                    expire_block_height: 0x0102030405060708,
1✔
2511
                    data_url: UrlString::try_from("https://the-new-interwebs.com:4008/the-data")
1✔
2512
                        .unwrap(),
1✔
2513
                },
1✔
2514
            }),
1✔
2515
            StacksMessageType::HandshakeReject,
1✔
2516
            StacksMessageType::GetNeighbors,
1✔
2517
            StacksMessageType::Neighbors(NeighborsData {
1✔
2518
                neighbors: vec![
1✔
2519
                    NeighborAddress {
1✔
2520
                        addrbytes: PeerAddress([
1✔
2521
                            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
2522
                            0x0c, 0x0d, 0x0e, 0x0f,
1✔
2523
                        ]),
1✔
2524
                        port: 12345,
1✔
2525
                        public_key_hash: Hash160::from_bytes(
1✔
2526
                            &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2527
                        )
1✔
2528
                        .unwrap(),
1✔
2529
                    },
1✔
2530
                    NeighborAddress {
1✔
2531
                        addrbytes: PeerAddress([
1✔
2532
                            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
1✔
2533
                            0x1c, 0x1d, 0x1e, 0x1f,
1✔
2534
                        ]),
1✔
2535
                        port: 23456,
1✔
2536
                        public_key_hash: Hash160::from_bytes(
1✔
2537
                            &hex_bytes("2222222222222222222222222222222222222222").unwrap(),
1✔
2538
                        )
1✔
2539
                        .unwrap(),
1✔
2540
                    },
1✔
2541
                ],
1✔
2542
            }),
1✔
2543
            StacksMessageType::GetPoxInv(GetPoxInv {
1✔
2544
                consensus_hash: ConsensusHash([0x55; 20]),
1✔
2545
                num_cycles: GETPOXINV_MAX_BITLEN as u16,
1✔
2546
            }),
1✔
2547
            StacksMessageType::PoxInv(PoxInvData {
1✔
2548
                bitlen: 2,
1✔
2549
                pox_bitvec: vec![0x03],
1✔
2550
            }),
1✔
2551
            StacksMessageType::GetBlocksInv(GetBlocksInv {
1✔
2552
                consensus_hash: ConsensusHash([0x55; 20]),
1✔
2553
                num_blocks: 32,
1✔
2554
            }),
1✔
2555
            StacksMessageType::BlocksInv(BlocksInvData {
1✔
2556
                bitlen: 2,
1✔
2557
                block_bitvec: vec![0x03],
1✔
2558
                microblocks_bitvec: vec![0x03],
1✔
2559
            }),
1✔
2560
            StacksMessageType::BlocksAvailable(BlocksAvailableData {
1✔
2561
                available: vec![
1✔
2562
                    (ConsensusHash([0x11; 20]), BurnchainHeaderHash([0x22; 32])),
1✔
2563
                    (ConsensusHash([0x33; 20]), BurnchainHeaderHash([0x44; 32])),
1✔
2564
                ],
1✔
2565
            }),
1✔
2566
            StacksMessageType::MicroblocksAvailable(BlocksAvailableData {
1✔
2567
                available: vec![
1✔
2568
                    (ConsensusHash([0x11; 20]), BurnchainHeaderHash([0x22; 32])),
1✔
2569
                    (ConsensusHash([0x33; 20]), BurnchainHeaderHash([0x44; 32])),
1✔
2570
                ],
1✔
2571
            }),
1✔
2572
            // TODO: Blocks
2573
            // TODO: Microblocks
2574
            // TODO: Transaction
2575
            StacksMessageType::Nack(NackData {
1✔
2576
                error_code: 0x01020304,
1✔
2577
            }),
1✔
2578
            StacksMessageType::Ping(PingData { nonce: 0x01020304 }),
1✔
2579
            StacksMessageType::Pong(PongData { nonce: 0x01020304 }),
1✔
2580
            StacksMessageType::NatPunchRequest(0x12345678),
1✔
2581
            StacksMessageType::NatPunchReply(NatPunchData {
1✔
2582
                addrbytes: PeerAddress([
1✔
2583
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2584
                    0x0d, 0x0e, 0x0f,
1✔
2585
                ]),
1✔
2586
                port: 12345,
1✔
2587
                nonce: 0x12345678,
1✔
2588
            }),
1✔
2589
            StacksMessageType::StackerDBHandshakeAccept(
1✔
2590
                HandshakeAcceptData {
1✔
2591
                    heartbeat_interval: 0x01020304,
1✔
2592
                    handshake: HandshakeData {
1✔
2593
                        addrbytes: PeerAddress([
1✔
2594
                            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
1✔
2595
                            0x0c, 0x0d, 0x0e, 0x0f,
1✔
2596
                        ]),
1✔
2597
                        port: 12345,
1✔
2598
                        services: 0x0001,
1✔
2599
                        node_public_key: StacksPublicKeyBuffer::from_bytes(
1✔
2600
                            &hex_bytes(
1✔
2601
                                "034e316be04870cef1795fba64d581cf64bad0c894b01a068fb9edf85321dcd9bb",
1✔
2602
                            )
1✔
2603
                            .unwrap(),
1✔
2604
                        )
1✔
2605
                        .unwrap(),
1✔
2606
                        expire_block_height: 0x0102030405060708,
1✔
2607
                        data_url: UrlString::try_from("https://the-new-interwebs.com:4008/the-data")
1✔
2608
                            .unwrap(),
1✔
2609
                    },
1✔
2610
                },
1✔
2611
                StackerDBHandshakeData {
1✔
2612
                    rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2613
                    smart_contracts: vec![QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(), QualifiedContractIdentifier::parse("SP28D54YKFCMRKXBR6BR0E4BPN57S62RSM4XEVPRP.bar").unwrap()]
1✔
2614
                }
1✔
2615
            ),
1✔
2616
            StacksMessageType::StackerDBGetChunkInv(StackerDBGetChunkInvData {
1✔
2617
                contract_id: QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(),
1✔
2618
                rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2619
            }),
1✔
2620
            StacksMessageType::StackerDBChunkInv(StackerDBChunkInvData {
1✔
2621
                slot_versions: vec![0, 1, 2, 3],
1✔
2622
                num_outbound_replicas: 4,
1✔
2623
            }),
1✔
2624
            StacksMessageType::StackerDBGetChunk(StackerDBGetChunkData {
1✔
2625
                contract_id: QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(),
1✔
2626
                rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2627
                slot_id: 2,
1✔
2628
                slot_version: 3
1✔
2629
            }),
1✔
2630
            StacksMessageType::StackerDBChunk(StackerDBChunkData {
1✔
2631
                slot_id: 2,
1✔
2632
                slot_version: 3,
1✔
2633
                sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2634
                data: vec![0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
1✔
2635
            }),
1✔
2636
            StacksMessageType::StackerDBPushChunk(StackerDBPushChunkData {
1✔
2637
                contract_id: QualifiedContractIdentifier::parse("SP8QPP8TVXYAXS1VFSERG978A6WKBF59NSYJQEMN.foo").unwrap(),
1✔
2638
                rc_consensus_hash: ConsensusHash([0x01; 20]),
1✔
2639
                chunk_data: StackerDBChunkData {
1✔
2640
                    slot_id: 2,
1✔
2641
                    slot_version: 3,
1✔
2642
                    sig: MessageSignature::from_raw(&[0x44; 65]),
1✔
2643
                    data: vec![0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
1✔
2644
                }
1✔
2645
            }),
1✔
2646
            StacksMessageType::GetNakamotoInv(GetNakamotoInvData {
1✔
2647
                consensus_hash: ConsensusHash([0x01; 20]),
1✔
2648
            }),
1✔
2649
            StacksMessageType::NakamotoInv(NakamotoInvData {
1✔
2650
                tenures: BitVec::<2100>::try_from(
1✔
2651
                    // 0xdd
1✔
2652
                    vec![true, true, false, true, true, true, false, true,
1✔
2653
                    // 0xee
1✔
2654
                    true, true, true, false, true, true, true, false,
1✔
2655
                    // 0xaa
1✔
2656
                    true, false, true, false, true, false, true, false,
1✔
2657
                    // 0xdd
1✔
2658
                    true, true, false, true, true, true, false, true,
1✔
2659
                    // 0xbb
1✔
2660
                    true, false, true, true, true, false, true, true,
1✔
2661
                    // 0xee
1✔
2662
                    true, true, true, false, true, true, true, false,
1✔
2663
                    // 0xee
1✔
2664
                    true, true, true, false, true, true, true, false,
1✔
2665
                    // 0xff
1✔
2666
                    true, true, true, true, true, true, true, true].as_slice()
1✔
2667
                ).unwrap()
1✔
2668
            }),
1✔
2669
        ];
2670

2671
        let mut maximal_relayers: Vec<RelayData> = vec![];
1✔
2672
        let mut too_many_relayers: Vec<RelayData> = vec![];
1✔
2673
        for i in 0..MAX_RELAYERS_LEN {
16✔
2674
            let next_relayer = RelayData {
16✔
2675
                peer: NeighborAddress {
16✔
2676
                    addrbytes: PeerAddress([
16✔
2677
                        i as u8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
16✔
2678
                        0x0c, 0x0d, 0x0e, 0x0f,
16✔
2679
                    ]),
16✔
2680
                    port: 12345 + (i as u16),
16✔
2681
                    public_key_hash: Hash160::from_bytes(
16✔
2682
                        &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
16✔
2683
                    )
16✔
2684
                    .unwrap(),
16✔
2685
                },
16✔
2686
                seq: 0x01020304 + i,
16✔
2687
            };
16✔
2688
            too_many_relayers.push(next_relayer.clone());
16✔
2689
            maximal_relayers.push(next_relayer);
16✔
2690
        }
16✔
2691
        too_many_relayers.push(RelayData {
1✔
2692
            peer: NeighborAddress {
1✔
2693
                addrbytes: PeerAddress([
1✔
2694
                    0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1✔
2695
                    0x0d, 0x0e, 0x0f,
1✔
2696
                ]),
1✔
2697
                port: 65535,
1✔
2698
                public_key_hash: Hash160::from_bytes(
1✔
2699
                    &hex_bytes("1111111111111111111111111111111111111111").unwrap(),
1✔
2700
                )
1✔
2701
                .unwrap(),
1✔
2702
            },
1✔
2703
            seq: 0x010203ff,
1✔
2704
        });
1✔
2705

2706
        let mut relayers_bytes: Vec<u8> = vec![];
1✔
2707
        maximal_relayers
1✔
2708
            .consensus_serialize(&mut relayers_bytes)
1✔
2709
            .unwrap();
1✔
2710

2711
        let mut too_many_relayer_bytes: Vec<u8> = vec![];
1✔
2712
        too_many_relayers
1✔
2713
            .consensus_serialize(&mut too_many_relayer_bytes)
1✔
2714
            .unwrap();
1✔
2715

2716
        for payload in &payloads {
24✔
2717
            // just testing codec; don't worry about signatures
2718
            // (only payload_len must be valid)
2719
            let mut payload_bytes: Vec<u8> = vec![];
24✔
2720
            payload.consensus_serialize(&mut payload_bytes).unwrap();
24✔
2721

2722
            let preamble = Preamble {
24✔
2723
                peer_version: 0x01020304,
24✔
2724
                network_id: 0x05060708,
24✔
2725
                seq: 0x090a0b0c,
24✔
2726
                burn_block_height: 0x00001122,
24✔
2727
                burn_block_hash: BurnchainHeaderHash([0x11; 32]),
24✔
2728
                burn_stable_block_height: 0x00001111,
24✔
2729
                burn_stable_block_hash: BurnchainHeaderHash([0x22; 32]),
24✔
2730
                additional_data: 0x33333333,
24✔
2731
                signature: MessageSignature::from_raw(&[0x44; 65]),
24✔
2732
                payload_len: (relayers_bytes.len() + payload_bytes.len()) as u32,
24✔
2733
            };
24✔
2734

2735
            let stacks_message = StacksMessage {
24✔
2736
                preamble: preamble.clone(),
24✔
2737
                relayers: maximal_relayers.clone(),
24✔
2738
                payload: payload.clone(),
24✔
2739
            };
24✔
2740

2741
            let mut stacks_message_bytes: Vec<u8> = vec![];
24✔
2742
            preamble
24✔
2743
                .consensus_serialize(&mut stacks_message_bytes)
24✔
2744
                .unwrap();
24✔
2745
            stacks_message_bytes.append(&mut relayers_bytes.clone());
24✔
2746
            stacks_message_bytes.append(&mut payload_bytes.clone());
24✔
2747

2748
            test_debug!(
24✔
2749
                "Test {}-byte relayer, {}-byte payload {:?}",
UNCOV
2750
                relayers_bytes.len(),
×
UNCOV
2751
                payload_bytes.len(),
×
2752
                &payload
×
2753
            );
2754
            check_codec_and_corruption::<StacksMessage>(&stacks_message, &stacks_message_bytes);
24✔
2755

2756
            // can't have too many relayers
2757
            let mut preamble_too_many_relayers = preamble.clone();
24✔
2758
            preamble_too_many_relayers.payload_len =
24✔
2759
                (too_many_relayer_bytes.len() + payload_bytes.len() + 1) as u32;
24✔
2760

2761
            let stacks_message_too_many_relayers = StacksMessage {
24✔
2762
                preamble: preamble_too_many_relayers.clone(),
24✔
2763
                relayers: too_many_relayers.clone(),
24✔
2764
                payload: payload.clone(),
24✔
2765
            };
24✔
2766
            assert!(check_deserialize_failure(&stacks_message_too_many_relayers));
24✔
2767
        }
2768
    }
1✔
2769

2770
    #[test]
2771
    fn codec_sign_and_verify() {
1✔
2772
        let privkey = Secp256k1PrivateKey::random();
1✔
2773
        let pubkey_buf =
1✔
2774
            StacksPublicKeyBuffer::from_public_key(&Secp256k1PublicKey::from_private(&privkey));
1✔
2775

2776
        let mut ping = StacksMessage::new(
1✔
2777
            PEER_VERSION_TESTNET,
2778
            0x9abcdef0,
2779
            12345,
2780
            &BurnchainHeaderHash([0x11; 32]),
1✔
2781
            12339,
2782
            &BurnchainHeaderHash([0x22; 32]),
1✔
2783
            StacksMessageType::Ping(PingData { nonce: 0x01020304 }),
1✔
2784
        );
2785

2786
        ping.sign(444, &privkey).unwrap();
1✔
2787
        ping.verify_secp256k1(&pubkey_buf).unwrap();
1✔
2788
    }
1✔
2789

2790
    #[test]
2791
    fn codec_stacks_public_key_roundtrip() {
1✔
2792
        for i in 0..100 {
100✔
2793
            let privkey = Secp256k1PrivateKey::random();
100✔
2794
            let pubkey = Secp256k1PublicKey::from_private(&privkey);
100✔
2795

2796
            let pubkey_buf = StacksPublicKeyBuffer::from_public_key(&pubkey);
100✔
2797
            let pubkey_2 = pubkey_buf.to_public_key().unwrap();
100✔
2798

2799
            assert_eq!(pubkey, pubkey_2);
100✔
2800
        }
2801
    }
1✔
2802

2803
    #[test]
2804
    fn blocks_inv_compress_bools() {
1✔
2805
        let block_flags = vec![
1✔
2806
            true, true, true, false, false, false, false, true, true, false, true,
2807
        ];
2808
        let block_bitvec = BlocksInvData::compress_bools(&block_flags);
1✔
2809
        assert_eq!(block_bitvec, vec![0x87, 0x05]);
1✔
2810

2811
        let short_block_flags = vec![true, false, true];
1✔
2812
        let short_block_bitvec = BlocksInvData::compress_bools(&short_block_flags);
1✔
2813
        assert_eq!(short_block_bitvec, vec![0x05]);
1✔
2814
    }
1✔
2815
}
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