Tip Selection

Jede Transaktion im Tangle muss auf zwei vorherige Transaktionen verweisen. Mit „Tip Selection“ bezeichnet man den Prozess, bei dem eine IRI-Node zwei zufällige Tip-Transaktionen aus seinem Subtangle auswählt. Diese Tip-Transaktionen werden von neuen Transaktionen referenziert, bevor sie zur Validierung an eine IRI-Node gesendet werden.

Die Tipauswahl (tip selection) wird von Clients angefordert, damit sie mit neuen Transaktionen auf zwei vorherige Transaktionen verweisen können.

Während der Auswahl der Tips validiert der IRI-Node den Verlauf einer Tip-Transaktion, beginnend mit einem benutzerdefinierten Meilenstein. Wenn eine Transaktion auf eine andere verweist, wird sie zum Genehmiger der Transaktion.

Im Allgemeinen wählt die Tip Selection Tip-Transaktionen aus, für die es noch keine Genehmiger gibt.

Obwohl der Tipselectionalgorithmus in die IOTA-Nodesoftware (IRI) eingebettet ist, wird er vom Netzwerk nicht erzwungen. Stattdessen erhalten IRI-Nodes einen Anreiz, den Tipselectionalgorithmus zu verwenden.

In den folgenden Informationen wird beschrieben, was der IRI-Node tut, wenn ein Client den Endpunkt getTransactionsToApprove aufruft.

Clients rufen diesen Endpunkt an, wenn sie eine Transaktion senden möchten. Der Endpunkt führt zu zwei Tip-Transaktions-Hashes, die in trunkTransaction und branchTransaction Felder der neuen Transaktion verwendet werden.

Tipp: Erfahren Sie mehr über die Struktur einer Transaktion.

Wenn dieser Endpunkt aufgerufen wird, startet der IRI-Node den Auswahlalgorithmus (tip selection algorithm), der in die folgenden Stufen unterteilt ist:

  1. Vorbereitung
  2. Bewertungsberechnung
  3. Gewicht im Random Work

Das Ziel des Algorithmus ist es, zwei nicht im Konflikt stehende Tipptransaktionen als Ergebnis des API-Aufrufs zurückzugeben.

Der Algorithmus wählt einen Untergraphen des Ledgers aus und führt zwei zufällig gewichtete Durchgänge durch. Jeder zufällig gewichtet Durchgang gibt einen Tipp-Transaktionshash zurück.

Auswahl des Untergraphen

Ein Untergraph ist ein Abschnitt des Ledgers, der alle Transaktionen zwischen einer Meilensteintransaktion und Tipptransaktionen enthält.

Die Auswahl der Tipps erfolgt auf einem Subgraph des Ledgers, um Rechenleistung zu sparen. Je mehr Transaktionen der Algorithmus in den gewichteten Random Walk einschließt, desto länger dauert der Auswahlvorgang.

Für den Tippauswahlprozess wird die Meilensteintransaktion für den Subgraph vom Client definiert und wie folgt berechnet:

latestMilestoneIndex - depth

Das Ergebnis dieser Berechnung entspricht dem Index der Meilenstein-Transaktion, die zur Bildung des Untergraphen verwendet wird.

Hinweis: Je höher der Wert des Tiefenparameters ist, desto mehr Berechnungen muss der IRI-Knoten durchführen. Um den Wert des Tiefenparameters einzuschränken, legen Sie die Konfigurationsoption MAX-DEPTH fest.

Eintrittspunkte auswählen

Die gewichteten Random Walk beginnt mit derselben Meilenstein-Transaktion (latestSolidMilestone - Depth).

Wenn der Client ein reference Argument für den API-Aufruf angibt, beginnt der Zweigpfad mit der Transaktion in der reference Argument, wenn es in der Subgraph enthalten ist.

Wenn die Transaktion im reference Argument älter ist als der Meilensteinindex für die depth, schlägt der API-Aufruf mit der folgenden Fehlermeldung fehl: Die Referenztransaktion ist zu alt.

Der Algorithmus berechnet die Bewertung jeder Transaktion im Subgraph. Diese Bewertungen werden anschließend während des gewichteten zufälligen Gehens in Gewichte umgewandelt, um den Pfad des Wanderers zu beeinflussen.

Die Ratingberechnung wird nur einmal ausgeführt und zur Auswahl beider Tipptransaktionen verwendet.

