metering.rs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use darkfi::blockchain::Header;
  19. use darkfi_serial::serialize;
  20. use crate::proto::{
  21. ForkHeaderHashRequest, ForkHeaderHashResponse, ForkHeadersRequest, ForkHeadersResponse,
  22. ForkProposalsRequest, ForkSyncRequest, HeaderSyncRequest, HeaderSyncResponse, SyncRequest,
  23. TipRequest, TipResponse, BATCH,
  24. };
  25. #[test]
  26. fn darkfid_protocols_metering() {
  27. // Known constant bytes lengths
  28. const BOOL_LEN: usize = 1;
  29. const OPTION_LEN: usize = 1;
  30. const U32_LEN: usize = 4;
  31. const VARINT_LEN: usize = 1;
  32. const HEADER_HASH_LEN: usize = 32;
  33. // MAX_POW_DATA_LEN = ENUM_LEN + MAX_MM_POW_DATA_LEN =
  34. // 1 + (8 + 8 + 8 + 32 + 4) + 60 + 2 + 32 + 1030 + (200 + 8 + 8 + 1 + 1) + 1060 + 1030 =
  35. // 1 + 60 + 60 + 2 + 32 + 1030 + 218 + 1060 + 1030 = 3493
  36. // Header = U8_LEN + HEADER_HASH_LEN + U32_LEN + U32_LEN + U64_LEN + (U8_LEN * 32) + STATE_HASH_LEN + MAX_POW_DATA_LEN =
  37. // 1 + 32 + 4 + 4 + 8 + (1 * 32) + 32 + 3493 = 49 + 32 + 32 + 3493 = 3606
  38. const MAX_HEADER_LEN: usize = 3606;
  39. // Generate a dummy `Header`.
  40. // Its bytes vector length is constant.
  41. let header = Header::default();
  42. assert!(serialize(&header).len() <= MAX_HEADER_LEN);
  43. // Its hash bytes vector length is constant.
  44. let header_hash = header.hash();
  45. assert_eq!(serialize(&header_hash).len(), HEADER_HASH_LEN);
  46. // Protocol sync `TipRequest` message has constant bytes length
  47. let tip_request = TipRequest { tip: header_hash };
  48. assert_eq!(serialize(&tip_request).len(), HEADER_HASH_LEN);
  49. // Protocol sync `TipResponse` message has constant bytes length,
  50. // based on its structure.
  51. let tip_response = TipResponse { synced: false, height: None, hash: None };
  52. // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN = 1 + 1 + 1 = 3
  53. assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + OPTION_LEN);
  54. let tip_response = TipResponse { synced: false, height: Some(42), hash: None };
  55. // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN = 1 + 1 + 4 + 1 = 7
  56. assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN);
  57. let tip_response = TipResponse { synced: false, height: None, hash: Some(header_hash) };
  58. // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN = 1 + 1 + 1 + 32 = 35
  59. assert_eq!(
  60. serialize(&tip_response).len(),
  61. BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN
  62. );
  63. let tip_response = TipResponse { synced: false, height: Some(42), hash: Some(header_hash) };
  64. // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN =
  65. // 1 + 1 + 4 + 1 + 32 = 39
  66. assert_eq!(
  67. serialize(&tip_response).len(),
  68. BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN
  69. );
  70. let tip_response = TipResponse { synced: true, height: None, hash: None };
  71. // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN = 1 + 1 + 1 = 3
  72. assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + OPTION_LEN);
  73. let tip_response = TipResponse { synced: true, height: Some(42), hash: None };
  74. // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN = 1 + 1 + 4 + 1 = 7
  75. assert_eq!(serialize(&tip_response).len(), BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN);
  76. let tip_response = TipResponse { synced: true, height: None, hash: Some(header_hash) };
  77. // Length = BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN = 1 + 1 + 1 + 32 = 35
  78. assert_eq!(
  79. serialize(&tip_response).len(),
  80. BOOL_LEN + OPTION_LEN + OPTION_LEN + HEADER_HASH_LEN
  81. );
  82. let tip_response = TipResponse { synced: true, height: Some(42), hash: Some(header_hash) };
  83. // Length = BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN =
  84. // 1 + 1 + 4 + 1 + 32 = 39
  85. assert_eq!(
  86. serialize(&tip_response).len(),
  87. BOOL_LEN + OPTION_LEN + U32_LEN + OPTION_LEN + HEADER_HASH_LEN
  88. );
  89. // Protocol sync `HeaderSyncRequest` message has constant bytes length
  90. let header_sync_request = HeaderSyncRequest { height: 42 };
  91. // Length = 4
  92. assert_eq!(serialize(&header_sync_request).len(), U32_LEN);
  93. // Protocol sync `HeaderSyncResponse` is limited by `BATCH` so it has a
  94. // constant max bytes length limit.
  95. let header_sync_response = HeaderSyncResponse { headers: vec![header.clone(); BATCH] };
  96. // When we serialize a `Vec`, its length is encoded as a `VarInt`.
  97. // Based on length size/type, this can add from 1(u8) to 8(u64) bytes.
  98. // Since `BATCH` is 20, its `VarInt` will be represented as a u8,
  99. // adding an extra byte.
  100. // Length = (BATCH * MAX_HEADER_LEN) + VARINT_LEN = (20 * 3606) + 1 = 72120 + 1 = 72121
  101. assert!(serialize(&header_sync_response).len() <= (BATCH * MAX_HEADER_LEN) + VARINT_LEN);
  102. // Protocol sync `SyncRequest` is limited by `BATCH` so it has a
  103. // constant max bytes length limit.
  104. let sync_request = SyncRequest { headers: vec![header_hash; BATCH] };
  105. // Don't forget the extra byte from `Vec` length.
  106. // Length = (BATCH * HEADER_HASH_LEN) + VARINT_LEN = (20 * 32) + 1 = 640 + 1 = 641
  107. assert_eq!(serialize(&sync_request).len(), (BATCH * HEADER_HASH_LEN) + VARINT_LEN);
  108. // Protocol sync `SyncResponse` is limited by `BATCH` so it can have a
  109. // constant max bytes length limit, but we are not limiting `BlockInfo` size.
  110. // Protocol sync `ForkSyncRequest` message has constant bytes length,
  111. // based on its structure.
  112. let fork_sync_request = ForkSyncRequest { tip: header_hash, fork_tip: None };
  113. // Length = HEADER_HASH_LEN + OPTION_LEN = 32 + 1 = 33
  114. assert_eq!(serialize(&fork_sync_request).len(), HEADER_HASH_LEN + OPTION_LEN);
  115. let fork_sync_request = ForkSyncRequest { tip: header_hash, fork_tip: Some(header_hash) };
  116. // Length = HEADER_HASH_LEN + OPTION_LEN + HEADER_HASH_LEN = 32 + 1 + 32 = 65
  117. assert_eq!(serialize(&fork_sync_request).len(), HEADER_HASH_LEN + OPTION_LEN + HEADER_HASH_LEN);
  118. // Protocol sync `ForkSyncResponse` is limited by `BATCH` so it can have a
  119. // constant max bytes length limit, but we are not limiting `Proposal` size.
  120. // Protocol sync `ForkHeaderHashRequest` message has constant bytes length
  121. let fork_header_hash_request = ForkHeaderHashRequest { height: 42, fork_header: header_hash };
  122. // Length = U32_LEN + HEADER_HASH_LEN = 4 + 32 = 36
  123. assert_eq!(serialize(&fork_header_hash_request).len(), U32_LEN + HEADER_HASH_LEN);
  124. // Protocol sync `ForkHeaderHashResponse` message has constant bytes length,
  125. // based on its structure.
  126. let fork_header_hash_response = ForkHeaderHashResponse { fork_header: None };
  127. // Length = OPTION_LEN = 1
  128. assert_eq!(serialize(&fork_header_hash_response).len(), OPTION_LEN);
  129. let fork_header_hash_response = ForkHeaderHashResponse { fork_header: Some(header_hash) };
  130. // Length = OPTION_LEN + HEADER_HASH_LEN = 1 + 32 = 33
  131. assert_eq!(serialize(&fork_header_hash_response).len(), OPTION_LEN + HEADER_HASH_LEN);
  132. // Protocol sync `ForkHeadersRequest` is limited by `BATCH` so it has a
  133. // constant max bytes length limit.
  134. let fork_headers_request =
  135. ForkHeadersRequest { headers: vec![header_hash; BATCH], fork_header: header_hash };
  136. // Don't forget the extra byte from `Vec` length.
  137. // Length = (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN =
  138. // (20 * 32) + 1 + 32 = 640 + 33 = 673
  139. assert_eq!(
  140. serialize(&fork_headers_request).len(),
  141. (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN
  142. );
  143. // Protocol sync `ForkHeadersResponse` is limited by `BATCH` so it has a
  144. // constant max bytes length limit.
  145. let fork_headers_response = ForkHeadersResponse { headers: vec![header; BATCH] };
  146. // Don't forget the extra byte from `Vec` length.
  147. // Length = (BATCH * MAX_HEADER_LEN) + VARINT_LEN = (20 * 3606) + 1 = 72120 + 1 = 72121
  148. assert!(serialize(&fork_headers_response).len() <= (BATCH * MAX_HEADER_LEN) + VARINT_LEN);
  149. // Protocol sync `ForkProposalsRequest` is limited by `BATCH` so it has a
  150. // constant max bytes length limit.
  151. let fork_proposals_request =
  152. ForkProposalsRequest { headers: vec![header_hash; BATCH], fork_header: header_hash };
  153. // Don't forget the extra byte from `Vec` length.
  154. // Length = (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN =
  155. // (20 * 32) + 1 + 32 = 640 + 33 = 673
  156. assert_eq!(
  157. serialize(&fork_proposals_request).len(),
  158. (BATCH * HEADER_HASH_LEN) + VARINT_LEN + HEADER_HASH_LEN
  159. );
  160. // Protocol sync `ForkProposalsResponse` is limited by `BATCH` so it can have a
  161. // constant max bytes length limit, but we are not limiting `Proposal` size.
  162. // Protocol proposal `ProposalMessage` can have a constant max bytes length limit,
  163. // but we are not limiting `Proposal` size.
  164. // Protocol tx `Transaction` can have constant max bytes length limit,
  165. // but we are not limiting `Transaction` size.
  166. }