#dusk $DUSK @Dusk Ich habe schon immer neugierig auf ein konkretes Szenario geschaut: Was passiert, wenn jemand an der Reihe ist, einen Block zu erstellen, aber genau dessen Knoten feststeckt oder offline geht? Wartet das Netzwerk dann einfach ab – oder gibt es eine automatische Umschalt- bzw. Ausweichlösung? Ich habe mir deshalb gezielt angesehen, wie dieser Abschnitt im Dusk-Konsensprozess gestaltet ist.
Beim Blockproduzieren in Dusk gibt es drei Schritte: Zuerst schlägt der ausgewählte Knoten einen Block vor. Danach bestätigt eine Reihe von Knoten den Block per Signatur-Voing. Anschließend führt eine andere Gruppe eine zweite Runde der Abstimmung durch, fasst die Ergebnisse der vorherigen Runde zusammen und erreicht offiziell den Konsens. Diese drei Schritte zusammen gelten als eine Runde. Wenn der ausgewählte Knoten den vorgeschlagenen Block nicht innerhalb der vorgegebenen Zeit ordnungsgemäß einreicht oder wenn während der Abstimmung nicht genug Stimmen zusammenkommen, dann schlägt diese Runde wegen Zeitüberschreitung fehl. Es geht dann in die nächste Iteration über: Man wechselt erneut die beteiligten Knoten und versucht es von vorn, und das wird so lange wiederholt, bis tatsächlich ein Konsens erreicht ist.
Ursprünglich dachte ich, dass dieses „nach Timeout neu starten“ starr und unveränderlich ist – also dass nach jedem Timeout immer eine fest definierte Dauer gewartet wird und dann erneut ein Versuch erfolgt. Als ich jedoch in ihre Entwicklungstagebücher geschaut habe, stellte ich fest: dem ist nicht so. Dort gibt es eine Änderung, die explizit mit „adaptive Timeouts implementieren“ beschrieben ist. Zusätzlich gibt es noch eine andere Änderung mit „Blöcke auf eine niedrigere Runde zurücksetzen zulassen“. Das bedeutet: Das System verwendet nicht durchgehend dieselbe feste Wartezeit von Anfang bis Ende, sondern passt das Zeitfenster an die tatsächlichen Bedingungen im Netzwerk an. Außerdem behandelt es Fälle wie diesen: Wenn es bereits akzeptierte Blöcke aus früheren Runden gibt, wird diese spätere Runde nicht mehr unnötig herumprobiert.
Dieser Detailpunkt ist mir erst aufgefallen, weil ich ihn in einem Update der Aufzeichnungen aus einem bestimmten Entwicklungszyklus entdeckt habe. Wenn man nur die Bezeichnung des Protokolls und die Beschreibung der Schritte liest, erkennt man diese Ebene der dynamischen Anpassung überhaupt nicht.
Für mich löst dieses Mechanismus-Design ein ziemlich reales Problem: Je mehr Knoten im Netzwerk sind, desto eher gibt es immer jemanden, der durch Netzwerk-Jitter „zappelt“ oder zwischendurch offline geht. Ohne diese automatische Neuauswahl und die dynamische Timeout-Anpassung könnte das Netzwerk jederzeit an genau einem unglücklichen Knoten festhängen, der einfach nicht rechtzeitig reagiert. Ich habe allerdings keine konkreten historischen Daten gefunden – zum Beispiel wie oft der Hauptnetzbetrieb bisher tatsächlich aufgrund solcher Timeout-Neuauswahlen ausgelöst wurde, und wie lange es im Durchschnitt dauert, bis der Betrieb nach dem Auslösen wieder normal läuft. Dafür habe ich bislang noch keine verwertbaren Zahlen zur Verifizierung gefunden.
Beim Blockproduzieren in Dusk gibt es drei Schritte: Zuerst schlägt der ausgewählte Knoten einen Block vor. Danach bestätigt eine Reihe von Knoten den Block per Signatur-Voing. Anschließend führt eine andere Gruppe eine zweite Runde der Abstimmung durch, fasst die Ergebnisse der vorherigen Runde zusammen und erreicht offiziell den Konsens. Diese drei Schritte zusammen gelten als eine Runde. Wenn der ausgewählte Knoten den vorgeschlagenen Block nicht innerhalb der vorgegebenen Zeit ordnungsgemäß einreicht oder wenn während der Abstimmung nicht genug Stimmen zusammenkommen, dann schlägt diese Runde wegen Zeitüberschreitung fehl. Es geht dann in die nächste Iteration über: Man wechselt erneut die beteiligten Knoten und versucht es von vorn, und das wird so lange wiederholt, bis tatsächlich ein Konsens erreicht ist.
Ursprünglich dachte ich, dass dieses „nach Timeout neu starten“ starr und unveränderlich ist – also dass nach jedem Timeout immer eine fest definierte Dauer gewartet wird und dann erneut ein Versuch erfolgt. Als ich jedoch in ihre Entwicklungstagebücher geschaut habe, stellte ich fest: dem ist nicht so. Dort gibt es eine Änderung, die explizit mit „adaptive Timeouts implementieren“ beschrieben ist. Zusätzlich gibt es noch eine andere Änderung mit „Blöcke auf eine niedrigere Runde zurücksetzen zulassen“. Das bedeutet: Das System verwendet nicht durchgehend dieselbe feste Wartezeit von Anfang bis Ende, sondern passt das Zeitfenster an die tatsächlichen Bedingungen im Netzwerk an. Außerdem behandelt es Fälle wie diesen: Wenn es bereits akzeptierte Blöcke aus früheren Runden gibt, wird diese spätere Runde nicht mehr unnötig herumprobiert.
Dieser Detailpunkt ist mir erst aufgefallen, weil ich ihn in einem Update der Aufzeichnungen aus einem bestimmten Entwicklungszyklus entdeckt habe. Wenn man nur die Bezeichnung des Protokolls und die Beschreibung der Schritte liest, erkennt man diese Ebene der dynamischen Anpassung überhaupt nicht.
Für mich löst dieses Mechanismus-Design ein ziemlich reales Problem: Je mehr Knoten im Netzwerk sind, desto eher gibt es immer jemanden, der durch Netzwerk-Jitter „zappelt“ oder zwischendurch offline geht. Ohne diese automatische Neuauswahl und die dynamische Timeout-Anpassung könnte das Netzwerk jederzeit an genau einem unglücklichen Knoten festhängen, der einfach nicht rechtzeitig reagiert. Ich habe allerdings keine konkreten historischen Daten gefunden – zum Beispiel wie oft der Hauptnetzbetrieb bisher tatsächlich aufgrund solcher Timeout-Neuauswahlen ausgelöst wurde, und wie lange es im Durchschnitt dauert, bis der Betrieb nach dem Auslösen wieder normal läuft. Dafür habe ich bislang noch keine verwertbaren Zahlen zur Verifizierung gefunden.