Add tests for WitnessVersion and Opcode
What changed, and why it matters
This commit only adds unit tests for existing WitnessVersion and Opcode logic. It does not change any production behavior except making one internal opcode constant available during test builds. There is no security issue here.
No action needed; this is a routine test-only commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit adds test coverage to primitives/src/witness_version.rs and adjusts a #[cfg] guard on OP_PUSHDATA4 in primitives/src/opcodes.rs so the constant is visible under #[cfg(test)] without the alloc feature. The production code paths are unchanged. No vulnerability is introduced or fixed.
Changed components
primitives/src/witness_version.rsprimitives/src/opcodes.rsInspect captured patch +60 / −1
diff --git a/primitives/src/opcodes.rs b/primitives/src/opcodes.rs
index 06b88a82..d4d8be09 100644
--- a/primitives/src/opcodes.rs
+++ b/primitives/src/opcodes.rs
@@ -160,7 +160,7 @@ pub(crate) const OP_PUSHDATA2: u8 = 0x4d;
/// Read the following 4 bytes as a little-endian length, and read the following
/// bytes as a push of that length.
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
pub(crate) const OP_PUSHDATA4: u8 = 0x4e;
/// Push an empty array onto the stack.
diff --git a/primitives/src/witness_version.rs b/primitives/src/witness_version.rs
index 44a748b6..960d0547 100644
--- a/primitives/src/witness_version.rs
+++ b/primitives/src/witness_version.rs
@@ -218,3 +218,62 @@ pub mod error {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ #[cfg(feature = "alloc")]
+ use alloc::string::ToString;
+
+ use super::*;
+ use crate::opcodes::OP_PUSHDATA4;
+
+ #[test]
+ fn witness_version_to_num() {
+ assert_eq!(WitnessVersion::V0.to_num(), 0);
+ assert_eq!(WitnessVersion::V1.to_num(), 1);
+ assert_eq!(WitnessVersion::V2.to_num(), 2);
+ assert_eq!(WitnessVersion::V16.to_num(), 16);
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn witness_version_display() {
+ assert_eq!(WitnessVersion::V0.to_string(), "0");
+ assert_eq!(WitnessVersion::V1.to_string(), "1");
+ assert_eq!(WitnessVersion::V10.to_string(), "10");
+ assert_eq!(WitnessVersion::V16.to_string(), "16");
+ }
+
+ #[test]
+ fn witness_version_try_from_opcode() {
+ assert_eq!(WitnessVersion::try_from(OP_PUSHBYTES_0).unwrap(), WitnessVersion::V0);
+ assert_eq!(WitnessVersion::try_from(OP_1).unwrap(), WitnessVersion::V1);
+ assert_eq!(WitnessVersion::try_from(OP_16).unwrap(), WitnessVersion::V16);
+
+ // Only Opcodes in range OP_1 to OP_16, or 0, are valid.
+ let op = Opcode::from(OP_1.to_u8() - 1);
+ assert_eq!(WitnessVersion::try_from(op).unwrap_err().invalid_version(), OP_1.to_u8() - 1);
+ let op = Opcode::from(0xff);
+ assert_eq!(WitnessVersion::try_from(op).unwrap_err().invalid_version(), 0xff);
+ assert_eq!(
+ WitnessVersion::try_from(Opcode::from(OP_PUSHDATA4)).unwrap_err().invalid_version(),
+ OP_PUSHDATA4
+ );
+ }
+
+ #[test]
+ fn witness_version_into_opcode() {
+ assert_eq!(Opcode::from(WitnessVersion::V0), OP_PUSHBYTES_0);
+ assert_eq!(Opcode::from(WitnessVersion::V1), OP_1);
+ assert_eq!(Opcode::from(WitnessVersion::V16), OP_16);
+ }
+
+ #[test]
+ fn witness_version_opcode_round_trip() {
+ for version in 0u8..=16 {
+ let wv = WitnessVersion::try_from(version).unwrap();
+ let opcode = Opcode::from(wv);
+ assert_eq!(WitnessVersion::try_from(opcode).unwrap(), wv);
+ }
+ }
+}
Why this scored 15/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.