Skip to content

Commit 72ff7fb

Browse files
committed
non-working tree hash
1 parent e9ebfd2 commit 72ff7fb

File tree

3 files changed

+140
-51
lines changed

3 files changed

+140
-51
lines changed

Diff for: anchor/common/ssv_types/src/message.rs

+113-15
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use std::{
66
use ssz::{Decode, DecodeError, Encode};
77
use ssz_derive::{Decode, Encode};
88
use thiserror::Error;
9-
use tree_hash::{PackedEncoding, TreeHash, TreeHashType};
10-
use zerocopy::IntoBytes;
9+
use tree_hash::{merkle_root, mix_in_length, MerkleHasher, PackedEncoding, TreeHash, TreeHashType};
10+
use types::Hash256;
1111

1212
use crate::{
1313
message::{
@@ -82,16 +82,17 @@ impl TreeHash for MsgType {
8282
}
8383

8484
fn tree_hash_packed_encoding(&self) -> PackedEncoding {
85-
todo!()
85+
let value = self.clone() as u64;
86+
value.tree_hash_packed_encoding()
8687
}
8788

8889
fn tree_hash_packing_factor() -> usize {
89-
1
90+
u64::tree_hash_packing_factor()
9091
}
9192

9293
fn tree_hash_root(&self) -> tree_hash::Hash256 {
93-
let encoding = self.tree_hash_packed_encoding();
94-
tree_hash::Hash256::from_slice(encoding.as_bytes())
94+
let value = self.clone() as u64;
95+
value.tree_hash_root()
9596
}
9697
}
9798

@@ -181,19 +182,44 @@ pub struct SSVMessage {
181182

182183
impl TreeHash for SSVMessage {
183184
fn tree_hash_type() -> TreeHashType {
184-
todo!()
185+
TreeHashType::Container
185186
}
186187

187188
fn tree_hash_packed_encoding(&self) -> PackedEncoding {
188-
todo!()
189+
unreachable!("Container should not be packed")
189190
}
190191

191192
fn tree_hash_packing_factor() -> usize {
192-
todo!()
193+
unreachable!("Container should not be packed")
193194
}
194195

195196
fn tree_hash_root(&self) -> tree_hash::Hash256 {
196-
todo!()
197+
let mut hasher = MerkleHasher::with_leaves(3);
198+
199+
hasher
200+
.write(self.msg_type.tree_hash_root().as_slice())
201+
.unwrap();
202+
hasher
203+
.write(self.msg_id.tree_hash_root().as_slice())
204+
.unwrap();
205+
// Field 2: Data - variable-length byte array
206+
// First get the data index
207+
// Calculate chunks needed ((max_size + 31) / 32)
208+
let chunks_needed = (722412 + 31) / 32;
209+
210+
// Merkleize the data with the calculated chunk count
211+
let data_root = merkle_root(&self.data, chunks_needed);
212+
213+
// Mix in the length - this is equivalent to MerkleizeWithMixin in Go
214+
let data_with_length = mix_in_length(&data_root, self.data.len());
215+
216+
// Add hashed data to the main tree
217+
hasher
218+
.write(data_with_length.as_slice())
219+
.expect("Failed to write data");
220+
221+
// Finalize and return the root
222+
hasher.finish().expect("Failed to finish hashing")
197223
}
198224
}
199225

@@ -331,19 +357,91 @@ pub struct SignedSSVMessage {
331357

332358
impl TreeHash for SignedSSVMessage {
333359
fn tree_hash_type() -> TreeHashType {
334-
todo!()
360+
TreeHashType::Container
335361
}
336362

337363
fn tree_hash_packed_encoding(&self) -> PackedEncoding {
338-
todo!()
364+
unreachable!("Container should never be packed.")
339365
}
340366

341367
fn tree_hash_packing_factor() -> usize {
342-
todo!()
368+
unreachable!("Container should never be packed.")
343369
}
344370

345-
fn tree_hash_root(&self) -> tree_hash::Hash256 {
346-
todo!()
371+
fn tree_hash_root(&self) -> Hash256 {
372+
// Create hasher for 4 fields
373+
let mut hasher = MerkleHasher::with_leaves(4);
374+
375+
let signatures_root = self.hash_signatures();
376+
hasher
377+
.write(signatures_root.as_slice())
378+
.expect("Failed to write signatures");
379+
380+
let operator_ids_root = self.hash_operator_ids();
381+
hasher
382+
.write(operator_ids_root.as_slice())
383+
.expect("Failed to write operator IDs");
384+
385+
hasher
386+
.write(self.ssv_message.tree_hash_root().as_slice())
387+
.expect("Failed to write SSV message");
388+
389+
let max_chunks = (8388836 + 31) / 32;
390+
let full_data_root = merkle_root(&self.full_data, max_chunks);
391+
let full_data_with_length = mix_in_length(&full_data_root, self.full_data.len());
392+
393+
hasher
394+
.write(full_data_with_length.as_slice())
395+
.expect("Failed to write full data");
396+
397+
// Finalize and return root hash
398+
hasher.finish().expect("Failed to finish hashing")
399+
}
400+
}
401+
402+
// Helper methods to keep the main implementation cleaner
403+
impl SignedSSVMessage {
404+
fn hash_signatures(&self) -> Hash256 {
405+
// Create a hasher for the signatures list
406+
let mut signatures_hasher = MerkleHasher::with_leaves(self.signatures.len());
407+
408+
// Hash each signature
409+
for signature in &self.signatures {
410+
// Each signature is a variable-length byte array with max 256 bytes
411+
let signature_chunks = (256 + 31) / 32;
412+
let signature_root = merkle_root(signature, signature_chunks);
413+
let signature_with_length = mix_in_length(&signature_root, signature.len());
414+
415+
signatures_hasher
416+
.write(signature_with_length.as_slice())
417+
.expect("Failed to write signature");
418+
}
419+
420+
// Get the signatures list root and mix in length
421+
let root = signatures_hasher
422+
.finish()
423+
.expect("Failed to hash signatures");
424+
mix_in_length(&root, self.signatures.len())
425+
}
426+
427+
fn hash_operator_ids(&self) -> Hash256 {
428+
// Create a hasher for the operator IDs list
429+
let mut operators_hasher = MerkleHasher::with_leaves(self.operator_ids.len());
430+
431+
// Hash each operator ID
432+
for operator_id in &self.operator_ids {
433+
// Assuming OperatorId can be converted to u64
434+
let id_value: u64 = operator_id.0;
435+
operators_hasher
436+
.write(id_value.tree_hash_root().as_slice())
437+
.expect("Failed to write operator ID");
438+
}
439+
440+
// Get the operator IDs list root and mix in length
441+
let root = operators_hasher
442+
.finish()
443+
.expect("Failed to hash operator IDs");
444+
mix_in_length(&root, self.operator_ids.len())
347445
}
348446
}
349447

Diff for: anchor/spec_tests/src/qbft/create_message.rs

+7-19
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
use std::{collections::VecDeque, sync::Arc};
2-
31
use openssl::pkey::{PKey, Private};
4-
use parking_lot::RwLock;
5-
use qbft::UnsignedWrappedQbftMessage;
62
use serde::Deserialize;
7-
use ssv_types::{consensus::QbftMessageType, OperatorId, Round};
3+
use ssv_types::{consensus::QbftMessageType, IndexSet, OperatorId, Round};
84
use types::Hash256;
95

106
use super::{qbft_deserializers::*, SpecQbft};
@@ -19,15 +15,10 @@ impl SpecTest for CreateMessageTest {
1915
fn run(&self) -> bool {
2016
let spec_qbft = self.spec_qbft.as_ref().expect("Setup has been called");
2117
let key = self.signing_key.as_ref().expect("Setup has been called");
22-
let msg_queue = self.msg_rx.as_ref().expect("Setup has been called").clone();
2318

2419
// Create a new unsigned message. Have to create a new unsigned message to be received on
2520
// the queue and then perform signing
26-
spec_qbft.create_message(self.create_type, self.root);
27-
let unsigned_message = msg_queue
28-
.write()
29-
.pop_back()
30-
.expect("Have already created the message");
21+
let unsigned_message = spec_qbft.create_message(self.create_type, self.root);
3122
let signed_message = spec_qbft.sign(unsigned_message, key);
3223

3324
// Compute the merkle root of the message and compare it to the expected_root
@@ -36,21 +27,22 @@ impl SpecTest for CreateMessageTest {
3627

3728
// Setup the qbft instance for constructing a new message
3829
fn setup(&mut self) {
39-
let four_key_set = TestKeySet::four_share_set();
30+
let four_share_set = TestKeySet::four_share_set();
31+
let committee: IndexSet<OperatorId> =
32+
four_share_set.operator_keys.keys().cloned().collect();
4033

4134
// All message creation testing code uses operator one as the message signer
42-
let operator_one_private = four_key_set
35+
let operator_one_private = four_share_set
4336
.operator_keys
4437
.get(&OperatorId::from(1))
4538
.expect("Exists");
4639
let operator_one_private =
4740
PKey::from_rsa(operator_one_private.to_owned()).expect("Valid key");
4841

49-
let (qbft, queue) = SpecQbft::new();
42+
let qbft = SpecQbft::new(committee);
5043

5144
// Complete the setup
5245
self.spec_qbft = Some(qbft);
53-
self.msg_rx = Some(queue);
5446
self.signing_key = Some(operator_one_private);
5547
}
5648

@@ -104,10 +96,6 @@ pub struct CreateMessageTest {
10496
#[serde(skip)]
10597
pub spec_qbft: Option<SpecQbft>,
10698

107-
// Unsigned message receiver
108-
#[serde(skip)]
109-
pub msg_rx: Option<Arc<RwLock<VecDeque<UnsignedWrappedQbftMessage>>>>,
110-
11199
// The operator private key for message signing
112100
#[serde(skip)]
113101
pub signing_key: Option<PKey<Private>>,

Diff for: anchor/spec_tests/src/qbft/mod.rs

+20-17
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use ssv_types::{
2323
consensus::{BeaconVote, QbftMessageType},
2424
message::SignedSSVMessage,
2525
msgid::MessageId,
26-
OperatorId, Round,
26+
IndexSet, OperatorId, Round,
2727
};
2828
use ssz::Encode;
2929
pub use timeout::TimeoutTest;
@@ -39,15 +39,14 @@ pub type ExplicitSendFn = Arc<RwLock<VecDeque<UnsignedWrappedQbftMessage>>>;
3939
pub struct SpecQbft(pub ExplicitQbft);
4040
impl SpecQbft {
4141
// Construct a wrapped qbft instance
42-
pub fn new() -> (Self, ExplicitSendFn) {
43-
let config: Config<DefaultLeaderFunction> = ConfigBuilder::new(
44-
1.into(),
45-
InstanceHeight::default(),
46-
(1..=4).map(OperatorId::from).collect(),
47-
)
48-
.build()
49-
.unwrap();
50-
42+
pub fn new(committee: IndexSet<OperatorId>) -> Self {
43+
let config: Config<DefaultLeaderFunction> =
44+
ConfigBuilder::new(1.into(), InstanceHeight::default(), committee)
45+
.build()
46+
.unwrap();
47+
48+
// Todo!(). For creation tests, start data does not matter since we are not testing
49+
// consensus. Adjust for consensus tests
5150
let data = BeaconVote {
5251
block_root: Hash256::random(),
5352
source: types::Checkpoint::default(),
@@ -57,18 +56,23 @@ impl SpecQbft {
5756
let msg_queue = Arc::new(RwLock::new(VecDeque::new()));
5857
let msg_queue_clone = msg_queue.clone();
5958

60-
let message_handler: QbftSendFn =
61-
Box::new(move |message| msg_queue_clone.write().push_back(message));
59+
let message_handler: QbftSendFn = Box::new(move |message| {
60+
msg_queue_clone.write().push_back(message);
61+
});
6262

6363
let qbft = Qbft::new(config, data, MessageId::from([0; 56]), message_handler);
6464

65-
(SpecQbft(qbft), msg_queue)
65+
SpecQbft(qbft)
6666
}
6767

6868
// Create a new UnsignedSSVMessage. Will be send to the queue registered with the qbft instance
69-
pub fn create_message(&self, message_type: QbftMessageType, data_hash: Hash256) {
69+
pub fn create_message(
70+
&self,
71+
message_type: QbftMessageType,
72+
data_hash: Hash256,
73+
) -> UnsignedWrappedQbftMessage {
7074
self.0
71-
.new_unsigned_message_spec(message_type, data_hash, vec![], vec![]);
75+
.new_unsigned_message_spec(message_type, data_hash, vec![], vec![])
7276
}
7377

7478
// In favor of not having to construct an entire NetworkMessageSender, just copy the signing
@@ -96,8 +100,7 @@ impl SpecQbft {
96100

97101
// Confirm that merkle root of signed message equals the expected root
98102
pub fn verify_root(&self, msg: SignedSSVMessage, root: Hash256) -> bool {
99-
let spec_message: qbft_spec_types::SpecSignedSSVMessage = msg.into();
100-
spec_message.tree_hash_root() == root
103+
msg.tree_hash_root() == root
101104
}
102105
}
103106

0 commit comments

Comments
 (0)