Skip to content

Commit

Permalink
Merge pull request #1141 from interlay/fix/txid-coinbase
Browse files Browse the repository at this point in the history
fix: txid calculation of low-height coinbase tx
  • Loading branch information
sander2 authored Jul 26, 2023
2 parents f2f48a1 + d283fe3 commit a3aadba
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 10 deletions.
29 changes: 25 additions & 4 deletions crates/bitcoin/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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]);
}
7 changes: 1 addition & 6 deletions crates/bitcoin/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit a3aadba

Please sign in to comment.