MetacoSA / NBitcoin

Comprehensive Bitcoin library for the .NET framework.
MIT License
1.86k stars 841 forks source link

Get the public key given a Tx out #1219

Closed qui8t closed 3 weeks ago

qui8t commented 3 weeks ago

Could someone please let me know how I can extract a public key from any given Tx output, regardless of the output type, at least including the most common types. For instance,

"vout": [
    {
        "value": 50.00000000,
        "n": 0,
        "scriptPubKey": {
            "asm": "04fa4b30422c7820c4ef979eaa39f770b32dcddc433cfd4d3040d3f2dc337e445dfd80fd4a3afbabe11e861fe30a28c5acc0f59915d9e419ffecd8ce374d46ddf5 OP_CHECKSIG",
            "desc": "pk(04fa4b30422c7820c4ef979eaa39f770b32dcddc433cfd4d3040d3f2dc337e445dfd80fd4a3afbabe11e861fe30a28c5acc0f59915d9e419ffecd8ce374d46ddf5)#rdr7xke8",
            "hex": "4104fa4b30422c7820c4ef979eaa39f770b32dcddc433cfd4d3040d3f2dc337e445dfd80fd4a3afbabe11e861fe30a28c5acc0f59915d9e419ffecd8ce374d46ddf5ac",
            "type": "pubkey"
        }
    }
],

or

"vout": [
    {
        "value": 100.00000000,
        "n": 0,
        "scriptPubKey": {
            "asm": "OP_DUP OP_HASH160 12ab8dc588ca9d5787dde7eb29569da63c3a238c OP_EQUALVERIFY OP_CHECKSIG",
            "desc": "addr(12higDjoCCNXSA95xZMWUdPvXNmkAduhWv)#zn56zju2",
            "hex": "76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac",
            "address": "12higDjoCCNXSA95xZMWUdPvXNmkAduhWv",
            "type": "pubkeyhash"
        }
    }
],
joemphilips commented 3 weeks ago

The first one already has uncompressed pubkey which starts from 04. Second one is pubkeyhash so you can not extract it. The actual pubkey will be included in the next tx input. So if this txo is already spent, you can check the next input, if not, you cannot get pubkey unless this is your UTXO.

qui8t commented 3 weeks ago

Two follow-up questions:

joemphilips commented 3 weeks ago

 Does NBitcoin has any parsing method that returns the pubkey? Such that it returns value from pk(value) in the first example, and returns None in the second? Because I suppose there are many different types of vout each with their unique pubkey logics, so I'm trying to avoid implementing vout-specific parsing methods and use NBitcoin instead.

There are two ways.

1. Parse output descriptor ("desc"), something like

if (NBitcoin.Scripting.OutputDescriptor.TryParse(
        "pk(04fa4b30422c7820c4ef979eaa39f770b32dcddc433cfd4d3040d3f2dc337e445dfd80fd4a3afbabe11e861fe30a28c5acc0f59915d9e419ffecd8ce374d46ddf5)#rdr7xke8",
        NBitcoin.Network.Main,
        out var foo))
{
    var msg = (foo) switch
    {
        OutputDescriptor.PK pk when pk.PkProvider is NBitcoin.Scripting.PubKeyProvider.Const pkp => pkp.Pk,
        _ => null,
    };
}

2. Parse "hex" scirptpubkey directly

Something like


var hex = NBitcoin.Script.FromHex(
        "4104fa4b30422c7820c4ef979eaa39f770b32dcddc433cfd4d3040d3f2dc337e445dfd80fd4a3afbabe11e861fe30a28c5acc0f59915d9e419ffecd8ce374d46ddf5ac");

foreach (var op in hex.ToOps())
{
    if (op.PushData is not null)
    {
        try {
            var pk = new NBitcoin.PubKey(op.PushData);
            Console.WriteLine($"Pubkey from script is {pk}");
        } catch { }
    }
}

What is the correlation between pubkey and address? (as referenced in the second example)

https://bitcoin.stackexchange.com/questions/72184/why-is-p2pkh-used-instead-of-the-simpler-p2pk

qui8t commented 3 weeks ago

Both options are excellent, thank you!!

What is the correlation between pubkey and address? (as referenced in the second example)

https://bitcoin.stackexchange.com/questions/72184/why-is-p2pkh-used-instead-of-the-simpler-p2pk

Is there any approach in NBitcoin to return address given any tx out? (given the output type is either to address, pk, or any compatible script.)

joemphilips commented 3 weeks ago

Is there any approach in NBitcoin to return address given any tx out? (given the output type is either to address, pk, or any compatible script.)

No, p2pk does not have an address format.

https://bitcoin.stackexchange.com/questions/72194/why-dont-p2pk-scripts-have-their-own-address

qui8t commented 3 weeks ago

Would not RipeMD160(SHA256(pk)) in p2pk create the address?

joemphilips commented 3 weeks ago

that's not p2pk anymore, it is p2pkh.

qui8t commented 3 weeks ago

True, though would not the address be compatible?

My goal is to get either the address or pubkey for most types of tx outputs; and it seems getting address is more feasible than pubkey. So, I am looking for how I can use NBitcoin to return an address, or some field I can use to build address from.

I assume all the following types either have an address, or address is constructable:

joemphilips commented 3 weeks ago

True, though would not the address be compatible?

Not really. Please read the link that you have pasted more carefully.

I made a comment in #1220. You can close this issue I suppose.

qui8t commented 3 weeks ago

Thank you.