Skip to content

Commit 225250d

Browse files
committed
test: add test compute tree_hash_root
1 parent e9a81c5 commit 225250d

3 files changed

Lines changed: 77 additions & 9 deletions

File tree

crates/charon/src/obolapi/client.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ impl Client {
7777
/// Returns the Launchpad cluster dashboard page for a
7878
/// given lock, on the given Obol API client.
7979
pub fn launchpad_url_for_lock(&self, lock: &Lock) -> String {
80-
let mut url = self.url();
81-
url.set_path(&launchpad_url_path(lock));
80+
let url = self.build_url(&launchpad_url_path(lock));
8281
url.to_string()
8382
}
8483

crates/charon/src/obolapi/exit.rs

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ const FETCH_FULL_EXIT_TMPL: &str = "/exp/exit/{lock_hash}/{share_index}/{validat
202202

203203
impl Client {
204204
/// Posts the set of msg's to the Obol API, for a given lock hash.
205-
// It respects the timeout specified in the Client instance.
205+
/// It respects the timeout specified in the Client instance.
206206
pub async fn post_partial_exits(
207207
&self,
208208
lock_hash: &[u8],
@@ -301,11 +301,9 @@ impl Client {
301301
let mut sig = [0u8; 96];
302302
sig.copy_from_slice(&sig_bytes);
303303

304-
// Signature indices are 1-based in threshold BLS
305-
let share_idx = sig_idx
306-
.checked_add(1)
307-
.and_then(|idx| u8::try_from(idx).ok())
308-
.ok_or_else(|| Error::InvalidSignatureSize(sig_idx.saturating_add(1)))?;
304+
// `BlstImpl::threshold_aggregate` shifts the index to 1-based internally
305+
let share_idx = u8::try_from(sig_idx)
306+
.map_err(|_| Error::InvalidSignatureSize(sig_idx.saturating_add(1)))?;
309307
raw_signatures.insert(share_idx, sig);
310308
}
311309

@@ -328,7 +326,7 @@ impl Client {
328326

329327
/// Deletes the partial exit message for a given validator public key, lock
330328
/// hash and share index.
331-
// It respects the timeout specified in the Client instance.
329+
/// It respects the timeout specified in the Client instance.
332330
pub async fn delete_partial_exit(
333331
&self,
334332
val_pubkey: &str,
@@ -608,4 +606,74 @@ mod tests {
608606
"https://api.obol.tech/v1/exp/exit/0xlockhash/5/0xpubkey"
609607
);
610608
}
609+
610+
/// These test vectors were generated from Go `charon/app/obolapi` using
611+
/// fastssz
612+
#[test]
613+
fn test_ssz_root_parity_exit_models() -> std::result::Result<(), Box<dyn std::error::Error>> {
614+
fn decode_hex(s: &str) -> std::result::Result<Vec<u8>, hex::FromHexError> {
615+
hex::decode(s)
616+
}
617+
618+
fn decode_hex_32(s: &str) -> std::result::Result<[u8; 32], Box<dyn std::error::Error>> {
619+
let bytes = decode_hex(s)?;
620+
let len = bytes.len();
621+
let arr: [u8; 32] = bytes
622+
.try_into()
623+
.map_err(|_| format!("expected 32 bytes, got {}", len))?;
624+
Ok(arr)
625+
}
626+
627+
let lock_hash: Vec<u8> =
628+
decode_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")?;
629+
let validator_pubkey: Vec<u8> = decode_hex(
630+
"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20\
631+
2122232425262728292a2b2c2d2e2f30",
632+
)?;
633+
let bls_sig_hex = "0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\
634+
202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\
635+
404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f";
636+
637+
let exit_blob = ExitBlob {
638+
public_key: Some(to_0x(&validator_pubkey)),
639+
signed_exit_message: SignedVoluntaryExit {
640+
message: Phase0SignedVoluntaryExitMessage {
641+
epoch: "194048".to_string(),
642+
validator_index: "42".to_string(),
643+
},
644+
signature: bls_sig_hex.to_string(),
645+
},
646+
};
647+
let partial_exits: PartialExits = vec![exit_blob.clone()].into();
648+
let unsigned = UnsignedPartialExitRequest {
649+
partial_exits: partial_exits.clone(),
650+
share_idx: 3,
651+
};
652+
let auth = FullExitAuthBlob {
653+
lock_hash,
654+
validator_pubkey,
655+
share_index: 3,
656+
};
657+
658+
let got_exit = exit_blob.hash_tree_root()?;
659+
let got_partial = partial_exits.hash_tree_root()?;
660+
let got_unsigned = unsigned.hash_tree_root()?;
661+
let got_auth = auth.hash_tree_root()?;
662+
663+
let want_exit =
664+
decode_hex_32("af0b1a9d98ac628035219391f59ee2708d813a3d860c6d17fa8cae0fb0746d20")?;
665+
let want_partial =
666+
decode_hex_32("9f310361788c9dfc6b0a3cfd77febad4c9a834c368be91ae0e570a40f82e810e")?;
667+
let want_unsigned =
668+
decode_hex_32("b58b5989634e567fa82b7c141918e30e44051c1ed6d0c36c3269021c531f4669")?;
669+
let want_auth =
670+
decode_hex_32("f7fec0dccbdeba7a7aa5978058df8891d1c403bb455a481677ecb5360b2f7fd6")?;
671+
672+
assert_eq!(got_exit, want_exit);
673+
assert_eq!(got_partial, want_partial);
674+
assert_eq!(got_unsigned, want_unsigned);
675+
assert_eq!(got_auth, want_auth);
676+
677+
Ok(())
678+
}
611679
}

crates/charon/src/obolapi/helper.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub fn to_0x(data: &[u8]) -> String {
3535
pub fn bearer_string(data: &[u8]) -> String {
3636
format!("Bearer {}", to_0x(data))
3737
}
38+
3839
#[cfg(test)]
3940
mod tests {
4041
use super::*;

0 commit comments

Comments
 (0)