walletd_bitcoin 0.2.0

Bitcoin walletd library
Documentation
extern crate walletd_bitcoin;

use hex;
use walletd_bitcoin::blockstream::{BTransaction, Input, Output, Status};
use walletd_bitcoin::{BitcoinPrivateKey, BitcoinWallet, Network};
fn main() {
    println!("Recreating an example found online here for testing/validation");
    // Comparing with example: https://medium.com/coinmonks/creating-and-signing-a-segwit-transaction-from-scratch-ec98577b526a

    // the legacy input
    let input1 = Input{
      txid: "d1a92ad68a031c5324981aa920152bd16975686905db41e3fc9d51c7ff4a20ed".to_string(),
      vout: 1,
      prevout: Output {
          scriptpubkey: "76a914b780d54c6b03b053916333b50a213d566bbedd1388ac".to_string(),
          scriptpubkey_asm: "OP_DUP OP_HASH160 OP_PUSHBYTES_20 b780d54c6b03b053916333b50a213d566bbedd13 OP_EQUALVERIFY OP_CHECKSIG".to_string(),
          scriptpubkey_type: "p2pkh".to_string(),
          scriptpubkey_address: "mxFEHeSxxKjy9YcmFzXNpuE3FFJyby56jA".to_string(),
          pubkeyhash: "b780d54c6b03b053916333b50a213d566bbedd13".to_string(),
          value: 52000,
      },
      scriptsig: "76a914b780d54c6b03b053916333b50a213d566bbedd1388ac".to_string(),
      scriptsig_asm: "".to_string(),
      witness: Vec::new(),
      is_coinbase: false,
      sequence: 0xffffffff,
      inner_redeemscript_asm: "".to_string(),
  };

    let input2_txid = BTransaction::hex_reverse_byte_order(
        &"9cb872539fbe1bc0b9c5562195095f3f35e6e13919259956c6263c9bd53b20b7".to_string(),
    )
    .unwrap();
    println!("input2_txid: {}", &input2_txid);

    // SegWit
    let input2 = Input {
        txid: input2_txid,
        vout: 1,
        prevout: Output {
            scriptpubkey: "0014594c2e3da92d1904f7e7c856220f8cae5efb5564".to_string(),
            scriptpubkey_asm: "OP_0 OP_PUSHBYTES_20 594c2e3da92d1904f7e7c856220f8cae5efb5564"
                .to_string(),
            scriptpubkey_type: "v0_p2wpkh".to_string(),
            scriptpubkey_address: "tb1qt9xzu0df95vsfal8eptzyruv4e00k4ty6d8zhh".to_string(),
            pubkeyhash: "594c2e3da92d1904f7e7c856220f8cae5efb5564".to_string(),
            value: 9300,
            ..Default::default()
        },
        scriptsig: "".to_string(),
        scriptsig_asm: "".to_string(),
        witness: Vec::new(),
        is_coinbase: false,
        sequence: 0xFFFFFFFF,
        inner_redeemscript_asm: "".to_string(),
    };

    let input3_txid = BTransaction::hex_reverse_byte_order(
        &"8012f1ec8aa9a63cf8b200c25ddae2dece42a2495cc473c1758972cfcd84d904".to_string(),
    )
    .unwrap();
    println!("input3_txid: {}", &input3_txid);

    let input3 = Input {
        txid: input3_txid,
        vout: 1,
        prevout: Output {
            scriptpubkey: "a9146a721dcca372f3c17b2c649b2ba61aa0fda98a9187".to_string(),
            scriptpubkey_asm:
                "OP_HASH160 OP_PUSHBYTES_20 6a721dcca372f3c17b2c649b2ba61aa0fda98a91 OP_EQUAL"
                    .to_string(),
            scriptpubkey_type: "p2sh".to_string(),
            scriptpubkey_address: "2N4yEhDwic9Tm4BRN9EP1hnSu9f6cWJrU31".to_string(),
            pubkeyhash: "6a721dcca372f3c17b2c649b2ba61aa0fda98a91".to_string(),
            value: 16029969,
        },
        scriptsig: "".to_string(),
        scriptsig_asm: "".to_string(),
        witness: Vec::new(),
        is_coinbase: false,
        sequence: 0xFFFFFFFF,
        inner_redeemscript_asm: "".to_string(),
    };

    let output1 = Output {
        scriptpubkey: "0014cb61ee4568082cb59ac26bb96ec8fbe0109a4c00".to_string(),
        scriptpubkey_asm: "OP_0 OP_PUSHBYTES_20 cb61ee4568082cb59ac26bb96ec8fbe0109a4c00"
            .to_string(),
        scriptpubkey_type: "v0_p2wpkh".to_string(),
        scriptpubkey_address: "tb1qeds7u3tgpqkttxkzdwukaj8muqgf5nqq6w05ak".to_string(),
        value: 16089269,
        pubkeyhash: "cb61ee4568082cb59ac26bb96ec8fbe0109a4c00".to_string(),
    };

    let transaction = BTransaction {
        txid: "".to_string(),
        version: 2,
        locktime: 0,
        vin: vec![input1, input2, input3],
        vout: vec![output1],
        size: 0,
        weight: 0,
        fee: 0,
        status: Status {
            ..Default::default()
        },
    };
    let unsigned_serialized = BTransaction::serialize(&transaction).unwrap();
    println!("unsigned transaction serialized: {}", &unsigned_serialized);

    let for_input1 = unsigned_serialized + "01000000";
    println!("serialized transaction for input 1 signing: {}", for_input1);
    let sighash_for_input1 = &transaction.txid().unwrap();
    println!("sighash_for_input1: {}", sighash_for_input1);
    let secret_key1 =
        BitcoinPrivateKey::from_slice(
            &hex::decode("DBFF11E0F2F1AA5089465A591C5E523D1CA92668DED893155CDFABC94CC14E30")
                .unwrap()[..],
            Network::Testnet,
        )
        .unwrap();

    let first_signature =
        BitcoinWallet::signature_sighashall_for_transaction_hash(&sighash_for_input1, &secret_key1)
            .unwrap();
    println!("first_signature: {}", first_signature);

    let for_input2 = &transaction
        .serialize_for_segwit_input_index_with_sighash(1, 1)
        .unwrap();
    println!("serialized transaction for input 2 signing: {}", for_input2);
    let sighash_for_input2 = &transaction
        .transaction_hash_for_signing_segwit_input_index(1, 1)
        .unwrap();
    println!("sighash_for_input2: {}", sighash_for_input2);
    let secret_key2 =
        BitcoinPrivateKey::from_slice(
            &hex::decode("26F85CE8B2C635AD92F6148E4443FE415F512F3F29F44AB0E2CBDA819295BBD5")
                .unwrap()[..],
            Network::Testnet,
        )
        .unwrap();

    let second_signature =
        BitcoinWallet::signature_sighashall_for_transaction_hash(&sighash_for_input2, &secret_key2)
            .unwrap();
    println!("second_signature: {}", second_signature);

    let for_input3 = &transaction
        .serialize_for_segwit_input_index_with_sighash(2, 1)
        .unwrap();
    println!("serialized transaction for input 3 signing: {}", for_input3);
    let sighash_for_input3 = &transaction
        .transaction_hash_for_signing_segwit_input_index(2, 1)
        .unwrap();
    println!("sighash_for_input3: {}", sighash_for_input3);
    let secret_key3 =
        BitcoinPrivateKey::from_slice(
            &hex::decode("D9172189D7700FDFB4B6A5C4A83990EAEAFE455441B7D43FF85678EB93AC2713")
                .unwrap()[..],
            Network::Testnet,
        )
        .unwrap();
    let third_signature =
        BitcoinWallet::signature_sighashall_for_transaction_hash(&sighash_for_input3, &secret_key3)
            .unwrap();
    println!("third_signature: {}", second_signature);

    // adding signing info to the transaction
    let mut signed_transaction = transaction;
    signed_transaction.vin[0].scriptsig = "47".to_string()
        + first_signature.as_str()
        + "210242BF11B788DDFF450C791F16E83465CC67328CA945C703469A08E37EF0D0E061";
    signed_transaction.vin[2].scriptsig =
        "171600146a721dcca372f3c17b2c649b2ba61aa0fda98a91".to_string();
    signed_transaction.vin[1].witness = vec![
        second_signature,
        "025972A1F2532B44348501075075B31EB21C02EEF276B91DB99D30703F2081B773".to_string(),
    ];
    signed_transaction.vin[2].witness = vec![
        third_signature,
        "02AE68D299CBB8AB99BF24C9AF79A7B13D28AC8CD21F6F7F750300EDA41A589A5D".to_string(),
    ];
    let raw_tx_hex = BTransaction::serialize(&signed_transaction).unwrap();
    println!("raw_tx_hex: {}", raw_tx_hex);
}