diff --git a/crates/bitcoin/src/script.rs b/crates/bitcoin/src/script.rs index 8ddc0a709d..6fc9510323 100644 --- a/crates/bitcoin/src/script.rs +++ b/crates/bitcoin/src/script.rs @@ -27,10 +27,24 @@ impl Script { pub(crate) fn height(height: u32) -> Script { let mut script = Script::new(); - let len: u8 = 0x03; // Note: NOT OP3. See https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki - script.append(len); - let bytes = height.to_le_bytes(); - script.append(&bytes[0..=2]); + + // The format is described here https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki + // Tl;dr: first byte is number of bytes in the number, following bytes are little-endian + // representation of the number + + let mut height_bytes = height.to_le_bytes().to_vec(); + for i in (1..4).rev() { + // remove trailing zeroes, but always keep first byte even if it's zero + if height_bytes[i] == 0 { + height_bytes.remove(i); + } else { + break; + } + } + + // note: formatting the height_bytes vec automatically prepends the length of the vec, so no need + // to append it manually + script.append(height_bytes); script } @@ -129,3 +143,10 @@ impl std::convert::TryFrom<&str> for Script { Ok(Script { bytes }) } } + +#[test] +fn test_script_height() { + assert_eq!(Script::height(7).bytes, vec![1, 7]); + assert_eq!(Script::height(256).bytes, vec![2, 0x00, 0x01]); + assert_eq!(Script::height(65536).bytes, vec![3, 0x00, 0x00, 0x01]); +} diff --git a/crates/bitcoin/src/types.rs b/crates/bitcoin/src/types.rs index c2892aec72..42e9f01dfc 100644 --- a/crates/bitcoin/src/types.rs +++ b/crates/bitcoin/src/types.rs @@ -980,11 +980,6 @@ mod tests { assert_eq!(sha256d_le(&tx_bytes), expected_txid); } - #[test] - fn test_script_height() { - assert_eq!(Script::height(100).len(), 4); - } - #[test] fn test_transaction_input_builder() { let source = TransactionInputSource::FromOutput(H256Le::from_bytes_le(&[5; 32]), 123); @@ -1091,7 +1086,7 @@ mod tests { assert_eq!(block.header.version, 4); assert_eq!(block.header.merkle_root, block.transactions[0].tx_id()); // should be 2, might change if block is changed (last change was due to coinbase txid calculation fix) - assert_eq!(block.header.nonce, 2); + assert_eq!(block.header.nonce, 3); assert!(block.header.nonce > 0); }