Get public key from an outgoing transaction with pycoin

11 replies 272 views
lonevectorFull Member
Posts: 72 · Reputation: 409
#1Aug 11, 2017, 01:11 PM
From what I understand so far, you should be able to use block explorer APIs like blockchain.info, blockcypher, or chain.so with the pycoin library in Python. The docs give a brief overview of this, but I'm struggling to make my specific query work. Can anyone help me out with a code example on how to utilize these pycoin services to get the query right? Here's what I'm trying to do: Bitcoin Address for the query: 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH Transaction to check: 3da9b8e4a9c056b22d4fd09784402fd1caab1ecf621ba074efc20dc03ff04277 I need a Python script that will pull the public key from this transaction, which is: 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 Any help would be awesome. Thanks!
4 Reply Quote Share
byte_protoFull Member
Posts: 84 · Reputation: 625
#2Aug 11, 2017, 05:33 PM
Op did you try to use any block explorer (blockchain.com or blockcypher.com) API key, I think you need this in order to get the  information, I wrote a code referencing the pycoin documentation but without the API key I doubt, it will output the desire results. Though I will like to see your code also and maybe we can use other means outside the pycoin documentation. PS: In order to have an API key one need to create an account in these block explorers and I don't want to at the moment.
4 Reply Quote Share
lonevectorFull Member
Posts: 72 · Reputation: 409
#3Aug 11, 2017, 09:16 PM
ofc I have an API key
4 Reply Quote Share
byte_protoFull Member
Posts: 84 · Reputation: 625
#4Aug 12, 2017, 02:09 AM
Alright I guessed we can agree that the pycoin documentation for extracting transaction need some fixings, after much research online including help from Ai, since I'm not an entirely good & knowledgeable in writing bitcoin related code but took this as a challenge to learn and spent almost all through yesterday trying to get it. Using blockcypher.com API from their site documentation, here's a code for extracting the pub key from a txid using the python request and regular expressions  library
7 Reply Quote Share
im_apeHero Member
Posts: 629 · Reputation: 3824
#5Aug 12, 2017, 06:37 AM
The problem is that 0x2102 or 0x2103 doesn't have to be the start of a public key being pushed to the stack. It can be anything inside the entire transaction hex, for example part of the the TXID inside of the outpoint in one of the inputs can be that! 2 bytes is too small and can collide with anything... There is also these transactions that apparently contain no public keys! https://api.blockcypher.com/v1/btc/main/txs/504fec6334052e0c4efdc57ceb2518f793e1190a3aa6eaa3d4aceeb4d2c08bdb?limit=50&includeHex=true It is spending a Taproot output, the pubkey is inside the output script being spent.
3 Reply Quote Share
byte_protoFull Member
Posts: 84 · Reputation: 625
#6Aug 12, 2017, 09:46 AM
Yes this is among the reason I needed help from Ai, to review my code and also help when I'm in need of clarification, though expert does it better, based on your comment, I did try to improve my code, in the aspect of shorter length script, it output the entire script, would love more clarification from you thanks.
0 Reply Quote Share
im_apeHero Member
Posts: 629 · Reputation: 3824
#7Aug 12, 2017, 03:37 PM
Well if we are going to get technical we first need to determine how accurate we want our code to be. Technically if you want to extract public keys correctly, you must decode the transaction hex, evaluate the scripts, maybe even execute them just like you would when verifying the transaction and when you reach any of the 4 OP_CHECK(MULTI)SIG(VERIFY) op codes or the OP_CHECKSIGADD op code you add a break there to extract the public key(s) used in the signature verification. But if we don't want to be accurate and want to have a workaround, you just have to be aware of the exceptions. Using blockcypher API I would change the code to work based on the "script_type" that it returns for each input inside the "inputs" array. Add the rest of the branches I skipped and then you have to fill in each branch with how you'd extract the pubkey. For example in the P2PKH case pubkey is inside the "script" and it is the top stack element. Your code should work fine there. But for the P2WPKH case the pubkey is inside the "witness" and it is already split into stack items so it is the last item. Your code doesn't have anything to handle this.But then for P2TR the public key is not inside this transaction, you will have to download another hex from the API using the "prev_hash" and then extract the public key from the output of that tx using the "output_index" you got from the first tx! Then you also have to keep in mind that it is the tweaked pubkey used by Taproot! Your code doesn't have anything to handle this either.And so on. It will also get more complicated for "script-hash" types like P2SH and P2WSH and P2TR that isn't the simple single key script.... Then you have to also keep in mind that there are exceptions. Meaning not all public keys start with 2 or 3 and are 33 bytes long. There are actually 3 types of public keys: 1. Compressed pubkeys that start with 2 or 3 and are 33 bytes long (The most common) 2. Uncompressed pubkeys that start with 4 and are 65 bytes long (Used to be common but not any more) 3. Hybrid public keys that start with 6 or 7 and are 65 bytes long (extremely rare) So now you have to decide whether you want a correct and complete code or are you just winging it. So this line has to handle all 3 cases if you want it to be complete. I don't know what language this is but this conditional branch needs two ORs. Something like this: Note that the keys starting with 04 have a different length and have to be handled separately not like what you did in your code.
4 Reply Quote Share
byte_protoFull Member
Posts: 84 · Reputation: 625
#8Aug 12, 2017, 09:56 PM
Would prefer accuracy here, though I'm really lacking in knowledge on OP_CHECK(MULTI)SIG or OP_CHECKSIGADD, will try to go do more research about this and see how I can go about writing the script while if I can't will just stick to changing the code to work with the script type.
0 Reply Quote Share
Posts: 2 · Reputation: 53
#9Aug 13, 2017, 04:14 AM
I use a simple one https://blockchain.info/q/pubkeyaddr/{address} only need "requests" lib
4 Reply Quote Share
lonevectorFull Member
Posts: 72 · Reputation: 409
#10Aug 13, 2017, 09:46 AM
that's nice, thank you. However, it won't display the correct pubkey for the TX that pooya87 mentioned. The relevant adress is bc1ppg6p0rlq9fnvk92zph0x660l07f7j8s8t6d44dew3uu3f9mwl7vqyqqwx5 and when you paste this into the query URL it will fail: URL: https://blockchain.info/q/pubkeyaddr/bc1ppg6p0rlq9fnvk92zph0x660l07f7j8s8t6d44dew3uu3f9mwl7vqyqqwx5 The correct pubkey for that particular transaction would be: 0a34178fe02a66cb15420dde6d69ff7f93e91e075e9b5ab72e8f3914976eff98
3 Reply Quote Share
byte_protoFull Member
Posts: 84 · Reputation: 625
#11Aug 13, 2017, 10:56 AM
After research, I discovered learnmeabitcoin as a tool to extract pubkey, though didn't see the code, but with just the script from the TXID, the pubkey can be gotten, https://learnmeabitcoin.com/tools/#script-tool, which is found under the transaction tool related to script. My code work in getting the script for P2PKH, P2SH and P2WSH and P2TR. While the P2WPKH it was the pubkey itself.
2 Reply Quote Share
im_apeHero Member
Posts: 629 · Reputation: 3824
#12Aug 13, 2017, 01:14 PM
The owner of learnmeabitcoin.com has a github account with some of the backend source code shared on it. If you are interested in seeing how it works and can read Ruby/PHP then start here: https://github.com/in3rsha/learnmeabitcoin-code
1 Reply Quote Share

Related topics