Was ist der beste Weg, um Replay-Angriffe im Falle eines Bitcoin-Hard-Forks zu verhindern?

Ich dachte ursprünglich, es wäre relativ einfach, im Falle eines Forks einen Replay-Angriffsschutz hinzuzufügen (etwas daran zu ändern, wie der TX-Hash generiert wird). Aber die BU-Leute erwähnten, dass dies SPV-Clients (einschließlich vieler mobiler Geldbörsen) beschädigen würde. Es ist also nicht frei, dies zu tun, obwohl es immer noch eine Option ist.

Eine Lösung, die wir uns ausgedacht haben, bestand darin, einige Münzen zu verwenden, die nur auf einer Kette gültig waren (z. B. neu abgebaute Münzen), und allen generierten Transaktionen 1 Satoshi "Taint" hinzuzufügen. Das würde funktionieren, ist aber nicht perfekt. Zum Beispiel können neu geschürfte Coins nicht für 100 Blöcke ausgegeben werden, so dass es zumindest zu einer Verzögerung der Wirtschaftsknoten im Falle eines Hard Forks kommen würde. Es ist auch für jede Wallet-Software nicht trivial, dies zu implementieren (ein ziemlicher Arbeitsaufwand, insbesondere im großen Maßstab). Es gibt auch eine operative Herausforderung, bei der Sie sich beeilen müssten, um diese neu geschürften Münzen zu erhalten, während die Hard Fork stattfand, sodass Sie sich nicht im Voraus vorbereiten konnten. Es wäre sicher eine Sauerei.

Eine andere Option wäre, zu versuchen, einige Münzen über die gegabelten Ketten doppelt auszugeben (eine Transaktion mit einigen Münzen zu erhalten, die an zwei verschiedene Adressen gehen, die über die beiden Ketten hinweg abgebaut werden). Diese Coins könnten dann auch für „Taint“ verwendet werden, man müsste aber nicht die vollen 100 Blöcke warten. Das ist etwas besser, aber immer noch nicht perfekt.

Ich vermute aber, dass es eine bessere Lösung gibt. Was sind die Gedanken der Menschen?

Antworten (3)

Eine Lösung, die wir uns ausgedacht haben, bestand darin, einige Münzen zu verwenden, die nur auf einer Kette gültig waren (z. B. neu abgebaute Münzen), und allen generierten Transaktionen 1 Satoshi "Taint" hinzuzufügen. Das würde funktionieren, ist aber nicht perfekt.

Das klingt so, als hättest du zwei Probleme:

  1. So erhalten Sie einige Eingaben, die nur auf einer Seite der Kette gültig sind.
  2. Wie Sie diese Eingaben mit all Ihren Transaktionen mischen.

Auf die zweite Frage habe ich keine guten Antworten; Sie müssen die Eingaben mischen, indem Sie sie entweder in jede von Ihnen gesendete Transaktion einfügen oder indem Sie sie mit einer großen Menge Münzen mischen, die Sie dann in Dutzende oder Hunderte von Eingaben aufteilen, die Sie normalerweise verwenden.

Zur ersten Frage:

Coin-Splitting

Der beste Weg wäre, auf den Replay-Schutz in den Hard-Fork-Clients zu drängen, da sie bereits die Regeln ändern. Aber wenn das nicht möglich ist, gibt es einige potenzielle Unterschiede zwischen Ketten, die verwendet werden können, um eine Version einer Transaktion auf einer Kette und eine andere Version derselben Transaktion auf der anderen Kette zu bestätigen.

Ich warne davor, dass (1) Bitcoin-Clients nicht dafür ausgelegt sind, unter laufenden Hard Forks zu arbeiten, so dass viele Dinge, die normalerweise gut funktionieren würden, zu finanziellen Verlusten führen können, (2) ohne Replay-Angriffsschutz gibt es dafür keine Garantie Jeder der unten aufgeführten Mechanismen wird Ihre Coins aufteilen – also sollten Sie wahrscheinlich die Coins von sich selbst an sich selbst senden, damit Sie, wenn die Aufteilung fehlschlägt, immer noch alle Ihre Coins haben (abzüglich etwaiger Transaktionsgebühren), und (3) in a Hard Fork, jede Regel kann geändert werden, sodass die folgenden allgemeinen Informationen möglicherweise nicht auf die Hard Fork-Kette zutreffen; Wenden Sie sich an die Hard Fork-Entwickler, um sicherzugehen.

