Как найти значение Z мультиподписной транзакции?

например, эта транзакция: http://2coin.org/txinfo.aspx?txid=6c3dc603da32bba3f56f2b33053aaf0f0f17322386c0c6846786bffe49f6ef22&cur=BTC

Скрипт не подходит по размеру для scriptSig, ожидал 2, но получил 4

Думаю, нам понадобится немного больше информации, чтобы мы могли вам помочь. О каком значении "Z" вы говорите?
Я имею в виду хэш выходов, которые нужно подписать. также этот вопрос близок к тому, что я спрашиваю, однако он спрашивает о транзакции с одной подписью: bitcoin.stackexchange.com/questions/25387/…
Я бы сформулировал вопрос примерно так: «Как понять, что подписывать для мультиподписной транзакции?» Это, вероятно, будет более полезным и доступным для поиска, чем указание значения Z.

Ответы (1)

Вы спрашиваете, как выяснить, что подписывать для мультиподписной транзакции.

Multisig на самом деле очень близок к этому ответу . Однако есть несколько тонких отличий, поэтому позвольте мне попытаться обобщить шаг за шагом, используя транзакцию, как она видна в блокчейне .

Обратите внимание, что для каждого входа фактический хэш, который будет подписан, будет другим. А именно, вам нужно будет заполнить сценарий выкупа только для этого ввода и нули для каждого другого ввода. Чтобы проиллюстрировать, давайте разберемся, что вам нужно подписать для самого первого ввода.

  1. Версия сделки:01000000
  2. Количество входов:03
  3. Tx ввод № 1 хеш:fdb1fe0b4506f8d412f8498a0d747701bc5ed8c009e779ee670c82361c1d1dd5
  4. Tx вход №1, индекс:01000000
  5. Tx input #1 Длина скрипта выкупа: 47(71 байт)
  6. Сценарий выкупа Tx input #1:522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae
  7. Последовательность входа Tx №1:ffffffff
  8. Tx ввод № 2 хэш:a614d26f1878078a00a3c296085576cd7e6361234ea82c865681041fcfdacea8
  9. Tx вход № 2, индекс:01000000
  10. Tx input #2 длина скрипта выкупа: 00(ничего)
  11. Последовательность входа Tx № 2:ffffffff
  12. Tx ввод № 3 хэш:d064d2f9cf9e5196a9d81dd87718c9cfbec97f3ccac7164946d956421597c7f1
  13. Вход Tx № 3, индекс:01000000
  14. Tx input #3 длина скрипта выкупа: 00(ничего)
  15. Последовательность входа Tx № 3:ffffffff
  16. Количество выходов:01000000
  17. Сумма, отправляемая на первый (и единственный) выход:e068704600000000
  18. Длина выходного скрипта:19
  19. Выходной скрипт:76a9142c76e6fdd1a81c902afa62e78ec71435708d9d9d88ac
  20. Поле времени блокировки:00000000
  21. SIGHASH_ALL:01000000

Теперь, если вы удвоите sha256 эти байты, вы получите:

9c4b551f37f4b383af9216045d80b2fcd4ed57bddca8df388ec29601cbd2a4f1

И действительно, когда вы проверяете встроенную подпись этой транзакции, вы можете видеть, что это действительно подписанный хэш. Вот пример кода для проверки с помощью отличной библиотеки btcd, написанной на 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))

}

Вы можете сделать то же самое с вводом № 2 и вводом № 3, чтобы получить хэш, который будет подписан, изменив № 5 и № 6 (объединенные) на и № 10 00или № 14 в шагах выше, чтобы быть47522102cebf6ab580948d146b7cc771d8e646974349d3d7b11f3e03287d0997a477d3b921037ba651485b7a2cb222191eb64a55926e62bbabfe9b5ed2a9488aad547b20428252ae

Я пересобрал все с шага 1 по шаг 21 вручную, на уровне оболочки, и не получил значения dsha256, пока не обнаружил, что шаг 16 (номер TX-OUT) должен быть "01" вместо "01000000". ". Это var_int (также называемый в вики компактным размером).