| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- /* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- use darkfi::blockchain::Header;
- use darkfi_serial::serialize;
- use crate::proto::{
- ForkHeaderHashRequest, ForkHeaderHashResponse, ForkHeadersRequest, ForkHeadersResponse,
- ForkProposalsRequest, ForkSyncRequest, HeaderSyncRequest, HeaderSyncResponse, SyncRequest,
- TipRequest, TipResponse, BATCH,
- };
- #[test]
- fn darkfid_protocols_metering() {
- // Known constant bytes lengths
- const BOOL_LEN: usize = 1;
- const OPTION_LEN: usize = 1;
- const U32_LEN: usize = 4;
- const VARINT_LEN: usize = 1;
- const HEADER_HASH_LEN: usize = 32;
- // MAX_POW_DATA_LEN = ENUM_LEN + MAX_MM_POW_DATA_LEN =
- // 1 + (8 + 8 + 8 + 32 + 4) + 60 + 2 + 32 + 1030 + (200 + 8 + 8 + 1 + 1) + 1060 + 1030 =
- // 1 + 60 + 60 + 2 + 32 + 1030 + 218 + 1060 + 1030 = 3493
- // Header = U8_LEN + HEADER_HASH_LEN + U32_LEN + U32_LEN + U64_LEN + (U8_LEN * 32) + STATE_HASH_LEN + MAX_POW_DATA_LEN =
- // 1 + 32 + 4 + 4 + 8 + (1 * 32) + 32 + 3493 = 49 + 32 + 32 + 3493 = 3606
- const MAX_HEADER_LEN: usize = 3606;
- // Generate a dummy `Header`.
- // Its bytes vector length is constant.
- let header = Header::default();
- assert!(serialize(&header).len() <= MAX_HEADER_LEN);
- // Its hash bytes vector length is constant.
- let header_hash = header.hash();
- assert_eq!(serialize(&header_hash).len(), HEADER_HASH_LEN);
- // Protocol sync `TipRequest` message has constant bytes length
- let tip_request = TipRequest { tip: header_hash };
- assert_eq!(serialize(&tip_request).len(), HEADER_HASH_LEN);
- // Protocol sync `TipResponse` message has constant bytes length,
- // based on its structure.
- let tip_response = TipResponse { synced: false, height: None, hash: None };
- // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN = 1 + 1 + 1 = 3
- assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + OPTION_LEN);
- let tip_response = TipResponse { synced: false, height: Some(42), hash: None };
- // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN = 1 + 1 + 4 + 1 = 7
- assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN);
- let tip_response = TipResponse { synced: false, height: None, hash: Some(header_hash) };
- // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN = 1 + 1 + 1 + 32 = 35
- assert_eq!(
- serialize(&tip_response).len(),
- BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN
- );
- let tip_response = TipResponse { synced: false, height: Some(42), hash: Some(header_hash) };
- // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN =
- // 1 + 1 + 4 + 1 + 32 = 39
- assert_eq!(
- serialize(&tip_response).len(),
- BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN
- );
- let tip_response = TipResponse { synced: true, height: None, hash: None };
- // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN = 1 + 1 + 1 = 3
- assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + OPTION_LEN);
- let tip_response = TipResponse { synced: true, height: Some(42), hash: None };
- // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN = 1 + 1 + 4 + 1 = 7
- assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN);
- let tip_response = TipResponse { synced: true, height: None, hash: Some(header_hash) };
- // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN = 1 + 1 + 1 + 32 = 35
- assert_eq!(
- serialize(&tip_response).len(),
- BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN
- );
- let tip_response = TipResponse { synced: true, height: Some(42), hash: Some(header_hash) };
- // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN =
- // 1 + 1 + 4 + 1 + 32 = 39
- assert_eq!(
- serialize(&tip_response).len(),
- BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN
- );
- // Protocol sync `HeaderSyncRequest` message has constant bytes length
- let header_sync_request = HeaderSyncRequest { height: 42 };
- // Length = 4
- assert_eq!(serialize(&header_sync_request).len(), U32_LEN);
- // Protocol sync `HeaderSyncResponse` is limited by `BATCH` so it has a
- // constant max bytes length limit.
- let header_sync_response = HeaderSyncResponse { headers: vec![header.clone(); BATCH] };
- // When we serialize a `Vec`, its length is encoded as a `VarInt`.
- // Based on length size/type, this can add from 1(u8) to 8(u64) bytes.
- // Since `BATCH` is 20, its `VarInt` will be represented as a u8,
- // adding an extra byte.
- // Length = (BATCH * MAX_HEADER_LEN) + VARINT_LEN = (20 * 3606) + 1 = 72120 + 1 = 72121
- assert!(serialize(&header_sync_response).len() <= (BATCH * MAX_HEADER_LEN) + VARINT_LEN);
- // Protocol sync `SyncRequest` is limited by `BATCH` so it has a
- // constant max bytes length limit.
- let sync_request = SyncRequest { headers: vec![header_hash; BATCH] };
- // Don't forget the extra byte from `Vec` length.
- // Length = (BATCH * HEADER_HASH_LEN) + VARINT_LEN = (20 * 32) + 1 = 640 + 1 = 641
- assert_eq!(serialize(&sync_request).len(), (BATCH * HEADER_HASH_LEN) + VARINT_LEN);
- // Protocol sync `SyncResponse` is limited by `BATCH` so it can have a
- // constant max bytes length limit, but we are not limiting `BlockInfo` size.
- // Protocol sync `ForkSyncRequest` message has constant bytes length,
- // based on its structure.
- let fork_sync_request = ForkSyncRequest { tip: header_hash, fork_tip: None };
- // Length = HEADER_HASH_LEN + OPTION_LEN = 32 + 1 = 33
- assert_eq!(serialize(&fork_sync_request).len(), HEADER_HASH_LEN + OPTION_LEN);
- let fork_sync_request = ForkSyncRequest { tip: header_hash, fork_tip: Some(header_hash) };
- // Length = HEADER_HASH_LEN + OPTION_LEN + HEADER_HASH_LEN = 32 + 1 + 32 = 65
- assert_eq!(serialize(&fork_sync_request).len(), HEADER_HASH_LEN + OPTION_LEN + HEADER_HASH_LEN);
- // Protocol sync `ForkSyncResponse` is limited by `BATCH` so it can have a
- // constant max bytes length limit, but we are not limiting `Proposal` size.
- // Protocol sync `ForkHeaderHashRequest` message has constant bytes length
- let fork_header_hash_request = ForkHeaderHashRequest { height: 42, fork_header: header_hash };
- // Length = U32_LEN + HEADER_HASH_LEN = 4 + 32 = 36
- assert_eq!(serialize(&fork_header_hash_request).len(), U32_LEN + HEADER_HASH_LEN);
- // Protocol sync `ForkHeaderHashResponse` message has constant bytes length,
- // based on its structure.
- let fork_header_hash_response = ForkHeaderHashResponse { fork_header: None };
- // Length = OPTION_LEN = 1
- assert_eq!(serialize(&fork_header_hash_response).len(), OPTION_LEN);
- let fork_header_hash_response = ForkHeaderHashResponse { fork_header: Some(header_hash) };
- // Length = OPTION_LEN + HEADER_HASH_LEN = 1 + 32 = 33
- assert_eq!(serialize(&fork_header_hash_response).len(), OPTION_LEN + HEADER_HASH_LEN);
- // Protocol sync `ForkHeadersRequest` is limited by `BATCH` so it has a
- // constant max bytes length limit.
- let fork_headers_request =
- ForkHeadersRequest { headers: vec![header_hash; BATCH], fork_header: header_hash };
- // Don't forget the extra byte from `Vec` length.
- // Length = (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN =
- // (20 * 32) + 1 + 32 = 640 + 33 = 673
- assert_eq!(
- serialize(&fork_headers_request).len(),
- (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN
- );
- // Protocol sync `ForkHeadersResponse` is limited by `BATCH` so it has a
- // constant max bytes length limit.
- let fork_headers_response = ForkHeadersResponse { headers: vec![header; BATCH] };
- // Don't forget the extra byte from `Vec` length.
- // Length = (BATCH * MAX_HEADER_LEN) + VARINT_LEN = (20 * 3606) + 1 = 72120 + 1 = 72121
- assert!(serialize(&fork_headers_response).len() <= (BATCH * MAX_HEADER_LEN) + VARINT_LEN);
- // Protocol sync `ForkProposalsRequest` is limited by `BATCH` so it has a
- // constant max bytes length limit.
- let fork_proposals_request =
- ForkProposalsRequest { headers: vec![header_hash; BATCH], fork_header: header_hash };
- // Don't forget the extra byte from `Vec` length.
- // Length = (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN =
- // (20 * 32) + 1 + 32 = 640 + 33 = 673
- assert_eq!(
- serialize(&fork_proposals_request).len(),
- (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN
- );
- // Protocol sync `ForkProposalsResponse` is limited by `BATCH` so it can have a
- // constant max bytes length limit, but we are not limiting `Proposal` size.
- // Protocol proposal `ProposalMessage` can have a constant max bytes length limit,
- // but we are not limiting `Proposal` size.
- // Protocol tx `Transaction` can have constant max bytes length limit,
- // but we are not limiting `Transaction` size.
- }
|