Schnittstelle

Damit Sie verschiedene Bewertungsalgorithmen erstellen können, haben wir eine generische Schnittstelle erstellt, an die sich jeder Bewertungsrechner halten sollte.

Map calculate(TxId entryPoint)

Jeder Bewertungsrechner wird mit einem entryPoint aufgerufen Transaktion, sollte eine Abbildung von Transaktions-IDs zurückgeben, deren zugehöriger Bewertungswert als ganze Zahlen ausgedrückt wird.

Kumulatives Gewicht

Das kumulative Gewicht ist ein Algorithmus, der jeder Transaktion eine Bewertung gibt, die der Anzahl der Transaktionen entspricht, die direkt oder indirekt auf sie verweisen. Diese Transaktionen werden als zukünftiger Satz bezeichnet.

Um die Berechnung durchzuführen, wird der Subgraph zuerst in topologischer Reihenfolge sortiert. Wenn also Transaktion A Transaktion B genehmigt, kommt Transaktion B vor Transaktion A und belässt die Tip-Transaktionen am Ende des Untergraphen.

Für jede in unserem sortierten Subgraph enthaltene Transaktion wird ein zukünftiger Satz erstellt, der direkte und indirekte Genehmiger enthält. Die Bewertung jeder Transaktion ist die Größe ihrer zukünftigen Menge 1 (das eigene Gewicht der Transaktion).

entryPoint = latestSolidMilestone - depth

entryPointTrunk = entryPoint

entryPointBranch = reference or entryPoint

ratings = CumulativeWeightCalculator.calculate(entryPointTrunk)

class CumulativeWeightCalculator(RatingCalculator):

    def calculate(startTx):

        rating = dict()

        subgraph = Tangle(startTx)

        topologicalSubgraph = sortTopologically(subgraph)

        for tx in topologicalSubgraph:

            rating[tx] = len(futureSet(tx))   1

        return rating

Optimierungen

  • Um beim Speichern der Transaktionsbezeichner Speicherplatz zu sparen, speichern wir nur einen Teil der Hash-Bytes der Transaktion und verkürzen ihn auf die Länge von PREFIX_LENGTH. Derzeit ist dieser Wert mit 44 Bytes fest codiert, was 220 Tricks entspricht.
  • Um den Speicherverbrauch des Algorithmus zu begrenzen, können wir für die von uns betrachtete Transaktion bis zu MAX_FUTURE_SET_SIZE Anzahl der Genehmigenden speichern, unter der Annahme, dass eine höhere Bewertung nicht wesentlich zur Beeinflussung des Gehers beiträgt. Dieser Wert wurde heuristisch auf 5000 hartcodiert. Beachten Sie, dass diese Optimierung den Arbeitsspeicher während der Laufzeit begrenzt und den Beginn des betrachteten Untergraphen zufälliger verhält, da die zukünftigen Mengen dieser Transaktionen mit höherer Wahrscheinlichkeit begrenzt werden zu MAX_FUTURE_SET_SIZE. Das erwünschte Verhalten ist vielmehr das Gegenteil: Wir möchten, dass der Beginn der Wanderung stark in Richtung des Hauptastes geneigt ist, während er zufällig näher an den Spitzen ist und die Chance für jeden von ihnen zur Auswahl bietet.

Nachdem die Bewertungen der Transaktionen berechnet wurden, beginnt der gewichtete zufällige Gang.

Schnittstelle

Damit Sie unterschiedliche gewichtete Random-Walk-Algorithmen erstellen können, haben wir eine generische Schnittstelle entwickelt, an die sich jede Implementierung halten sollte.

TxId walk(TxId entryPoint, Map Integer> ratings, WalkValidator validator)

Diese Funktion sollte die ausgewählte Tipptransaktion zurückgeben.

WalkerAlpha-Implementierung

Der WalkerAlpha ist ein Random-Walker-Algorithmus, der einen Subgraph in Richtung der Tip-Transaktionen durchläuft. Die Zufälligkeit des Algorithmus kann mit der alpha Konfigurationsoption eingestellt werden.

Ein alpha = 0 Faktor macht den Lauf rein zufällig: Die Bewertung einer Transaktion beeinflusst den Lauf in keiner Weise. Ein alpha = ∞ Faktor hingegen führt den Weg in Richtung der am höchsten bewerteten Transaktion.

