sanitizes shreds recovered from erasure shards (#29286)

Instead of sanitizing shreds late in recover code:
https://github.com/solana-labs/solana/blob/50ad0390f/ledger/src/shred/merkle.rs#L786

Shred{Code,Data}::from_recovered_shard should sanitize shreds before
returning:
https://github.com/solana-labs/solana/blob/50ad0390f/ledger/src/shred/merkle.rs#L192-L216
https://github.com/solana-labs/solana/blob/50ad0390f/ledger/src/shred/merkle.rs#L324-L350
This commit is contained in:
behzad nouri 2022-12-15 20:09:15 +00:00 committed by GitHub
parent ccd96e246b
commit 73c42dde6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 17 additions and 16 deletions

View File

@ -208,11 +208,14 @@ impl ShredData {
return Err(Error::InvalidShardSize(shard_size)); return Err(Error::InvalidShardSize(shard_size));
} }
let data_header = deserialize_from_with_limit(&mut cursor)?; let data_header = deserialize_from_with_limit(&mut cursor)?;
Ok(Self { let shred = Self {
common_header, common_header,
data_header, data_header,
payload: shard, payload: shard,
}) };
// Merkle proof is not erasure coded and is not yet available here.
shred.sanitize(/*verify_merkle_proof:*/ false)?;
Ok(shred)
} }
fn set_merkle_branch(&mut self, merkle_branch: &MerkleBranch) -> Result<(), Error> { fn set_merkle_branch(&mut self, merkle_branch: &MerkleBranch) -> Result<(), Error> {
@ -238,9 +241,7 @@ impl ShredData {
if !matches!(shred_variant, ShredVariant::MerkleData(_)) { if !matches!(shred_variant, ShredVariant::MerkleData(_)) {
return Err(Error::InvalidShredVariant); return Err(Error::InvalidShredVariant);
} }
if !verify_merkle_proof { if verify_merkle_proof && !self.verify_merkle_proof()? {
debug_assert_matches!(self.verify_merkle_proof(), Ok(true));
} else if !self.verify_merkle_proof()? {
return Err(Error::InvalidMerkleProof); return Err(Error::InvalidMerkleProof);
} }
shred_data::sanitize(self) shred_data::sanitize(self)
@ -342,11 +343,14 @@ impl ShredCode {
let mut cursor = Cursor::new(&mut shard[..]); let mut cursor = Cursor::new(&mut shard[..]);
bincode::serialize_into(&mut cursor, &common_header)?; bincode::serialize_into(&mut cursor, &common_header)?;
bincode::serialize_into(&mut cursor, &coding_header)?; bincode::serialize_into(&mut cursor, &coding_header)?;
Ok(Self { let shred = Self {
common_header, common_header,
coding_header, coding_header,
payload: shard, payload: shard,
}) };
// Merkle proof is not erasure coded and is not yet available here.
shred.sanitize(/*verify_merkle_proof:*/ false)?;
Ok(shred)
} }
fn set_merkle_branch(&mut self, merkle_branch: &MerkleBranch) -> Result<(), Error> { fn set_merkle_branch(&mut self, merkle_branch: &MerkleBranch) -> Result<(), Error> {
@ -372,9 +376,7 @@ impl ShredCode {
if !matches!(shred_variant, ShredVariant::MerkleCode(_)) { if !matches!(shred_variant, ShredVariant::MerkleCode(_)) {
return Err(Error::InvalidShredVariant); return Err(Error::InvalidShredVariant);
} }
if !verify_merkle_proof { if verify_merkle_proof && !self.verify_merkle_proof()? {
debug_assert_matches!(self.verify_merkle_proof(), Ok(true));
} else if !self.verify_merkle_proof()? {
return Err(Error::InvalidMerkleProof); return Err(Error::InvalidMerkleProof);
} }
shred_code::sanitize(self) shred_code::sanitize(self)
@ -771,6 +773,8 @@ pub(super) fn recover(
return Err(Error::InvalidMerkleProof); return Err(Error::InvalidMerkleProof);
} }
shred.set_merkle_branch(&merkle_branch)?; shred.set_merkle_branch(&merkle_branch)?;
// Already sanitized in Shred{Code,Data}::from_recovered_shard.
debug_assert_matches!(shred.sanitize(/*verify_merkle_proof:*/ true), Ok(()));
// Assert that shred payload is fully populated. // Assert that shred payload is fully populated.
debug_assert_eq!(shred, { debug_assert_eq!(shred, {
let shred = shred.payload().clone(); let shred = shred.payload().clone();
@ -778,15 +782,12 @@ pub(super) fn recover(
}); });
} }
} }
shreds Ok(shreds
.into_iter() .into_iter()
.zip(mask) .zip(mask)
.filter(|(_, mask)| !mask) .filter(|(_, mask)| !mask)
.map(|(shred, _)| { .map(|(shred, _)| shred)
shred.sanitize(/*verify_merkle_proof:*/ false)?; .collect())
Ok(shred)
})
.collect()
} }
// Maps number of (code + data) shreds to MerkleBranch.proof.len(). // Maps number of (code + data) shreds to MerkleBranch.proof.len().