consensus_encoding: remove Transitioning state
What changed, and why it matters
This is a small internal code cleanup in a Rust Bitcoin library. It removes an unused 'Transitioning' state from a two-stage data decoder and simplifies how the decoder switches from its first stage to its second stage. There is no indication this fixes a security vulnerability or changes observable behavior for users.
No security action required. Treat as a normal refactoring/reliability improvement. Reviewers may optionally verify that the new inline transition logic preserves the same error paths as the old transition() method.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors Decoder2State in consensus_encoding/src/decode/decoders.rs. It deletes the Transitioning variant and the associated transition() helper, replacing the state swap with an inline mem::replace into Errored. If the first decoder’s end() fails, the state is left as Errored; otherwise it becomes Second. The behavior is equivalent to before because Transitioning was only ever a transient internal placeholder and was documented as ‘should never be observed.’ The change reduces code size and removes a panic branch for an unreachable state.
Changed components
consensus_encoding/src/decode/decoders.rsDecoder2State enumDecoder2 two-stage decoderInspect captured patch +9 / −33
diff --git a/consensus_encoding/src/decode/decoders.rs b/consensus_encoding/src/decode/decoders.rs
index 4ed1a929..3c8d14e8 100644
--- a/consensus_encoding/src/decode/decoders.rs
+++ b/consensus_encoding/src/decode/decoders.rs
@@ -295,26 +295,6 @@ enum Decoder2State<A: Decoder, B: Decoder> {
Second(A::Output, B),
/// Decoder has failed and cannot be used again.
Errored,
- /// Temporary state during transitions from First to Second, should never be observed.
- Transitioning,
-}
-
-impl<A: Decoder, B: Decoder> Decoder2State<A, B> {
- /// Transitions from the first state to second by extracting both decoders.
- ///
- /// We use `mem::replace` to atomically swap the entire state, giving us
- /// ownership of the decoders so we can consume the first decoder while
- /// holding a mutable reference to the state.
- ///
- /// If this method is called when not in the `First` state, we panic
- /// with `#[track_caller]` to show where the bug occurred.
- #[track_caller]
- fn transition(&mut self) -> (A, B) {
- match mem::replace(self, Decoder2State::Transitioning) {
- Decoder2State::First(first, second) => (first, second),
- _ => panic!("transition called on invalid state"),
- }
- }
}
impl<A, B, Err> Decoder2<A, B, Err>
@@ -347,12 +327,15 @@ where
}
// First decoder is complete, transition to second.
- let (first, second) = self.state.transition();
- let first_result = first.end().map_err(|error| {
- self.state = Decoder2State::Errored;
- Err::from(error)
- })?;
- self.state = Decoder2State::Second(first_result, second);
+ // If the first decoder fails, the composite decoder
+ // remains in an Errored state.
+ match mem::replace(&mut self.state, Decoder2State::Errored) {
+ Decoder2State::First(first, second) => {
+ let first_result = first.end()?;
+ self.state = Decoder2State::Second(first_result, second);
+ }
+ _ => unreachable!("we know we're in First state"),
+ }
}
Decoder2State::Second(_, second_decoder) => {
return second_decoder.push_bytes(bytes).map_err(|error| {
@@ -363,9 +346,6 @@ where
Decoder2State::Errored => {
panic!("use of failed decoder");
}
- Decoder2State::Transitioning => {
- panic!("use of decoder in transitioning state");
- }
}
}
}
@@ -388,9 +368,6 @@ where
Decoder2State::Errored => {
panic!("use of failed decoder");
}
- Decoder2State::Transitioning => {
- panic!("use of decoder in transitioning state");
- }
}
}
@@ -401,7 +378,6 @@ where
first_decoder.read_limit() + second_decoder.read_limit(),
Decoder2State::Second(_, second_decoder) => second_decoder.read_limit(),
Decoder2State::Errored => 0,
- Decoder2State::Transitioning => 0,
}
}
}
Why this scored 11/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.