0

for example this transaction: http://2coin.org/txinfo.aspx?txid=6c3dc603da32bba3f56f2b33053aaf0f0f17322386c0c6846786bffe49f6ef22&cur=BTC

Script not of right size to be a scriptSig, expecting 2 but got 4

  • I think we are going to need a little more info to be able to help you out. Which "Z" value are you talking about? – morsecoder Jan 29 '15 at 16:54
  • I mean hash of the outputs to be signed. also this question is close to what i`m asking however it asks about single-sig transaction: bitcoin.stackexchange.com/questions/25387/… – user23124 Jan 29 '15 at 17:03
  • I would phrase the question as something like "How do I figure out what to sign for a multisig transaction?" That will probably be more useful and searchable than saying Z value. – Jimmy Song Jan 29 '15 at 21:51
1

What you're asking for is how to figure out what to sign for a multisig transaction.

Multisig is actually very close to this answer. There are a few subtle differences, however, so let me try to summarize step-by-step using the transaction as seen on the blockchain

Note that for each input, the actual hash to be signed is going to be different. Namely, you will need to fill in the redeem script for that input only and nulls for every other input. To illustrate, let's figure out what you need to sign for the very first input.

  1. Transaction version: 01000000
  2. Number of inputs: 03
  3. Tx input #1 hash: fdb1fe0b4506f8d412f8498a0d747701bc5ed8c009e779ee670c82361c1d1dd5
  4. Tx input #1 index: 01000000
  5. Tx input #1 redeem script length: 47 (71 bytes)
  6. Tx input #1 redeem script: 522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae
  7. Tx input #1 sequence: ffffffff
  8. Tx input #2 hash: a614d26f1878078a00a3c296085576cd7e6361234ea82c865681041fcfdacea8
  9. Tx input #2 index: 01000000
  10. Tx input #2 redeem script length: 00 (nothing)
  11. Tx input #2 sequence: ffffffff
  12. Tx input #3 hash: d064d2f9cf9e5196a9d81dd87718c9cfbec97f3ccac7164946d956421597c7f1
  13. Tx input #3 index: 01000000
  14. Tx input #3 redeem script length: 00 (nothing)
  15. Tx input #3 sequence: ffffffff
  16. Number of outputs: 01000000
  17. Amount being sent to the first (and only) output: e068704600000000
  18. Output script length: 19
  19. Output script: 76a9142c76e6fdd1a81c902afa62e78ec71435708d9d9d88ac
  20. Lock time field: 00000000
  21. SIGHASH_ALL: 01000000

Now, if you double-sha256 these bytes you get:

9c4b551f37f4b383af9216045d80b2fcd4ed57bddca8df388ec29601cbd2a4f1

And indeed when you check against the embedded signature of that transaction, you can see that that is indeed the hash that was signed. Here's a code sample to verify using the excellent btcd library written in go:

package main

import (
    "encoding/hex"
    "fmt"
    "hash"

    "github.com/btcsuite/btcec"
    "github.com/btcsuite/fastsha256"
)

// Calculate the hash of hasher over buf.
func calcHash(buf []byte, hasher hash.Hash) []byte {
    hasher.Write(buf)
    return hasher.Sum(nil)
}

// Hash160 calculates the hash ripemd160(sha256(b)).
func Hash256(buf []byte) []byte {
    return calcHash(calcHash(buf, fastsha256.New()), fastsha256.New())
}

func main() {
    x := "0100000003fdb1fe0b4506f8d412f8498a0d747701bc5ed8c009e779ee670c82361c1d1dd50100000047522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252aeffffffffa614d26f1878078a00a3c296085576cd7e6361234ea82c865681041fcfdacea80100000000ffffffffd064d2f9cf9e5196a9d81dd87718c9cfbec97f3ccac7164946d956421597c7f10100000000ffffffff01e0687046000000001976a9142c76e6fdd1a81c902afa62e78ec71435708d9d9d88ac0000000001000000"

    b, _ := hex.DecodeString(x)

    hash := Hash256(b)
    fmt.Printf("hash of thing to sign: %x\n", hash)

    pubkeyStr := "02cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b9"
    pubkeyStr2 := "037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b204282"
    pubkeyBytes, _ := hex.DecodeString(pubkeyStr)
    pubkeyBytes2, _ := hex.DecodeString(pubkeyStr2)

    p, _ := btcec.ParsePubKey(pubkeyBytes, btcec.S256())
    p2, _ := btcec.ParsePubKey(pubkeyBytes2, btcec.S256())

    fmt.Printf("pubkeys: %s, %s\n", p, p2)

    sigStr := "3044022025332b6dabf11e493fbc62c93e7302c48666512e1cf88157c26176f4af6d064702201ee7ec25d0917244e514c402e8751f112dfd1bef2b22ec5e496fbafabb52bf010148"

    sigStr2 := "3045022100fa1f17bf59bee0ac33ae5f682711c5471c73a4aeb898aee218478289a4c7aa6e02207b40dfeae3fa4a50dc147bd42be40370d76a35d72c0b27b27c4ba2439a565fb901"

    sigBytes, _ := hex.DecodeString(sigStr)
    sigBytes2, _ := hex.DecodeString(sigStr2)

    s, _ := btcec.ParseDERSignature(sigBytes, btcec.S256())
    s2, _ := btcec.ParseDERSignature(sigBytes2, btcec.S256())

    fmt.Printf("sig: %s\n", s)

    fmt.Printf("signature valid: %v\n", s.Verify(hash, p))
    fmt.Printf("signature valid: %v\n", s2.Verify(hash, p2))

}

You can do the same thing with input #2 and input #3 to get the hash that gets signed by changing #5 and #6 (combined) to be 00 and #10 or #14 in the steps above to be 47522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae

  • I re-assembled everything from step 1 to step 21 manually, at the shell level, and didn't get the dsha256 value, until I discovered, that step 16 (number of TX-OUT) should be "01" instead of "01000000". It is a var_int (or also called compact size in the wiki). – pebwindkraft Nov 22 '17 at 17:43

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.