3

Assume we have a 2 of 3 multi signature address and we send some bitcoin to that address.

Then we spend the funds from that address by signing and broadcasting a transaction.

Just by looking at that transaction, can you tell the public keys whose private keys were used to sign that transaction?

2 Answers 2

2

Yes.

After the spending multisig transaction is on the blockchain (not the funding transaction), you can see the public keys used to spend those multisig funds.

These public keys are found in the full redeemScript provided in the spending transaction. See a breakdown of a multisig spending transaction here, which shows that a redeemScript is indeed included in the spending transaction. See a breakdown of the full redeemScript here, which shows that the public keys are included in this full redeemScript.

Let me clarify that the public keys are not seen in the funding transaction because only the redeemScript hash is revealed here, not the full redeem script.

Note: In the explanation above, I'm assuming you are talking about the Pay to Script Hash (P2SH) form of multisig, which is the more common and modern form of multisig. The answer to your question would still be yes for a non-P2SH multisig transaction, except that the public keys are visible in the funding transaction, rather than the spending transaction. The public keys are revealed in the scriptPubKey of the funding transaction, which looks like:

<m> <A pubkey> [B pubkey] [C pubkey...] <n> OP_CHECKMULTISIG

Source: https://bitcoin.org/en/developer-guide#multisig

1

A P2SH multisig Tx (which first appeared in 9c08a4d78931342b37fd5f72900fb9983087e6f46c4a097d8a1f52c74e28eaf6) is comparable to P2PKH (pay to pubkeyhash) in that the hash is what is being referenced by the spending Tx's scriptSig (ie the Tx which eventually "unlocks" the multisig funds).

If you're interested in seeing how this the P2SH address is calculated, there's Python 2.7 code showing that below. Note that the general form (as mentioned by @soroushjp) of a multisig Tx is <m> <A pubkey> [B pubkey] [C pubkey...] <n> OP_CHECKMULTISIG and the redemption script MUST run the signatures in order and the script MUST begin with OP_0/0x00 due to an off by 1 error which pops an extra value from the stack.

PYTHON CODE:

I'll use pybitcointools

from bitcoin import * # this is importing all pybitcointools functions

privkeys, pubkeys, addrs = [], [], []
privkeys = [random_key() for x in range(0, 3)]
pubkeys = [privtopub(x) for x in privkeys]
addrs = [privtoaddr(x, magicbyte=0) for x in privkeys] # magicbyte = 0x6f for testnet
mykeys = zip(privkeys, pubkeys, addrs)

print mykeys
>>> [('b24b72423d008a252f47bcfcb270dcd71a364a91a574adb266e1aa22d3d2543d', '04eba461feced2a3d86aae5ca726c4d41f6d2a84f68fb83b5d91ead68fb0f9974886b0f24032db18a1603530c4039b54095acc460f84e47f192ee001230171be36', '18oYZEBqN2xPsiWvbmvSNVQDaS49RK2wCq'), ('f0764f256ad87129fbbc77af32b016680bce7e91be236231ee08ab4b66a6de84', '049ca1fa12b955f2fc1b6dab2e3138946f2d9ba6cb0c477c47bf3397f21d5709e100040d9675cef90cc1a0389293ec8ffdb2487093265290cbe66390dee36dcadd', '1DkBSD6pCRrNbWAkhxTbppnRPe42ciu2jB'), ('62666580151ada2dbf70d2a80c94a2bc20f5cc2f871a9aabb0eb11c6af24464b', '04982b9b7c004edc76cbedd363dd198fb4bcb6140e2bd589b4e33c9ecb741ed28c2ca3a6a54907d6d27f18be8898e88095cec7a7dc8cdffe7e5900794fa782ee8f', '1E7gn9B82hXmawmeyY7sJ9BPoSfYCXkxh7')]

   # making the raw script
   rawscript = mk_multisig_script(pubkeys, 2)  # means make a 2 of 3 multisig redeemScript
   descript = deserialize_script(script) # shows the op_codes pushed to stack
   print descript
   print script

[2, '04eba461feced2a3d86aae5ca726c4d41f6d2a84f68fb83b5d91ead68fb0f9974886b0f24032db18a1603530c4039b54095acc460f84e47f192ee001230171be36', '049ca1fa12b955f2fc1b6dab2e3138946f2d9ba6cb0c477c47bf3397f21d5709e100040d9675cef90cc1a0389293ec8ffdb2487093265290cbe66390dee36dcadd', '04982b9b7c004edc76cbedd363dd198fb4bcb6140e2bd589b4e33c9ecb741ed28c2ca3a6a54907d6d27f18be8898e88095cec7a7dc8cdffe7e5900794fa782ee8f', 3, 174]

524104eba461feced2a3d86aae5ca726c4d41f6d2a84f68fb83b5d91ead68fb0f9974886b0f24032db18a1603530c4039b54095acc460f84e47f192ee001230171be3641049ca1fa12b955f2fc1b6dab2e3138946f2d9ba6cb0c477c47bf3397f21d5709e100040d9675cef90cc1a0389293ec8ffdb2487093265290cbe66390dee36dcadd4104982b9b7c004edc76cbedd363dd198fb4bcb6140e2bd589b4e33c9ecb741ed28c2ca3a6a54907d6d27f18be8898e88095cec7a7dc8cdffe7e5900794fa782ee8f53ae

# cheating here, but see comments following
scriptaddress = scriptaddr(script)    # 37TtE1nfm51u6LNkNzzsjuBcuYmhTEmkq6

scriptaddr is doing the following:

  1. SHA256 of 524104eb...8f53ae
  2. RIPEMD160 of #1
  3. Converting #2 from hex ==> Base58

It's worth mentioning that a standard Tx (ie accepted by core software, miners) does allow for using the script directly (without using P2SH) however the limit for this method is a 2of3 multisig. Why? Take an example of a m-of-15 using uncompressed public keys, which has a minimum size of 15 * 65 = 975 bytes in size just for the outputs.

Some other multisig variations:

OP_1 OP_DATA_65 OP_DATA_65 OP_2 OP_CHECK_MULTISIG: 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1 OP_1 OP_DATA_33 OP_DATA_33 OP_DATA_33 OP_3 OP_CHECK_MULTISIG: 0109e3f8d2d324b8d0c0fdd34d369ebcc69fbcc5a0cabe781f69867a0ba1dd74 OP_1 OP_DATA_65 OP_DATA_33 OP_DATA_33 OP_3 OP_CHECK_MULTISIG: 14015bd586c0c7a28979ca294b114441f23bfc97be17cd6077b9e12e2709fec3 OP_2 OP_DATA_65 OP_DATA_65 OP_DATA_65 OP_3 OP_CHECK_MULTISIG: 6d5088c138e2fbf4ea7a8c2cb1b57a76c4b0a5fab5f4c188696aad807a5ba6d8 OP_2 OP_DATA_65 OP_DATA_65 OP_2 OP_CHECK_MULTISIG: 947539645c59e6ab0cda61826cbacb55ef97a8178f012f8c18abe504bf66d4ce OP_1 OP_DATA_33 OP_1 OP_CHECK_MULTISIG: b96af3b69b48a82c5eae3e44ebb6ef93f30d7764b1d5b40243e11b0d374ac1b7

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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