Signieren Sie manuell P2WSH native mit Openssl

Ich studiere den Segwit-Teil und möchte P2WSH (nativ) manuell signieren (openssl).

Ich habe gerade gelesen BIP0143und sehe den neuen Transaktionsauszug.

Double SHA256 of the serialization of:
     1. nVersion of the transaction (4-byte little endian)
     2. hashPrevouts (32-byte hash)
     3. hashSequence (32-byte hash)
     4. outpoint (32-byte hash + 4-byte little endian) 
     5. scriptCode of the input (serialized as scripts inside CTxOuts)
     6. value of the output spent by this input (8-byte little endian)
     7. nSequence of the input (4-byte little endian)
     8. hashOutputs (32-byte hash)
     9. nLocktime of the transaction (4-byte little endian)
    10. sighash type of the signature (4-byte little endian

Ich verwende Regtest und erstelle eine Transaktion von meinem P2WSH zu P2WPKH, wo ich ~49,999991 Bitcoins verschiebe.

Es ist mein UTXO

   020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000220020896386cc04087d76450a506b09e88de6d68bba45f50c4967818e6fd10e6eaade0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000
{
  "txid": "0237415f2eb789a48e43ed68862ea9db3455f7b21203f4b526cd88b970b1329b",
  "hash": "76069338f9fd11b43901b6b5260e6b279dd26071148643a1b31fc41190dc73f1",
  "version": 2,
  "size": 180,
  "vsize": 153,
  "weight": 612,
  "locktime": 0,
  "vin": [
    {
      "coinbase": "510101",
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 50,
      "n": 0,
      "scriptPubKey": {
        "asm": "0 896386cc04087d76450a506b09e88de6d68bba45f50c4967818e6fd10e6eaade",
        "hex": "0020896386cc04087d76450a506b09e88de6d68bba45f50c4967818e6fd10e6eaade",
        "reqSigs": 1,
        "type": "witness_v0_scripthash",
        "addresses": [
          "bcrt1q393cdnqypp7hv3g22p4sn6ydumtghwj975xyjeup3ehazrnw4t0q7p0v3p"
        ]
      }
    },
    {
      "value": 0,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_RETURN aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9",
        "hex": "6a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9",
        "type": "nulldata"
      }
    }
  ],
  "hex": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000220020896386cc04087d76450a506b09e88de6d68bba45f50c4967818e6fd10e6eaade0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
  "blockhash": "42f85575b186494c8ac18487a0f21f4645346c6d9740d17f764a8a56e74fa2e3",
  "confirmations": 101,
  "time": 1587537959,
  "blocktime": 1587537959
}

Meine rohen Transaktionsdaten sind:

02000000019b32b170b988cd26b5f40312b2f75534dba92e8668ed438ea489b72e5f4137020000000000ffffffff017cee052a01000000160014f545040775837a55962bb8abfcc341f574d6791700000000

Und ich erstelle den neuen Transaktions-Digest wie folgt:

    TX_VERSION: 02000000
    OUTPOINT: 9b32b170b988cd26b5f40312b2f75534dba92e8668ed438ea489b72e5f41370200000000
    HASH_PREV_OUT: b98dd14dcfff442ee1562d70b507402d6ba089dc8af7fe0360f422ff5d60a206
(HASH_PREV_OUT is SHA256 twice of $OUTPOINT)
    SEQUENCE: ffffffff
    HASH_SEQUENCE: 3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044
(HASH_SEQUENCE is SHA256 twice of $SEQUENCE)
    SCRIPTCODE: 1976a91427275283377b40957701cecd37d2e170c41d387488AC
    AMOUNT: 00f2052a01000000
 (TOTAL AMOUNT - 50 bitcoin )
    OUTPUT: 160014f545040775837a55962bb8abfcc341f574d67917
    OUTPUT_HASH: 9fbf0bcf967eb3f1fcd41f60ce73e69f8b5073185ff81f787d9caac0e5992fd2
(OUTPUT_HASH is SHA256 twice of $AMOUNT$OUTPUT)
    LOCKTIME_PART: 00000000
    SIGHASH: 01000000

Wo SCRIPT-CODE mein UTXO Witness-Skript ist (das Skript ist P2PKH) Dann "füge" ich alle Werte wie folgt zusammen:

$ WITNESS_V0_DIGEST=$TX_VERSION$HASH_PREV_OUT$HASH_SEQUENCE$OUTPOINT$SCRIPTCODE$AMOUNT$SEQUENCE$OUTPUT_HASH$LOCKTIME_PART$SIGHASH
$ echo $WITNESS_V0_DIGEST
02000000b98dd14dcfff442ee1562d70b507402d6ba089dc8af7fe0360f422ff5d60a2063bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e706650449b32b170b988cd26b5f40312b2f75534dba92e8668ed438ea489b72e5f413702000000001976a91427275283377b40957701cecd37d2e170c41d387488AC00f2052a01000000ffffffff9fbf0bcf967eb3f1fcd41f60ce73e69f8b5073185ff81f787d9caac0e5992fd20000000001000000

Dann kann ich das doppelte SHA56 machen und es signieren:

