¿Cómo encontrar el valor Z de una transacción multisig?

por ejemplo esta transacción: http://2coin.org/txinfo.aspx?txid=6c3dc603da32bba3f56f2b33053aaf0f0f17322386c0c6846786bffe49f6ef22&cur=BTC

El script no tiene el tamaño correcto para ser un scriptSig, esperaba 2 pero obtuve 4

Creo que vamos a necesitar un poco más de información para poder ayudarte. ¿De qué valor "Z" estás hablando?
Me refiero al hash de las salidas a firmar. también esta pregunta está cerca de lo que estoy preguntando, sin embargo, pregunta sobre la transacción de una sola firma: bitcoin.stackexchange.com/questions/25387/…
Formularía la pregunta como algo así como "¿Cómo averiguo qué firmar para una transacción multisig?" Eso probablemente será más útil y fácil de buscar que decir el valor Z.

Respuestas (1)

Lo que está preguntando es cómo averiguar qué firmar para una transacción multisig.

Multisig está realmente muy cerca de esta respuesta . Sin embargo, hay algunas diferencias sutiles, así que permítanme intentar resumir paso a paso usando la transacción como se ve en la cadena de bloques .

Tenga en cuenta que para cada entrada, el hash real que se firmará será diferente. Es decir, deberá completar el script de canje solo para esa entrada y nulos para todas las demás entradas. Para ilustrar, averigüemos qué necesita firmar para la primera entrada.

  1. Versión de transacción:01000000
  2. Número de entradas:03
  3. Hash de entrada tx #1:fdb1fe0b4506f8d412f8498a0d747701bc5ed8c009e779ee670c82361c1d1dd5
  4. Índice de entrada tx #1:01000000
  5. Longitud del script de canje de entrada n.° 1 de Tx: 47(71 bytes)
  6. Script de canje de entrada TX n.° 1:522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae
  7. Secuencia de entrada tx #1:ffffffff
  8. Hash de entrada n.º 2 de Tx:a614d26f1878078a00a3c296085576cd7e6361234ea82c865681041fcfdacea8
  9. Índice de entrada tx #2:01000000
  10. Longitud del script de canje de la entrada tx n.º 2: 00(nada)
  11. Secuencia de entrada tx #2:ffffffff
  12. Hash de entrada tx #3:d064d2f9cf9e5196a9d81dd87718c9cfbec97f3ccac7164946d956421597c7f1
  13. Índice de la entrada #3 de Tx:01000000
  14. Longitud del script de canje de la entrada tx n.° 3: 00(nada)
  15. Secuencia de entrada tx #3:ffffffff
  16. Número de salidas:01000000
  17. Cantidad que se envía a la primera (y única) salida:e068704600000000
  18. Longitud del script de salida:19
  19. Guión de salida:76a9142c76e6fdd1a81c902afa62e78ec71435708d9d9d88ac
  20. Campo de tiempo de bloqueo:00000000
  21. SIGHASH_TODOS:01000000

Ahora, si hace doble sha256 en estos bytes, obtiene:

9c4b551f37f4b383af9216045d80b2fcd4ed57bddca8df388ec29601cbd2a4f1

Y, de hecho, cuando verifica la firma incrustada de esa transacción, puede ver que ese es el hash que se firmó. Aquí hay una muestra de código para verificar usando la excelente biblioteca btcd escrita en 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))

}

Puede hacer lo mismo con la entrada n.º 2 y la entrada n.º 3 para obtener el hash que se firma al cambiar el n.º 5 y el n.º 6 (combinados) para que sean y el n.º 10 o el n.º 14 00en los pasos anteriores para que sean47522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae

Volví a ensamblar todo, desde el paso 1 hasta el paso 21 manualmente, a nivel de shell, y no obtuve el valor dsha256, hasta que descubrí que el paso 16 (número de TX-OUT) debería ser "01" en lugar de "01000000 ". Es un var_int (o también llamado tamaño compacto en la wiki).