MetacoSA / NBitcoin

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

How can i get collection address when ScriptPubKey.GetDestinationAddress() returns null #994

Open shawenbin opened 3 years ago

shawenbin commented 3 years ago

eg. block No.1 has a collection address "12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX",but ScriptPubKey.GetDestinationAddress() returns null

GetBlockResponse gbr = await client.GetBlock(new BlockFeature(1));
gbr.Block.Transactions.ForEach(tr =>
    tr.Outputs.ForEach(ot =>
    {
        BitcoinAddress ad = ot.ScriptPubKey.GetDestinationAddress(Network.Main);
    }));

How can I get collection address "12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX" in block 1? Thanks.

lontivero commented 3 years ago

P2PK scripts don't have addresses. You are using a block explorer which is lying to you.

shawenbin commented 3 years ago

P2PK scripts don't have addresses. You are using a block explorer which is lying to you.

Why the block explorer can get collection address of the block No.1, but i can't through using the same block data. Is there another way base on NBitcoin instead of a block explorer.

lontivero commented 3 years ago

Why do you need a wrong result? Is it really important for your software to provide wrong values and make its users to potentially loss money?

shawenbin commented 3 years ago

Maybe I don't understand deeply enough. Can I continue to ask you some questions? Even if it is pay to public key, the public key should also correspond to a unique address. I try to change my the code below:

GetBlockResponse gbr = await client.GetBlock(new BlockFeature(1));
gbr.Block.Transactions.ForEach(tr =>
    tr.Outputs.ForEach(ot =>
    {
        BitcoinAddress add = ot.ScriptPubKey.GetDestinationAddress(Network.Main);
        if(add == null)
        {
            var dpk = ot.ScriptPubKey.GetDestinationPublicKeys();
            add = dpk[0].GetAddress(ScriptPubKeyType.Legacy, Network.Main);
        }
    }));

Then add is the same value as which a block explorer show me. Why do you say it's wrong?This address can be used to query the balance.

lontivero commented 3 years ago

Even if it is pay to public key, the public key should also correspond to a unique address.

No. There are many different types of scripts that can use does public key. For example, with a public key you can generate what is known as a Legacy address (p2pkh: those starting in 1) a segwit address (p2wpkh: those starting with bc1) and others. So, no, one public key is not associated to a unique address.

Why do you say it's wrong?

Because it is. It is also dangerous because if someone sends money to that address those bitcoins will be lose forever. No serious software should provide misleading information as your code does. What you should do is to improve the situation and do the best for you and your users instead of copying the worst from others. Take a look at how blockstream.info does it, it doesn't display a fake address just because everybody else does.

shawenbin commented 3 years ago

Thank you for your detailed description of the reason. I understand why sometimes ScriptPubKey.GetDestinationAddress() returns null. It also outputs data according to your hypothesis on blockstream.info. Thank you again.