diff --git a/.changelog/unreleased/improvements/1413-reuse-sign-bytes.md b/.changelog/unreleased/improvements/1413-reuse-sign-bytes.md new file mode 100644 index 000000000..4198ceae5 --- /dev/null +++ b/.changelog/unreleased/improvements/1413-reuse-sign-bytes.md @@ -0,0 +1,3 @@ +- `[tendermint-light-client-verifier]` Reuse buffer used to store + sign_bytes to reduce number of allocations and deallocations. + ([\#1413](https://github.com/informalsystems/tendermint-rs/pull/1413)) diff --git a/light-client-verifier/src/operations/voting_power.rs b/light-client-verifier/src/operations/voting_power.rs index 1f7e9f0ed..0511cc426 100644 --- a/light-client-verifier/src/operations/voting_power.rs +++ b/light-client-verifier/src/operations/voting_power.rs @@ -264,6 +264,11 @@ impl NonAbsentCommitVote { struct NonAbsentCommitVotes { /// Votes sorted by validator address. votes: Vec, + /// Internal buffer for storing sign_bytes. + /// + /// The buffer is reused for each canonical vote so that we allocate it + /// once. + sign_bytes: Vec, } impl NonAbsentCommitVotes { @@ -297,7 +302,12 @@ impl NonAbsentCommitVotes { pair[0].validator_id(), )) } else { - Ok(Self { votes }) + // As of protocol 0.38, 160 buffer is enough for chain identifier up + // to 44 bytes. + Ok(Self { + votes, + sign_bytes: Vec::with_capacity(160), + }) } } @@ -319,14 +329,18 @@ impl NonAbsentCommitVotes { }; if !vote.verified { - let sign_bytes = vote.signed_vote.sign_bytes(); + self.sign_bytes.truncate(0); + vote.signed_vote + .sign_bytes_into(&mut self.sign_bytes) + .unwrap(); + let sign_bytes = self.sign_bytes.as_slice(); validator - .verify_signature::(&sign_bytes, vote.signed_vote.signature()) + .verify_signature::(sign_bytes, vote.signed_vote.signature()) .map_err(|_| { VerificationError::invalid_signature( vote.signed_vote.signature().as_bytes().to_vec(), Box::new(validator.clone()), - sign_bytes, + sign_bytes.to_vec(), ) })?; } diff --git a/tendermint/src/vote.rs b/tendermint/src/vote.rs index cd37c728d..a4cd82ce0 100644 --- a/tendermint/src/vote.rs +++ b/tendermint/src/vote.rs @@ -329,6 +329,10 @@ impl SignedVote { Protobuf::::encode_length_delimited_vec(self.vote.clone()) } + pub fn sign_bytes_into(&self, buf: &mut impl BufMut) -> Result<(), ProtobufError> { + Protobuf::::encode_length_delimited(self.vote.clone(), buf) + } + /// Return the actual signature on the canonicalized vote. pub fn signature(&self) -> &Signature { &self.signature