Wie finde ich den Z-Wert einer Multisig-Transaktion?

zum Beispiel diese Transaktion: http://2coin.org/txinfo.aspx?txid=6c3dc603da32bba3f56f2b33053aaf0f0f17322386c0c6846786bffe49f6ef22&cur=BTC

Skript hat nicht die richtige Größe, um ein scriptSig zu sein, erwartet 2, hat aber 4

Ich denke, wir brauchen ein paar mehr Informationen, um dir helfen zu können. Von welchem ​​"Z"-Wert sprichst du?
Ich meine den Hash der zu signierenden Ausgaben. Auch diese Frage kommt dem, was ich frage, nahe, fragt jedoch nach Single-Sig-Transaktionen: bitcoin.stackexchange.com/questions/25387/…
Ich würde die Frage etwa so formulieren: "Wie finde ich heraus, was ich für eine Multisig-Transaktion unterschreiben muss?" Das wird wahrscheinlich nützlicher und durchsuchbarer sein, als den Z-Wert zu sagen.

Antworten (1)

Was Sie fragen, ist, wie Sie herausfinden, was für eine Multisig-Transaktion zu unterzeichnen ist.

Multisig kommt dieser Antwort tatsächlich sehr nahe . Es gibt jedoch ein paar subtile Unterschiede, also lassen Sie mich versuchen, die Transaktion Schritt für Schritt zusammenzufassen, wie sie in der Blockchain zu sehen ist

Beachten Sie, dass der tatsächlich zu signierende Hash für jede Eingabe anders sein wird. Das heißt, Sie müssen das Einlösungsskript nur für diese Eingabe und Nullen für jede andere Eingabe ausfüllen. Lassen Sie uns zur Veranschaulichung herausfinden, was Sie für die allererste Eingabe signieren müssen.

  1. Transaktionsversion:01000000
  2. Anzahl Eingänge:03
  3. Tx-Eingang #1 Hash:fdb1fe0b4506f8d412f8498a0d747701bc5ed8c009e779ee670c82361c1d1dd5
  4. Tx-Eingang Nr. 1 Index:01000000
  5. Tx-Eingabe Nr. 1 Einlösungsskriptlänge: 47(71 Byte)
  6. Tx-Eingabe Nr. 1 Einlösungsskript:522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae
  7. Sequenz des Tx-Eingangs Nr. 1:ffffffff
  8. Tx-Eingang #2 Hash:a614d26f1878078a00a3c296085576cd7e6361234ea82c865681041fcfdacea8
  9. Tx-Eingang Nr. 2 Index:01000000
  10. Tx-Eingabe #2 Skriptlänge einlösen: 00(nichts)
  11. Sequenz des Tx-Eingangs Nr. 2:ffffffff
  12. Tx-Eingang #3 Hash:d064d2f9cf9e5196a9d81dd87718c9cfbec97f3ccac7164946d956421597c7f1
  13. Tx-Eingang Nr. 3 Index:01000000
  14. Tx-Eingabe #3 Skriptlänge einlösen: 00(nichts)
  15. Sequenz des Tx-Eingangs Nr. 3:ffffffff
  16. Anzahl Ausgänge:01000000
  17. Betrag, der an die erste (und einzige) Ausgabe gesendet wird:e068704600000000
  18. Länge des Ausgabeskripts:19
  19. Ausgabeskript:76a9142c76e6fdd1a81c902afa62e78ec71435708d9d9d88ac
  20. Feld Sperrzeit:00000000
  21. SIGHASH_ALL:01000000

Wenn Sie nun diese Bytes doppelt sha256 machen, erhalten Sie:

9c4b551f37f4b383af9216045d80b2fcd4ed57bddca8df388ec29601cbd2a4f1

Und tatsächlich, wenn Sie mit der eingebetteten Signatur dieser Transaktion vergleichen, können Sie sehen, dass dies tatsächlich der signierte Hash ist. Hier ist ein Codebeispiel, das mit der ausgezeichneten btcd-Bibliothek, die in go geschrieben wurde, überprüft werden kann:

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))

}

Sie können dasselbe mit Eingang Nr. 2 und Eingang Nr. 3 tun, um den Hash zu erhalten, der signiert wird, indem Sie in den 00obigen Schritten Nr. 5 und Nr. 6 (kombiniert) in sein und Nr. 10 oder Nr. 14 ändern47522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae

Ich habe alles von Schritt 1 bis Schritt 21 manuell auf Shell-Ebene neu zusammengesetzt und den dsha256-Wert nicht erhalten, bis ich entdeckte, dass Schritt 16 (Nummer von TX-OUT) "01" statt "01000000" sein sollte ". Es ist eine var_int (oder im Wiki auch als kompakte Größe bezeichnet).