Methoden:

  1. Coinbase-Transaktionen: nicht die Art, die Ihr Unternehmen durchführt, sondern die Art, die Bergleute verwenden, um Subventionen und Transaktionsgebühren zu fordern. Wie Ihre Frage andeutet, sind diese nur auf der Seite der Hard Fork gültig, auf der sie generiert werden, aber sie müssen auch 100 Blöcke warten, bis sie ausgereift sind.

    Vorteile: einfach, funktioniert garantiert

    Nachteile: erfordert Bergmannshilfe, muss 100 Blöcke warten

  2. nLockTime: Wenn die beiden Ketten unterschiedlich hoch sind, können Sie eine Transaktion erstellen, bei der die nLockTime auf die Höhe der längsten Kette eingestellt ist. Diese Transaktion kann sofort auf dieser Kette bestätigt werden, aber sie kann nicht zur kürzeren Kette hinzugefügt werden, bis diese Kette die gleiche Höhe erreicht hat – was Ihnen ein Zeitfenster gibt, in dem Sie eine alternative Transaktion auf der kürzeren Kette übertragen können und teilen Sie Ihre Münzen.

    Praktischerweise verfügt Bitcoin Core über eine Funktion namens Anti-Fee Sniping, die (in aktuellen Versionen) die nLockTime automatisch auf die aktuelle Blockhöhe für Standard-Wallet-Transaktionen setzt, sodass dieser Trick ziemlich einfach ist, wenn Sie nur Ihre Bitcoin Core-Wallet aufteilen möchten.

    Vorteile: Sollte ziemlich effektiv sein, da es von Konsensregeln abhängt

    Nachteile: Sie müssen immer noch ein paar Blocks nach der Gabelung warten, um den Ketten Zeit zu geben, in der Kettenhöhe auseinander zu gehen.

    (Credit: Ich habe zum ersten Mal von einer Methode wie dieser von Peter Todd gehört; ich weiß nicht, ob er sie entwickelt hat, noch ob dies genau die Methode ist, an die er dachte – ich musste von ihm erraten, wie sie funktionieren würde Sagen Sie einfach "nLockTime verwenden".)

    Sie können dasselbe auch mit konsenserzwungener nSequence tun, aber es bringt Ihnen nichts Zusätzliches.

  3. Gebührenunterschiede: Es ist möglich, dass Bergleute auf der einen Seite des Forks Transaktionen mit niedrigeren Gebühren abbauen als auf der anderen Seite, sodass Sie eine gebührengünstige Version Ihrer Transaktion auf der gebührenfreien Kette übertragen können, warten Sie, bis sie bestätigt wird. und senden Sie dann eine Version mit höheren Gebühren auf der Kette mit hohen Gebühren.

    Vorteile: einfach

    Nachteile: Sie müssen möglicherweise noch ein paar Blöcke warten, bis die Gebühren stark voneinander abweichen, und da jeder Miner seine eigenen Richtlinien hat, müssen Sie es möglicherweise mehrmals versuchen. Außerdem lassen viele Brieftaschen Sie keine willkürlichen Gebühren wählen (sie geben Ihnen nur eine angemessene Gebühr oder lassen Sie aus einer angemessenen Gebührenpalette wählen).

    (Gutschrift: Ich habe das heute zum ersten Mal von @ElectrumWallet auf Twitter gehört.)

  4. Finden Sie ein anderes Merkmal, das zwischen den Bergleuten in den beiden Ketten divergiert. Während ich dies schreibe, denke ich zum Beispiel, dass Bitcoin Core standardmäßig keine Transaktionen in seinen Speicherpool akzeptiert, die das Mining von mehr als 20 Vorfahren erfordern (dies verhindert Missbrauch und ermöglicht eine effizientere Ausführung des Mining-Codes, da Bitcoin Core untergeordnete -Pays-for-Parent (CPFP)-Mining); Bitcoin Unlimited, das auf einer älteren Version von Bitcoin Core basiert, bietet keine CPFP-Optimierung und ermöglicht daher eine unbegrenzte Tiefe von Transaktionsvorfahren, um in den Mempool einzutreten. Das bedeutet, dass Sie beispielsweise 101 verwandte Transaktionen auf der einen Seite des Forks abbauen könnten und dann bis zu fünf Blöcke Zeit hätten, um eine andere 101. Transaktion auf der anderen Seite des Forks abzubauen.

    Es gibt möglicherweise andere dieser Unterschiede auf Relaisebene zwischen Clients, die verwendet werden könnten.

    Vorteile: Relay-Unterschiede könnten möglicherweise unmittelbar nach einem Hard Fork verwendet werden, um eine Transaktion im ersten Fork-Block (wenn Sie wussten, wann das passieren würde) oder im zweiten Fork-Block (wenn Sie direkt nach dem ersten Fork-Block begonnen haben) abzubauen wurde produziert). Außerdem können sie ziemlich einfach sein.

    Nachteile: Diese Tricks hängen davon ab, dass alle Miner auf einer Seite der Kette eine Version des Codes ausführen und alle Miner auf der anderen Seite eine andere Version des Codes ausführen. Je mehr Überschneidungen vorhanden sind, desto geringer ist die Wahrscheinlichkeit, dass diese Tricks funktionieren.