Zusammenfassend gilt: Je höher der alpha Faktor ist, desto wahrscheinlicher ist es, dass eine Transaktion mit hohem Rating als nächster Schritt ausgewählt wird. Die Suche nach einem idealen Wert für den alpha Faktor ist immer noch ein Forschungsthema. Weitere Informationen finden Sie in diesem Blog-Post.

Ausgehend von einem bestimmten Einstiegspunkt geht der Algorithmus in Richtung der Tip-Transaktionen, indem er bei jedem Schritt einen einzelnen Genehmiger auswählt. Die Wahl des zu verwendenden Pfads hängt von der Bewertung der Genehmigenden-Transaktion ab.

Bei jedem Schritt wird die Konsistenz des Ledger-Status mit dem Prüferobjekt geprüft. Jeder Schritt sollte ein Bündel bis zum Ende durchlaufen, da die Konsistenz sonst nicht überprüft werden konnte. Beim Erreichen eines inkonsistenten Zustands macht der Spaziergänger den gerade durchgeführten Schritt ungültig, kehrt zum vorherigen Schwanz zurück und führt die Auswahl des Genehmigers erneut aus.

Die Wahrscheinlichkeit, zu einem bestimmten Genehmigenden zu gehen, wird mit der folgenden Formel berechnet, wobei H das Gewicht einer bestimmten Transaktion ist.

Mit Hilfe der alpha Konfigurationsoption werden Ratings normalisiert und in weights umgewandelt. Schließlich wird ein random Wert zwischen 0 und der Summe aller Gewichtungen generiert und von den Gewichten der Genehmigenden subtrahiert, bis der Wert 0 erreicht ist. Der Genehmiger, der den random Wert auf 0 gesetzt hat, wird als nächster Schritt des Laufs ausgewählt.

class WalkerAlpha(Walker):

    def walk(entryPoint, ratings, validator):

        step = entryPoint

        prevStep = None

        while step:

            approvers = getApprovers(step)

            prevStep = step

            step = nextStep(ratings, approvers, validator)

        # When there are no more steps, this transaction is a tip

        return prevStep

    def nextStep(ratings, approvers, validator):

        approversWithRating = approvers.filter(a => ratings.contains(a))

        # There is no valid approver, this transaction is a tip

        if len(approversWithRating) == 0:

            return None

        approversRatings = approverswithRating.map(a => ratings.get(a))

        weights = ratingsToWeights(approversRatings)

        approver = weightedChoice(approversWithRating, weights)

        if approver is not None:

            tail = validator.findTail(approver)

            # If the selected approver is invalid, step back and try again

            if validator.isInvalid(tail):

                approvers = approvers.remove(approver)

                return nextStep(ratings, approvers, validator)

            return tail

        return None

    def weightedChoice(approvers, weights):

        randomNumber = random(0, sum(weights))

        for approver in approvers:

            randomNumber = randomNumber - weights.get(approver)

            if randomNumber <= 0:

                return approver

    def ratingsToWeights(ratings):

        highestRating = max(ratings)

        normalizedRatings = ratings.map(r => r - highestRating)

        weights = normalizedRatings.map(r => math.exp(r * alpha))

        return weights

Validator-Bedingungen

Eine Transaktion gilt als ungültig, wenn eine der folgenden Bedingungen eintritt:

  • Es ist nicht solide und wir können seinen Zustand nicht rekonstruieren, da ein Teil der Verwicklungen dieser Transaktionsreferenzen unbekannt ist.
  • Sie referenziert eine Transaktion zu weit in der Vergangenheit, und zwar jenseits von latestSolidMilestone - maxDepth.
  • Der daraus berechnete Ledger-Status ist nicht konsistent, wie der Versuch, fehlende Mittel auszugeben oder doppelte Ausgaben zu tätigen.
  • Der Prüfer führt eine Liste von Transaktionen, die auf Gültigkeit geprüft wurden. Bei jeder Validierung einer neuen Transaktion wird auch diese geprüft.
class WalkValidator:

    previousTransactions = []

    def isInvalid(transaction):

        previousTransactions.append(transaction)

        if notSolid(transaction):

            return True

        if belowMaxDepth(transaction):

            return True

        if inconsistent(transaction):

            return True

        if inconsistentWithPreviousTransactions(transaction):

            return True

        return False

