Unexpected behaviour when using sortedmulti_a descriptor #30518

issue KonradStaniec openend this issue on July 24, 2024
  1. KonradStaniec commented at 8:12 am on July 24, 2024: none

    Is there an existing issue for this?

    • I have searched the existing issues

    Current behaviour

    Currently running:

    0getdescriptorinfo "tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),multi_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e)))"
    

    will respond with success for such descriptor:

    0{
    1  "descriptor": "tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),multi_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e)))#dy2rfhga",
    2  "checksum": "dy2rfhga",
    3  "isrange": false,
    4  "issolvable": true,
    5  "hasprivatekeys": false
    6}
    

    Though running the same command with the same data but with sortedmulti_a instead of multi_a will generate error:

    0getdescriptorinfo "tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),sortedmulti_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e)))"
    

    and error:

    0'and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),sortedmulti_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e))' is not a valid descriptor function
    

    Expected behaviour

    I would expect that the call

    0getdescriptorinfo "tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),sortedmulti_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e)))"
    

    will also succeed

    Steps to reproduce

    call command

    0getdescriptorinfo "tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),sortedmulti_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e)))"
    

    Relevant log output

    No response

    How did you obtain Bitcoin Core

    Other

    What version of Bitcoin Core are you using?

    v27.0

    Operating system and version

    MacOs Sonoma 14.5

    Machine specifications

    No response

  2. willcl-ark commented at 9:20 am on July 25, 2024: member

    Thanks for the report.

    I would also expect to see these decodes behave the same as the only difference between them should be the sorting. I didn’t investigate further yet, but incidentally I see the same behaviour in a toy rust-miniscript parser I have:

     0Loading descriptor: tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),multi_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e)))
     1Loaded descriptor
     2Descriptor type: Tr
     3Segwit version: V1
     4Has wildcard: false
     5Max weight to satisfy: 272
     6Satisfaction structure:
     7  Taproot:
     8    Internal Key: 50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0
     9    Has script tree
    10    
    11    
    12Loading descriptor: tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,and_v(v:pk(b6df9cc452123b137ae8ad15927ff78b7e4e010a97b8ef6732d6d9d692abd993),sortedmulti_a(1,0153089cb23a34755aeba2737cb2134add1708e09dca8ae128ccdb1f035f3197,572706d9cf6b553f179daaf22f456b8e31200f59f51d9dcef936cde61918220e)))
    13Error analyzing descriptor: unexpected «sortedmulti_a(3 args) while parsing Miniscript»
    
  3. sipa commented at 11:07 am on July 25, 2024: member

    This apparent inconsistency is due to the fact that multi_a exists both as a top-level descriptor fragment and inside miniscript, but sortedmulti_a only as a top-level fragment.

    We should probably add sortedmulti_a to miniscript too.

  4. darosior commented at 12:48 pm on August 6, 2024: member

    I’m not sure. sortedmulti_a was introduced for compatibility with legacy pre-descriptor practices. I can’t think of any reason to ever prefer sortedmulti_a/sortedmulti to multi_a/multi inside Miniscript. And there is no legacy compatibility concern since any Miniscript-using wallet must have been created in a post-descriptor world.

    So i don’t think it’s worth adding sorted* fragments to Miniscript.

  5. sipa commented at 6:30 pm on August 6, 2024: member
    @darosior I vaguely recall discussing this before, but I don’t remember the reasoning. Imagine some particular application uses a specific fancy timelock/hashlock/2-of-3 combination that (when the script path is used) readily gives away it’s a transaction by that particular application due to its unusual script. If the descriptor for that uses multi_a(mobile_xpub,desktop_xpub,server_xpub), then the location of the key signed with will additionally publish which parties are involved on chain. Using sortedmulti_a there instead would reduce that information leak.
  6. darosior commented at 11:17 am on October 15, 2024: member
    @sipa i agree it’s a point in favour of ordering (or randomizing) the order of keys. But i don’t think it’s a reason to have it in the descriptor language itself. The application can just randomize the order before creating the descriptor.
  7. darosior commented at 11:26 am on October 15, 2024: member
    This is also very specific to one usecase. If the descriptor used by the application is c:or_i(pk_k(A),pk_k(B)) does this mean the language needs a sorted_or_i (same goes for all combination fragments)? In my opinion no, it just means the application shouldn’t leak the order by always placing the key for the same role in the same spot.

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-10-18 04:12 UTC

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