Fehler beim Erstellen/Senden von Multisig-Transaktionen

Anhand des Beispiels hier: https://bitcoinj.github.io/working-with-contracts

Ich glaube, ich habe alles richtig gemacht. Mein Programm kann sich jedoch entweder nicht richtig verbreiten oder liegt an einem TX-Fehler, und ich kann nicht feststellen, warum

Ein paar Dinge, von denen ich glaube, dass sie der Grund sind

1) Meine peergroup.broadcastTransaction (spendTx) sendet nicht richtig 2) Eine fehlerhafte Rohtransaktion oder Skriptsig (ich nehme an, es ist dies, aber auch hier keine Fehler) 3) Im Allgemeinen verstehe ich nicht die beste Methode, um Ausgaben mit Eingaben zu verknüpfen und sie zu signieren angemessen (verwende ich zum Beispiel die UTXO-Klasse oder TransactionSignature) 3) Versuchen, Geld von einer überwachten Adresse auszugeben. Ich habe die notwendigen Schlüssel, um die UTXOs freizuschalten, aber ich würde gerne sehen, ob ich das Geld ohne die Verwendung der Wallet-Klasse ausgeben kann. 4) Multisig-Unterstützung im Allgemeinen für Bitcoin ist nicht vorhanden oder unvollständig. Ich hoffe, es ist nicht das, da ich es wirklich gerne zum Laufen bringen würde. Aber – ich glaube nicht, dass dies das größte Problem ist, weil ich die Unit-Tests durchgeführt habe und sie immer noch alle sauber auschecken.

Ein Schritt durch den Code, um gründlich zu sein:

