Extracting Wallet IDs (Public Keys) from Bitcoin Blockchain Data Structures

3.4k Views Asked by At

I'm trying to locate the public keys associated with a Bitcoin block's transaction inputs and outputs.

Can anyone tell me where those are encoded?

Thank you.

2

There are 2 best solutions below

8
On

Simply put, in general you can't.

Depending on the signature schema, all you could get would be a hash of that public key, or, even worse, a hash of a redeem script.

More specifically, you could get some public keys in some cases. This is a partial list of what you could get:

  1. Pay-to-pubkey-hash scripts (P2PKH): you get the public key from the scriptSig for the input BTC address
  2. Pay-to-pubkey (P2PK): you get the public key from scriptPubKey for the output BTC address
  3. Pay-to-script-hash scripts (P2SH): you get the public keys from the scriptSig for the input BTC address

There are other signature schemes and in standard transactions you should be able to get either the source public key or the destination public key.

What you could do is indexing the whole blockchain and fill the gaps in transactions where BTC addresses are not included together with their public key. But, for instance, if your BTC address appears only in P2PKH outputs, you have no means to find that public key.

0
On

I cannot say they all work correctly and I didn't do multisig but this is what I have using NBitcoin:

public static string? GetScriptPubKey(this TxOut txOut)
{
    if (txOut.ScriptPubKey.FindTemplate() is PayToWitTemplate p2w)
        return p2w.ExtractScriptPubKeyParameters(txOut.ScriptPubKey)?.GetAddress(Network.Main).ToString();

    if (txOut.ScriptPubKey.FindTemplate() is PayToScriptHashTemplate p2sh)
        return p2sh.ExtractScriptPubKeyParameters(txOut.ScriptPubKey)?.GetAddress(Network.Main).ToString();

    if (txOut.ScriptPubKey.FindTemplate() is PayToTaprootTemplate p2t)
        return p2t.ExtractScriptPubKeyParameters(txOut.ScriptPubKey)?.GetAddress(Network.Main).ToString();

    if (txOut.ScriptPubKey.FindTemplate() is PayToPubkeyHashTemplate p2pkh)
        return p2pkh.ExtractScriptPubKeyParameters(txOut.ScriptPubKey)?.GetAddress(Network.Main).ToString();

    if (txOut.ScriptPubKey.FindTemplate() is PayToPubkeyTemplate p2pk)
        return p2pk.ExtractScriptPubKeyParameters(txOut.ScriptPubKey).ToString();

    if (txOut.ScriptPubKey.FindTemplate() is PayToWitPubKeyHashTemplate p2wpkh)
        return p2wpkh.ExtractScriptPubKeyParameters(txOut.ScriptPubKey)?.GetAddress(Network.Main).ToString();

    if (txOut.ScriptPubKey.FindTemplate() is PayToWitScriptHashTemplate p2wsh)
        return p2wsh.ExtractScriptPubKeyParameters(txOut.ScriptPubKey)?.GetAddress(Network.Main).ToString();

    return null;
}