LedgerHQ / app-bitcoin-new

Modern Bitcoin Application based on PSBT and Descriptors
Apache License 2.0
93 stars 73 forks source link

TransportStatusError: Ledger device: Invalid data received #299

Closed javiervargas closed 1 week ago

javiervargas commented 1 month ago

Hi!,

I'm getting this message when trying to sign a psbt. TransportStatusError: Ledger device: Invalid data received (0x6a80)

Comparing with psbt examples noticed my psbt shows:

], "outputs": [ { } ], "fee": 0.00095000 }

I'm adding outputs like this and adding Global

   const {address} = bitcoin.payments.p2pkh({ pubkey: cosigner2Pubkey, network: bitcoin.networks.testnet })
    const spendable = 10000;
    const fees = spendable - 5000;
    const totalToSend = spendable - fees;
    psbt.addOutput({address: address, value: totalToSend})

GlobalXpub


  psbt.updateGlobal({
  globalXpub: [
    {
      extendedPubkey, // 78 byte buffer (contents of xpub string decoded from base58check)
      masterFingerprint, // 4 byte buffer with masterFingerprint of the root private key
      path, // The path from the root private key to the xpub in extendedPubkey
    },
    { ... },
    { ... },
  ]
});

Attach my base64 psbt.

PSBT base64: cHNidP8BAFUCAAAAAbbUXGeNYQet/rSpcibXRxpEk0s+qcQ13AIv6TsR7CRxAAAAAAD/////AYgTAAAAAAAAGXapFNPCFDSmzeYKli+eAgd5bQx5dJI+iKwAAAAATwEENYfPAwACfNaAAAAAitcBOSwrKKPETTFTQB2dV2vR7JeW0oWISULd7zff6YwD7CHlhpedfqFMPs/Ynyylrt1MmciorP8y5NheFXQsVBQQRMEfWC0AAIABAACAAAAAgE8BBDWHzwNDTstqgAAAADyYUIjJ0r+BE97TSLMAxAVXqykmzpXn8OjrOZXpGtypAiscEQVdgAYz+aaLNncVAez1gcKaGbwAm9aUjCmBUP3QEK042eotAACAAQAAgAAAAIBPAQQ1h88DgoJ17wAAAACLzmO+hByJ5sRId8P2Yk2ocvvCRfE71oHTxzvR3kFdVQNOPE/+YNwEpZpgurYl3xqaFl7O0iZ6lonO5dkt6egLSBCTxBDYLQAAgAEAAAAAAAAAAAEA4AIAAAAAAQGIBXP7hwAy6E96KP4N/8V/Tfm4vxlR/upITB78hh8fsgAAAAAA/f///wJXHwIAAAAAABepFO9+OkwJ33cbkuScONov2H9WuEnzh6CGAQAAAAAAF6kUFsT5HlQZ3oe3saQ57nNEsrsyEmyHAkcwRAIge7VOHNcQsoLT7uwYuqaaiM4kRhZ8gEEU4cWbDyMbuGoCIBrO5a75aw+y8vhigNmzeKK1Giga1wMrTpFnzNr+XrMRASED3rqKjW60B9oFWHFsBRsXKxOZNOoK5HH01pYAbDqWJ7M0tDAAAQRpUiECI3IHP1F93YV4O5y27ztzqRZ+nLF/jn2cumFBLsJdFDYhAjahpn8UmMFHCIsODyIv7uZwUokqfOo6W5HxwRB9x3mjIQOMWCtjMi9QvCg3MVs+kA4Q8gkf1+NFTR+PrlxfllGrj1OuIgYCKxwRBV2ABjP5pos2dxUB7PWBwpoZvACb1pSMKYFQ/dAQrTjZ6i0AAIABAACAAAAAgCIGA048T/5g3ASlmmC6tiXfGpoWXs7SJnqWic7l2S3p6AtIEJPEENgtAACAAQAAAAAAAAAiBgPsIeWGl51+oUw+z9ifLKWu3UyZyKis/zLk2F4VdCxUFBBEwR9YLQAAgAEAAIAAAACAAAA= In console from web browser:

Multisig wallet address: 2MuKcpSGWdnXawi1QwuZdLH85x9DTrC9DUc