Erstellen Sie 3 ECKeys für einen 2-von-3-Multisig-Vertrag, fügen Sie sie in eine Liste ein, erstellen Sie ein Einlösungsskript, das Schlüssel in lexikografischer Reihenfolge sortiert und ein m-von-n-Multisigoutput-Skript schreibt, dann instanziieren Sie ein Transaktionsobjekt und weisen Sie es als OUTPUT zu die ich als INPUT (Betrag + Einlösungsskript) verwenden werde, AKA das UTXO, das ich ausgeben werde (EDIT: Kurze Erwähnung. Die ECKeys, die ich wirklich verwende, sind fest codierte Werte, die ich vor einiger Zeit erstellt habe, diese dienen der Veranschaulichung. Ich sollte auch erwähnen, dass dies ein P2SH-Multisig ist, nicht das rohe Nicht-Standard-Multisig.

ECKey keyA = new ECKey();
ECKey keyB = new ECKey();
ECKey keyC = new ECKey();

List<ECKey> keys = ImmutableList.of(key1, key2, key3);

Script script = ScriptBuilder.createRedeemScript(2, keys);
Script scriptPubKey = ScriptBuilder.createP2SHOutputScript(script);

Transaction contract = new Transaction(params);
TransactionOutput multiSigOutput = contract.addOutput(Coin.valueOf(50000), scriptPubKey);

Erstellen Sie ein zweites Transaktionsobjekt, das ich verwenden werde, um das Ausgabeskript zusammenzustellen, auch bekannt als die (Wert + Ziel)-Adresse, an der ich mein UTXO anmelden werde. Auch wo der sigHash mit 2 meiner Schlüssel signiert und zum scriptSig der Transaktion hinzugefügt wird

                        Transaction spendTx = new Transaction(params);
                        Address address = Address.fromBase58(params, "19EfMrs5WkcvtBBnuEqP6v1yppeWww61Kc");
                        Script outputScript = ScriptBuilder.createOutputScript(address);
                        spendTx.addOutput(multiSigOutput.getValue(), outputScript);
//                        System.out.println(spendTx.getOutputs());
                        TransactionInput input = spendTx.addInput(multiSigOutput);

Jetzt die Eingaben manuell signieren ... (Signaturen sind in derselben Reihenfolge wie im Skript)

//sign transaction manually
Sha256Hash sigHash = spendTx.hashForSignature(0, script, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature signature = list.get(0).sign(sigHash);
ECKey.ECDSASignature signature1 = list.get(1).sign(sigHash);
TransactionSignature txSig = new TransactionSignature(signature, Transaction.SigHash.ALL, false);
TransactionSignature txSig1 = new TransactionSignature(signature1, Transaction.SigHash.ALL, false);

...jetzt multisiginputscript erstellen, tx validieren und senden

                        Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript((ImmutableList.of(txSig, txSig1)));
//                        System.out.println(inputScript);
                        input.setScriptSig(inputScript);
                        input.verify(multiSigOutput);

                        peerGroup.broadcastTransaction(spendTx);

                        System.out.println(kit.peerGroup().getConnectedPeers());
                        System.out.println("transaction broadcasted");

ok ... dies wird nicht weitergegeben, aber die Überprüfung wird überprüft. und ich weiß nicht einmal, ob es sich eher um ein Netzwerkproblem als um ein Codeproblem handelt, denn wenn ich den Wert im Ausgabeskript auf > den Saldo des UTXO ändere, wird keine InsufficientMoneyException ausgelöst, wie ich es mir vorstelle. Ich würde einige Fehlerprotokolle anzeigen, aber es gibt keine. Der einzige Fehler ist, wenn ich das createmultisiginputscript in createP2SHmultisiginputscript ändere, gibt die Konsole einen Nicht-Null-Nulldummy-Fehler aus, bei dessen Behebung ich auch Probleme habe, sodass ich nie wissen konnte, ob der Wechsel zu dieser Methode auch die richtige Lösung ist. Ich glaube, ich habe auch die Verbindung zur Peergroup richtig eingerichtet

File chainFile = new File(this.getFilesDir(), "test.spvchain");
System.out.println("does chainfile exist?"  + chainFile.exists());
if(chainFile.exists()) {
    try {
        SPVBlockStore chainStore = new SPVBlockStore(params, chainFile);
        BlockChain chain = new BlockChain(params, chainStore);
        peerGroup = new PeerGroup(params, chain);
        peerGroup.addPeerDiscovery(new DnsDiscovery(params));
        peerGroup.startAsync();
    } catch (BlockStoreException e) {
        e.printStackTrace();
    }

Also verstehe ich es nicht wirklich ... Ich bin zu dem Schluss gekommen, dass mein Verständnis irgendwie falsch ist. Sorry für den verwirrenden langen Beitrag. Es ist Tage her. Kann jemand helfen?

EDIT: Hier ist die rohe Transaktion

In Hex:

In Protokollen:

fbb119d8990cd3912a9ec0118fe3ad8ad61a8388e4a13dd342d9eb67aacfdc65

01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: in 0[] PUSHDATA(71)[3044022022b97b9372d35acaea70f3735dee290f5697cab7b5d6be6f7cdfe31139fba4f90220651091b83570843d4fe8afe02d81417194908b0f6af6f8f3b8f1ad020592409f01] PUSHDATA(71)[3044022036eff4f54b8bf3f834f7bb6e417a04a6a696047f5c75a896c6f9b624ad87680a02200bf2115b64b3b15647178b69151d4588d8a4ade16a4d66e375d0e1265c79fad601] PUSHDATA1[5221025ab78e076801b45ccb2172bce562103cce1714edbeb02ce6123ce1235eb08c762102d1b74577050b696d5886a7afa61d099ea7ab0a3797766f9819dbd72526b0ce512103facf04db5d9bee657151e30c21e839489c326a277891ebcf75b736ec1e17fc1f53ae] 0.0005 BTC 01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: outpoint:c33858b433ef445db35a84daa4da772895df7f03af4b31f21cfa199ea1c017d9:0 hash160:6d49586d7529626aaab49812bcd7839aee7e5800 01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: out DUP HASH160 PUSHDATA(20)[5a566f4eda18e818b8d5ca04ee7c5fa3cfbf0e00] EQUALVERIFY CHECKSIG 0.0005 BTC 12.01 01-12 17:49:20.670 2507-2507/com.cryptoapp.app I/System.out: prps UNKNOWN

Antworten (1)

Ein paar Kommentare von der Überprüfung der von Ihnen geposteten Transaktionsdaten.

1) Ich habe den UTXO überprüft, von dem Sie ausgeben, der UTXO ist

  • 9e7562d19165077d566af47bfbc18283629ed6799da8862660dfb037c353de11
  • Index 0

Ihre Transaktionseingabe verweist jedoch derzeit auf das folgende UTXO:

  • c33858b433ef445db35a84daa4da772895df7f03af4b31f21cfa199ea1c017d9
  • Index 0

Was keine bestätigte Transaktion im Hauptnetz ist.

2) Ihr Eingabeskript scheint richtig geformt zu sein, um Ihre P2SH(Multisig)-Ausgabe auszugeben:

  • zero
  • [3044022022b97b9372d35acaea70f3735dee290f5697cab7b5d6be6f7cdfe31139fba4f90220651091b83570843d4fe8afe02d81417194908b0f6af6f8f3b8f1ad020592409f01]
  • [3044022036eff4f54b8bf3f834f7bb6e417a04a6a696047f5c75a896c6f9b624ad87680a02200bf2115b64b3b15647178b69151d4588d8a4ade16a4d66e375d0e1265c79fad601]
  • [2 [025ab78e076801b45ccb2172bce562103cce1714edbeb02ce6123ce1235eb08c76] [02d1b74577050b696d5886a7afa61d099ea7ab0a3797766f9819dbd72526b0ce51] [03facf04db5d9bee657151e30c21e839489c326a277891ebcf75b736ec1e17fc1f] 3 checkmultisig]

Das letzte Element ist das eingebettete Skript und sollte mit dem 20-B-Digest in Ihrem UTXO hashen, das Sie ausgeben: Es hash160 tatsächlich korrekt zu 6d49586d7529626aaab49812bcd7839aee7e5800.

Als Referenz lautet das P2SH(Multisig)-Ausgabeskript Ihres UTXO: "hash160 [6d49586d7529626aaab49812bcd7839aee7e5800] equal"Beachten Sie, dass die Hashes gleich sind, das ist also gut.

3) Sie haben keine Gebühr in Ihre Transaktion aufgenommen. Die Ausgabemenge von 50000 Sats ist identisch mit der UTXO-Menge. Damit diese Transaktion vom Mempool akzeptiert wird, muss eine Mindestgebühr erhoben werden.