Hier ist das Github-Ticket, in dem wir über dieses Problem für Zcash nachgedacht haben. Im Vergleich zu Bitcoin hat Zcash den Luxus einer kleineren installierten Basis und einer längeren Landebahn vor einem möglichen Blockchain-Split, sodass wir nicht so viele Einschränkungen beim Designraum haben wie Sie, aber dennoch könnten einige dieser Ideen hilfreich sein:

https://github.com/zcash/zcash/issues/174

Hier ist eine Idee:

https://github.com/luke-jr/bips/blob/bip-noreplay/bip-noreplay.mediawiki

Es scheint mir, dass dies funktionieren würde und nicht mit SPV-Clients inkompatibel wäre, soweit ich denken kann.

Hallo Zooko, willkommen bei Bitcoin.SE. Könnten Sie bitte Ihre Antwort bearbeiten, um eine kurze Zusammenfassung der verknüpften Ressourcen hinzuzufügen? Es wäre schön, wenn Sie in Ihrer Antwort eine kleine Idee hätten, ohne eine weitere Seite lesen zu müssen.

A) Derzeit behält Unlimited das Richtlinienlimit von 100.000 MAX_STANDARD_TX_SIZE bei https://github.com/BitcoinUnlimited/BitcoinUnlimited/blob/release/src/policy/policy.h#L23 , sodass es schwierig wäre, eine große Transaktion über P2P zu verbreiten. Ein Miner könnte jedoch einen großen 1-MB-TX abbauen, wenn Sie einen direkt zu ihm bekommen, und dann könnten die UTXOs aus dem großen TX für Taint verwendet werden, da sie nur in der Unlimited-Kette enthalten wären. Außerdem könnten Unterschiede in der Knotenrichtlinie zwischen Unlimited und Core wahrscheinlich dazu verwendet werden, Transaktionen dazu zu bringen, sich auf nur einer Seite der Aufteilung auszubreiten und daher abgebaut zu werden.

B) TX-Verformbarkeit könnte nützlich sein, um beim Splitten zu helfen. Beispielsweise könnten Miner einen Service anbieten, um UTXOs aufzuteilen. Es gibt zumindest ein paar Möglichkeiten:

Option 1) Signieren Sie Ihre Eingaben mit SIGHASH_ANYONECANPAY|SIGHASH_ALL und erlauben Sie den Bergleuten, eine einzelne mit Satosi behaftete Eingabe hinzuzufügen, die sie in Form von Gebühren zurückerhalten (Bergleute können aufgrund des SIGHASH_ALL der Signaturen für diese Option keine Ausgaben hinzufügen).

Option 2) Signieren Sie Ihre Eingaben mit SIGHASH_ANYONECANPAY|SIGHASH_SINGLE und verwenden Sie eine Indexausgabe mit einer einzigen Null. Dies ermöglicht es einem Miner, Eingaben und Ausgaben hinzuzufügen, die Taint eingeben und eine ihrer Adressen zurückzahlen. Diese würden auffallen, weil sie deutlich anders als normal signiert sind. Siehe Regtest-Beispiel unten.

Option 3) Miner auf der einen Seite könnten mechanisch ScriptSig-Formbarkeitstransformationen durchführen, um Ausgaben mit anderen TXIDs als die der anderen Kette zu bestätigen.

regtest network example:
WIF private key --> regtest network address
cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA --> mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r
cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87K7XCyj5v --> mg8Jz5776UdyiYcBb9Z873NTozEiADRW5H
cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87KcLPVfXz --> mrzKXEpXfEDHk7vFS3LBXVXoa4YXFcCkje

> ./bitcoin/src/qt/bitcoin-qt -regtest -txindex -datadir=/test/1/

in debug window rpc console:
generatetoaddress 1 mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r
generatetoaddress 1 mrzKXEpXfEDHk7vFS3LBXVXoa4YXFcCkje
generate 100
getblock(getblockhash(1))[tx][0]
getblock(getblockhash(2))[tx][0]

