bip174: add global xpub field #784

pull achow101 wants to merge 2 commits into bitcoin:master from achow101:bip174-xpubs changing 1 files +23 −0
  1. achow101 commented at 2:01 AM on May 14, 2019: member

    Adds a global type for xpubs as discussed on the bitcoin-dev mailing list: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-April/016894.html

  2. achow101 commented at 2:02 AM on May 14, 2019: member
  3. doc-hex commented at 12:47 PM on May 14, 2019: none

    +1 would implement

  4. stepansnigirev commented at 3:39 PM on May 14, 2019: contributor

    Just to clarify

    It should be the public key at the highest hardened derivation index

    Should means that it's a recommendation and I still can use non-hardened derivation index, right? If so, +1 from my side.

  5. achow101 commented at 3:49 PM on May 14, 2019: member

    Should means that it's a recommendation and I still can use non-hardened derivation index, right?

    Yes. It is a recommendation, not a requirement.

  6. matthewleon commented at 11:27 PM on May 14, 2019: none

    It should be the public key at the highest hardened derivation index so that the unhardened child keys used in the transaction can be derived.

    This is a somewhat confusing sentence. At a minimum, the word highest seems ambiguous. Perhaps an example could also be provided to clarify?

  7. doc-hex commented at 1:17 PM on May 17, 2019: none

    I think we're going to need a different 'key' for this field. Here are three xpub's with the same fingerprint, and if BIP45 was being used, they would all have the same derivation (m/45'). Without having a repeating key value, there is no way to represent this in the proposed PSBT format.

    tpubD8NXmKsmWp3a3HvTG3Pe2mmkmwMfNPvVd4GorFdaQpnwV8v79zEchTuLkt1Ehz7ou5icAFYxDbS7gR592VocShPqNnmwDQcdbcPdDyVhAiG
    tpubD8NXmKsmWp3a2S1WnJk9GBXBpJNEWEd5HEQsMtV29Kk4uBzxuH1JGBq8oLAHmmVgZCiXdGANT35niN1ibSZatwQ7zHYsTtWrzjo6aKK11g4
    tpubD8NXmKsmWp3a1Hj6i1Be5fVbbRfH4Hg2reAZ9ctaizJFc9ddLG5GSHnS4f3iprEmrbFPWLmgsir2s9CaXQp2fVVMs5zVbJTnhvMxoErXQCW
    

    [Aside: All share F1CFD170. These are constructed by modulating the chain code, but as a 32-bit truncated hash, there will be legitimate fingerprint collisions in real-world examples.]

    As for a better key value to use, I think an index (32-bits, ascending) would be enough, or we could use the public key (33 bytes, compressed only).

    IMHO, the key derivation path is not useful information since I cannot verify it, but maybe it's useful to detect innocent errors between the global section and paths in the ins/outs.

    In conclusion, I propose we switch from using the (extended key fingerprint + key path) to just an (index + key path). Must start at zero, no gaps and so on.

  8. achow101 commented at 11:22 PM on May 20, 2019: member

    In conclusion, I propose we switch from using the (extended key fingerprint + key path) to just an (index + key path). Must start at zero, no gaps and so on.

    I don't think requiring it to start at 0 and increment is really needed. We just need some fixed sized nonce that makes it unique. Also, I think it would be worth keeping the extended key fingerprint as that would allow for efficient lookups in the case where fingerprints don't collide. So the key would be nonce + fingerprint + path. I would prefer something else that can be used for uniqueness that would be known from the child pubkey, although I can't think of one right now.

  9. doc-hex commented at 1:08 PM on May 21, 2019: none
    • yes to keeping the fingerprint, I missed that, and we need it for any xpub that has child_depth > 1.
    • nonce vs. index: sure. I'd use an index myself and still be compliant.
  10. stepansnigirev commented at 1:25 PM on May 25, 2019: contributor

    We could use the fingerprint of the key itself as a nonce. It's a bit redundant as it can be calculated from the xpub, but sometimes people don't know the root fingerprint and use the fingerprint of the last hardened key instead. So it may help to do quick lookups in such cases. Or we could save 3 bytes and use a 1-byte nonce without any meaning - should be enough to prevent collisions.

  11. dominik666w approved
  12. NicolasDorier commented at 7:34 AM on June 3, 2019: contributor

    I don't understand the reasoning. Because A wallet should already know out of band the xpub of B if his wallet want to create a new deposit address.

    If A knows about the xpubs out of band, then he can detect that the output of E is not the proper change.

  13. NicolasDorier commented at 7:38 AM on June 3, 2019: contributor

    It is not specific to multisig wallets actually. In general the wallet A should know how to derive addresses, and as such know the xpubs already. Not only the xpub, but if you make a more complex wallet based on mini script for example, the wallet A not only need all the xpub out of band, but also the miniscript!

    Also, what if the attacker replace the xpubof B in PSBT_GLOBAL_XPUB with his?

  14. doc-hex commented at 1:10 PM on June 3, 2019: none

    I can only comment on the Coldcard. We will support out-of-band methods to setup the xpubs involved in a multisig wallet, and also support the PSBT globals section. However there is a setting, called "Trust PSBT" with values:

    • Verify Only. Do not import the xpubs found, but do verify the correct wallet already exists on the Coldcard.

    • Offer Import. If it's a new multisig wallet, offer to import the details and store them as a new wallet in the Coldcard. (The user can view fingerprints and xpubs and M/N at this point before import.)

    • Trust PSBT. Use the wallet data in the PSBT as a temporary, multisig wallet, and do not import it. This permits some deniability and additional privacy.

    When the XPUB data is not provided in the PSBT, regardless of the above, we require the appropriate multisig wallet to already exist on the Coldcard. Default is to 'Offer' unless a multisig wallet already exists, otherwise 'Verify'.

  15. NicolasDorier commented at 2:01 PM on June 3, 2019: contributor

    @peter-conalgo

    and also support the PSBT globals section.

    Stop me if I miss something, but if Coldcard does not know the xpubs out of band, then what prevent the attacker to put his own xpub in the PSBT global section? I don't understand how this proposal fix the problem it is aiming to solve.

  16. doc-hex commented at 2:10 PM on June 3, 2019: none

    In my opinion, hardware wallets must track the M/N and xpubs for multisig wallets with which they are involved or else, yes, they will be vulnerable to changes to the PSBT. How that is stored/setup is out of scope for BIP-174 (IMHO) but with this addition to the PSBT format, HW wallets can implement a "trust on first use" model, which has proven to be very useful security model (example: SSH server pub keys).

  17. NicolasDorier commented at 2:14 PM on June 3, 2019: contributor

    @peter-conalgo good point. I think that @achow101 should clearly clarify this.

    The "trust on first use" is the only reason for this global xpub field. This seems a good way to initialize a multisig wallet.

  18. NicolasDorier changes_requested
  19. NicolasDorier commented at 2:16 PM on June 3, 2019: contributor

    The only reason to use this global xpub field is for trust on first use scenario where one wants to initialize the multisig wallet by signing the first PSBT. Else this field must be disregarded, as an attacker could very well put his own xpub.

  20. NicolasDorier commented at 2:19 PM on June 3, 2019: contributor

    @peter-conalgo I think that this global xpub is not even useful in trust on first use scenario. Because you can't even know about m...

  21. doc-hex commented at 2:20 PM on June 3, 2019: none

    @NicolasDorier Coldcard takes M/N from the first multisig input of the associated transaction.

  22. stepansnigirev commented at 2:20 PM on June 3, 2019: contributor

    @NicolasDorier, why is it the only reason? When multisignature wallet already exists and I am doing a transaction with some change going back to the wallet how can I verify that the change address uses the same master public keys without xpubs? That was the idea of this change. Storing xpubs on hardware wallets is an option, but if the hardware wallet is stateless (or wiped and initialized again) it helps.

  23. NicolasDorier commented at 2:21 PM on June 3, 2019: contributor

    @stepansnigirev because the attacker E can put his own xpub in this global field, and the HW has no way to know.

  24. NicolasDorier commented at 2:23 PM on June 3, 2019: contributor

    I like @peter-conalgo approach as this technique can be used as a very good UX to initialize wallets with more complex scripts without changing or adding PSBT fields later.

  25. stepansnigirev commented at 2:25 PM on June 3, 2019: contributor

    So there is an xpub E from the attacker, it is not in the input but it is in the output => the address is not a change address and we need to show to the user that keys are different. Let's say input is from 2 of 3 multisig with keys xpub1/derivation1, xpub2/derivation2, xpub3/derivation3, if the output uses the same xpubs it will be considered as change address, if not - spending output. How can the attacker include his E in the output?

    Can you describe the attack you are thinking of in more details? I don't understand.

  26. NicolasDorier commented at 2:32 PM on June 3, 2019: contributor

    @stepansnigirev

    • Global XPubs: A,B,E
    • Input 1: A+B (1/2)
    • Output 1: Destination
    • Output 2: A+E (1/2)
  27. NicolasDorier commented at 2:34 PM on June 3, 2019: contributor

    A see that A and B are in input 1 => OK Then A see that A and E are in output 2 => OK that's change

  28. NicolasDorier commented at 2:35 PM on June 3, 2019: contributor

    @stepansnigirev I don't believe about a stateless wallet which can't save in its memory the multi sig xpubs and m. Because how the HW would be able to give you securely a new address? How could you confirm securely on the trusted display that an address you see on your computer screen is indeed belonging to your secure wallet?

  29. NicolasDorier commented at 2:43 PM on June 3, 2019: contributor

    I am not against this BIP, but I think it is created for the wrong reason. And if HW wallet use this feature the wrong way here the problems:

    • Software supporting PSBT but not supporting the global XPUB will be unable to be used with HW wallet depending on this, resulting in user confusion. (@peter-conalgo use case of trust on first use does not fall into this problem, as coldcard will not require this field)
    • There is still many way to trick the HW into thinking an output is a change. This is a mine field, and the easiest way to deal with this minefield is by making sure the HW can itself derive the scriptPubKey, without relying on the PSBT (outside of the keypaths in the output).
  30. stepansnigirev commented at 5:45 PM on June 3, 2019: contributor

    @NicolasDorier , change address is a change address if ALL keys in inputs and change output are the same. As (A,B) != (A,E) the second output is not a change address => HW will show it as spending output.

    Software that doesn't use xpubs will be able to use hardware wallets with single keys (without multisig) or with multisig but the change address will be shown to the user as a normal spending address if the hardware wallet doesn't store the xpubs. It HW stores xpubs - no problem, HW can ignore this field.

    At the moment the fact that we are missing xpubs field in the standard makes PSBT incompatible with Trezor wallet. They don't use PSBT but they rely on xpubs.

  31. NicolasDorier commented at 11:20 PM on June 3, 2019: contributor

    @stepansnigirev so in this case it means:

    1. Wallet requiring this can't sign a coinjoined transaction. (because if there is two input A+B and A+E, then you need to use an heuristic to say "this should be a transaction signed by the A+B wallet because input A+B is the first input")
    2. They need additional logic to extract the template of the scriptPubKey of A+B and enforce that the change has the same template. Which is not an obvious thing to do outside the simplest case of multisig. (Even for multisig, this is hard as you don't know if you need to reorder the pubkeys lexicographically or not)
  32. NicolasDorier commented at 11:25 PM on June 3, 2019: contributor

    @stepansnigirev if the HW does not understand PSBT natively like coldcard does, then the responsibility to tell what is the change or not goes to the component interfacing with the HW (like HWI). This component should pass some hints to the HW to tell which input and output to sign explicitly, which can be done outside of the PSBT spec. (this make sense because which input and output to sign for a wallet is not known by the PSBT creator)

  33. stepansnigirev commented at 9:39 PM on June 4, 2019: contributor
    1. The wallet will sign anything you want, it will just display all other addresses without marking them as a change (as they are not). You also don't need to pass xpubs if you don't want to. Just a small comment, with current PSBT you can't sign CoinJoin transactions securely, there should be other changes in PSBT that would allow that. We are working on that.

    2. Yes, that might be tricky, I agree.

    3. It increases complexity of HWI as PSBT will be incomplete and HWI will need to get information from somewhere else, but we can go this way as well.

  34. NicolasDorier commented at 2:25 AM on June 5, 2019: contributor

    I am aware of this replay attack, but I don't think it is a good argument.

    Extracting the template of the wallet based on the first input is super hacky. Instead of having a global xpub field, the best would be to have the output descriptor (or miniscript) that the wallet need to sign.

    If too difficult to implement at first for the HW wallet it can start by only supporting a subset of miniscript.

  35. stepansnigirev commented at 5:29 AM on June 5, 2019: contributor

    @NicolasDorier, I like the idea of a miniscript and output descriptors much better! In this case we still get xpubs, plus we have a template for the script - sounds awesome!

  36. NicolasDorier commented at 6:55 AM on June 5, 2019: contributor

    Yeah, I think that having only the xpubs are really not useful and would require too much hack to detect the change address. Even with multisig (1 of A+B), and with the simplest case where there is only 1 input, then some change might be detected on some wallet and not other just because there is different pubkey ordering.

    There is really no way to fix those dumb differences than to tell the wallet how to precisely derive addresses, and this is what miniscript/output descriptor are meant to be useful for.

  37. achow101 commented at 8:48 AM on June 5, 2019: member

    The whole point of this is to allow for change detection. As mentioned, if a multisig input has keys derived from xpubs A, B, and C, then A, B, and C need to be provided in global field. An output will only be marked changed if it also has keys derived from A, B, and C.

    Descriptors don't really provide anymore information than this does. A script can be converted to a descriptor and vice versa, so the descriptors for many scripts provided in the transaction can be inferred from the script itself. Those that can't aren't part of the miniscript subset and aren't described by descriptors. The only thing that descriptors provide that can't be inferred are the xpubs.

  38. sipa commented at 9:29 AM on June 5, 2019: member

    @NicolasDorier Descriptors would indeed provide that information as well, but the descriptor language is designed for humans, not machines, and is rapidly evolving with different implementations that will likely not be exactly compatible. As @achow101 points out, the only information in descriptors that isn't already in PSBT is the xpubs (as the scripts involved are already in the UTXO output, or in one of the redeemscript/witnessscript fields).

  39. NicolasDorier commented at 11:29 AM on June 5, 2019: contributor

    the only information in descriptors that isn't already in PSBT is the xpubs

    I disagree.

    • For multisig: there is no information whether public key should be ordered or not when making the script, and m is missing. One could detect m by some heuristic (say, checking input 0) and assume that keys should be ordered, but this is hackish, and unspecified. If different implementation use different heuristic, then we can get incompatibilities.
    • For any non multisig/single sig use case, the xpub list is not sufficient to know the change.

    An output will only be marked changed if it also has keys derived from A, B, and C.

    If you implement it that way, then you have a vulnerability. If A is malicious and PSBT creator, he could make a change 1-of-A+B instead of 2-of-A+B and B would happily detect it as a correct change address.

    Another point: what if the hardware support both ordered and non ordered pubkeys fine. But that the UTXO tracker only support ordered (say wasabi, electrum or NBXplorer)? You can get in a situation where the HW will sign a transaction with a change that will not be detected by the software you use to track UTXOs. Nor can such software track all possible ordering of pubkeys as this grow up exponentially based on m.

    Those kind of unspecified point can only be resolved if there is a properly specified DSL, which is what miniscript and output descriptor are about. The HW does not have to be able to parse the whole grammar either.

    the descriptor language is designed for humans, not machines, and is rapidly evolving with different implementations

    I think this is completely fine, a wallet only supporting multisig and singlesig does not have to be able to parse every output descriptor. Also, what about miniscript?

    Not only this! The hardware wallet SHOULD show such descriptor/miniscript on the screen to a human anyway, to make sure you sign with the wallet you are expecting to! The fact that it is human readable is important.

  40. achow101 commented at 11:57 AM on June 5, 2019: member

    For multisig: there is no information whether public key should be ordered or not when making the script, and m is missing.

    That information is already in the scriptPubKey/redeemScript/witnessScript. The script itself is already provided, which contains all of this information.

    For any non multisig/single sig use case, the xpub list is not sufficient to know the change.

    Why?

    If you implement it that way, then you have a vulnerability. If A is malicious and PSBT createor, he could make a change 1-of-A+B instead of 2-of-A+B and B would happily detect it as a change.

    Obviously it isn't just checking the xpubs, it's also checking that the rest of the scripts match. I was stating what the point of including the global xpubs here was. Of course when you do change detection you are looking at other stuff, the xpubs are part of it.

  41. NicolasDorier commented at 12:03 PM on June 5, 2019: contributor

    That information is already in the scriptPubKey/redeemScript/witnessScript. The script itself is already provided, which contains all of this information.

    From which input? what about pubkey ordering? Should all the input have exactly the same shape for the PSBT to be accepted? What about coinjoin? (assuming you protect yourself against replay signing with some techniques -it is possible to protect such attack with a stateless HW-)

    There is so many question to ask and to respond that are not specified in here. And this is only for the case of multisig, this is not even generic problems.

    I don't understand why leaving out information which the implementer will have to guess by himself how to fetch in the PSBT instead of just using output descriptors or miniscript which fix those edge cases entirely.

  42. NicolasDorier commented at 12:05 PM on June 5, 2019: contributor

    (I updated some points on #784 (comment))

  43. achow101 commented at 12:11 PM on June 5, 2019: member

    From which input? what about pubkey ordering? Should all the input have exactly the same shape for the PSBT to be accepted? What about coinjoin? (assuming you protect yourself against replay signing with some techniques -it is possible to protect such attack with a stateless HW-)

    That's completely unrelated to PSBT. That's up to the signer (software or hardware) to figure out themselves. PSBT is just to provide all of that information.

    I don't understand why leaving out information that the implementer must guess how to fetch instead of just using output descriptors or miniscript which fix those edge cases entirely.

    Because all of it is already in the PSBT! miniscript is just a subset of script that matches to a descriptor. Those scripts are already provided by the other fields in a PSBT. By parsing the already provided scripts (which are miniscript), then you can figure out the descriptor and the signing policy. Nothing is being left out.

    The scriptPubKey/redeemScript/witnessScript can be/is provided for an output, so nothing is needed from the inputs to infer anything except the xpub matching stuff for change detection.

    Another point: what if the hardware support both ordered and non ordered pubkeys fine. But that the UTXO tracker only support ordered (say wasabi, electrum or NBXplorer)?

    That doesn't matter. The signer can construct the descriptor from the provided scripts and xpubs for both inputs and outputs and check if they match. Again, unrelated to this proposal because PSBT will provide everything needed to do so. That's up to the signer to figure out.


    @NicolasDorier I think what you are missing is that you can go from a script to a descriptor and vice versa. It is unnecessary to explicitly provide the descriptor because it can be inferred from the information already provided.

  44. NicolasDorier commented at 12:15 PM on June 5, 2019: contributor
    1. Which scriptPubKey/redeemScript/witnessScript should you use?
    2. Should the pubkeys be ordered or not?
    3. What about coinjoin? how can the signer know which input's script to base its decision?

    You say it is unrelated to PSBT, I disagree. PSBT is a standard to communicate to a wallet what need to be signed.

    If the hardware signer already know about the points that you consider "unrelated to PSBT", then why the hardware signer can't also know already the xpubs before hand like coldcard does such that they don't have to be passed in the global field in the first place?

  45. achow101 commented at 12:20 PM on June 5, 2019: member

    Which scriptPubKey/redeemScript/witnessScript should you use?

    Use for what? For any input and output, using the scriptPubKey/redeemScript/witnessScript provided for that input or output, and using the global xpubs, you can construct the descriptor for it. This is the equivalent of providing the descriptor for that input or output.

    Should the pubkeys be ordered or not?

    You can determine the order of keys by inspecting the script.

    If the hardware signer already know about the points that you consider "unrelated to PSBT", then why the hardware signer can't also know already the xpubs such that they don't have to be passed in the global field?

    ??? The signer doesn't know anything except what PSBT provides. It has its own policy based on the information provided by a PSBT to figure out what is change. The PSBT can't say what is or isn't change because it will be different for every signer for the same transaction (e.g. in a CoinJoin).


    You are asking that a descriptor be provided for each input and output as that makes change detection or whatever easier. My point is that the PSBT (with this change) contains all of the information that a descriptor will have and that the descriptor can be constructed out of the already existing information.

  46. NicolasDorier commented at 12:28 PM on June 5, 2019: contributor

    Use for what? For any input and output, using the scriptPubKey/redeemScript/witnessScript provided for that input or output, and using the global xpubs, you can construct the descriptor for it.

    Imagine this situation:

    XPub: [A,B,C]
    
    Input 1: 1 of A,B (pubkeys ordered)
    Input 2: 1 of A,B (pubkeys unordered)
    Input 3: 2 of A,B
    Input 4: A
    
    Output:
    
    Output 1: 1 of A,B (ordered)
    Output 2: 1 of A,B (unordered)
    Output 3: 2 of A,B
    Output 4: C
    

    Can you tell me what a proper HW would consider as change outputs and what should it sign?

    On the other hand with a descriptor, there is no doubt possible

    Descriptor: 1 of A,B
    
    Input 1: 1 of A,B (pubkeys ordered)
    Input 2: 1 of A,B (pubkeys unordered)
    Input 3: 2 of A,B
    
    Output:
    
    Output 1: 1 of A,B (ordered)
    Output 2: 1 of A,B (unordered)
    Output 3: 2 of A,B
    Output 4: C
    

    There is only one change: Output 1. It should only sign Input 1.

    You can determine the order of keys by inspecting the script.

    No it can't. In the example below, if Input2 did not existed, Input 1 might had the pubkeys ordered by pure luck. If it was by luck, then output 1 and 2 should be change, else it should be only output 1.

  47. achow101 commented at 12:30 PM on June 5, 2019: member

    What do you mean by "pubkeys unordered"? A script specifies an explicit pubkey ordering! A descriptor specifies an explicit pubkey ordering.

  48. NicolasDorier commented at 12:33 PM on June 5, 2019: contributor

    @achow101 no it does not.

    Imagine 2-of-A,B

    You derive on keypath k both A and B, and get pubkeys A' and B'.

    Should the script be:

    2 A' B' 2 CHECKMULTISIG or 2 B' A' 2 CHECKMULTISIG or 2 P1 P2 2 CHECKMULTISIG where P1 and P2 are lexically ordered A and B.

    It should be lexically ordered to preserve privacy (in the case of 2-3, you don't want to leak information about which party did not signed!)

    Output descriptors and miniscript order it by design.

  49. achow101 commented at 12:40 PM on June 5, 2019: member

    On the other hand with a descriptor, there is no doubt possible

    Miniscript: 1 of A,B
    
    Input 1: 1 of A,B (pubkeys ordered)
    Input 2: 1 of A,B (pubkeys unordered)
    Input 3: 2 of A,B
    
    Output:
    
    Output 1: 1 of A,B (ordered)
    Output 2: 1 of A,B (unordered)
    Output 3: 2 of A,B
    Output 4: C
    

    There is only one change: Output 1.

    This is completely pointless, just add a new field to the output that says it's change then. There's no reason for you to provide a descriptor globally. But that's not the goal. In a CoinJoin, the change outputs for each person are different and this approach doesn't work.


    @achow101 no it does not.

    Imagine 2-of-A,B

    You derive on keypath k both A and B, and get pubkeys A' and B'.

    Should the script be:

    2 A' B' 2 CHECKMULTISIG or 2 B' A' 2 CHECKMULTISIG or 2 P1 P2 2 CHECKMULTISIG where P1 and P2 are lexically ordered A and B.

    It should be lexically ordered to preserve privacy (in the case of 2-3, you don't want to leak information about which party did not signed!)

    This is unrelated to a PSBT.

    When you create a PSBT, you have already determined what the inputs and outputs are. This means that the scripts for everything are already locked in - the scriptPubKeys for the outputs are already determined which sets the order of pubkeys because the scriptPubKey commits to the script hash of the multisig script which sets the order. And the scripts for the inputs are locked in because the order is set by the scriptPubKey of the output being spent. Ordering is determined beforehand and is not a concern for any signer that receives a PSBT.

  50. NicolasDorier commented at 12:52 PM on June 5, 2019: contributor

    I know that the PSBT lock the outputs, I am just asking whether the HW should consider scripts with wrong order of pubkeys as change or not.

    Ordering is determined beforehand and is not a concern for any signer that receives a PSBT.

    Which I disagree with, because if the UTXO tracker is ordering public keys, but not the signer then a PSBT creator not ordering will create a PSBT that successfully get signed by the HW, but then the UTXO tracker will be unable to detect the change output, resulting in loss of fund if the user is not technical enough to recover it.

    In a CoinJoin, the change outputs for each person are different and this approach doesn't work.

    The Wallet interface can fill up the missing info before passing it down to the HW wallet. I am already doing this in my own code in BTCPay, the PSBT creator I developped (NBXplorer) does not know the full BIP32 path. (only the change/index part)

    So BTCpay need to process the PSBT (adding the account key path and fingerprint to all hdkeys) before sending it to the HW.

    Do you have any down side to use output descriptors instead of a set of HD Keys?

  51. achow101 commented at 1:03 PM on June 5, 2019: member

    I am just asking whether the HW should consider scripts with wrong order of pubkeys as change or not.

    I don't see how this is relevant to PSBT. It isn't the job of PSBT to specify exactly what a signer should display or not. That's a policy for a hardware wallet manufacturer to determine for themselves. IMO, the order matters. Effectively, I think change should be determined by matching descriptors. I would sign the input that matches a particular descriptor, and mark as change the output that has the same descriptor. But this isn't something that PSBT should specify.

    Which I disagree with, because if the UTXO tracker is ordering public keys, but not the signer then a PSBT creator not ordering will create a PSBT that successfully get signed by the HW, but then the UTXO tracker will be unable to detect the change output, resulting in loss of fund if the user is not technical enough to recover it.

    Why is the creator not using the same set of scriptPubKeys that the UTXO tracker is? I think this is such a contrived case that it is useless and unnecessary to consider. This really seems like a problem that the user needs to reconcile as to why their software are doing two different things.

    The Wallet interface can fill up the missing info before passing it down to the HW wallet.

    Sure, but that's for the protocol between the wallet and the hardware, not for PSBT.

    Do you have any down side to use output descriptors instead of a set of HD Keys?

    It is relatively large and just duplicates information already provided. Descriptors are written in ASCII and it massively wastes space. Also, descriptors are not a finalized format and can and do change.

  52. doc-hex commented at 1:09 PM on June 5, 2019: none

    Datapoint: Coldcard will reject any redeem script that doesn't have sorted public keys (per BIP-67), inputs or outputs.

    Aside: We are putting the finishing touches on Coldcard's multisig support (see branch 'multisig'), and we already support the global XPUB field as originally proposed (with 32bit-nonce addition). Also, psbt_dump will parse and display them. @achow101 Could you add the nonce from upthread into the diff which we are discussing?

    My comment as a hardware wallet maker: to be safe the Coldcard has to understand precisely what we are signing. Therefore, duplicating any value that can be derived from the transaction itself is not helpful. It just becomes another value that we have to double-check. I like the original proposal as it provides just the information we need and no more. The proposal is sufficient for multisig, and IMHO, other transaction types, like Coinjoin, can add additional metadata to appropriate PSBT sections when we understand what they need to be safely signed.

  53. NicolasDorier commented at 1:52 PM on June 5, 2019: contributor

    Ok then if you insist on making this global xpub field, at list, in the BIP, describe how a HW should behave precisely, if I understand:

    1. Check first input's script, and extract m.
    2. Verify that the pubkeys in the input's script are all derived from xpubs present in the global xpub field.
    3. Verify that the pubkeys are ordered per BIP-67
    4. For each output, if the output's scriptPubKey can be derived from the xpubs extracted in the first input, m and the key paths, consider it as a change.
  54. achow101 commented at 2:45 PM on June 5, 2019: member

    describe how a HW should behave precisely,

    I think that is completely out of scope for this BIP. It is not a specification of how hardware wallets should behave, it is a description of a data structure and the abstract workflow around it.

  55. achow101 commented at 8:37 AM on June 6, 2019: member

    @peter-conalgo I don't really like the nonce idea. Do you really think that collisions will really be a problem? The probability of having a master key fingerprint colliding within a PSBT is very low and in many other places, the master fingerprint is being used for uniqueness.

  56. doc-hex commented at 4:04 PM on June 6, 2019: none

    Collisions with a 32-bit truncated-hash can be legit---it's only mildly bad luck by my standards. I don't see any other spots in BIP-174 where BIP32 path is the key, so I think this is the only area with this potential problem. Of course the various implementations will still fall over, but that's not a concern when defining the file format. We just have to make it possible to create a conforming implementation that handles all cases.

    Alternatives to the 32-bit nonce idea:

    1. We could loosen the rules about duplicate key values, maybe only in the global section, to allow repeated keys (but not repeated (key, value) pairs).

    2. We could insert a reserved value into the keypath when needed to make it unique (perhaps all ones). In case of multiple duplicates, you'd insert two of the reserved values.

    3. Use something else as the key, even just a counter, and then append the bip32 path after the xpub. More complex perhaps, but does allow growth in the future.

    The problem I see with (1) and (2) is they won't get implemented, since they only happen in this special case. Most coders are happy with "works most of the time"... The nonce idea, and (3) force implementations to do it right.

  57. NicolasDorier commented at 3:14 AM on June 7, 2019: contributor

    I prefer a solution forcing implementation to do it right. Else we will end up with people having money locked unexpectedly (unless they are wizards).

  58. stepansnigirev commented at 10:07 AM on June 7, 2019: contributor

    What if we flip key and value? Having xpub as a key and derivation path as a value would prevent collisions. It's harder to do lookups though. The only concern I have is that you could have multiple derivation paths for the same xpub depending on which parent key you consider a master key.

  59. achow101 force-pushed on Jun 9, 2019
  60. achow101 commented at 8:46 AM on June 9, 2019: member

    I've updated the changes as was discussed at Breaking Bitcoin.

    The key is changed to be the xpub and the value is the derivation path. The depth of the provided derivation path must match the depth specified in the xpub.

    I've also added a section on how change detection would work with this.

  61. bip174: add global xpub field 19d3b9dc82
  62. achow101 force-pushed on Jun 9, 2019
  63. stepansnigirev commented at 1:37 PM on June 9, 2019: contributor

    Looks good to me.

  64. doc-hex commented at 1:41 PM on June 9, 2019: none

    Love it.

  65. in bip-0174.mediawiki:378 in 9f569ded77 outdated
     373 | +For a single key output, a signer can observe whether the master fingerprint for the public key for that output belongs to itself.
     374 | +If it does, it can then derive the public key at the specified derivation path and check whether that key is the one present in that output.
     375 | +
     376 | +For outputs involving multiple keys, a signer can first examine the inputs that it is signing. It should determine the general pattern of the script.
     377 | +For example, it can observe the redeemScript or witnessScript and determine whether it is multisig.
     378 | +If it is multisig, it should determine how many keys there are, in what position they are, and how many signers are needed in order for the input to be valid.
    


    NicolasDorier commented at 1:46 PM on June 9, 2019:

    Make sure the pub keys are ordered (BIP-67) else there will be problems of changes not detected by the wallet software.


    achow101 commented at 1:52 PM on June 9, 2019:

    No. Enforcing multisig rules is out of scope for PSBT. This section is just to clarify how xpubs can be used for change detection. It isn't a description of what must be done.


    NicolasDorier commented at 1:54 PM on June 9, 2019:

    Then remove in what position they are because it assumes there is no ordering...


    NicolasDorier commented at 1:57 PM on June 9, 2019:

    If you specify in what position they are it means that if there is an input with 2 PubA PubB MULTISIG, then a change with 2 PubB' PubA' MULTISIG should not be considered a change. Which mean that BIP67 would be incompatible with what you are saying, not merely out of scope, but incompatible.


    stepansnigirev commented at 4:34 PM on June 9, 2019:

    Position matters in some cases. We could add an example: If A, B and C are xpubs, ai, bi, ci are keys derived from them and input uses a spending script with condition (a1 or b1) and c1 then output with condition (a2 or b2) and c2 or (b2 or a2) and c2 can be considered as change, but (a2 or c2) and b2 should not.


    achow101 commented at 9:40 PM on June 9, 2019:

    I've made it clearer that those things are examples of things that signers can check, not things that they must check.


    NicolasDorier commented at 3:59 AM on June 10, 2019:

    ~@stepansnigirev no, if you follow BIP67, then (a2 or c2) and b2 SHOULD be considered as change and not (b2 or a2) and c2.~ @stepansnigirev I am concerned only about multi sigs expressions. in the form of 2 A B 2 MULTISIG @achow101 please remove the in what position they are this will really cause problem in the future. Either you force implementer to check BIP67, or you don't imply they can check the order.

    If you say they can check the order, and that they do, we will have bunch of incompatibilities accross HW and wallet interfaces. This is an disincentive to use BIP67, which is bad: people using BIP67 will be incompatible with HW which check the order.

    The whole point of PSBT is to nail down incompatibilities, not add more of them.


    achow101 commented at 5:49 PM on June 10, 2019:

    @NicolasDorier The BIP is not saying anything about what signers must check. That whole section is about constructing the policy represented by a script, i.e. the descriptor. Public key order is something that can be part of such constructions. At no point does it say that signers must check that or that public key order must be part of the policy.

    Incompatibilities between signers is to be expected because they will all probably have different signing policies. Specifying those signing policies is out of scope for this BIP. PSBT is an interchange format, not a description of how a wallet should work.


    NicolasDorier commented at 6:30 AM on June 11, 2019:

    At no point does it say that signers must check that or that public key order must be part of the policy.

    I agree, but it does, and that's my problem! it says that the public key order must be part of the policy:

    If it is multisig, it should determine how many keys there are, in what position they are


    achow101 commented at 7:19 AM on June 11, 2019:

    How about you read and review the current text instead of an outdated one? It no longer says that!


    NicolasDorier commented at 7:33 AM on June 11, 2019:

    Indeed! The updated one seems OK to me.

  66. bip174: add section describing change detection e1f770e236
  67. achow101 force-pushed on Jun 9, 2019
  68. achow101 commented at 7:17 PM on June 12, 2019: member

    @luke-jr This looks to be RTM.

  69. achow101 cross-referenced this on Jun 16, 2019 from issue Coldcard v2.1.0 and above does multisig by doc-hex
  70. achow101 commented at 11:53 PM on July 9, 2019: member

    @luke-jr This can be merged.

  71. luke-jr merged this on Jul 10, 2019
  72. luke-jr closed this on Jul 10, 2019

  73. NicolasDorier commented at 9:00 AM on July 10, 2019: contributor

    @achow101 do you have a test vector somewhere?

  74. NicolasDorier referenced this in commit 853a63d993 on Jul 10, 2019
  75. NicolasDorier commented at 9:25 AM on July 10, 2019: contributor

    Here is what I get:

    cHNidP8BAJoCAAAAAqmeyBQKKaI4mLDsQKtdpzGKG+W1MpcqHafaxBqbiHg8AAAAAAD/////qZ7IFAopojiYsOxAq12nMYob5bUylyodp9rEGpuIeDwBAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAATwEENYfPA9tUzYaAAAAAPyQBTmKLwpLRdTq/jl153VaJxd4KnlaDe6Lv6N2k8KEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8Q2QxqTwAAAIAAAACAAAAAgAABAE4BAAAIAAIAwusLAAAAABl2qRQFw/p8wLK+KgyugzKd8/kd2nKDjoisAMLrCwAAAAAZdqkUHatMqMPhz5T3nB9d5BX6mSv77jGIrAAAAAAiBgPM2yteF/6Eznlt1wjiHtdnWCue+MH/36jP8/gx7RMm2xTZDGpPAAAAgAAAAIAAAACAAAAAgAABAE4BAAAIAAIAwusLAAAAABl2qRQFw/p8wLK+KgyugzKd8/kd2nKDjoisAMLrCwAAAAAZdqkUHatMqMPhz5T3nB9d5BX6mSv77jGIrAAAAAAiBgJ8eKXzQrU9QnNbxV5xU2g6eyIl9Pug2hG25WklswpitRTZDGpPAAAAgAAAAIAAAACAAQAAgAAAAA==
    
  76. junderw commented at 9:37 AM on July 23, 2019: contributor

    So, after properly reading this entire thread, I've come to realize that Cold-card is trying to implement a feature similar to my other global data point proposal #801

    However, instead of internalizing the whitelist data (via an HW internal state combined with Trust on First Seen) my proposal is to create a signature with a specific private key of the HW seed, and have that signature passed in through the PSBT... meaning the wallet does not need an internal state.

    My proposal also seems to deal with a few of @NicolasDorier concerns... (though some are still existing)

  77. achow101 cross-referenced this on Jul 25, 2019 from issue [BIP 174] Implement serialization support for GLOBAL_XPUB field. by achow101
  78. achow101 cross-referenced this on Jan 25, 2021 from issue [BIP 174] PSBT version, proprietary, and xpub fields by achow101
  79. laanwj referenced this in commit 50c502f54a on Dec 10, 2021
  80. sidhujag referenced this in commit 525d6c6f49 on Dec 11, 2021
  81. RandyMcMillan referenced this in commit 7f1a6eeaa8 on Dec 23, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bips. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-14 15:10 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me