`GetSigningProvider` returns a different key than expected #24822

issue w0xlt opened this issue on April 11, 2022
  1. w0xlt commented at 12:41 AM on April 11, 2022: contributor

    I'm trying to find the private key related to a specific CScript scriptPubKey, which belongs to the wallet and is of type TxoutType::WITNESS_V1_TAPROOT.

    So I was getting the key through DescriptorScriptPubKeyMan::GetSigningProvider(&script, true) and it looks like the returned key failed to recreate the scriptPubKey that was looked for.

    So I created the test below in the DescriptorScriptPubKeyMan and it looks like scriptPubKey created from the returned CKey is different from the one passed as parameter to GetSigningProvider(), as shown below.

    I don't think this is a error or a bug. Maybe I'm using a function differently than expected, but I thought it best to report it anyway.

    for (auto const& [scriptPubKey, index] : m_map_script_pub_keys)
      {
            std::vector<std::vector<unsigned char>> solutions;
            TxoutType whichType = Solver(scriptPubKey, solutions);
    
            // Confirm the scriptPubKey is WITNESS_V1_TAPROOT
            if (whichType != TxoutType::WITNESS_V1_TAPROOT) {
                return false;
            }
    
            std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(scriptPubKey, true);
    
            if (!coin_keys || coin_keys->keys.size() != 1) {
                return false;
            }
    
            auto& key = coin_keys->keys.begin()->second;
    
            XOnlyPubKey pubkey = XOnlyPubKey(key.GetPubKey());
            auto destScriptPubKey = GetScriptForDestination(WitnessV1Taproot(pubkey));
            CTxDestination address;
            ExtractDestination(destScriptPubKey, address);
    
            CTxDestination address2;
            ExtractDestination(scriptPubKey, address2);
    
            std::cout << "---> " << index  << std::endl;
            std::cout << "---> address from PrivKey              : " << EncodeDestination(address) << std::endl;
            std::cout << "---> address from m_map_script_pub_keys: " << EncodeDestination(address2) << std::endl;
        }
    

    results:

    ....
    ---> 827
    ---> address from PrivKey              : bcrt1pzrm0jd2k3xlht7qxly4frzmkcsl88tu36vh6qy6glqfsmy7pehqsljyf9g
    ---> address from m_map_script_pub_keys: bcrt1plmy7d5h7unq0w9e9crqmqmztnz29pnmz8j6jaw7hpm4fqt0wv59q0q4zlq
    ---> 524
    ---> address from PrivKey              : bcrt1pf3pxl3443umsux2345yddhgwtm2lyj5wnvg5cd00qj03ehs4ftxs5v3362
    ---> address from m_map_script_pub_keys: bcrt1plmv07yph7cpdylv74vxk8mqhmplrv9hucgsztggmyc00t5dz677sue0wcc
    ---> 668
    ---> address from PrivKey              : bcrt1p9jjeh99gcre5xvk7ap6slvmg42fcyzkakdqmyw0y3wmfe76jm0xsq68z9r
    ---> address from m_map_script_pub_keys: bcrt1playljc8rhyjm0d572r405tfj3g3nfxawuqerzcke6l00f0nfmy3qgrdx86
    ---> 196
    ---> address from PrivKey              : bcrt1paxnn7ve979qrxmujvy2t5gktu8tk8ynpq47ad2pr9g50s8lu30lqdl4z78
    ---> address from m_map_script_pub_keys: bcrt1pla0z8qefr0ngu7t2hx08l49j64whh60yjm6edkel5y9dln3uzxls0w2tlh
    
    
  2. sipa commented at 12:46 AM on April 11, 2022: member

    Taproot keys are tweaked, even when there is no script present. That means that the pubkey used in the scriptPubKey isn't actually a wallet key. The signing logic corrects for the tweak at signing time.

  3. w0xlt commented at 2:58 AM on April 11, 2022: contributor

    @sipa thanks for your quick reply. With the information you posted I was able to fix the script.

    for (auto const& [scriptPubKey, index] : m_map_script_pub_keys)
        {
            std::vector<std::vector<unsigned char>> solutions;
            TxoutType whichType = Solver(scriptPubKey, solutions);
    
            // Confirm the scriptPubKey is WITNESS_V1_TAPROOT
            if (whichType != TxoutType::WITNESS_V1_TAPROOT) {
                return false;
            }
    
            auto xOnlyPubKey = XOnlyPubKey(solutions[0]);
    
            std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(scriptPubKey, true);
    
            TaprootSpendData spenddata;
            coin_keys->GetTaprootSpendData(xOnlyPubKey, spenddata);
    
            if (!coin_keys || coin_keys->keys.size() != 1) {
                return false;
            }
    
            auto& key = coin_keys->keys.begin()->second;
    
            XOnlyPubKey pubkey = XOnlyPubKey(key.GetPubKey());
            auto tweakedPubkeyRet = pubkey.CreateTapTweak(spenddata.merkle_root.IsNull() ? nullptr : &spenddata.merkle_root);
    
            if (!tweakedPubkeyRet || tweakedPubkeyRet->first == pubkey) {
                std::cout << "tweak failed" << std::endl;
                return false;
            }
    
            XOnlyPubKey tweakedPubkey = tweakedPubkeyRet->first;
    
            auto destScriptPubKey = GetScriptForDestination(WitnessV1Taproot(tweakedPubkey));
            CTxDestination address;
            ExtractDestination(destScriptPubKey, address);
    
            CTxDestination address2;
            ExtractDestination(scriptPubKey, address2);
    
            std::cout << "---> " << index  << std::endl;
            std::cout << "---> address from PrivKey              : " << EncodeDestination(address) << std::endl;
            std::cout << "---> address from m_map_script_pub_keys: " << EncodeDestination(address2) << std::endl;
        }
    

    Results:

    ---> 827
    ---> address from PrivKey              : bcrt1plmy7d5h7unq0w9e9crqmqmztnz29pnmz8j6jaw7hpm4fqt0wv59q0q4zlq
    ---> address from m_map_script_pub_keys: bcrt1plmy7d5h7unq0w9e9crqmqmztnz29pnmz8j6jaw7hpm4fqt0wv59q0q4zlq
    ---> 524
    ---> address from PrivKey              : bcrt1plmv07yph7cpdylv74vxk8mqhmplrv9hucgsztggmyc00t5dz677sue0wcc
    ---> address from m_map_script_pub_keys: bcrt1plmv07yph7cpdylv74vxk8mqhmplrv9hucgsztggmyc00t5dz677sue0wcc
    ---> 668
    ---> address from PrivKey              : bcrt1playljc8rhyjm0d572r405tfj3g3nfxawuqerzcke6l00f0nfmy3qgrdx86
    ---> address from m_map_script_pub_keys: bcrt1playljc8rhyjm0d572r405tfj3g3nfxawuqerzcke6l00f0nfmy3qgrdx86
    ---> 196
    ---> address from PrivKey              : bcrt1pla0z8qefr0ngu7t2hx08l49j64whh60yjm6edkel5y9dln3uzxls0w2tlh
    ---> address from m_map_script_pub_keys: bcrt1pla0z8qefr0ngu7t2hx08l49j64whh60yjm6edkel5y9dln3uzxls0w2tlh
    
  4. w0xlt closed this on Apr 11, 2022

  5. DrahtBot locked this on Apr 11, 2023
Contributors

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-04-21 00:14 UTC

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