Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in multisig transaction with ledger and local key #52

Open
kleash opened this issue Apr 4, 2020 · 1 comment
Open

Error in multisig transaction with ledger and local key #52

kleash opened this issue Apr 4, 2020 · 1 comment
Assignees

Comments

@kleash
Copy link

kleash commented Apr 4, 2020

Hi,

I am trying to do a multisig p2sh transaction, signing first by ledger and then by locally stored key.

This is my current code mostly based on Multi Sig guide and P2SH ledger example

Code:

'use strict';

const fs = require('fs');
const bcoin = require('bcoin');
const assert = require('assert');
const KeyRing = bcoin.wallet.WalletKey;
const Script = bcoin.Script;
const MTX = bcoin.MTX;
const TX = bcoin.TX;
const Amount = bcoin.Amount;
const Coin = bcoin.Coin;

const bledger = require('../lib/bledger');
const {LedgerBcoin, LedgerTXInput} = bledger;
const {Device} = bledger.USB;

const NETWORK = 'testnet';
const compressed = true;

// Read keys from local system
const secret1 = fs.readFileSync(`./${NETWORK}-key1.wif`).toString();
const ring1 = KeyRing.fromSecret(secret1);

(async () => {

    // LEDGER INIT CODE --START
    const device = await Device.requestDevice();
    device.set({timeout: 50000});
    await device.open();
    const path = 'm/44\'/0\'/0\'';
    const path1 = `${path}/1/1`;
    const bcoinApp = new LedgerBcoin({device});
    const hdpub1 = await bcoinApp.getPublicKey(path1);
    const pub1 = hdpub1.publicKey;
    // LEDGER INIT CODE --FINISH

    //Create Script
    const [pk1, pk2] = [hdpub1.publicKey, ring1.publicKey];
    const [m, n] = [2, 2];

    const redeem = Script.fromMultisig(m, n, [pk1, pk2]);
    // p2sh script
    const script = Script.fromScripthash(redeem.hash160());
    const changeAddr = script.getAddress().toBase58(NETWORK);

    // tx info
    const sendTo = '2N4MrGXsu2PtDFMXZrvG34YQxK4Y77bmk7g';
    const txInfo = {
        // How much we received with this transaction
        value: Amount.fromBTC('0.0002').toValue(),

        // prevout txid and vout
        hash: 'aa253ca490d7f1c914246ad459a89c997291da9ca3dc7ec749f6555d2a5aabdf',
        index: 0
    };

    const coin = Coin.fromJSON({
        version: 1,
        height: -1,
        value: txInfo.value,
        coinbase: false,

        script: script.toJSON(),
        hash: txInfo.hash,
        index: txInfo.index
    });

    // Now we create mutable transaction object for signing with ledger
    const spend1 = new MTX();
    spend1.script = redeem;

    // send
    spend1.addOutput({
        address: sendTo,
        value: Amount.fromBTC('0.0001').toValue()
    });


    // send change to ourselves
    spend1.addOutput({
        address: changeAddr,
        value: Amount.fromBTC('0.00005').toValue()
    });

    spend1.addCoin(coin);

    const ledgerInputs = [];

    // Hex of input transaction
    const tx = TX.fromRaw(Buffer.from("01000000000101cdede91d7a739ba4100a46d3287fc20fa683720a39ca2b6e8f474a24570ab86a000000001716001409785e5b583363e2cfcff123be008fef302bd151ffffffff023cf30e000000000017a91470329ef305289ecfe4f2bc6448a6bac4b16b99b887204e00000000000017a9149fd0d66463fafe0ce272189faa4d196ab816ccf787024830450221008a727b5cf7d1f66f1cb3a3311937827a10818d6f8fd6320ebd55df7c5a6d0755022066a4a2f236f01ec6827e7627e5381f1f5ffee56b404d81b44d14ab86b593141d012102e054e792bf5c8e49d2ad73c60a2882e4a34f42db79b0981f95062718dff95a0b00000000", 'hex'))

    const ledgerInput = new LedgerTXInput({
        tx: tx,
        index: 0,
        redeem: redeem,
        path: path,
        publicKey: pub1
    });

    ledgerInputs.push(ledgerInput);

    await bcoinApp.signTransaction(spend1, ledgerInputs);

    //Get raw txn signed by ledger
    const raw = spend1.toRaw();

    // use raw tx to be signed by local key
    const spend2 = MTX.fromRaw(raw);
    spend2.script = redeem;

    // Because input already exists in transaction
    // we only need to provide Coin to CoinView
    spend2.view.addCoin(coin);

    // now we sign
    spend2.signInput(0, coin, ring1);

    //Check if transaction is valid
    assert(spend2.verify(), 'Transaction isnt valid.');

    console.log(spend2.toRaw().toString('hex'));


    await device.close();
})().catch((e) => {
    console.error(e);
    process.exit(1);
});

Currently, It's throwing me following error:

Error: Could not template input.
    at LedgerBcoin.applySignature (/ledger/bcoin/bledger/lib/ledger/ledgerbcoin.js:370:13)
    at LedgerBcoin._signTransaction (/ledger/bcoin/bledger/lib/ledger/ledgerbcoin.js:340:19)

Any pointers on what I am doing wrong?

@kleash
Copy link
Author

kleash commented Apr 4, 2020

I think something is wrong with this part:

    const ledgerInput = new LedgerTXInput({
        tx: tx, (This is input transaction to my p2sh address)
        index: 0,
        redeem: redeem, (Redeem script I created above)
        path: path, (Path of my ledger key)
        publicKey: pub1 (My ledger's pub key)
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants