Repository: rust-bitcoin/rust-bitcoin (language: rust)

Issue:
transaction::Version should be stored as u32 instead of i32
Since https://github.com/rust-bitcoin/rust-bitcoin/pull/458 it was changed to `i32`. Since https://github.com/bitcoin/bitcoin/pull/29325 it is stored as `uint32_t`. The `bitcoind` JSON-RPC response now returns it as an unsigned 32 bit integer, so transactions `c659729a7fea5071361c2c1a68551ca2bf77679b27086cc415adeeb03852e369` and `35e79ee733fad376e76d16d1f10088273c2f4c2eaba1374a837378a88e530005` fail to deserialize the `version` field.


Also see https://github.com/rust-bitcoin/rust-bitcoin/issues/287.


Discussion / hints:

Fix patch:
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index d9ec07c80..0a99677e0 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -631,7 +631,7 @@ crate::internal_macros::define_extension_trait! {
     /// Extension functionality for the [`Version`] type.
     pub trait VersionExt impl for Version {
         /// Constructs a new non-standard transaction version.
-        fn non_standard(version: i32) -> Version { Self(version) }
+        fn non_standard(version: u32) -> Version { Self(version) }
 
         /// Returns true if this transaction version number is considered standard.
         fn is_standard(&self) -> bool { *self == Version::ONE || *self == Version::TWO || *self == Version::THREE }
@@ -1369,17 +1369,11 @@ mod tests {
 
     #[test]
     fn transaction_version() {
-        let tx_bytes = hex!("ffffff7f0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
+        let tx_bytes = hex!("ffffffff0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
         let tx: Result<Transaction, _> = deserialize(&tx_bytes);
         assert!(tx.is_ok());
         let realtx = tx.unwrap();
-        assert_eq!(realtx.version, Version::non_standard(2147483647));
-
-        let tx2_bytes = hex!("000000800100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
-        let tx2: Result<Transaction, _> = deserialize(&tx2_bytes);
-        assert!(tx2.is_ok());
-        let realtx2 = tx2.unwrap();
-        assert_eq!(realtx2.version, Version::non_standard(-2147483648));
+        assert_eq!(realtx.version, Version::non_standard(u32::MAX));
     }
 
     #[test]
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index e91540e55..df1bef8a8 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -510,7 +510,7 @@ impl Wtxid {
 ///
 /// Currently, as specified by [BIP-68] and [BIP-431], version 1, 2, and 3 are considered standard.
 ///
-/// Standardness of the inner `i32` is not an invariant because you are free to create transactions
+/// Standardness of the inner `u32` is not an invariant because you are free to create transactions
 /// of any version, transactions with non-standard version numbers will not be relayed by the
 /// Bitcoin network.
 ///
@@ -518,7 +518,7 @@ impl Wtxid {
 /// [BIP-431]: https://github.com/bitcoin/bips/blob/master/bip-0431.mediawiki
 #[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-pub struct Version(pub i32);
+pub struct Version(pub u32);
 
 impl Version {
     /// The original Bitcoin transaction version (pre-BIP-68).


Test patch: