Bitcoin
An incorrect transaction ID is being calculated for the p2wpkh transaction.
RAW signed transaction (seal)
020000000001013ccb46c8366e39d7ff36df4f199813aa8b9dc4bed143a0eb9205cf698ca16298e400000000ffffffff0240420f00000000002200202d67ce38ba266a68f0f7c4668e9d0f5584c6da7c454bcc2368bf9fff10135157a086010000000000160014d765749aa66430b85765bdedee488f5fe3c82a8e02483045022100f71bd596f18d3caf1297a74f5619cd6c823d58acaf5f9172bea7d7d6ef82cfd502206c7c7960accd4409cccb1ca97d8268af12664de50b905d1c3579e6237c0fb823012102d3428014dd5ccf1927c6dc164e6324e2c0945a9f50b84769592e195ae6a40e8a00000000
Transaction ID returned.
"txid": "1d81e1dae9d956fd61cf79efa6a64de11465d6a1ead46e24ba043e278360fb35",
"wtxid": "d9e69e8d05c61c78796b2d73b731a705334e07c013e7e714e10eaf45885a144c"
Transaction ID calculated based on Raw_tx.
22d008e988b168165bd6c06dc4200ad57d456f1b152d25e540e75e38bb023c40
Transaction ID calculated by hashing the raw signed transaction
82fbc313fec14a7cf05309544b24bc97dc785bb82e4a9a713bb6e8d5f3cf4aeb
I followed the transaction format above. Signed raw transactions follow the specifications provided in the bicoin developer raw transaction format.
Here’s the implementation code in Rust:
fn get_txid(inputs: Vec<Vec<u8>>, outputs: Vec<Vec<u8>>) -> (u8; 32)
let mut tx = Vec::new();
//adding version
let version: u32 = 0x00000002;
tx.extend_from_slice(&version.to_le_bytes());
let inputs_length: u32 = inputs.len() as u32;
tx.extend_from_slice(&inputs_length.to_le_bytes());
for input in inputs
tx.extend_from_slice(&input);
let outputs_length: u32 = outputs.len() as u32;
tx.extend_from_slice(&outputs_length.to_le_bytes());
for output in outputs
tx.extend_from_slice(&output);
let locktime: u32 = 0x00000000;
tx.extend_from_slice(&locktime.to_le_bytes());
let txid = sha256_hash(&sha256_hash(&tx));
//output
let tx_array: (u8; 32) = match txid.try_into()
Ok(arr) => arr,
Err(_) => panic!("Expected a Vec of length 32, but it was ", tx.len()),
;
// reverse txid
let mut reversed_txid = (0; 32);
for i in 0..32
reversed_txid(i) = tx_array(31 - i);
reversed_txid
Output serialization
fn output_from_options(script: &(u8), value: u32) -> Vec<u8>
let mut output = Vec::new();
let valhue: u64 = value as u64;
let value_in_8_bytes_in_little_endian = valhue.to_le_bytes();
output.extend_from_slice(&value_in_8_bytes_in_little_endian);
let script_length = script.len() as u64;
let script_length_varint = turn_to_varint(script_length);
output.extend_from_slice(&script_length_varint);
output.extend_from_slice(script); //scriptpubkey p2wpkh and p2wsh
output
//OK
Input serialization
fn input_from_utxo(txid: &(u8), index: u32) -> Vec<u8>
let mut input = Vec::new();
//txid
let reversed_txid: Vec<u8> = txid.iter().rev().cloned().collect();
input.extend_from_slice(&reversed_txid);
//index
let index_in_little_endian_bytes = index.to_le_bytes(); // fixed 4 bytes
input.extend_from_slice(&index_in_little_endian_bytes);
//script length (default is zero for us)
input.push(0x00);
//sequence
let sequence: u32 = 0xffffffff;
input.extend_from_slice(&sequence.to_le_bytes());
input
//OK