User does this:
createrawtransaction '[{"txid":"54bdb97bdc75580f8564f348ab312f2147c945fcb96a7c2a01231aff50030212","vout":0}]' '{"mg8Jz5776UdyiYcBb9Z873NTozEiADRW5H":49.099}'
signrawtransaction 020000000112020350ff1a23012a7c6ab9fc45c947212f31ab48f364850f5875dc7bb9bd540000000000ffffffff01e020a724010000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00000000 'null' '["cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA"]' 'SINGLE|ANYONECANPAY'
020000000112020350ff1a23012a7c6ab9fc45c947212f31ab48f364850f5875dc7bb9bd54000000006a47304402202e229bf02236b209271da602cf9a16b2e651b8419d3610d311a5d443804b0bba022072c5cbc37310f27e047a5110ac2fae802d7fb51ed0fda86eeaa0c6ab5518b1ec83210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01e020a724010000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00000000

The above raw transaction is what you would send to the network in actual usage.

Miner does this:
createrawtransaction '[{"txid":"cebee3f6f6f2d74f4513fa04d67040954ef216c962f3b000ed68cd7a37234293","vout":0}]' '{"mrzKXEpXfEDHk7vFS3LBXVXoa4YXFcCkje":50}'
0200000001934223377acd68ed00b0f362c916f24e954070d604fa13454fd7f2f6f6e3bece0000000000ffffffff0100f2052a010000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac00000000

Miners manually merge the previous two raw transactions into:
020000000212020350ff1a23012a7c6ab9fc45c947212f31ab48f364850f5875dc7bb9bd54000000006a47304402202e229bf02236b209271da602cf9a16b2e651b8419d3610d311a5d443804b0bba022072c5cbc37310f27e047a5110ac2fae802d7fb51ed0fda86eeaa0c6ab5518b1ec83210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff934223377acd68ed00b0f362c916f24e954070d604fa13454fd7f2f6f6e3bece0000000000ffffffff02e020a724010000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00f2052a010000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac00000000

signrawtransaction 020000000212020350ff1a23012a7c6ab9fc45c947212f31ab48f364850f5875dc7bb9bd54000000006a47304402202e229bf02236b209271da602cf9a16b2e651b8419d3610d311a5d443804b0bba022072c5cbc37310f27e047a5110ac2fae802d7fb51ed0fda86eeaa0c6ab5518b1ec83210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff934223377acd68ed00b0f362c916f24e954070d604fa13454fd7f2f6f6e3bece0000000000ffffffff02e020a724010000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00f2052a010000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac00000000 'null' '["cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87KcLPVfXz"]' 'ALL'
020000000212020350ff1a23012a7c6ab9fc45c947212f31ab48f364850f5875dc7bb9bd54000000006a47304402202e229bf02236b209271da602cf9a16b2e651b8419d3610d311a5d443804b0bba022072c5cbc37310f27e047a5110ac2fae802d7fb51ed0fda86eeaa0c6ab5518b1ec83210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff934223377acd68ed00b0f362c916f24e954070d604fa13454fd7f2f6f6e3bece000000006a473044022013d1c41326ff95dafc1f15a25bcec916d06da6e61a5808ca9ad6de0b8a527cb902206f120f53512809721cb71b3d1a797e698621229cba2b2e87b1c654e2f9336b02012102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9ffffffff02e020a724010000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00f2052a010000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac00000000

This is effectively what the miner would put in a block:
sendrawtransaction 020000000212020350ff1a23012a7c6ab9fc45c947212f31ab48f364850f5875dc7bb9bd54000000006a47304402202e229bf02236b209271da602cf9a16b2e651b8419d3610d311a5d443804b0bba022072c5cbc37310f27e047a5110ac2fae802d7fb51ed0fda86eeaa0c6ab5518b1ec83210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff934223377acd68ed00b0f362c916f24e954070d604fa13454fd7f2f6f6e3bece000000006a473044022013d1c41326ff95dafc1f15a25bcec916d06da6e61a5808ca9ad6de0b8a527cb902206f120f53512809721cb71b3d1a797e698621229cba2b2e87b1c654e2f9336b02012102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9ffffffff02e020a724010000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00f2052a010000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac00000000 true

double check that the tx is accepted and mined:
generate 6
gettxout(882f4d4faf6880572cde354dcc6d41de9d14fb2a184bc12635822e36dfa9b2e9, 0)[confirmations]
gettxout(882f4d4faf6880572cde354dcc6d41de9d14fb2a184bc12635822e36dfa9b2e9, 0)
gettxout(882f4d4faf6880572cde354dcc6d41de9d14fb2a184bc12635822e36dfa9b2e9, 1)

notes: to understand how this works and limitations, see:
https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1052-#L1141
https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1223-#L1243