LedgerHQ / app-bitcoin

Legacy Bitcoin wallet application for Ledger devices
Apache License 2.0
127 stars 190 forks source link

Internal error, please report (0x6f01) and Invalid Signature #57

Open blockchainguyy opened 6 years ago

blockchainguyy commented 6 years ago

I was receiving Errors while using signatures produced by signP2SHTransaction function of @ledgerhq/hw-app-btc. So I created a script using bitcore-lib to cross check it against the signature produced by Ledger and pinpoint the change causing the Error. I also verified all my input params and found them to be correct.

I will detail both scripts here, though I think it is an issue of ledger's signP2SHTransaction function.

I'm using the following dependencies and node v8.9.3:

 "@ledgerhq/hw-app-btc": "^4.17.0",
    "@ledgerhq/hw-app-eth": "^4.19.0",
    "@ledgerhq/hw-transport-node-hid": "^4.18.0",
    "babel-runtime": "^6.26.0",
    "bip32": "^0.1.0",
    "bitcoinjs-lib": "^3.3.2",
    "bitcore-lib": "^0.15.0"

I have created a 2 of 2 Multisig address using the following 2 paths of my ledger- 44'/0'/0'/0/0, 44'/0'/0'/0/1. I used the following rawTx:

0100000001917f0f1321da9d0f44806a3d6dfa15063b1b83a30e582f61ea6324b1db36a71c020000004900475221028ef85ec7646df8744eac5c0499eefc794ccd6479f6e4ed089907f6440474bc572103ed25b9cf381feaa222c9a50dfe4d0ca4c983d67762b7d042bb45de91d15b3da952aeffffffff02393000000000000017a9145d2cf0d68efd203d4f1d3b1b7c2a7cfe72a6b73f8755af71010000000017a9145d2cf0d68efd203d4f1d3b1b7c2a7cfe72a6b73f8700000000

I used the following Redeem Script:

5221028ef85ec7646df8744eac5c0499eefc794ccd6479f6e4ed089907f6440474bc572103ed25b9cf381feaa222c9a50dfe4d0ca4c983d67762b7d042bb45de91d15b3da952ae

Here's the code I used to produce it:

const bitcore = require("bitcore-lib");
const PublicKey = bitcore.PublicKey;
const Script = bitcore.Script;

var publicKey1 = new PublicKey(
  "02a9d50f9817a9cf20f3feb7ad4038e88c8bd471e90dfba3a80c2e0bfd79c89312"
); // public key for path- 44'/0'/0'/0/0

var publicKey = new PublicKey(
  "02faf805ea3652cec322dda6f7571d926f359d8abbd73af1512924151edbec90e7"
); // public key for path- 44'/0'/0'/0/1

var pubkeys = [publicKey, publicKey1];

var redeemScript = Script.buildMultisigOut(pubkeys, 2);

console.log(redeemScript.toHex());

You can decode it here: https://live.blockcypher.com/btc/decodetx/ Here is my ledger's code which is creating a signature for 48'/0'/0'/69/0/0 path:

const TransportHid = require("@ledgerhq/hw-transport-node-hid").default;
const AppBtc = require("@ledgerhq/hw-app-btc").default;

TransportHid.create()
  .then(async transport => {
    if (!transport) return console.log("err: Unable to establish connection");
    var btc = new AppBtc(transport);

    const rawTx = "0100000001917f0f1321da9d0f44806a3d6dfa15063b1b83a30e582f61ea6324b1db36a71c020000004900475221028ef85ec7646df8744eac5c0499eefc794ccd6479f6e4ed089907f6440474bc572103ed25b9cf381feaa222c9a50dfe4d0ca4c983d67762b7d042bb45de91d15b3da952aeffffffff02393000000000000017a9145d2cf0d68efd203d4f1d3b1b7c2a7cfe72a6b73f8755af71010000000017a9145d2cf0d68efd203d4f1d3b1b7c2a7cfe72a6b73f8700000000";
    const redeemHex =
      "5221028ef85ec7646df8744eac5c0499eefc794ccd6479f6e4ed089907f6440474bc572103ed25b9cf381feaa222c9a50dfe4d0ca4c983d67762b7d042bb45de91d15b3da952ae";
    const bufferedData = await btc.splitTransaction(rawTx);

    const data = 
        [{
            transaction_hash: "4a3081d782fe84d95d6e353a665bf7677cba90c2002436d169e2a30a85cc3303",
            hex:"0100000001611ccf1bf54eca69fc3069137820e297cc2fa4afab9a8b4facca5fd88ed08a8001000000db00483045022100fdd7aa8c55292a88a5f28c4c0263d4302db9ab543aaf39ef8f6d333e63b3880802200d50a48fce6b9ed818f8a3267ac759bb43ce679560e8a571ae3709bf0c42e7ed01483045022100810c43b531759dfc54b5f88fd45e215e8c24f11239a3060606685d3a396b791e022073973063d13359c217b220780a79d50887b1094b48b8cc830b0f506dc71a009701475221028ef85ec7646df8744eac5c0499eefc794ccd6479f6e4ed089907f6440474bc572103ed25b9cf381feaa222c9a50dfe4d0ca4c983d67762b7d042bb45de91d15b3da952aeffffffff030000000000000000166a146f6d6e69000000000000001f000000003b9aca00aa0a00000000000017a9145d2cf0d68efd203d4f1d3b1b7c2a7cfe72a6b73f8708807f010000000017a9145d2cf0d68efd203d4f1d3b1b7c2a7cfe72a6b73f8700000000"
        }];
        let tx = btc.splitTransaction(
            data[0].hex,
            true,
            undefined
        );
    txs.push(tx);
    indexes.push(1);
    redeemScripts.push(
        redeemHex
    );
    const inputs = _.zip(txs, indexes, redeemScripts);
    const outputScript = btc
      .serializeTransactionOutputs(bufferedData)
      .toString("hex");

    console.log("\nOutput script hex:", outputScript);

    const accountIndex = 69;

    console.log("\npath:", `48'/0'/0'/${accountIndex}/0/0`);

    await btc
      .signP2SHTransaction(
        inputs,
        [`44'/0'/0'/0/${accountIndex}/0/0`],
        outputScript,
         undefined,
        undefined,
        segwit
      )
      .then(sig => console.log("\n\nSig hash:", sig))
      .catch(err => console.log("\n\nErr:", err));
  })
  .catch(err => console.log(err));

So as I am using the above code when I toggle to segwit as true in calling Ledger P2SH function signP2SHTransaction. The ledger device accepts the provided input data and produces the invalid signature.

When I toggle to segwit as false in calling Ledger P2SH function signP2SHTransaction. The ledger device throws this error:

TransportStatusError: Ledger device: Internal error, please report (0x6faa)

While my its legacy transaction so It must run without setting segwit to true. So could you please suggest what might be the problem.

kantai commented 6 years ago

I also experienced this issue, while working with ledgerjs -- and I think the issue lies there, not in the hw app. The transaction preparing code in @ledgerhq/hw-app-btc assumes that non-segwit signing transactions won't have inputs which are segwit.

monokh commented 5 years ago

Have this exact issue as well, did you find any resolution @kantai @ayush-techracers? Seems odd that this means you can only include pure legacy utxos in a legacy transaction. Can see this issue being very common.