Importing musig descriptor with identical (private) keys in tapleaf and only musig subderivation different fails #34273

issue scgbckbone openend this issue on January 13, 2026
  1. scgbckbone commented at 4:32 pm on January 13, 2026: contributor

    Is there an existing issue for this?

    • I have searched the existing issues

    Current behaviour

    Below is very silly policy, that has two almost identical musig expressions in single tapleaf. Keys inside musig expressions are the same, only musig derivation is different, yielding different resulting keys.

    tr($H,and_v(v:pk(musig($0,$1,$2)/<0;1>/*),pk(musig($0,$1,$2)/<2;3>/*)))

    I have no issues importing descriptor from above policy with only public keys into bitcoin core. Yet when I replace with private keys I’m getting is not sane: contains duplicate public keys

    Expected behaviour

    regardless whether descriptor contains private or public keys, it should import without duplicate keys error as musig key expression should be treated as only one key and only that key should be considered for duplicate check

    Steps to reproduce

    Descriptor with only public keys that imports no problem:

    0tr(tpubD6NzVbkrYhZ4WMCcYXEgDrM1AFATSGmrFyMnA2Dgx1Y551VueaE3iemHhQBxhKWjepG76Cy5QmXv8z4KwN6ARTnZ5hVuShfxL129NVGXZuE/<0;1>/*,and_v(v:pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,[bd6eb0b5/44h/1h/0h]tpubDDZuASpyXjtMrnf1rDDREY1VXt89RNS4ZHU99KSkvUYd7CcuDQMPizr1sBHEXhjDy3qU8sAK2i4vkcgAat84S2w4wMJM8BpJ9dPuQKV1Uqh,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/<0;1>/*),pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,[bd6eb0b5/44h/1h/0h]tpubDDZuASpyXjtMrnf1rDDREY1VXt89RNS4ZHU99KSkvUYd7CcuDQMPizr1sBHEXhjDy3qU8sAK2i4vkcgAat84S2w4wMJM8BpJ9dPuQKV1Uqh,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/<2;3>/*)))
    

    Replace one public key with corresponding private key:

    0[{'desc': 'tr(tpubD6NzVbkrYhZ4WMCcYXEgDrM1AFATSGmrFyMnA2Dgx1Y551VueaE3iemHhQBxhKWjepG76Cy5QmXv8z4KwN6ARTnZ5hVuShfxL129NVGXZuE/0/*,and_v(v:pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,tprv8ZgxMBicQKsPd3QxqYNKLfXHkRYHSayji5qWZDLuSiDAG3S7oyhbV9VRZ4RD35LTYM11aDpvTsovP9mafLAqyCsPpwmAzt6Y6GPr8wNeHNQ/44h/1h/0h,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/0/*),pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,tprv8ZgxMBicQKsPd3QxqYNKLfXHkRYHSayji5qWZDLuSiDAG3S7oyhbV9VRZ4RD35LTYM11aDpvTsovP9mafLAqyCsPpwmAzt6Y6GPr8wNeHNQ/44h/1h/0h,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/2/*)))#vqqlj5dt', 'timestamp': 1768321595, 'active': True, 'internal': False, 'range': [0, 100]}, {'desc': 'tr(tpubD6NzVbkrYhZ4WMCcYXEgDrM1AFATSGmrFyMnA2Dgx1Y551VueaE3iemHhQBxhKWjepG76Cy5QmXv8z4KwN6ARTnZ5hVuShfxL129NVGXZuE/1/*,and_v(v:pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,tprv8ZgxMBicQKsPd3QxqYNKLfXHkRYHSayji5qWZDLuSiDAG3S7oyhbV9VRZ4RD35LTYM11aDpvTsovP9mafLAqyCsPpwmAzt6Y6GPr8wNeHNQ/44h/1h/0h,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/1/*),pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,tprv8ZgxMBicQKsPd3QxqYNKLfXHkRYHSayji5qWZDLuSiDAG3S7oyhbV9VRZ4RD35LTYM11aDpvTsovP9mafLAqyCsPpwmAzt6Y6GPr8wNeHNQ/44h/1h/0h,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/3/*)))#d20d849q', 'timestamp': 1768321595, 'active': True, 'internal': True, 'range': [0, 100]}]
    

    results in error:

    0{'success': False, 'error': {'code': -5, 'message': 'and_v(v:pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,tpubD6NzVbkrYhZ4WWSkjC2uk5BQKT4DbvAeHPSHqjPCrz1Z6XgtSNXBfe7HjCVKqpPEnSb2LNxw2KxDeWvM22UPDoYmf7rkbdW1qc8yWJUnpFe/44h/1h/0h,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/0/*),pk(musig([0f056943/86h/1h/0h]tpubDCeEX49avtiXrBTv3JWTtco99Ka499jXdZHBRtm7va2gkMAui11ctZjqNAT9dLVNaEozt2C1kfTM88cnvZCXsWLJN2p4viGvsyGjtKVV7A1,tpubD6NzVbkrYhZ4WWSkjC2uk5BQKT4DbvAeHPSHqjPCrz1Z6XgtSNXBfe7HjCVKqpPEnSb2LNxw2KxDeWvM22UPDoYmf7rkbdW1qc8yWJUnpFe/44h/1h/0h,[18953581/44h/1h/0h]tpubDDJDF4KvHFML8KW4QCstjJaSes1D5uEcEZWTSA3ZpQPTuQTXobVBT7sGkJbLebJ88xrtvWS5fMVMNK1xTSNWNsWWc2tUybdz96HPMKA3LFV)/2/*)) is not sane: contains duplicate public keys'}}
    

    Same error can be seen if one uses getdescriptorinfo rpc

    Relevant log output

    No response

    How did you obtain Bitcoin Core

    Compiled from source

    What version of Bitcoin Core are you using?

    using code from PR #34141

    Operating system and version

    Linux … 6.14.0-37-generic #37~24.04.1-Ubuntu … x86_64 x86_64 x86_64 GNU/Linux

    Machine specifications

    No response

  2. 151henry151 commented at 9:50 pm on January 13, 2026: contributor

    If the duplicate key check is examining the individual participant keys rather than the aggregated MuSig keys, then maybe when private keys are involved the aggregation step behaves differently during validation, causing the underlying participant keys to be compared instead.

    Alternatively, perhaps the aggregation with private keys isn’t properly applying the MuSig derivation paths, resulting in both expressions producing the same aggregate key.

    I’d think to look at how duplicate checking handles MuSig expressions when it can’t fully resolve the aggregated key. This might be happening when GetPubKey(0, dummy, dummy) is called during duplicate checking with an empty SigningProvider, which could cause the aggregation to fail or behave differently when private keys are present.

  3. willcl-ark added the label Wallet on Jan 14, 2026
  4. willcl-ark added the label Descriptors on Jan 14, 2026

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: 2026-01-16 21:13 UTC

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