65 lines
3.0 KiB
Plaintext
65 lines
3.0 KiB
Plaintext
@startuml
|
|
title Node Initialization — Peer A (InitNode)
|
|
|
|
participant "main (Peer A)" as MainA
|
|
participant "Node A" as NodeA
|
|
participant "libp2p (Peer A)" as libp2pA
|
|
participant "ConnectionGater A" as GaterA
|
|
participant "DB Peer A (oc-lib)" as DBA
|
|
participant "NATS A" as NATSA
|
|
participant "Indexer (shared)" as IndexerA
|
|
participant "DHT A" as DHTA
|
|
participant "StreamService A" as StreamA
|
|
participant "PubSubService A" as PubSubA
|
|
|
|
MainA -> NodeA: InitNode(isNode=true, isIndexer=false)
|
|
|
|
NodeA -> NodeA: LoadKeyFromFilePrivate() → priv
|
|
NodeA -> NodeA: LoadPSKFromFile() → psk
|
|
|
|
NodeA -> GaterA: newOCConnectionGater(nil)
|
|
NodeA -> libp2pA: New(\n PrivateNetwork(psk),\n Identity(priv),\n ListenAddr: tcp/4001,\n ConnectionGater(gater)\n)
|
|
libp2pA --> NodeA: host A (PeerID_A)
|
|
NodeA -> GaterA: gater.host = host A
|
|
|
|
note over GaterA: InterceptSecured (inbound):\n1. DB lookup by peer_id\n → BLACKLIST : refuse\n → found : accept\n2. Not found → DHT sequential check\n (transport-error fallthrough only)
|
|
|
|
NodeA -> libp2pA: SetStreamHandler(/opencloud/probe/1.0, HandleBandwidthProbe)
|
|
NodeA -> libp2pA: SetStreamHandler(/opencloud/witness/1.0, HandleWitnessQuery)
|
|
|
|
NodeA -> libp2pA: NewGossipSub(ctx, host) → ps (GossipSub)
|
|
|
|
NodeA -> NodeA: buildRecord() closure\n→ signs fresh PeerRecord (expiry=now+2min)\n embedded in each heartbeat tick
|
|
|
|
NodeA -> IndexerA: ConnectToIndexers(host, minIndexer=1, maxIndexer=5, buildRecord)
|
|
note over IndexerA: Reads IndexerAddresses from config\nAdds seeds → Indexers Directory (IsSeed=true)\nLaunches SendHeartbeat goroutine (20s ticker)
|
|
|
|
IndexerA -> DHTA: proactive DHT discovery (after 5s warmup)\ninitNodeDHT(h, seeds)\nDiscoverIndexersFromDHT → SelectByFillRate\n→ add to Indexers Directory + NudgeIt()
|
|
|
|
NodeA -> NodeA: claimInfo(name, hostname)
|
|
NodeA -> IndexerA: TempStream /opencloud/record/publish/1.0
|
|
NodeA -> IndexerA: stream.Encode(Signed PeerRecord A)
|
|
IndexerA -> DHTA: PutValue("/node/"+DID_A, record)
|
|
|
|
NodeA -> NodeA: StartGC(30s)
|
|
|
|
NodeA -> StreamA: InitStream(ctx, host, PeerID_A, 1000, nodeA)
|
|
StreamA -> StreamA: SetStreamHandler(resource/search, create, update,\n delete, planner, verify, considers)
|
|
StreamA --> NodeA: StreamService A
|
|
|
|
NodeA -> PubSubA: InitPubSub(ctx, host, ps, nodeA, streamA)
|
|
PubSubA -> PubSubA: subscribeEvents(PB_SEARCH, timeout=-1)
|
|
PubSubA --> NodeA: PubSubService A
|
|
|
|
NodeA -> NodeA: SubscribeToSearch(ps, callback)
|
|
note over NodeA: callback: if evt.From != self\n → GetPeerRecord(evt.From)\n → StreamService.SendResponse
|
|
|
|
NodeA -> NATSA: ListenNATS(nodeA)
|
|
note over NATSA: Subscribes:\nCREATE_RESOURCE → partner on-demand\nPROPALGATION_EVENT → resource propagation
|
|
|
|
NodeA --> MainA: *Node A is ready
|
|
|
|
note over NodeA,IndexerA: SendHeartbeat goroutine (permanent, 20s ticker):\nNode → Indexer : Heartbeat{name, PeerID, indexersBinded, need, challenges?, record}\nIndexer → Node : HeartbeatResponse{fillRate, challenges, suggestions, witnesses, suggestMigrate}\nScore updated (7 dimensions), pool managed autonomously
|
|
|
|
@enduml
|