policy :  
WalletPolicy {name: 'Cold storage', descriptorTemplate: 'sh(sortedmulti(2,@0/**,@1/**,@2/**))', keys: Array(3)}
descriptorTemplate
: 
"sh(sortedmulti(2,@0/**,@1/**,@2/**))"
keys
: 
Array(3)
0
: 
"[ad38d9ea/45'/1'/0']tpubDC2QJtarETt4NkxuTuGc6mvtBKgpnwJwPt8paKvQZKWiUESbHyMzgZyLfjzdnENJWNidnqcCmXhKUfShJ7xz1tgLP7jZpkoXpr7SGaTcEt3"
1
: 
"[44c11f58/45'/1'/0']tpubDCX6KddsMhFLwWyEvvwSAAYH4KpQnZ8kXw9UweqDbQacVcWzXhEvB7XwdSoUpRWiVMGciGaQoMk3qn61e2eCDzmHqCzVkJX9ezv4Vc5BYqD"
2
: 
"[93c410d8/45'/1/0]tpubDCz33uKPCZzeN4agYd2vxyyBiJeZJBZKAhW638xyN9C4KxAG4MhiBrDtrq1fRADmt7jqkgym2jUefCuE4UQQgzM6MQLiPfNnpH5H5sGQkjb"
length
: 
3
[[Prototype]]
: 
Array(0)
name
: 
"Cold storage"
[[Prototype]]
: 
Object

policyMac: a15d0a482bcce5bad61e7c53e90e7baa963420009d666cd02041d313bfa98236

Fails here:

const result = await app.signPsbt(psbt, multisigPolicy, hmacBuffer);

decodepst

