Inhaltsverzeichnis

std.blockchain.p2p — Blockchain P2P-Netzwerk

std.blockchain.p2p implementiert eine TCP-basierte P2P-Kommunikationsschicht für Blockchain-Knoten. Jeder Knoten kann bis zu 32 Peers verbinden, Transaktionen und Blöcke broadcasten und eingehende Verbindungen akzeptieren.

std.blockchain (Kern) · Standard Library


Protokoll

Binäres Nachrichtenformat: [1 Byte Typ][4 Bytes Länge BE][N Bytes Payload]

Konstante Wert Richtung Bedeutung
BLP2P_MSG_QUERY_LATEST 1 → Peer Letzten Block anfordern
BLP2P_MSG_RESP_LATEST 2 ← Peer Antwort mit letztem Block
BLP2P_MSG_QUERY_CHAIN 3 → Peer Vollständige Kette anfordern (ab Index)
BLP2P_MSG_RESP_CHAIN 4 ← Peer Ketten-Antwort (definiert, nicht implementiert)
BLP2P_MSG_BROADCAST_TX 5 ↔ beide Neue Transaktion verteilen
BLP2P_MSG_BROADCAST_BLOCK 6 ↔ beide Neuen Block verteilen

Wichtig: QUERY_CHAIN (3) wird gesendet wenn die eigene Kette kürzer ist, aber BLP2PHandleIncoming behandelt weder QUERY_CHAIN noch RESP_CHAIN. Chain-Synchronisation ist daher noch nicht vollständig implementiert.

Weitere Konstanten:

Konstante Wert Bedeutung
BLP2P_MAX_PEERS 32 Maximale gleichzeitige Peer-Verbindungen
BLP2P_MSG_HDR_LEN 5 Header-Größe: 1 Typ + 4 Länge

Node-Struktur (40 Bytes)

Offset Feld Beschreibung
0 bc Zeiger auf die zugehörige Blockchain (aus std.blockchain)
8 listenPort TCP-Port zum Lauschen
16 serverFd Server-Socket-Deskriptor; -1 wenn nicht gestartet
24 peerCount Anzahl aktiver Peer-Verbindungen
32 peerFds Zeiger auf Array mit 32 × int64 Socket-FDs (-1 = freier Slot)

Offset-Konstanten: BLP2P_NODE_BC (0), BLP2P_NODE_PORT (8), BLP2P_NODE_SERVER_FD (16), BLP2P_NODE_PEER_COUNT (24), BLP2P_NODE_PEER_FDS (32), BLP2P_NODE_SIZE (40)


Öffentliche API

Node-Lebenszyklus

Funktion Rückgabe Beschreibung
BLP2PNodeNew(bc, port) int64 Node-Ptr Erstellt P2P-Knoten; alle Peer-Slots auf -1 initialisiert
BLP2PNodeFree(node) void Schließt alle Verbindungen und gibt Node frei
BLP2PNodeStart(node) int64 1/0 Bindet Socket, startet Lauschen; setzt SO_REUSEADDR; 1 = OK
BLP2PNodeStop(node) void Schließt Server-Socket (Peer-Verbindungen bleiben offen)

Verbindungen

Funktion Rückgabe Beschreibung
BLP2PConnectPeer(node, ip, port) int64 1/0 Verbindet zu Peer; ip als int64 (4 Bytes big-endian); sendet sofort QUERY_LATEST; 0 wenn kein freier Slot
BLP2PPoll(node) int64 1/0 Akzeptiert eine neue eingehende Verbindung; sendet RESP_LATEST an neuen Peer

Achtung: BLP2PPoll verwendet blockierendes accept trotz des Namens. Es wartet auf eine neue Verbindung und kehrt nicht sofort zurück wenn keine anliegt. Für nicht-blockierende Nutzung muss der Server-FD vorab auf non-blocking gesetzt werden.

Nachrichtenverarbeitung

Funktion Rückgabe Beschreibung
BLP2PHandleIncoming(node, fd) int64 1/0 Liest und verarbeitet eine Nachricht vom angegebenen FD; 0 = Verbindung getrennt
BLP2PBroadcastTx(node, tx) void Serialisiert TX und sendet ihn an alle Peers
BLP2PBroadcastBlock(node, block) void Serialisiert Block und sendet ihn an alle Peers

