Aus der Design-Begründung :
Eine Schwäche des Kontoparadigmas besteht darin, dass jede Transaktion eine "Nonce" haben muss, um Replay-Angriffe zu verhindern, sodass das Konto die verwendeten Nonces verfolgt und eine Transaktion nur akzeptiert, wenn ihre Nonce nach der letzten verwendeten Nonce 1 ist.
Auf dieser Seite gab es einige Fragen zu zu niedrigen Transaktionsnonces. Was passiert, wenn eine Transaktionsnonce zu hoch ist?
Zusammenfassung
From:
Adresse mit Nonces außerhalb der Reihenfolge.From:
Adresse mit Nonces außerhalb der Reihenfolge gefüllt wird, beispielsweise durch:
Details unten.
Was passiert, wenn die Transaktions-Nonce zu niedrig ist?
Ich habe zwei neue Konten in meinem privaten --dev-Netzwerk mit erstellt
geth -datadir ./data --dev account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat Passphrase:
Address: {c18f2996c11ba48c7e14233710e5a8580c4fb9ee}
geth -datadir ./data --dev account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat Passphrase:
Address: {e1fb110faa8850b4c6be5bdb3b7940d1ede87dfb}
Ich habe eine Mining-Geth-Instanz in einem separaten Fenster gestartet, sodass auf das erste Konto (Coinbase) mehr Geld eingezahlt wird, wenn neue Blöcke abgebaut werden.
geth --datadir ./data --dev --mine --minerthreads 1 console
In meinem Hauptfenster habe ich eine Geth-Instanz gestartet, die an die Mining-Instanz angehängt ist.
geth --datadir ./data --dev attach
Ich sende meine erste Transaktion von meinem ersten Konto an mein zweites Konto
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether")})
Unlock account c18f2996c11ba48c7e14233710e5a8580c4fb9ee
Passphrase:
"0xd17510a4c9880155b0237cac58423e05b61ad3f2d5ee90f72d3db2b7d4ea2d47"
Hier sind die Transaktionsdetails für die erste Transaktion. Für diese Transaktion wurde automatisch eine Nonce von 0 zugewiesen.
> eth.getTransaction("0xd17510a4c9880155b0237cac58423e05b61ad3f2d5ee90f72d3db2b7d4ea2d47")
{
blockHash: "0x519ddf8c3d1a094933d2975bb7c9cdf3680c9d66b880ba22b26627f70d90bb54",
blockNumber: 88,
from: "0xc18f2996c11ba48c7e14233710e5a8580c4fb9ee",
gas: 90000,
gasPrice: 20000000000,
hash: "0xd17510a4c9880155b0237cac58423e05b61ad3f2d5ee90f72d3db2b7d4ea2d47",
input: "0x",
nonce: 0,
to: "0xe1fb110faa8850b4c6be5bdb3b7940d1ede87dfb",
transactionIndex: 0,
value: 1000000000000000000
}
Ich sende eine zweite Transaktion von meinem ersten Konto an mein zweites Konto, gebe eine Nonce von 0 an und erhalte das erwartete Ergebnis von "Nonce too low".
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether"), nonce:0})
Nonce too low
at InvalidResponse (<anonymous>:-81662:-106)
at send (<anonymous>:-156322:-106)
at sendTransaction (<anonymous>:-133322:-106)
at <anonymous>:1:1
Was passiert, wenn die Transaktions-Nonce zu hoch ist?
Ich sende nun eine dritte Transaktion von meinem ersten Konto an mein zweites Konto, gebe eine Nonce von 10000 an und bekomme einen Transaktions-Hash zurück, dass die Transaktion an den Transaktionspool gesendet wurde.
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether"), nonce:10000})
"0x5b09270d6bcd33297527a1f6b08fa1528deec01e82a100c7e62ee93fbdcd1f7d"
Im Mining-Fenster zeigt eine Nachricht an, dass die Transaktion eingegangen ist. Die Transaktion wird jedoch nie abgebaut.
I0409 15:25:07.699859 10726 worker.go:569] commit new work on block 95 with 0 txs & 0 uncles. Took 289.587µs
I0409 15:25:08.493883 10726 xeth.go:1028] Tx(0x5b09270d6bcd33297527a1f6b08fa1528deec01e82a100c7e62ee93fbdcd1f7d) to: 0xe1fb110faa8850b4c6be5bdb3b7940d1ede87dfb
> I0409 15:26:13.472919 10726 worker.go:348] 🔨 Mined block (#95 / 7fe1ada0). Wait 5 blocks for confirmation
I0409 15:26:13.473634 10726 worker.go:569] commit new work on block 96 with 0 txs & 0 uncles. Took 630.605µs
I0409 15:26:13.473707 10726 worker.go:447] 🔨 🔗 Mined 5 blocks back: block #90
I0409 15:26:13.474252 10726 worker.go:569] commit new work on block 96 with 0 txs & 0 uncles. Took 447.451µs
I0409 15:26:18.921404 10726 worker.go:348] 🔨 Mined block (#96 / 760e117c). Wait 5 blocks for confirmation
I0409 15:26:18.922033 10726 worker.go:569] commit new work on block 97 with 0 txs & 0 uncles. Took 547.204µs
I0409 15:26:18.922096 10726 worker.go:447] 🔨 🔗 Mined 5 blocks back: block #91
Ich versuche, die Transaktionsdetails für meine dritte Transaktion abzurufen. Der blockHash und die blockNumber bleiben für immer null.
> eth.getTransaction("0x5b09270d6bcd33297527a1f6b08fa1528deec01e82a100c7e62ee93fbdcd1f7d")
{
blockHash: null,
blockNumber: null,
from: "0xc18f2996c11ba48c7e14233710e5a8580c4fb9ee",
gas: 90000,
gasPrice: 20000000000,
hash: "0x5b09270d6bcd33297527a1f6b08fa1528deec01e82a100c7e62ee93fbdcd1f7d",
input: "0x",
nonce: 10000,
to: "0xe1fb110faa8850b4c6be5bdb3b7940d1ede87dfb",
transactionIndex: null,
value: 1000000000000000000
}
Ich überprüfe den Status des Transaktionspools und gehe davon aus, dass sich die Transaktion mit Nonce 10000 in der Warteschlange befindet.
> txpool.status
{
pending: 0,
queued: 1
}
Ich versuche, eine vierte Transaktion mit einer Nonce von 1 zu senden. Die Transaktion wird abgebaut.
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether"), nonce:1})
"0x545af0a0276e154a8669921373de8904a330b829318a7c83f5bd9f9771e71ff8"
> eth.getTransaction("0x545af0a0276e154a8669921373de8904a330b829318a7c83f5bd9f9771e71ff8")
{
blockHash: "0xc125f5da96e36ac87728a35eae8ff8046bcc08c6242825daa4b6bb1e7b460a01",
blockNumber: 101,
from: "0xc18f2996c11ba48c7e14233710e5a8580c4fb9ee",
gas: 90000,
gasPrice: 20000000000,
hash: "0x545af0a0276e154a8669921373de8904a330b829318a7c83f5bd9f9771e71ff8",
input: "0x",
nonce: 1,
to: "0xe1fb110faa8850b4c6be5bdb3b7940d1ede87dfb",
transactionIndex: 0,
value: 1000000000000000000
}
Also versuche ich, eine fünfte Transaktion mit einer Nonce von 3 zu senden (es gibt jetzt eine Lücke, da die letzte gültige Nonce 1 ist). Die Transaktion geht in die Warteschlange des Transaktionspools und wird nicht abgebaut.
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether"), nonce:3})
"0x895ec329c3a1d53acf7a429721025f2ff01d5558feee0595daa0fa9c0282d461"
> eth.getTransaction("0x895ec329c3a1d53acf7a429721025f2ff01d5558feee0595daa0fa9c0282d461")
{
blockHash: null,
blockNumber: null,
from: "0xc18f2996c11ba48c7e14233710e5a8580c4fb9ee",
gas: 90000,
gasPrice: 20000000000,
hash: "0x895ec329c3a1d53acf7a429721025f2ff01d5558feee0595daa0fa9c0282d461",
input: "0x",
nonce: 3,
to: "0xe1fb110faa8850b4c6be5bdb3b7940d1ede87dfb",
transactionIndex: null,
value: 1000000000000000000
}
Ich sende eine sechste Transaktion mit einer Nonce von 2 (dies füllt die Lücke zwischen der letzten gültigen Nonce von 1 und der Transaktion in der Warteschlange mit einer Nonce von 3).
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether"), nonce:2})
"0xea7a6350d6f7aa61a5f515452021de905917338d3b4d354e19fc53d8bd4982f4"
Beide Transaktionen mit den Nonces 2 und 3 werden jetzt abgebaut.
> eth.getTransaction("0xea7a6350d6f7aa61a5f515452021de905917338d3b4d354e19fc53d8bd4982f4")
{
blockHash: "0xabcfea8140fdbe3d04bab05cb0232a8c73de4a6bc2307907ede9d45ad58d7107",
blockNumber: 170,
from: "0xc18f2996c11ba48c7e14233710e5a8580c4fb9ee",
gas: 90000,
gasPrice: 20000000000,
hash: "0xea7a6350d6f7aa61a5f515452021de905917338d3b4d354e19fc53d8bd4982f4",
input: "0x",
nonce: 2,
to: "0xe1fb110faa8850b4c6be5bdb3b7940d1ede87dfb",
transactionIndex: 0,
value: 1000000000000000000
}
> eth.getTransaction("0x895ec329c3a1d53acf7a429721025f2ff01d5558feee0595daa0fa9c0282d461")
{
blockHash: "0xabcfea8140fdbe3d04bab05cb0232a8c73de4a6bc2307907ede9d45ad58d7107",
blockNumber: 170,
from: "0xc18f2996c11ba48c7e14233710e5a8580c4fb9ee",
gas: 90000,
gasPrice: 20000000000,
hash: "0x895ec329c3a1d53acf7a429721025f2ff01d5558feee0595daa0fa9c0282d461",
input: "0x",
nonce: 3,
to: "0xe1fb110faa8850b4c6be5bdb3b7940d1ede87dfb",
transactionIndex: 1,
value: 1000000000000000000
}
Ich überprüfe den Status des Transaktionspools und die Transaktion mit Nonce 10000 befindet sich immer noch in der Warteschlange und wird für immer bleiben.
> txpool.status
{
pending: 0,
queued: 1
}
Ich fahre meine Mining-Geth-Instanz und meine angehängte Geth-Instanz herunter und starte beide neu. Ich überprüfe jetzt den Status des Transaktionspools und die Transaktion mit Nonce 10000 ist verschwunden.
> txpool.status
{
pending: 0,
queued: 0
}
Quellcode des Transaktionspools
Betrachtet man core/tx_pool.go (#48-50) , gibt es eine maximale Warteschlangengröße von 64 Transaktionen für Transaktionen mit Out-of-Order-Nonce-Sequenz pro Sendeadresse.
const (
maxQueued = 64 // max limit of queued txs per address
)
Und core/tx_pool.go (#436-456) zeigt den Code, der Transaktionen entfernt, wenn die Warteschlange zu voll ist:
for i, entry := range promote {
// If we reached a gap in the nonces, enforce transaction limit and stop
if entry.Nonce() > guessedNonce {
if len(promote)-i > maxQueued {
if glog.V(logger.Debug) {
glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:]))
}
for _, drop := range promote[i+maxQueued:] {
delete(txs, drop.hash)
}
}
break
}
// Otherwise promote the transaction and move the guess nonce if needed
pool.addTx(entry.hash, address, entry.Transaction)
delete(txs, entry.hash)
if entry.Nonce() == guessedNonce {
guessedNonce++
}
}
Crashtest von Geth mit zu hoher Nonce
sudo swapoff -a
unter Linux läuft) abschalte und andere speicherraubende Programme ausführe.Wenn Sie Hardhat + Metamask verwenden und dies nach dem Neustart des Knotens sehen, versuchen Sie, Ihr Konto auf Metamask zurückzusetzen: Einstellungen > Erweitert > Konto zurücksetzen.
Was passiert, wenn eine Transaktionsnonce zu hoch ist?
Eine „zu hohe“ Nonce-Transaktion könnte in tx_pool hinzugefügt werden und die Validierung der ersten Stufe bestehen, aber sie wird in der Validierung der zweiten Stufe während der Zustandsübergangsausführung fehlschlagen.
Es folgte strikt der Design-Rationale: "Akzeptiert eine Transaktion nur, wenn ihre Nonce 1 nach der letzten verwendeten Nonce ist."
go-ethereum/core/state_transition.go
func (self *StateTransition) preCheck() (err error) {
msg := self.msg
sender := self.from()
// Make sure this transaction's nonce is correct
if msg.CheckNonce() {
if n := self.state.GetNonce(sender.Address()); n != msg.Nonce() {
return NonceError(msg.Nonce(), n)
}
}
// Pre-pay gas
if err = self.buyGas(); err != nil {
if IsGasLimitErr(err) {
return err
}
return InvalidTxError(err)
}
return nil
}
Beim Blockchain.info-Austausch, bei dem Shapeshift-Transfers zwischen zwei Kryptos, z. B. Ethereum zu Bitcoin, verwendet werden, wird diese Meldung angezeigt, wenn Ihr erster Transaktionsstatus noch aussteht.
Es soll vor Doppeltransaktionen schützen. Warten Sie, bis die erste Transaktion abgeschlossen ist, bevor Sie versuchen, weitere zu verschieben.
Taywano
Datenschutz ist ein Menschenrecht.eth
q9f
Datenschutz ist ein Menschenrecht.eth
Thomas Cloes
Alper
Datenschutz ist ein Menschenrecht.eth
swapoff -a
schaltet die Auslagerungsdatei aus, sodass mein effektiver Speicher nur 4 GB beträgt.sudo
Robert Öschler
Ashwani Agarwal