{
  "tx": {
    "txid": "ec9e6088e2872d89bdda74a1df3caa3c32e86b296a77f0cf727db6ad28ce5a02",
    "hash": "ec9e6088e2872d89bdda74a1df3caa3c32e86b296a77f0cf727db6ad28ce5a02",
    "version": 2,
    "size": 85,
    "vsize": 85,
    "weight": 340,
    "locktime": 0,
    "vin": [
      {
        "txid": "7124ec113be92f02dc35c4a93e4b93441a47d72672a9b4fead07618d675cd4b6",
        "vout": 0,
        "scriptSig": {
          "asm": "",
          "hex": ""
        },
        "sequence": 4294967295
      }
    ],
    "vout": [
      {
        "value": 0.00005000,
        "n": 0,
        "scriptPubKey": {
          "asm": "OP_DUP OP_HASH160 d3c21434a6cde60a962f9e0207796d0c7974923e OP_EQUALVERIFY OP_CHECKSIG",
          "desc": "addr(mzpdNNSvCGtBNw352HVuakn5nXdpNiZ41y)#2pn9twsk",
          "hex": "76a914d3c21434a6cde60a962f9e0207796d0c7974923e88ac",
          "address": "mzpdNNSvCGtBNw352HVuakn5nXdpNiZ41y",
          "type": "pubkeyhash"
        }
      }
    ]
  },
  "global_xpubs": [
    {
      "xpub": "tpubDC2QJtarETt4NkxuTuGc6mvtBKgpnwJwPt8paKvQZKWiUESbHyMzgZyLfjzdnENJWNidnqcCmXhKUfShJ7xz1tgLP7jZpkoXpr7SGaTcEt3",
      "master_fingerprint": "44c11f58",
      "path": "m/45'/1'/0'"
    },
    {
      "xpub": "tpubDCz33uKPCZzeN4agYd2vxyyBiJeZJBZKAhW638xyN9C4KxAG4MhiBrDtrq1fRADmt7jqkgym2jUefCuE4UQQgzM6MQLiPfNnpH5H5sGQkjb",
      "master_fingerprint": "93c410d8",
      "path": "m/45'/1/0"
    },
    {
      "xpub": "tpubDCX6KddsMhFLwWyEvvwSAAYH4KpQnZ8kXw9UweqDbQacVcWzXhEvB7XwdSoUpRWiVMGciGaQoMk3qn61e2eCDzmHqCzVkJX9ezv4Vc5BYqD",
      "master_fingerprint": "ad38d9ea",
      "path": "m/45'/1'/0'"
    }
  ],
  "psbt_version": 0,
  "proprietary": [
  ],
  "unknown": {
  },
  "inputs": [
    {
      "non_witness_utxo": {
        "txid": "7124ec113be92f02dc35c4a93e4b93441a47d72672a9b4fead07618d675cd4b6",
        "hash": "c45cac5d35a62e0f248df1af0600b6afd57254eb5536376121cb3fb807bd800f",
        "version": 2,
        "size": 224,
        "vsize": 143,
        "weight": 569,
        "locktime": 3191860,
        "vin": [
          {
            "txid": "b21f1f86fc1e4c48eafe5119bfb8f94d7fc5ff0dfe287a4fe8320087fb730588",
            "vout": 0,
            "scriptSig": {
              "asm": "",
              "hex": ""
            },
            "txinwitness": [
              "304402207bb54e1cd710b282d3eeec18baa69a88ce2446167c804114e1c59b0f231bb86a02201acee5aef96b0fb2f2f86280d9b378a2b51a281ad7032b4e9167ccdafe5eb31101",
              "03deba8a8d6eb407da0558716c051b172b139934ea0ae471f4d696006c3a9627b3"
            ],
            "sequence": 4294967293
          }
        ],
        "vout": [
          {
            "value": 0.00139095,
            "n": 0,
            "scriptPubKey": {
              "asm": "OP_HASH160 ef7e3a4c09df771b92e49c38da2fd87f56b849f3 OP_EQUAL",
              "desc": "addr(2NF5Yhb27tbwyL54GR59uaGUZgkJjRq4GjP)#cwyvr42c",
              "hex": "a914ef7e3a4c09df771b92e49c38da2fd87f56b849f387",
              "address": "2NF5Yhb27tbwyL54GR59uaGUZgkJjRq4GjP",
              "type": "scripthash"
            }
          },
          {
            "value": 0.00100000,
            "n": 1,
            "scriptPubKey": {
              "asm": "OP_HASH160 16c4f91e5419de87b7b1a439ee7344b2bb32126c OP_EQUAL",
              "desc": "addr(2MuKcpSGWdnXawi1QwuZdLH85x9DTrC9DUc)#kjp7fhug",
              "hex": "a91416c4f91e5419de87b7b1a439ee7344b2bb32126c87",
              "address": "2MuKcpSGWdnXawi1QwuZdLH85x9DTrC9DUc",
              "type": "scripthash"
            }
          }
        ]
      },
      "redeem_script": {
        "asm": "2 022372073f517ddd85783b9cb6ef3b73a9167e9cb17f8e7d9cba61412ec25d1436 0236a1a67f1498c147088b0e0f222feee67052892a7cea3a5b91f1c1107dc779a3 038c582b63322f50bc2837315b3e900e10f2091fd7e3454d1f8fae5c5f9651ab8f 3 OP_CHECKMULTISIG",
        "hex": "5221022372073f517ddd85783b9cb6ef3b73a9167e9cb17f8e7d9cba61412ec25d1436210236a1a67f1498c147088b0e0f222feee67052892a7cea3a5b91f1c1107dc779a321038c582b63322f50bc2837315b3e900e10f2091fd7e3454d1f8fae5c5f9651ab8f53ae",
        "type": "multisig"
      },
      "bip32_derivs": [
        {
          "pubkey": "022b1c11055d800633f9a68b36771501ecf581c29a19bc009bd6948c298150fdd0",
          "master_fingerprint": "ad38d9ea",
          "path": "m/45'/1'/0'"
        },
        {
          "pubkey": "034e3c4ffe60dc04a59a60bab625df1a9a165eced2267a9689cee5d92de9e80b48",
          "master_fingerprint": "93c410d8",
          "path": "m/45'/1/0"
        },
        {
          "pubkey": "03ec21e586979d7ea14c3ecfd89f2ca5aedd4c99c8a8acff32e4d85e15742c5414",
          "master_fingerprint": "44c11f58",
          "path": "m/45'/1'/0'"
        }
      ]
    }
  ],
  "outputs": [
    {
    }
  ],
  "fee": 0.00034095
}

What I'm missing?

Thanks!

bigspider commented 1 month ago

Hi, I'd first observe that the 93c410d8 key has the unusual derivation m/45'/1/0 instead of the m/45'/1'/0' of the other two keys. Is that intended? That's unusual, so it might be a possible mistake.

In any case, the bip32_derivs of the input are certainly wrong: there you'd expect a path like m/45'/1'/0'/0/<something> or m/45'/1'/0'/1/<something>, where the final two derivation steps are the same for all the keys.

javiervargas commented 1 month ago

Thanks for your answer @bigspider .

First, it's the way that works to achieve recover this address on other open wallets like Caravan, I think it's a ColdCard matter.