BLP2PHandleIncoming behandelt:

Block-Empfang (BROADCAST_BLOCK)

Situation Aktion
index == lastIdx + 1 und Hash + PoW gültig Block an Kette anhängen, Ledger aktualisieren, Block rebroadcasten
index > lastIdx + 1 (eigene Kette kürzer) QUERY_CHAIN senden (Antwort wird nicht verarbeitet — bekannte Einschränkung)
index ≤ lastIdx Block verwerfen

Deserializer

Die Deserializer-Funktionen werden intern von BLP2PHandleIncoming genutzt, sind aber auch öffentlich für eigene Protokoll-Erweiterungen.

Funktion Rückgabe Beschreibung
BLDeserializeInt32(buf, off) int64 Liest 4-Byte big-endian ab Offset off
BLDeserializeInt64(buf, off) int64 Liest 8-Byte big-endian ab Offset off
BLDeserializeTx(buf, off, outPtr) int64 neuer Offset Deserialisiert TX aus buf ab off; schreibt allokierten TX-Ptr nach outPtr[0]; gibt neuen Offset zurück

BLDeserializeTx allokiert intern einen neuen TX (224 Bytes). Der Aufrufer muss den TX freigeben wenn er nicht via BLAddTransaction an den Mempool übergeben wird.


IP-Adresse übergeben

BLP2PConnectPeer erwartet die IPv4-Adresse als int64 (4 Bytes, big-endian):

// 192.168.1.100 → (192 << 24) | (168 << 16) | (1 << 8) | 100
var ip: int64 := (192 << 24) | (168 << 16) | (1 << 8) | 100;
BLP2PConnectPeer(node, ip, 9000);


Vollständiges Beispiel

import std.blockchain;
import std.blockchain.p2p;
import std.alloc;
import std.io;

fn main(): int64 {
    // Blockchain erstellen
    var bc: int64 := BLBlockchainNew(1, 50000000, 10);

    // P2P-Knoten auf Port 9000 starten
    var node: int64 := BLP2PNodeNew(bc, 9000);
    if BLP2PNodeStart(node) == 0 then {
        PrintLn("Fehler: Port 9000 belegt"c);
        BLP2PNodeFree(node);
        BLBlockchainFree(bc);
        return 1;
    }

    PrintLn("P2P-Knoten lauscht auf Port 9000"c);

    // Zu einem bekannten Peer verbinden: 192.168.1.50:9000
    var peerIp: int64 := (192 << 24) | (168 << 16) | (1 << 8) | 50;
    if BLP2PConnectPeer(node, peerIp, 9000) == 1 then {
        PrintLn("Verbunden mit 192.168.1.50"c);
    }

    // Hauptschleife (vereinfacht — in echtem Code: epoll/select verwenden)
    var fds: int64 := peek64(node + BLP2P_NODE_PEER_FDS);
    var i: int64 := 0;
    while i < BLP2P_MAX_PEERS do {
        var fd: int64 := peek64(fds + i * 8);
        if fd != (0 - 1) then {
            if BLP2PHandleIncoming(node, fd) == 0 then {
                // Verbindung getrennt — Slot freigeben
                poke64(fds + i * 8, 0 - 1);
            }
        }
        i := i + 1;
    }

    BLP2PNodeStop(node);
    BLP2PNodeFree(node);
    BLBlockchainFree(bc);
    return 0;
}


Einschränkungen

Einschränkung Details
Blockierendes accept BLP2PPoll wartet auf neue Verbindungen — nicht für Event-Loop ohne epoll geeignet
Chain-Sync unvollständig QUERY_CHAIN wird gesendet, RESP_CHAIN nicht verarbeitet — kein vollständiger Catch-up möglich
Max. 32 Peers Feste Obergrenze — kein dynamisches Wachstum
Kein Peer-Discovery Peer-Adressen müssen manuell via BLP2PConnectPeer eingetragen werden
Kein Timeout Hängende Verbindungen blockieren BLP2PHandleIncoming
Nur IPv4 Kein IPv6-Support

Letzte Aktualisierung: 2026-06-13