Skip to content

Commit 2410531

Browse files
vicsnljedrz
authored andcommitted
Store a bitset of transmissions in compact subdag.
New types: - CompactCertificate - CompactHeader - Subdag enum can hold either - NarwhalCertificate trait provides an interface - We use BitSet, which used to be part of standard library Co-authored-by ljedrz <ljedrz@users.noreply.github.com>
1 parent 114b6b0 commit 2410531

File tree

51 files changed

+3840
-352
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+3840
-352
lines changed

.circleci/config.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,20 @@ jobs:
484484
- run_test:
485485
workspace_member: snarkvm-ledger-narwhal-batch-header
486486

487+
ledger-narwhal-compact-certificate:
488+
executor: rust-docker
489+
resource_class: << pipeline.parameters.twoxlarge >>
490+
steps:
491+
- run_test:
492+
workspace_member: snarkvm-ledger-narwhal-compact-certificate
493+
494+
ledger-narwhal-compact-header:
495+
executor: rust-docker
496+
resource_class: << pipeline.parameters.twoxlarge >>
497+
steps:
498+
- run_test:
499+
workspace_member: snarkvm-ledger-narwhal-compact-header
500+
487501
ledger-narwhal-data:
488502
executor: rust-docker
489503
resource_class: << pipeline.parameters.small >>
@@ -891,6 +905,8 @@ workflows:
891905
- ledger-narwhal
892906
- ledger-narwhal-batch-certificate
893907
- ledger-narwhal-batch-header
908+
- ledger-narwhal-compact-certificate
909+
- ledger-narwhal-compact-header
894910
- ledger-narwhal-data
895911
- ledger-narwhal-subdag
896912
- ledger-narwhal-transmission

Cargo.lock