About derivation paths, so I should include complete paths like this, right? changed psbt and get same output.

    bip32Derivation: [
                {
                    masterFingerprint: Buffer.from('44c11f58', 'hex'),
                    pubkey: cosigner1Pubkey,
                    path: "m/45'/1'/0'/0/0", 
                },
                {
                    masterFingerprint: Buffer.from('ad38d9ea', 'hex'),
                    pubkey: cosigner2Pubkey,
                    path: "m/45'/1'/0'/0/0", 
                },
                {
                    masterFingerprint: Buffer.from('93c410d8', 'hex'),
                    pubkey: cosigner3Pubkey,
                    path: "m/45'/1/0/0/0", 
                }
            ]
        });
    psbt.updateGlobal({
        globalXpub: [
                {
                        masterFingerprint: Buffer.from('44c11f58', 'hex'),
                        extendedPubkey: Buffer.from(cosigner1ExtendedPubKey, 'hex'),
                         path: "m/45'/1'/0'/0/0"
                },
                {
                        masterFingerprint: Buffer.from('ad38d9ea', 'hex'),
                        extendedPubkey: Buffer.from(cosigner2ExtendedPubKey, 'hex'),
                        path: "m/45'/1'/0'/0/0"
                },
                {
                        masterFingerprint: Buffer.from('93c410d8', 'hex'),
                        extendedPubkey: Buffer.from(cosigner3ExtendedPubKey, 'hex'),
                        path: "m/45'/1/0/0/0"
                }
        ]
bigspider commented 1 month ago

The global_xpubs should be on the m/45'/1'/0' path; typically, the global xpubs are at the deepest hardened derivation step, as they are the root xpub from which all the keys used in the wallet are derived. For Ledger's wallet policies (that are compliant with BIP-388) bip32_paths should have exactly 2 additional unhardened extra derivation steps, /0/<number> or /1/<number> as mentioned above.

javiervargas commented 1 month ago

Code right now; same result. Is there any way to debug process or capture messages on web console?

Thanks for your help.

bip32Derivation: [
                {
                    masterFingerprint: Buffer.from('44c11f58', 'hex'),
                    pubkey: cosigner1Pubkey,
                    path: "m/45'/1'/0'/0/0", 
                },
                {
                    masterFingerprint: Buffer.from('ad38d9ea', 'hex'),
                    pubkey: cosigner2Pubkey,
                    path: "m/45'/1'/0'/0/0", 
                },
                {
                    masterFingerprint: Buffer.from('93c410d8', 'hex'),
                    pubkey: cosigner3Pubkey,
                    path: "m/45'/1/0/0/0", 
                }
            ]
        });
    psbt.updateGlobal({
        globalXpub: [
                {
                        masterFingerprint: Buffer.from('44c11f58', 'hex'),
                        extendedPubkey: Buffer.from(cosigner1ExtendedPubKey, 'hex'),
                         path: "m/45'/1'/0'"
                },
                {
                        masterFingerprint: Buffer.from('ad38d9ea', 'hex'),
                        extendedPubkey: Buffer.from(cosigner2ExtendedPubKey, 'hex'),
                        path: "m/45'/1'/0'"
                },
                {
                        masterFingerprint: Buffer.from('93c410d8', 'hex'),
                        extendedPubkey: Buffer.from(cosigner3ExtendedPubKey, 'hex'),
                        path: "m/45'/1/0"
                }

{type: 'transport', id: '434', date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time), message: 'Finalize, clearing busy guard', context: {…}}
index.4d6bcbeb.js:652 {type: 'transport', id: '435', date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time), message: 'Received response from exchange', context: {…}}
index.4d6bcbeb.js:652 {type: 'transport', id: '436', date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time), message: 'Starting an exchange', data: {…}, …}context: {function: 'send'}data: {abortTimeoutMs: undefined}date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time) {}id: "436"message: "Starting an exchange"type: "transport"[[Prototype]]: Object
index.4d6bcbeb.js:652 {type: 'apdu', id: '437', date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time), message: '=> f8010000e3e1e10002000000000101880573fb870032e84…c051b172b139934ea0ae471f4d696006c3a9627b334b43000'}
index.4d6bcbeb.js:652 {type: 'apdu', id: '438', date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time), message: '<= 6a80'}
index.4d6bcbeb.js:652 {type: 'transport', id: '439', date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time), message: 'Finalize, clearing busy guard', context: {…}}
index.4d6bcbeb.js:652 {type: 'transport', id: '440', date: Tue Oct 29 2024 21:44:17 GMT+0100 (Central European Standard Time), message: 'Received response from exchange', context: {…}}
index.4d6bcbeb.js:695 TransportStatusError: Ledger device: Invalid data received (0x6a80)
    at TransportWebUSB.<anonymous> (index.4d6bcbeb.js:33475:60)
    at Generator.next (<anonymous>)
    at fulfilled (index.4d6bcbeb.js:33395:32)`
bigspider commented 4 weeks ago

Not sure about the debug console (I don't use JavaScript), but if you're able to compile the app with DEBUG=1 and run it in speculos, there are a lot of debug statement that will be printed in the shell where speculos is running.

Build instructions are in the main README of the repository.

The most likely failure is still wrong info in the psbt: either wrong derivation paths, or not matching the info in the nonWitnessUtxo.

javiervargas commented 4 weeks ago

Trying to launch speculos, Meanwhile, Can you clarify please what's correct way to obtain hmac? According with samples (appClient.test.ts):

{
        policy: new WalletPolicy(
          "Cold storage",
          "wsh(sortedmulti(2,@0/**,@1/**))",
          [
            "[76223a6e/48'/1'/0'/2']tpubDE7NQymr4AFtewpAsWtnreyq9ghkzQBXpCZjWLFVRAvnbf7vya2eMTvT2fPapNqL8SuVvLQdbUbMfWLVDCZKnsEBqp6UK93QEzL8Ck23AwF",
            "[f5acc2fd/48'/1'/0'/2']tpubDFAqEGNyad35aBCKUAXbQGDjdVhNueno5ZZVEn3sQbW5ci457gLR7HyTmHBg93oourBssgUxuWz1jX5uhc1qaqFo9VsybY1J5FuedLfm4dK",
          ]
        ),
        change: 0,
        addrIndex: 0,
        expResult: "tb1qmyauyzn08cduzdqweexgna2spwd0rndj55fsrkefry2cpuyt4cpsn2pg28",
        walletHmac: Buffer.from("d7c7a60b4ab4a14c1bf8901ba627d72140b2fb907f2b4e35d2e693bce9fbb371", "hex")
      }

I'm doing this: I get hmac after register Wallet.

const [policyId, policyHmac] = await app.registerWallet(multisigPolicy);

Later should use all derivation paths? tried different combinations with same result.

const ourPubkey = await app.getExtendedPubkey("m/45'/1'/0'");
const ourKeyInfo = `[${fpr}/45'/1'/0'/0/]${ourPubkey}`;
const otherKeyInfo = "[ad38d9ea/45'/1'/0'/0]tpubDC2QJtarETt4NkxuTuGc6mvtBKgpnwJwPt8paKvQZKWiUESbHyMzgZyLfjzdnENJWNidnqcCmXhKUfShJ7xz1tgLP7jZpkoXpr7SGaTcEt3";
const coldKeyInfo = "[93c410d8/45'/1/0/0]tpubDCz33uKPCZzeN4agYd2vxyyBiJeZJBZKAhW638xyN9C4KxAG4MhiBrDtrq1fRADmt7jqkgym2jUefCuE4UQQgzM6MQLiPfNnpH5H5sGQkjb";
const multisigPolicy = new WalletPolicy(
                                        "Cold storage",
                                        "sh(sortedmulti(2,@0/**,@1/**,@2/**))", // a 2-of-3 multisig policy template
                                        [   
                                            otherKeyInfo, // some other bitcoiner
                                            ourKeyInfo,   // that's us
                                            coldKeyInfo
                                        ]
                                )
console.log(multisigPolicy);
const [policyId, policyHmac] = await app.registerWallet(multisigPolicy);
console.log(`Policy hmac: ${policyHmac.toString("hex")}. Store it safely (together with the policy).`);
console.log('policy : ', multisigPolicy);
console.log('policyMac: ', policyHmac.toString("hex"));
const hmac = Buffer.from(policyHmac, "hex");

const psbt = "cHNidP8BAFUCAAAAAbbUXGeNYQet/rSpcibXRxpEk0s+qcQ13AIv6TsR7CRxAQAAAAD/////AVgCAAAAAAAAGXapFNPCFDSmzeYKli+eAgd5bQx5dJI+iKwAAAAATwEENYfPAwACfNaAAAAAitcBOSwrKKPETTFTQB2dV2vR7JeW0oWISULd7zff6YwD7CHlhpedfqFMPs/Ynyylrt1MmciorP8y5NheFXQsVBQQRMEfWC0AAIABAACAAAAAgE8BBDWHzwNDTstqgAAAADyYUIjJ0r+BE97TSLMAxAVXqykmzpXn8OjrOZXpGtypAiscEQVdgAYz+aaLNncVAez1gcKaGbwAm9aUjCmBUP3QEK042eotAACAAQAAgAAAAIBPAQQ1h88DgoJ17wAAAACLzmO+hByJ5sRId8P2Yk2ocvvCRfE71oHTxzvR3kFdVQNOPE/+YNwEpZpgurYl3xqaFl7O0iZ6lonO5dkt6egLSBCTxBDYLQAAgAEAAAAAAAAAAAEA4AIAAAAAAQGIBXP7hwAy6E96KP4N/8V/Tfm4vxlR/upITB78hh8fsgAAAAAA/f///wJXHwIAAAAAABepFO9+OkwJ33cbkuScONov2H9WuEnzh6CGAQAAAAAAF6kUFsT5HlQZ3oe3saQ57nNEsrsyEmyHAkcwRAIge7VOHNcQsoLT7uwYuqaaiM4kRhZ8gEEU4cWbDyMbuGoCIBrO5a75aw+y8vhigNmzeKK1Giga1wMrTpFnzNr+XrMRASED3rqKjW60B9oFWHFsBRsXKxOZNOoK5HH01pYAbDqWJ7M0tDAAAQRpUiECI3IHP1F93YV4O5y27ztzqRZ+nLF/jn2cumFBLsJdFDYhAjahpn8UmMFHCIsODyIv7uZwUokqfOo6W5HxwRB9x3mjIQOMWCtjMi9QvCg3MVs+kA4Q8gkf1+NFTR+PrlxfllGrj1OuIgYCKxwRBV2ABjP5pos2dxUB7PWBwpoZvACb1pSMKYFQ/dAYrTjZ6i0AAIABAACAAAAAgAAAAAAAAAAAIgYDTjxP/mDcBKWaYLq2Jd8amhZeztImepaJzuXZLenoC0gYk8QQ2C0AAIABAAAAAAAAAAAAAAAAAAAAIgYD7CHlhpedfqFMPs/Ynyylrt1MmciorP8y5NheFXQsVBQYRMEfWC0AAIABAACAAAAAgAAAAAAAAAAAAAA=");
//                              const psbt = new PsbtV2();
//                              psbt.deserialize(psbtBuf);
if (!psbt || !multisigPolicy) {
        console.log("Nothing to sign :(");
        await transport.close();
        return;
}
try{
        const result = await app.signPsbt(psbt, multisigPolicy, hmac);
        console.log("Returned signatures:");
        console.log(result);
        await transport.close();
} catch (e) {}

