Files
lighthouse/crypto/kzg/src/kzg_commitment.rs
realbigsean ba891e1fed deneb related logging improvements (#4859)
1. Add commitments to logs and update the `Display` implementation of `KzgCommitment` to become truncated similarly to block root.

I've been finding it difficult to debug scenarios involving multiple blobs for the same `(index, block_root)`. Logging the commitment will help with this, we can match it to what exists in the block. 

Example output:

```
Oct 20 21:13:36.700 DEBG Successfully verified gossip blob       commitment: 0xa3c1…1cd8, index: 0, root: 0xf31e…f9de, slot: 154568
Oct 20 21:13:36.785 DEBG Successfully verified gossip block      commitments: [0xa3c1…1cd8, 0x8655…02ff, 0x8d6a…955a, 0x84ac…3a1b, 0x9752…629b, 0xb9fc…20fb], root: 0xf31eeb732702e429e89057b15e1c0c631e8452e09e03cb1924353f536ef4f9de, slot: 154568, graffiti: teku/besu, service: beacon
```

Example output in a block with no blobs (this will show up pre-deneb):
```
426734:Oct 20 21:15:24.113 DEBG Successfully verified gossip block, commitments: [], root: 0x619db1360ba0e8d44ae2a0f2450ebca47e167191feecffcfac0e8d7b6c39623c, slot: 154577, graffiti: teku/nethermind, service: beacon, module: beacon_chain::beacon_chain:2765
```

2. Remove `strum::IntoStaticStr` from `AvailabilityCheckError`. This is because `IntoStaticStr` end up dropping information inside the enum. So kzg commitments in this error are dropped, making it more difficult to debug
```
AvailabilityCheckError::KzgCommitmentMismatch {
        blob_commitment: KzgCommitment,
        block_commitment: KzgCommitment,
    },
```
which is output as just `AvailabilityCheckError`

3. Some additional misc sync logs I found useful in debugging https://github.com/sigp/lighthouse/pull/4869

4. This downgrades ”Block returned for single block lookup not present” to debug because I don’t think we can fix the scenario that causes this unless we can cancel inflight rpc requests

Co-authored-by: realbigsean <seananderson33@gmail.com>
2023-10-25 15:30:17 +00:00

145 lines
4.2 KiB
Rust

use c_kzg::BYTES_PER_COMMITMENT;
use derivative::Derivative;
use ethereum_hashing::hash_fixed;
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use ssz_derive::{Decode, Encode};
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
use tree_hash::{Hash256, PackedEncoding, TreeHash};
pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01;
#[derive(Derivative, Clone, Copy, Encode, Decode)]
#[derivative(PartialEq, Eq, Hash)]
#[ssz(struct_behaviour = "transparent")]
pub struct KzgCommitment(pub [u8; c_kzg::BYTES_PER_COMMITMENT]);
impl KzgCommitment {
pub fn calculate_versioned_hash(&self) -> Hash256 {
let mut versioned_hash = hash_fixed(&self.0);
versioned_hash[0] = VERSIONED_HASH_VERSION_KZG;
Hash256::from_slice(versioned_hash.as_slice())
}
pub fn empty_for_testing() -> Self {
KzgCommitment([0; c_kzg::BYTES_PER_COMMITMENT])
}
}
impl From<KzgCommitment> for c_kzg::Bytes48 {
fn from(value: KzgCommitment) -> Self {
value.0.into()
}
}
impl Display for KzgCommitment {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "0x")?;
for i in &self.0[0..2] {
write!(f, "{:02x}", i)?;
}
write!(f, "")?;
for i in &self.0[BYTES_PER_COMMITMENT - 2..BYTES_PER_COMMITMENT] {
write!(f, "{:02x}", i)?;
}
Ok(())
}
}
impl TreeHash for KzgCommitment {
fn tree_hash_type() -> tree_hash::TreeHashType {
<[u8; BYTES_PER_COMMITMENT] as TreeHash>::tree_hash_type()
}
fn tree_hash_packed_encoding(&self) -> PackedEncoding {
self.0.tree_hash_packed_encoding()
}
fn tree_hash_packing_factor() -> usize {
<[u8; BYTES_PER_COMMITMENT] as TreeHash>::tree_hash_packing_factor()
}
fn tree_hash_root(&self) -> tree_hash::Hash256 {
self.0.tree_hash_root()
}
}
impl Serialize for KzgCommitment {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&format!("{:?}", self))
}
}
impl<'de> Deserialize<'de> for KzgCommitment {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;
Self::from_str(&string).map_err(serde::de::Error::custom)
}
}
impl FromStr for KzgCommitment {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Some(stripped) = s.strip_prefix("0x") {
let bytes = hex::decode(stripped).map_err(|e| e.to_string())?;
if bytes.len() == BYTES_PER_COMMITMENT {
let mut kzg_commitment_bytes = [0; BYTES_PER_COMMITMENT];
kzg_commitment_bytes[..].copy_from_slice(&bytes);
Ok(Self(kzg_commitment_bytes))
} else {
Err(format!(
"InvalidByteLength: got {}, expected {}",
bytes.len(),
BYTES_PER_COMMITMENT
))
}
} else {
Err("must start with 0x".to_string())
}
}
}
impl Debug for KzgCommitment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", serde_utils::hex::encode(self.0))
}
}
impl arbitrary::Arbitrary<'_> for KzgCommitment {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let mut bytes = [0u8; BYTES_PER_COMMITMENT];
u.fill_buffer(&mut bytes)?;
Ok(KzgCommitment(bytes))
}
}
#[test]
fn kzg_commitment_display() {
let display_commitment_str = "0x53fa…adac";
let display_commitment = KzgCommitment::from_str(
"0x53fa09af35d1d1a9e76f65e16112a9064ce30d1e4e2df98583f0f5dc2e7dd13a4f421a9c89f518fafd952df76f23adac",
)
.unwrap()
.to_string();
assert_eq!(display_commitment, display_commitment_str);
}
#[test]
fn kzg_commitment_debug() {
let debug_commitment_str =
"0x53fa09af35d1d1a9e76f65e16112a9064ce30d1e4e2df98583f0f5dc2e7dd13a4f421a9c89f518fafd952df76f23adac";
let debug_commitment = KzgCommitment::from_str(debug_commitment_str).unwrap();
assert_eq!(format!("{debug_commitment:?}"), debug_commitment_str);
}