Ich hoffe das hilft.

Vielen Dank für Ihren Kommentar. Es verifiziert. Wenn dies nicht der Fall wäre, würde es einen Fehler ausgeben.
Skript script = ScriptBuilder.createRedeemScript(2, Schlüssel); und Skript script = ScriptBuilder.createMultiSigOutputScript(2, keys); sind dasselbe, außer dass createRedeemScript die Schlüssel in lexikografischer Reihenfolge anordnet, aber dieselbe Funktion zurückgibt
Können Sie beide Rohdaten hier posten, wäre es einfacher, beim Debuggen zu helfen.
Ah okay. Sie müssen also immer noch den ersten TX bestätigen, bevor Sie den zweiten senden.
Also ich bin etwas verwirrt. Ich dachte, das erste tx sei ein Ausgabeskript, das die Vorlage für das UTXO als Kontext für die zweite Transaktion (und die Überprüfung) erstellt. Sie sagen also, ich muss senden, wo ich das Multisig-Skript erstellt habe, und dann auch die Ausgaben senden?
Ja. Ihr Ausgabenskript hat nichts auszugeben: Sie generieren neue Schlüssel am Anfang Ihres Skripts, das heißt, es gibt noch keine Multisig-Ausgabe in der Blockchain, die Sie mit diesen Schlüsseln ausgeben können. Erst nachdem dieser TX mit der Multisig-Ausgabe abgebaut wurde, kann er ausgegeben werden. Ihr erster Multisig-Tx würde jedoch auch eine Eingabe benötigen, sonst würden wir Bitcoin aus dem Nichts erschaffen.
Oh, ich verstehe die Verwirrung. Diese ECKeys-Schlüssel sind eigentlich eine Vorlage für die echten Schlüssel, die ich verwende. Es gibt bereits ein UTXO an meiner richtigen Adresse hier: blockchain.com/btc/address/3BesSajTyegQaBeyJXes6kyav3srZC3p7D Also versuche ich, diese Ausgabe zu bekommen und sie mit denselben Schlüsseln/Skripten auszugeben, die ich verwendet habe, um diese P2SH-Adresse zu erstellen. Ich wollte sie hier einfach nicht bloßstellen. Sorry für die Verwechslung. Ich werde versuchen, es so zu ändern, dass es weniger zweideutig ist
Ok, Sie haben den P2SH-Wrapper oben nicht erwähnt. Wenn es sich um eine P2SH-verpackte Multisig handelt, die Sie ausgeben, erstellen Sie nicht den P2SH-Wrapper in Ihrer obigen Ausgabevorlage neu, sondern nur die rohe Multisig und auch kein P2SH-Einlöseskript in Ihrer Ausgabeneingabe.
OK. Danke. Ich habe versucht, ein P2SHredeemscript in meiner Ausgabeneingabe zu verwenden, aber es löst einen „non-null nulldummy“-Fehler aus, wenn bitcoinj 0.14.7 verwendet wird. Danke aber für diesen Tipp. Ich dachte, ich müsste einen OP_0-Code oben auf dem Stapel hinzufügen, aber das schien nicht von selbst zu funktionieren. Ich werde noch etwas damit spielen. Bitte lassen Sie mich wissen, was sonst noch falsch sein könnte.
Beitrag zur Klärung hoffentlich bearbeitet
Stellen Sie außerdem sicher, dass Sie Ihren ersten Template-TX genau so konstruieren, wie der, der abgebaut wird. Das heißt, es muss genau die gleichen Ein-/Ausgänge haben. Dies liegt daran, dass der zweite TX auf diesen ersten TX durch TXID verweist, bei dem es sich um einen Bitcoin256-Hash der vollständigen TX-Datenserialisierung handelt. Wenn Sie bei Ihrer ersten Transaktion Eingaben oder irgendetwas anderes weglassen (im Vergleich zu der bereits bestätigten TX), wird die zweite Transaktion auf die falsche TXID verweisen.
Großartig. Ich schätze Ihre Hilfe, Sir. Kann ich Ihnen eine E-Mail für eine kleine Klarstellung schicken?
Im Allgemeinen ja, aber es könnte besser sein, die Diskussion zu dieser Frage in diesem Forum öffentlich zu halten, damit andere sie auch sehen und validieren können. Sie können Ihre Frage jederzeit überarbeiten oder eine neu formulierte Frage posten, und ich helfe Ihnen gerne, wo ich kann.
Hallo, ich habe sowohl meine Eingabe- als auch Ausgabefunktionen migriert, um sie an das P2SH-Format des ursprünglichen UTXO anzupassen (aktualisierter Beitrag zur Anzeige). Ich bekomme jedoch immer noch den gleichen stillen Fehler, obwohl alles zusammenzupassen scheint. Jetzt bin ich mir nicht sicher, was möglicherweise das Problem sein könnte, außer dass es nicht an das Peer-Netzwerk sendet
Kannst du Rohdaten posten?
Hey. Ich habe meinen Beitrag so bearbeitet, dass er den Roh-TX in Hex und die Art und Weise, wie er in meiner Konsole angezeigt wird, enthält
ahh. Okay. Nachdem ich den Blockcypher-Transaktionsdecoder live.blockcypher.com/btc/decodetx verwendet und mein rohes Transaktions-Hex aus dem obigen Beitrag eingefügt habe ... glaube ich, dass ich eine fehlerhafte Transaktion kompiliert habe. Hmm
Ich habe die obige Antwort bearbeitet, um auf einige Beobachtungen hinzuweisen, die bei der Überprüfung Ihrer gebuchten Transaktion gemacht wurden.
Ja. Danke schön. Ich versuche jetzt schon seit fast einem Tag, diesen Endpunkt zu ändern. Ich habe keine Ahnung, warum es sich auf diese Transaktions-ID bezieht
Vielen Dank. Ich habe das Problem behoben, indem ich in meinen eigenen Outpoint geschrieben habe, weil ich keine Ahnung habe, warum die Bibliothek meine txid scheinbar ohne Grund geändert hat. Ich werde einen Fehlerbericht schreiben
Eindrucksvoll! Könnten Sie die Antwort markieren (ankreuzen), wenn sie Ihnen bei der Lösung Ihrer Frage geholfen hat? Sehr geschätzt.
Ich würde gerne, aber ich habe nicht genug Repräsentanten, um eine Antwort als akzeptiert zu markieren. Ich weiß nicht, warum sie dieses Limit hinzufügen, aber sobald ich genug Wiederholungen habe, werde ich es gerne tun
Keine Sorge, nur ein Nice-to-have. Solange Sie die benötigte Antwort erhalten und mit Ihrem Projekt fortfahren können, sind alle zufrieden.
Sir, ich habe gerade gesehen, dass Sie der Ausbilder für teachbitcoin.io waren. Kein Grund, dies zu posten, ich fand es nur cool, da ich diese Seite mit einem Lesezeichen versehen hatte
Cheers Stephen, froh, dass du an Bitcoin arbeitest :)
@Stephen: Ich denke, hier liegt ein Missverständnis vor. Sie können einen Beitrag nicht positiv bewerten, bis Sie einen Vertreter haben, aber Sie können Antworten auf Ihre Frage immer als die hilfreichste Antwort markieren. Ich denke, Sie haben vielleicht versucht, auf den "Pfeil nach oben" zu klicken, um einen Beitrag hochzustimmen. Versuchen Sie stattdessen, auf das "Häkchen" zu klicken!