Output:

Error during PSBT signing: TransportStatusError: Ledger device: Invalid data received (0x6a80)
    at TransportWebUSB.<anonymous> (index.4d6bcbeb.js:35747:60)
    at Generator.next (<anonymous>)
    at fulfilled (index.4d6bcbeb.js:35667:32)

Thanks!

bigspider commented 3 weeks ago

The code for registering the wallet policy is correct, except that again the derivation paths are unusual, which might suggest a mistake. You would expect just 45'/1'/0' for the derivation paths in the wallet policy, whereas the bip32 paths in the psbt (for each of the inputs, and for the change output, if any) would then have the pattern 45'/1'/0'/<0;1>/*.

javiervargas commented 3 weeks ago

Tried with that option before

     const ourPubkey = await app.getExtendedPubkey("m/45'/1'/0'");
     console.log(ourPubkey);
     const ourKeyInfo = `[${fpr}/45'/1'/0']${ourPubkey}`;
     const otherKeyInfo = "[ad38d9ea/45'/1'/0']tpubDC2QJtarETt4NkxuTuGc6mvtBKgpnwJwPt8paKvQZKWiUESbHyMzgZyLfjzdnENJWNidnqcCmXhKUfShJ7xz1tgLP7jZpkoXpr7SGaTcEt3";
     const coldKeyInfo = "[93c410d8/45'/1'/0']tpubDCz33uKPCZzeN4agYd2vxyyBiJeZJBZKAhW638xyN9C4KxAG4MhiBrDtrq1fRADmt7jqkgym2jUefCuE4UQQgzM6MQLiPfNnpH5H5sGQkjb";

     const multisigPolicy = new WalletPolicy(
         "Cold storage",
                  "sh(sortedmulti(2,@0/**,@1/**,@2/**))", // a 2-of-3 multisig policy template
                   [   
                       otherKeyInfo, // some other bitcoiner
                       ourKeyInfo,   // that's us
                       coldKeyInfo
                    ]
      )
      console.log(multisigPolicy);

With this psbt

const psbt = 'cHNidP8BAFUCAAAAAbbUXGeNYQet/rSpcibXRxpEk0s+qcQ13AIv6TsR7CRxAQAAAAD/////AVgCAAAAAAAAGXapFNPCFDSmzeYKli+eAgd5bQx5dJI+iKwAAAAATwEENYfPAwACfNaAAAAAitcBOSwrKKPETTFTQB2dV2vR7JeW0oWISULd7zff6YwD7CHlhpedfqFMPs/Ynyylrt1MmciorP8y5NheFXQsVBQQRMEfWC0AAIABAACAAAAAgE8BBDWHzwNDTstqgAAAADyYUIjJ0r+BE97TSLMAxAVXqykmzpXn8OjrOZXpGtypAiscEQVdgAYz+aaLNncVAez1gcKaGbwAm9aUjCmBUP3QEK042eotAACAAQAAgAAAAIBPAQQ1h88DgoJ17wAAAACLzmO+hByJ5sRId8P2Yk2ocvvCRfE71oHTxzvR3kFdVQNOPE/+YNwEpZpgurYl3xqaFl7O0iZ6lonO5dkt6egLSBCTxBDYLQAAgAEAAIAAAACAAAEA4AIAAAAAAQGIBXP7hwAy6E96KP4N/8V/Tfm4vxlR/upITB78hh8fsgAAAAAA/f///wJXHwIAAAAAABepFO9+OkwJ33cbkuScONov2H9WuEnzh6CGAQAAAAAAF6kUFsT5HlQZ3oe3saQ57nNEsrsyEmyHAkcwRAIge7VOHNcQsoLT7uwYuqaaiM4kRhZ8gEEU4cWbDyMbuGoCIBrO5a75aw+y8vhigNmzeKK1Giga1wMrTpFnzNr+XrMRASED3rqKjW60B9oFWHFsBRsXKxOZNOoK5HH01pYAbDqWJ7M0tDAAAQRpUiECI3IHP1F93YV4O5y27ztzqRZ+nLF/jn2cumFBLsJdFDYhAjahpn8UmMFHCIsODyIv7uZwUokqfOo6W5HxwRB9x3mjIQOMWCtjMi9QvCg3MVs+kA4Q8gkf1+NFTR+PrlxfllGrj1OuIgYCKxwRBV2ABjP5pos2dxUB7PWBwpoZvACb1pSMKYFQ/dAYrTjZ6i0AAIABAACAAAAAgAAAAAAAAAAAIgYDTjxP/mDcBKWaYLq2Jd8amhZeztImepaJzuXZLenoC0gYk8QQ2C0AAIABAACAAAAAgAAAAAAAAAAAIgYD7CHlhpedfqFMPs/Ynyylrt1MmciorP8y5NheFXQsVBQYRMEfWC0AAIABAACAAAAAgAAAAAAAAAAAAAA=';
bigspider commented 3 weeks ago

You shouldn't have to "try". You should already know what derivation paths were used when producing the utxo you're trying to spend, and fill the psbt with data that you know it's correct.

If you lost track, or if you used non-standard paths, starting over and funding a new output that you know how it's constructed is probably the shortest path.

A safe way to produce valid PSBTs for your tests is to use an existing multisig wallet to spend a transaction (e.g. Electrum / Specter / Sparrow). They all produce wallets and PSBTs that with standard derivation paths, and therefore fully compatible with BIP-388.

javiervargas commented 3 weeks ago

You're right, In fact my psbt is working on other wallets, just trying to figure out why this way not.

Just decided come back to old app.

    await btc
      .signP2SHTransaction()
      .then(sig => console.log("\n\nSig hash:", sig))
      .catch(err => console.log("\n\nErr:", err));

Thx!