printf $WITNESS_V0_DIGEST | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | xxd -r -p > WITNESS_V0_DIGEST.txt

SIGNATURE=`openssl pkeyutl -inkey private_key_1.pem -sign -in WITNESS_V0_DIGEST.txt -pkeyopt digest:sha256 | xxd -p -c 256`

SIGNATURE="${SIGNATURE}01"

Jetzt kann ich meine Transaktion wie folgt erstellen:

020000000001019b32b170b988cd26b5f40312b2f75534dba92e8668ed438ea489b72e5f4137020000000000ffffffff017cee052a01000000160014f545040775837a55962bb8abfcc341f574d679170347304402202d7d72d425e407160554e9c29688164a7e5c2f380c86e26c0595a7c6c8d526df02206ff13970212a77d6febcdcdcc2945db3947f02137324ae7d822b4fa7f81292100121024633c32245c6709e7f756c41e0f163919fa00977798f30245d3498f88c53e8941976a91427275283377b40957701cecd37d2e170c41d387488AC00000000

Es ist die entschlüsselte Version

     {
  "txid": "23704afa715351b1d1810f41015fd3bfc33fed75842530ae0c00564eb7f16103",
  "hash": "5f6b1edafdd814d8c9ec85bad6125dbf2efbb245c28017b62ee4aa35ab712789",
  "version": 2,
  "size": 217,
  "vsize": 116,
  "weight": 463,
  "locktime": 0,
  "vin": [
    {
      "txid": "0237415f2eb789a48e43ed68862ea9db3455f7b21203f4b526cd88b970b1329b",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "txinwitness": [
        "304402202d7d72d425e407160554e9c29688164a7e5c2f380c86e26c0595a7c6c8d526df02206ff13970212a77d6febcdcdcc2945db3947f02137324ae7d822b4fa7f812921001",
        "024633c32245c6709e7f756c41e0f163919fa00977798f30245d3498f88c53e894",
        "76a91427275283377b40957701cecd37d2e170c41d387488ac"
      ],
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 49.999991,
      "n": 0,
      "scriptPubKey": {
        "asm": "0 f545040775837a55962bb8abfcc341f574d67917",
        "hex": "0014f545040775837a55962bb8abfcc341f574d67917",
        "reqSigs": 1,
        "type": "witness_v0_keyhash",
        "addresses": [
          "bcrt1q74zsgpm4sda9t93thz4les6p746dv7gh4jhqxz"
        ]
      }
    }
  ]
}

Aber wenn ich versuche, es zu senden ( sendrawtransaction), erhalte ich diesen Fehler:

error code: -26
error message:
non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation) (code 64)

Antworten (1)

Wo SCRIPT-CODE mein UTXO scriptpubkey hex ist (Witness Version-Witness Programm) Dann "füge" ich alle Werte wie folgt zusammen:

Das ist Dein Problem. Wie bei P2SH ist der scriptCode für P2WSH nicht der scriptPubKey. Es ist das Skript, von dem diese P2WSH-Ausgabe den Hash hat. Der scriptCode ist also in diesem Fall das WitnessScript, nicht der scriptPubKey.

danke für die Antwort. Ich habe es mit Witness-Skript anstelle von Hash versucht (ich verwende p2pkh für Skript), dann wird mein Skriptcode (SCRIPTCODE: 76a914b32be131fb46d9e937f52be3fff9df7e4cca63cf88AC). Aber ich bekomme den gleichen Fehler non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation) (code 64)danke!
Können Sie Ihre Frage mit den Ergebnissen dieser Änderung bearbeiten?
Sicher! Ich habe meine Frage aktualisiert. Danke
Dem scriptCode muss eine kompakte Größe unsigned int vorangestellt werden.
Nochmals vielen Dank für Ihre Zeit, ich habe die Skriptcodelänge (19) hinzugefügt, aber ich habe das gleiche Problem. Ich habe meine Frage aktualisiert. Danke !
Was ist die tatsächliche UTXO, die Sie ausgeben? Ich denke, das nächste, was falsch sein könnte, ist die Menge. Es sieht so aus, als ob der von Ihnen angegebene Betrag der Ausgabewert ist. Das ist wahrscheinlich falsch, es sei denn, Sie beabsichtigen, keine Transaktionsgebühren zu zahlen.
Vielen Dank für Ihre Zeit. das UTXO ist die Coinbase (Genesis-Block) Ich benutze regtest, um mein Skript zu testen. Ich habe mit dem Gesamtbetrag (00f2052a01000000 - 50 Bitcoin) behoben, aber ich habe das gleiche Problem. Danke !!!!
Jetzt sind Ihre hashOutputs falsch. Sie verwenden die falsche Menge in diesem Hash. hashOutputs ist der Hash der Ausgaben, während sie serialisiert werden. Für jede Ausgabe ist es der Betrag, gefolgt vom Ausgabeskript, unabhängig vom Betrag für die zu signierende Eingabe. Was Sie getan haben, ist der Betrag für die Eingabe, die signiert wird. Das ist falsch. In hashOutputs müssen Sie 49,99 verwenden.... Im Feld für den Betrag des Seufzers müssen Sie 50 verwenden.
danke immer wieder. Ich (du) löse es auf!