Hinweis: Das gleiche Prüferobjekt wird für beide Durchgänge übergeben, sodass zwei miteinander übereinstimmende Tipptransaktionen erhalten werden.

Bündel und Konsistenz

Transaktionen in IOTA werden in Paketen gesendet. Wenn der Spaziergänger einen Genehmiger durchquert, befindet sich dieser Genehmiger möglicherweise in der Mitte eines Bündels. Um das Bündel zu validieren, findet der Walker die Endtransaktion, indem er die Trunk-Transaktionen durchläuft.

Die beiden Tip-Transaktionen werden auf Konsistenz geprüft, um sicherzustellen, dass keine der beiden ungültig ist. Daher bezieht sich die Transaktion des Kunden auf zwei gültige Transaktionen, die eine bessere Chance haben, von einer anderen Transaktion genehmigt zu werden, wodurch das kumulative Gewicht erhöht wird.


Anmerkung:

Der Inhalt kann durch die Übersetzung verfälscht sein. Im Zweifel gilt das englische Original von der IOTA Foundation (Quelle).

Quelle: https://docs.iota.org/docs/the-tangle/0.1/concepts/tip-selection

Auswahl des Untergraphen

Ein Untergraph ist ein Abschnitt des Ledgers, der alle Transaktionen zwischen einer Meilensteintransaktion und Tipptransaktionen enthält.

Die Auswahl der Tipps erfolgt auf einem Subgraph des Ledgers, um Rechenleistung zu sparen. Je mehr Transaktionen der Algorithmus in den gewichteten Random Walk einschließt, desto länger dauert der Auswahlvorgang.

Für den Tippauswahlprozess wird die Meilensteintransaktion für den Subgraph vom Client definiert und wie folgt berechnet:

latestMilestoneIndex - depth

Das Ergebnis dieser Berechnung entspricht dem Index der Meilenstein-Transaktion, die zur Bildung des Untergraphen verwendet wird.

Hinweis: Je höher der Wert des Tiefenparameters ist, desto mehr Berechnungen muss der IRI-Knoten durchführen. Um den Wert des Tiefenparameters einzuschränken, legen Sie die Konfigurationsoption MAX-DEPTH fest.

Eintrittspunkte auswählen

Die gewichteten Random Walk beginnt mit derselben Meilenstein-Transaktion (latestSolidMilestone - Depth).

Wenn der Client ein reference Argument für den API-Aufruf angibt, beginnt der Zweigpfad mit der Transaktion in der reference Argument, wenn es in der Subgraph enthalten ist.

Wenn die Transaktion im reference Argument älter ist als der Meilensteinindex für die depth, schlägt der API-Aufruf mit der folgenden Fehlermeldung fehl: Die Referenztransaktion ist zu alt.

Der Algorithmus berechnet die Bewertung jeder Transaktion im Subgraph. Diese Bewertungen werden anschließend während des gewichteten zufälligen Gehens in Gewichte umgewandelt, um den Pfad des Wanderers zu beeinflussen.

Die Ratingberechnung wird nur einmal ausgeführt und zur Auswahl beider Tipptransaktionen verwendet.

Schnittstelle

Damit Sie verschiedene Bewertungsalgorithmen erstellen können, haben wir eine generische Schnittstelle erstellt, an die sich jeder Bewertungsrechner halten sollte.

Map calculate(TxId entryPoint)

Jeder Bewertungsrechner wird mit einem entryPoint aufgerufen Transaktion, sollte eine Abbildung von Transaktions-IDs zurückgeben, deren zugehöriger Bewertungswert als ganze Zahlen ausgedrückt wird.

Kumulatives Gewicht

Das kumulative Gewicht ist ein Algorithmus, der jeder Transaktion eine Bewertung gibt, die der Anzahl der Transaktionen entspricht, die direkt oder indirekt auf sie verweisen. Diese Transaktionen werden als zukünftiger Satz bezeichnet.

Um die Berechnung durchzuführen, wird der Subgraph zuerst in topologischer Reihenfolge sortiert. Wenn also Transaktion A Transaktion B genehmigt, kommt Transaktion B vor Transaktion A und belässt die Tip-Transaktionen am Ende des Untergraphen.

