LedgerHQ / ledgerjs

⛔️ MOVED to monorepo "ledger-live"
https://github.com/LedgerHQ/ledger-live
Apache License 2.0
574 stars 382 forks source link

BCH: signP2SHTransaction is Producing Invalid Signature #210

Closed blockchainguyy closed 5 years ago

blockchainguyy commented 5 years ago

Hi @gre , @dhoffmann, @rottenbytes, @fdv, @hyperbolist

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. Although the same thing is working fine for Bitcoin transactions but the same code when I try to use to sign Bitcoin Cash transaction is not working properly since its producing invalid signature from Ledger Nano S device.

I will detail script here, though I am not sure what shall I change if I need to sign bitcoin cash transaction via 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- 48'/0'/0'/101/0/0. I used the following rawTx:

01000000010333cc850aa3e269d1362400c290ba7c67f75b663a356e5dd984fe82d781304a010000004900475221020a11b1f12e72bfd6c3d6ff57307eef68b970da73f8b6084d6b40fbb5c7e432e2210259b0fc383c913bcea795c870cf2a554014f804e00a9539a6e6ed443a6479b1f552aeffffffff02393000000000000017a9146c5f44c3228786fd7de11cc898a22a935e1dd35d87678b0d000000000017a9146c5f44c3228786fd7de11cc898a22a935e1dd35d8700000000

I used the following Redeem Script:

5221020a11b1f12e72bfd6c3d6ff57307eef68b970da73f8b6084d6b40fbb5c7e432e2210259b0fc383c913bcea795c870cf2a554014f804e00a9539a6e6ed443a6479b1f552ae

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(
  "020a11b1f12e72bfd6c3d6ff57307eef68b970da73f8b6084d6b40fbb5c7e432e2"
); // public key for path- 48'/0'/0'/101/0/0

var publicKey = new PublicKey(
  "0259b0fc383c913bcea795c870cf2a554014f804e00a9539a6e6ed443a6479b1f5"
); // public key for path- 48'/0'/0'/102/0/0

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 => {
    var createPaymentTransaction = async (
      recipientAddress,
      amount,
      utxos,
      path,
      coin
    ) => {
      amount = Math.floor(amount);
      let indexes = [];
      let txs = [];
      let redeemScripts = [];
      const btc = new AppBtc(transport);
      try {
        for (let h of utxos) {
          const data = [
            {
              transaction_hash:
                "4a3081d782fe84d95d6e353a665bf7677cba90c2002436d169e2a30a85cc3303",
              hex:
                "010000000139f10c9178dd5b7cb2bb636272f5dcbd3b05283e76f924eacb5491951ff799b5020000006b483045022100c2260cab4019133064daffdd3396cbe578ef8ce638484c89e0e849e39c553475022053d19835ffbb17b0ebb81244922d81866b9ad7939645810fc71928aad5863bae4121020bf7b9133778784f3efd0ecc1be0179fb560fc073232acd5a6db4061fd8b9360ffffffff03a08601000000000017a9140e452b22d0f7e2d27580e6048c167ecc82a4fa838740420f000000000017a9146c5f44c3228786fd7de11cc898a22a935e1dd35d8723487102000000001976a9145ab88be04d24edca465b635af330df340f5fe1ae88ac00000000"
            }
          ];
          //   Networks[coin].isSegwitSupported = false;
          let tx = btc.splitTransaction(
            data[0].hex,
            Networks[coin].isSegwitSupported,
            Networks[coin].areTransactionTimestamped
          );
          txs.push(tx);
          indexes.push(1);
          redeemScripts.push(
            "5221020a11b1f12e72bfd6c3d6ff57307eef68b970da73f8b6084d6b40fbb5c7e432e2210259b0fc383c913bcea795c870cf2a554014f804e00a9539a6e6ed443a6479b1f552ae"
          );
        }
      } catch (e) {
        console.log(e);
        throw Errors.networkError;
      }
      const inputs = _.zip(txs, indexes, redeemScripts);
      const rawTx =
        "01000000010333cc850aa3e269d1362400c290ba7c67f75b663a356e5dd984fe82d781304a010000004900475221020a11b1f12e72bfd6c3d6ff57307eef68b970da73f8b6084d6b40fbb5c7e432e2210259b0fc383c913bcea795c870cf2a554014f804e00a9539a6e6ed443a6479b1f552aeffffffff02393000000000000017a9146c5f44c3228786fd7de11cc898a22a935e1dd35d87678b0d000000000017a9146c5f44c3228786fd7de11cc898a22a935e1dd35d8700000000";
      const bufferedData = await btc.splitTransaction(rawTx);      

      const outputScript = btc
        .serializeTransactionOutputs(bufferedData)
        .toString("hex");
      const sigHash = 0x41;
      const res = await btc
        .signP2SHTransaction(
          inputs,
          Array(indexes.length).fill(path),
          outputScript,
          undefined,
          sigHash,
        )
        .catch(err => console.log("Error inside p2sh", err));
      console.log("signature-=====>" , res);
      return res;
    };

    createPaymentTransaction(
      "HGQ9VSWFpSv8B65W1bpSUTQR2bbeWwoZh3",
      12345,
      ["4a3081d782fe84d95d6e353a665bf7677cba90c2002436d169e2a30a85cc3303"],
      "48'/0'/0'/101/0/0",
      145
    );
  })
  .catch(err => console.log(err));

It returns the following Signature when I send call send data to ledger via signP2SHTransaction method:

Sig hash: [ '3045022100b9a7763fb2264e444f18390e6d5033aa652a68dc5534dc1e3bf2250d1606d8380220794b320322f03e38d258094a4edb869714591fe6678e26ea29436163c117f3c1' ]

This signature is unable to sign the transaction in a proper manner and it error while I validate it against the transaction.can you please help me. What shall i use when wish to sign the bch transaction from ledger nano s device.

blockchainguyy commented 5 years ago

Hi Guyz, I have found the solution around this issue thanks.

Ark-Chen commented 5 years ago

Can you explain how you solved it? I am currently experiencing the same problem.Thank you very much, look forward to your reply.