0

RAW Signed transaction (signet)

020000000001013ccb46c8366e39d7ff36df4f199813aa8b9dc4bed143a0eb9205cf698ca16298e400000000ffffffff0240420f00000000002200202d67ce38ba266a68f0f7c4668e9d0f5584c6da7c454bcc2368bf9fff10135157a086010000000000160014d765749aa66430b85765bdedee488f5fe3c82a8e02483045022100f71bd596f18d3caf1297a74f5619cd6c823d58acaf5f9172bea7d7d6ef82cfd502206c7c7960accd4409cccb1ca97d8268af12664de50b905d1c3579e6237c0fb823012102d3428014dd5ccf1927c6dc164e6324e2c0945a9f50b84769592e195ae6a40e8a00000000

Transaction id returned .

    "txid": "1d81e1dae9d956fd61cf79efa6a64de11465d6a1ead46e24ba043e278360fb35",
    "wtxid": "d9e69e8d05c61c78796b2d73b731a705334e07c013e7e714e10eaf45885a144c"

Transaction id calculated by following Raw_tx.

22d008e988b168165bd6c06dc4200ad57d456f1b152d25e540e75e38bb023c40

Transaction id calculated by hashing the Raw signed transaction

82fbc313fec14a7cf05309544b24bc97dc785bb82e4a9a713bb6e8d5f3cf4aeb

I have followed the above transaction formats. The signed raw transaction follows the specification given in bicoin developers raw transaction format.

Given are the implementation codes 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
}

1 Answer 1

2

The problem appears to be the lines where you encode the number of inputs and outputs:

    let inputs_length: u32 = inputs.len() as u32;
    tx.extend_from_slice(&inputs_length.to_le_bytes());
...
    let outputs_length: u32 = outputs.len() as u32;
    tx.extend_from_slice(&outputs_length.to_le_bytes());

These are not just 32 bit uints. These lengths are Compact Size unsigned ints which have a special encoding. You probably already know how to encode them since it's the same encoding for the script length in output scripts and there you use the function turn_to_varint. Assuming that function was implemented correctly, using that for the input and output lengths should resolve your issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.