Für jede in unserem sortierten Subgraph enthaltene Transaktion wird ein zukünftiger Satz erstellt, der direkte und indirekte Genehmiger enthält. Die Bewertung jeder Transaktion ist die Größe ihrer zukünftigen Menge + 1 (das eigene Gewicht der Transaktion).

entryPoint = latestSolidMilestone - depth

entryPointTrunk = entryPoint

entryPointBranch = reference or entryPoint

ratings = CumulativeWeightCalculator.calculate(entryPointTrunk)

class CumulativeWeightCalculator(RatingCalculator):

    def calculate(startTx):

        rating = dict()

        subgraph = Tangle(startTx)

        topologicalSubgraph = sortTopologically(subgraph)

        for tx in topologicalSubgraph:

            rating[tx] = len(futureSet(tx)) + 1

        return rating

Optimierungen

  • Um beim Speichern der Transaktionsbezeichner Speicherplatz zu sparen, speichern wir nur einen Teil der Hash-Bytes der Transaktion und verkürzen ihn auf die Länge von PREFIX_LENGTH. Derzeit ist dieser Wert mit 44 Bytes fest codiert, was 220 Tricks entspricht.
  • Um den Speicherverbrauch des Algorithmus zu begrenzen, können wir für die von uns betrachtete Transaktion bis zu MAX_FUTURE_SET_SIZE Anzahl der Genehmigenden speichern, unter der Annahme, dass eine höhere Bewertung nicht wesentlich zur Beeinflussung des Gehers beiträgt. Dieser Wert wurde heuristisch auf 5000 hartcodiert. Beachten Sie, dass diese Optimierung den Arbeitsspeicher während der Laufzeit begrenzt und den Beginn des betrachteten Untergraphen zufälliger verhält, da die zukünftigen Mengen dieser Transaktionen mit höherer Wahrscheinlichkeit begrenzt werden zu MAX_FUTURE_SET_SIZE. Das erwünschte Verhalten ist vielmehr das Gegenteil: Wir möchten, dass der Beginn der Wanderung stark in Richtung des Hauptastes geneigt ist, während er zufällig näher an den Spitzen ist und die Chance für jeden von ihnen zur Auswahl bietet.

Nachdem die Bewertungen der Transaktionen berechnet wurden, beginnt der gewichtete zufällige Gang.

Schnittstelle

Damit Sie unterschiedliche gewichtete Random-Walk-Algorithmen erstellen können, haben wir eine generische Schnittstelle entwickelt, an die sich jede Implementierung halten sollte.

TxId walk(TxId entryPoint, Map Integer> ratings, WalkValidator validator)

Diese Funktion sollte die ausgewählte Tipptransaktion zurückgeben.

WalkerAlpha-Implementierung

Der WalkerAlpha ist ein Random-Walker-Algorithmus, der einen Subgraph in Richtung der Tip-Transaktionen durchläuft. Die Zufälligkeit des Algorithmus kann mit der alpha Konfigurationsoption eingestellt werden.

Ein alpha = 0 Faktor macht den Lauf rein zufällig: Die Bewertung einer Transaktion beeinflusst den Lauf in keiner Weise. Ein alpha = ∞ Faktor hingegen führt den Weg in Richtung der am höchsten bewerteten Transaktion.

Zusammenfassend gilt: Je höher der alpha Faktor ist, desto wahrscheinlicher ist es, dass eine Transaktion mit hohem Rating als nächster Schritt ausgewählt wird. Die Suche nach einem idealen Wert für den alpha Faktor ist immer noch ein Forschungsthema. Weitere Informationen finden Sie in diesem Blog-Post.

Ausgehend von einem bestimmten Einstiegspunkt geht der Algorithmus in Richtung der Tip-Transaktionen, indem er bei jedem Schritt einen einzelnen Genehmiger auswählt. Die Wahl des zu verwendenden Pfads hängt von der Bewertung der Genehmigenden-Transaktion ab.

Bei jedem Schritt wird die Konsistenz des Ledger-Status mit dem Prüferobjekt geprüft. Jeder Schritt sollte ein Bündel bis zum Ende durchlaufen, da die Konsistenz sonst nicht überprüft werden konnte. Beim Erreichen eines inkonsistenten Zustands macht der Spaziergänger den gerade durchgeführten Schritt ungültig, kehrt zum vorherigen Schwanz zurück und führt die Auswahl des Genehmigers erneut aus.