Lines changed: 50 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ members = [
6868
"ledger/narwhal",
6969
"ledger/narwhal/batch-certificate",
7070
"ledger/narwhal/batch-header",
71+
"ledger/narwhal/compact-certificate",
72+
"ledger/narwhal/compact-header",
7173
"ledger/narwhal/data",
7274
"ledger/narwhal/subdag",
7375
"ledger/narwhal/transmission",
@@ -365,6 +367,18 @@ version = "=4.1.0"
365367
path = "ledger/narwhal/batch-certificate"
366368
version = "=4.1.0"
367369

370+
[workspace.dependencies.snarkvm-ledger-narwhal-compact-certificate]
371+
path = "ledger/narwhal/compact-certificate"
372+
version = "=4.0.0"
373+
374+
[workspace.dependencies.snarkvm-ledger-narwhal-compact-header]
375+
path = "ledger/narwhal/compact-header"
376+
version = "=4.0.0"
377+
378+
[workspace.dependencies.snarkvm-ledger-narwhal-traits]
379+
path = "ledger/narwhal/traits"
380+
version = "=4.0.0"
381+
368382
[workspace.dependencies.snarkvm-ledger-narwhal-subdag]
369383
path = "ledger/narwhal/subdag"
370384
version = "=4.1.0"

ledger/block/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ features = [ "default" ]
5050
[dependencies.snarkvm-ledger-narwhal-batch-header]
5151
workspace = true
5252

53+
[dependencies.snarkvm-ledger-narwhal-batch-certificate]
54+
workspace = true
55+
56+
[dependencies.snarkvm-ledger-narwhal-compact-certificate]
57+
workspace = true
58+
5359
[dependencies.snarkvm-ledger-narwhal-data]
5460
workspace = true
5561

@@ -68,6 +74,9 @@ workspace = true
6874
[dependencies.snarkvm-synthesizer-snark]
6975
workspace = true
7076

77+
[dependencies.bit-set]
78+
version = "0.8"
79+
7180
[dependencies.indexmap]
7281
workspace = true
7382
features = [ "serde" ]

ledger/block/src/bytes.rs

Lines changed: 124 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl<N: Network> FromBytes for Block<N> {
2222
// Read the version.
2323
let version = u8::read_le(&mut reader)?;
2424
// Ensure the version is valid.
25-
if version != 1 {
25+
if ![1, 2].contains(&version) {
2626
return Err(error("Invalid block version"));
2727
}
2828

@@ -42,32 +42,78 @@ impl<N: Network> FromBytes for Block<N> {
4242
// Read the solutions.
4343
let solutions: Solutions<N> = FromBytes::read_le(&mut reader)?;
4444

45-
// Read the number of aborted solution IDs.
46-
let num_aborted_solutions = u32::read_le(&mut reader)?;
47-
// Ensure the number of aborted solutions IDs is within bounds (this is an early safety check).
48-
if num_aborted_solutions as usize > Solutions::<N>::max_aborted_solutions().map_err(error)? {
49-
return Err(error("Invalid number of aborted solutions IDs in the block"));
50-
}
51-
// Read the aborted solution IDs.
52-
let mut aborted_solution_ids = Vec::with_capacity(num_aborted_solutions as usize);
53-
for _ in 0..num_aborted_solutions {
54-
aborted_solution_ids.push(FromBytes::read_le(&mut reader)?);
55-
}
45+
let (prior_solution_transmission_ids, aborted_solution_transmission_ids, aborted_solution_ids) = if version >= 2
46+
{
47+
// Read the number of prior solution transmission IDs.
48+
let num_prior_solutions = u32::read_le(&mut reader)?; // TODO: what is a sane bound on this value?
49+
// Read the prior solution transmission IDs.
50+
let mut prior_solution_transmission_ids = Vec::with_capacity(num_prior_solutions as usize);
51+
for _ in 0..num_prior_solutions {
52+
prior_solution_transmission_ids.push(FromBytes::read_le(&mut reader)?);
53+
}
54+
// Read the number of aborted solution transmission IDs.
55+
let num_aborted_solutions = u32::read_le(&mut reader)?;
56+
if num_aborted_solutions as usize > Solutions::<N>::max_aborted_solutions().map_err(error)? {
57+
return Err(error("Invalid number of aborted solutions IDs in the block"));
58+
}
59+
// Read the aborted solution transmission IDs.
60+
let mut aborted_solution_transmission_ids = Vec::with_capacity(num_aborted_solutions as usize);
61+
for _ in 0..num_aborted_solutions {
62+
aborted_solution_transmission_ids.push(FromBytes::read_le(&mut reader)?);
63+
}
64+
(Some(prior_solution_transmission_ids), Some(aborted_solution_transmission_ids), vec![])
65+
} else {
66+
// Read the number of aborted solution IDs.
67+
let num_aborted_solutions = u32::read_le(&mut reader)?;
68+
// Ensure the number of aborted solutions IDs is within bounds (this is an early safety check).
69+
if num_aborted_solutions as usize > Solutions::<N>::max_aborted_solutions().map_err(error)? {
70+
return Err(error("Invalid number of aborted solutions IDs in the block"));
71+
}
72+
// Read the aborted solution IDs.
73+
let mut aborted_solution_ids = Vec::with_capacity(num_aborted_solutions as usize);
74+
for _ in 0..num_aborted_solutions {
75+
aborted_solution_ids.push(FromBytes::read_le(&mut reader)?);
76+
}
77+
(None, None, aborted_solution_ids)
78+
};
5679

5780
// Read the transactions.
5881
let transactions = FromBytes::read_le(&mut reader)?;
5982

60-
// Read the number of aborted transaction IDs.
61-
let num_aborted_transactions = u32::read_le(&mut reader)?;
62-
// Ensure the number of aborted transaction IDs is within bounds (this is an early safety check).
63-
if num_aborted_transactions as usize > Transactions::<N>::max_aborted_transactions().map_err(error)? {
64-
return Err(error("Invalid number of aborted transaction IDs in the block"));
65-
}
66-
// Read the aborted transaction IDs.
67-
let mut aborted_transaction_ids = Vec::with_capacity(num_aborted_transactions as usize);
68-
for _ in 0..num_aborted_transactions {
69-
aborted_transaction_ids.push(FromBytes::read_le(&mut reader)?);
70-
}
83+
let (prior_transaction_transmission_ids, aborted_transaction_transmission_ids, aborted_transaction_ids) =
84+
if version >= 2 {
85+
// Read the number of prior transaction transmission IDs.
86+
let num_prior_transactions = u32::read_le(&mut reader)?; // TODO: what is a sane bound on this value?
87+
// Read the prior transaction transmission IDs.
88+
let mut prior_transaction_transmission_ids = Vec::with_capacity(num_prior_transactions as usize);
89+
for _ in 0..num_prior_transactions {
90+
prior_transaction_transmission_ids.push(FromBytes::read_le(&mut reader)?);
91+
}
92+
// Read the number of aborted transaction transmission IDs.
93+
let num_aborted_transactions = u32::read_le(&mut reader)?;
94+
if num_aborted_transactions as usize > Transactions::<N>::max_aborted_transactions().map_err(error)? {
95+
return Err(error("Invalid number of aborted transaction IDs in the block"));
96+
}
97+
// Read the aborted transaction transmission IDs.
98+
let mut aborted_transaction_transmission_ids = Vec::with_capacity(num_aborted_transactions as usize);
99+
for _ in 0..num_aborted_transactions {
100+
aborted_transaction_transmission_ids.push(FromBytes::read_le(&mut reader)?);
101+
}
102+
(Some(prior_transaction_transmission_ids), Some(aborted_transaction_transmission_ids), vec![])
103+
} else {
104+
// Read the number of aborted transaction IDs.
105+
let num_aborted_transactions = u32::read_le(&mut reader)?;
106+
// Ensure the number of aborted transaction IDs is within bounds (this is an early safety check).
107+
if num_aborted_transactions as usize > Transactions::<N>::max_aborted_transactions().map_err(error)? {
108+
return Err(error("Invalid number of aborted transaction IDs in the block"));
109+
}
110+
// Read the aborted transaction IDs.
111+
let mut aborted_transaction_ids = Vec::with_capacity(num_aborted_transactions as usize);
112+
for _ in 0..num_aborted_transactions {
113+
aborted_transaction_ids.push(FromBytes::read_le(&mut reader)?);
114+
}
115+
(None, None, aborted_transaction_ids)
116+
};
71117

72118
// Construct the block.
73119
let block = Self::from(
@@ -76,8 +122,12 @@ impl<N: Network> FromBytes for Block<N> {
76122
authority,
77123
ratifications,
78124
solutions,
125+
prior_solution_transmission_ids,
126+
aborted_solution_transmission_ids,
79127
aborted_solution_ids,
80128
transactions,
129+
prior_transaction_transmission_ids,
130+
aborted_transaction_transmission_ids,
81131
aborted_transaction_ids,
82132
)
83133
.map_err(error)?;
@@ -95,7 +145,9 @@ impl<N: Network> ToBytes for Block<N> {
95145
#[inline]
96146
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
97147
// Write the version.
98-
1u8.write_le(&mut writer)?;
148+
let version =
149+
if N::CONSENSUS_VERSION(self.height()).map_err(error)? >= ConsensusVersion::V10 { 2u8 } else { 1 };
150+
version.write_le(&mut writer)?;
99151

100152
// Write the block hash.
101153
self.block_hash.write_le(&mut writer)?;
@@ -113,16 +165,57 @@ impl<N: Network> ToBytes for Block<N> {
113165
// Write the solutions.
114166
self.solutions.write_le(&mut writer)?;
115167

116-
// Write the aborted solution IDs.
117-
(u32::try_from(self.aborted_solution_ids.len()).map_err(error))?.write_le(&mut writer)?;
118-
self.aborted_solution_ids.write_le(&mut writer)?;
168+
match version {
169+
1 => {
170+
// Write the aborted solution IDs.
171+
(u32::try_from(self.aborted_solution_ids.len()).map_err(error))?.write_le(&mut writer)?;
172+
self.aborted_solution_ids.write_le(&mut writer)?;
173+
}
174+
_ => {
175+
// Write the prior solution transmission ids.
176+
let prior_solution_transmission_ids = self
177+
.prior_solution_transmission_ids
178+
.as_ref()
179+
.ok_or(error("missing prior_solution_transmission_ids"))?;
180+
(u32::try_from(prior_solution_transmission_ids.len()).map_err(error))?.write_le(&mut writer)?;
181+
prior_solution_transmission_ids.write_le(&mut writer)?;
182+
// Write the aborted solution transmission ids.
183+
let aborted_solution_transmission_ids = self
184+
.aborted_solution_transmission_ids
185+
.as_ref()
186+
.ok_or(error("missing aborted_solution_transmission_ids"))?;
187+
(u32::try_from(aborted_solution_transmission_ids.len()).map_err(error))?.write_le(&mut writer)?;
188+
aborted_solution_transmission_ids.write_le(&mut writer)?;
189+
}
190+
}
119191

120192
// Write the transactions.
121193
self.transactions.write_le(&mut writer)?;
122194

123-
// Write the aborted transaction IDs.
124-
(u32::try_from(self.aborted_transaction_ids.len()).map_err(error))?.write_le(&mut writer)?;
125-
self.aborted_transaction_ids.write_le(&mut writer)
195+
match version {
196+
1 => {
197+
// Write the aborted transaction ids.
198+
(u32::try_from(self.aborted_transaction_ids.len()).map_err(error))?.write_le(&mut writer)?;
199+
self.aborted_transaction_ids.write_le(&mut writer)?;
200+
}
201+
_ => {
202+
// Write the prior transaction transmission ids.
203+
let prior_transaction_transmission_ids = self
204+
.prior_transaction_transmission_ids
205+
.as_ref()
206+
.ok_or(error("missing prior_transaction_transmission_ids"))?;
207+
(u32::try_from(prior_transaction_transmission_ids.len()).map_err(error))?.write_le(&mut writer)?;
208+
prior_transaction_transmission_ids.write_le(&mut writer)?;
209+
// Write the aborted transaction transmission ids.
210+
let aborted_transaction_transmission_ids = self
211+
.aborted_transaction_transmission_ids
212+
.as_ref()
213+
.ok_or(error("missing aborted_transaction_transmission_ids"))?;
214+
(u32::try_from(aborted_transaction_transmission_ids.len()).map_err(error))?.write_le(&mut writer)?;
215+
aborted_transaction_transmission_ids.write_le(&mut writer)?;
216+
}
217+
}
218+
Ok(())
126219
}
127220
}
128221

@@ -138,6 +231,7 @@ mod tests {
138231
let rng = &mut TestRng::default();
139232

140233
for expected in [crate::test_helpers::sample_genesis_block(rng)].into_iter() {
234+
// todo: sample compact too for the Block tests
141235
// Check the byte representation.
142236
let expected_bytes = expected.to_bytes_le()?;
143237
assert_eq!(expected, Block::read_le(&expected_bytes[..])?);

0 commit comments

Comments
 (0)