0

How can I retrieve the sender's public key in a Segwit transaction?

For example: https://www.blockchain.com/btc/tx/3179d18d6f36fa77b88909496535485d8188d96b79d295843789a9e0ff6c3e6a

I can happily parse the witness part as in

02 : 2 items to follow

47 : 0x47 = 71 bytes (signature)

304402201cf8db0c4afc164970ec4397327fe9b1dd9b7ff4a9093f94e554d624b5ffdcb702202848072c17f2bcce16b8d3d7cb2efdad87bc6c942b79f44b79f1c52f817d81ea01 : the actual signature (last byte is the sighash code)

21 : 0x21 = 33 bytes (the pubkey)

02384052a5ecde83bf8ee7ed77f378edb58aa65de22c4e91af87eee68015b9d509 : the actual pubkey

But this pubkey is not the public key of the sender. It's probably the pubkey of a segwit (or something like that)...

How exactly is this signature made up and what pubkey is that? And more importantly, how can I retrieve the sender's public key (the one belonging to 35yfMa3CRBiWny8DFdb4tUu9fn7fcdvVp9 in this example).

  • 1
    “public key of a segwit”? – Anonymous Jun 21 at 10:45
  • You have no idea who the sender is (in the sense that you can't just send coins back to that key and expect them to arrive at the sender's wallet). But it is the public key corresponding to the private key which previously controlled the funds. Segwit has nothing to do with this. – Pieter Wuille Jun 21 at 22:31
1

The public key that you mentioned is indeed the key that was used to derive the P2SH(P2WPKH) address: 35yfMa3CRBiWny8DFdb4tUu9fn7fcdvVp9. The way in which a P2SH(P2WPKH) address is derived is as follows:

1. witness_script = hash160(pub_key) #this is equal to '4b9d2d3dd1174ad656754a0c664e7a129b131f3b'
2. witness_version = 0x00  #current SegWit version
3. scriptSig = witness_version + OP_DATA(0x14) + witness_script 
#Above is equal to '00144b9d2d3dd1174ad656754a0c664e7a129b131f3b' and is the one you are seeing in the scriptSig in the explorer.
#0x14 tell the script to push the next 20 bytes to the stack
4. public_address = hash160(scriptSig)
5. bitcoin_address = base58check(public_address) #with prefix of 0x05
result = 35yfMa3CRBiWny8DFdb4tUu9fn7fcdvVp9

Native SegWit transactions works by locking an output with scriptPubKey: version + OP_DATA (bytes to push) + witness_script. For older clients, this looks as if it is any one can spend transaction, as it does not have an opcode verifying anything. So in order to take advantage of lower fees of spending SegWit transaction, but at the same time be compatible with wallet software that are not SegWit aware, we use the scriptPubKey as the script and create a P2SH locking script out of it. So the locking script is: OP_HASH160 <public_address> OP_EQUAL. (public_address convention is same as the one I mentioned when deriving the address above). So a customer can send you bitcoins without upgrading his wallet software to be SegWit aware, but when spending the bitcoins, you can take advantage of lower fees of SegWit.

Now, in terms of verification when this output is spent in a transaction: Older clients verifying the transaction will just look at the scriptSig, take its has160, verify with the public_address and consider this transaction to be valid. Newer clients will realize that the scriptSig is in itself a SegWit and will look for signatures in the Witness part of the transaction. There the clients will verify that the hash160 of the public key is equal to the witness_script and then the signature matches the public key when signed with the transaction as a message. The signature message digest is described in BIP 143.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.