Die Wahrscheinlichkeit, zu einem bestimmten Genehmigenden zu gehen, wird mit der folgenden Formel berechnet, wobei H das Gewicht einer bestimmten Transaktion ist.

Mit Hilfe der alpha Konfigurationsoption werden Ratings normalisiert und in weights umgewandelt. Schließlich wird ein random Wert zwischen 0 und der Summe aller Gewichtungen generiert und von den Gewichten der Genehmigenden subtrahiert, bis der Wert 0 erreicht ist. Der Genehmiger, der den random Wert auf 0 gesetzt hat, wird als nächster Schritt des Laufs ausgewählt.

class WalkerAlpha(Walker):

    def walk(entryPoint, ratings, validator):

        step = entryPoint

        prevStep = None

        while step:

            approvers = getApprovers(step)

            prevStep = step

            step = nextStep(ratings, approvers, validator)

        # When there are no more steps, this transaction is a tip

        return prevStep

    def nextStep(ratings, approvers, validator):

        approversWithRating = approvers.filter(a => ratings.contains(a))

        # There is no valid approver, this transaction is a tip

        if len(approversWithRating) == 0:

            return None

        approversRatings = approverswithRating.map(a => ratings.get(a))

        weights = ratingsToWeights(approversRatings)

        approver = weightedChoice(approversWithRating, weights)

        if approver is not None:

            tail = validator.findTail(approver)

            # If the selected approver is invalid, step back and try again

            if validator.isInvalid(tail):

                approvers = approvers.remove(approver)

                return nextStep(ratings, approvers, validator)

            return tail

        return None

    def weightedChoice(approvers, weights):

        randomNumber = random(0, sum(weights))

        for approver in approvers:

            randomNumber = randomNumber - weights.get(approver)

            if randomNumber <= 0:

                return approver

    def ratingsToWeights(ratings):

        highestRating = max(ratings)

        normalizedRatings = ratings.map(r => r - highestRating)

        weights = normalizedRatings.map(r => math.exp(r * alpha))

        return weights

Validator-Bedingungen

Eine Transaktion gilt als ungültig, wenn eine der folgenden Bedingungen eintritt:

  • Es ist nicht solide und wir können seinen Zustand nicht rekonstruieren, da ein Teil der Verwicklungen dieser Transaktionsreferenzen unbekannt ist.
  • Sie referenziert eine Transaktion zu weit in der Vergangenheit, und zwar jenseits von latestSolidMilestone - maxDepth.
  • Der daraus berechnete Ledger-Status ist nicht konsistent, wie der Versuch, fehlende Mittel auszugeben oder doppelte Ausgaben zu tätigen.
  • Der Prüfer führt eine Liste von Transaktionen, die auf Gültigkeit geprüft wurden. Bei jeder Validierung einer neuen Transaktion wird auch diese geprüft.
class WalkValidator:

    previousTransactions = []

    def isInvalid(transaction):

        previousTransactions.append(transaction)

        if notSolid(transaction):

            return True

        if belowMaxDepth(transaction):

            return True

        if inconsistent(transaction):

            return True

        if inconsistentWithPreviousTransactions(transaction):

            return True

        return False

Hinweis: Das gleiche Prüferobjekt wird für beide Durchgänge übergeben, sodass zwei miteinander übereinstimmende Tipptransaktionen erhalten werden.

Bündel und Konsistenz

Transaktionen in IOTA werden in Paketen gesendet. Wenn der Spaziergänger einen Genehmiger durchquert, befindet sich dieser Genehmiger möglicherweise in der Mitte eines Bündels. Um das Bündel zu validieren, findet der Walker die Endtransaktion, indem er die Trunk-Transaktionen durchläuft.

Die beiden Tip-Transaktionen werden auf Konsistenz geprüft, um sicherzustellen, dass keine der beiden ungültig ist. Daher bezieht sich die Transaktion des Kunden auf zwei gültige Transaktionen, die eine bessere Chance haben, von einer anderen Transaktion genehmigt zu werden, wodurch das kumulative Gewicht erhöht wird.


Anmerkung:

Der Inhalt kann durch die Übersetzung verfälscht sein. Im Zweifel gilt das englische Original von der IOTA Foundation (Quelle).

Quelle: https://docs.iota.org/docs/the-tangle/0.1/concepts/tip-selection

  • Zuletzt geändert: 2019/02/12 13:51
  • von vrom