Documentation
¶
Index ¶
- Constants
- type DB
- type FlatTable
- func (t *FlatTable) ActiveSize() int
- func (t *FlatTable) Add(n *node.Node) bool
- func (t *FlatTable) CanAddNodeByIP(n *node.Node) bool
- func (t *FlatTable) FindClosestNodes(target node.ID, k int) []*node.Node
- func (t *FlatTable) Get(nodeID node.ID) *node.Node
- func (t *FlatTable) GetActiveNodes() []*node.Node
- func (t *FlatTable) GetBucketNodes(bucketIndex int) []*node.Node
- func (t *FlatTable) GetNodesByDistance(targetID node.ID, distances []uint, k int) []*node.Node
- func (t *FlatTable) GetNodesNeedingPing() []*node.Node
- func (t *FlatTable) GetRandomActiveNodes(k int) []*node.Node
- func (t *FlatTable) GetStats() TableStats
- func (t *FlatTable) LoadInitialNodesFromDB() error
- func (t *FlatTable) NumBucketsFilled() int
- func (t *FlatTable) PerformSweep()
- func (t *FlatTable) SetForkScoringInfo(info *node.ForkScoringInfo)
- func (t *FlatTable) Size() int
- type FlatTableConfig
- type IPLimiter
- type IPStats
- type NodeChangedCallback
- type TableStats
Constants ¶
const ( // DefaultMaxActiveNodes is the maximum number of nodes to keep in the active state DefaultMaxActiveNodes = 500 // DefaultPingRate is the maximum number of pings per minute DefaultPingRate = 400 // DefaultSweepPercent is the percentage of active nodes to rotate during sweep DefaultSweepPercent = 10 )
FlatTable configuration constants
const ( RejectionIPLimit uint8 = 0x01 RejectionAdmission uint8 = 0x02 )
Rejection reason flags
const DefaultMaxFailures = 3
DefaultMaxFailures is the maximum consecutive failures before considering a node dead.
const DefaultMaxNodeAge = 24 * time.Hour
DefaultMaxNodeAge is the maximum time since last seen before considering a node dead.
const DefaultMaxNodesPerIP = 10
DefaultMaxNodesPerIP is the default maximum nodes per IP address.
const DefaultPingInterval = 30 * time.Second
DefaultPingInterval is how often we PING nodes to check liveness.
const RejectionLogTTL = 12 * time.Hour
RejectionLogTTL is how long we remember that we logged a rejection for a node.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type DB ¶
type DB interface {
StoreRejection(id node.ID, reason uint8, timestamp time.Time) error
LoadRejection(id node.ID) (flags uint8, timestamp time.Time, found bool, err error)
ExpireRejections(ttl time.Duration) (int, error)
}
DB is the interface for node database that supports rejection tracking.
type FlatTable ¶
type FlatTable struct {
// contains filtered or unexported fields
}
FlatTable is a flat node storage with capped active nodes.
Unlike the bucket-based Kademlia table, this maintains:
- All nodes in DB (active and inactive)
- Capped active nodes in memory (max 500)
- Distributed ping scheduling
- Periodic active/inactive rotation
func NewFlatTable ¶
func NewFlatTable(cfg FlatTableConfig) (*FlatTable, error)
NewFlatTable creates a new flat node table.
func (*FlatTable) ActiveSize ¶
ActiveSize returns the number of active nodes.
func (*FlatTable) Add ¶
Add adds a node to the active pool.
This method handles adding nodes to the active in-memory pool with the following strategy: - For nodes that already exist in active pool: updates ENR if newer. - For new nodes: adds to active pool even if over capacity (up to hard limit). - Hard limit: 2x maxActiveNodes. If reached, triggers immediate sweep. - IP limiter is still enforced.
This allows newly discovered nodes (which may not be working) to be added without rejecting them immediately. The next sweep will clean up excess nodes.
DB writes must be handled by caller.
func (*FlatTable) CanAddNodeByIP ¶
CanAddNodeByIP checks if we can add a node based on IP limits. This checks against all nodes (active + inactive) in the DB.
func (*FlatTable) FindClosestNodes ¶
FindClosestNodes finds the k closest active nodes to the target ID.
func (*FlatTable) Get ¶
Get retrieves a node by ID. First checks active nodes, then falls back to DB.
func (*FlatTable) GetActiveNodes ¶
GetActiveNodes returns a copy of all active nodes.
func (*FlatTable) GetBucketNodes ¶
GetBucketNodes is kept for compatibility but returns empty for flat table.
func (*FlatTable) GetNodesByDistance ¶
GetNodesByDistance returns nodes at specific distances with score-weighted random selection.
For each requested distance, it finds all matching nodes and selects up to k nodes with probability weighted by their score (RTT, success rate, fork compatibility).
This ensures:
- Different results on each call (randomized)
- Better nodes are returned more frequently (score-weighted)
- Specific distances are respected
func (*FlatTable) GetNodesNeedingPing ¶
GetNodesNeedingPing returns active nodes that need a PING check.
This implements distributed ping scheduling by limiting the number of nodes returned.
func (*FlatTable) GetRandomActiveNodes ¶
GetRandomActiveNodes returns up to k random active nodes.
func (*FlatTable) GetStats ¶
func (t *FlatTable) GetStats() TableStats
GetStats returns statistics about the table.
func (*FlatTable) LoadInitialNodesFromDB ¶
LoadInitialNodesFromDB loads random nodes from DB into the active pool.
func (*FlatTable) NumBucketsFilled ¶
NumBucketsFilled returns a compatibility value for the flat table. Since we don't have buckets, we return 1 if we have any active nodes, 0 otherwise.
func (*FlatTable) PerformSweep ¶
func (t *FlatTable) PerformSweep()
PerformSweep rotates nodes between active and inactive pools.
This should be called periodically (e.g., every 10 minutes). Only demotes nodes when over capacity. When at or under capacity, nodes are kept to allow newly discovered nodes to be tested before being demoted. Loads inactive nodes from DB and tries to promote them to fill available slots.
func (*FlatTable) SetForkScoringInfo ¶
func (t *FlatTable) SetForkScoringInfo(info *node.ForkScoringInfo)
SetForkScoringInfo updates the fork scoring information used for node ranking. This should be called periodically to reflect fork changes.
type FlatTableConfig ¶
type FlatTableConfig struct {
// LocalID is our node ID
LocalID node.ID
// DB is the primary node storage
DB *nodedb.NodeDB
// MaxActiveNodes is the maximum number of active nodes (default 500)
MaxActiveNodes int
// MaxNodesPerIP is the maximum nodes allowed per IP address
MaxNodesPerIP int
// PingInterval is how often to ping nodes
PingInterval time.Duration
// PingRate is maximum pings per minute (default 400)
PingRate int
// MaxNodeAge is the maximum time since last seen
MaxNodeAge time.Duration
// MaxFailures is the maximum consecutive failures
MaxFailures int
// SweepPercent is percentage of nodes to rotate during sweep (default 10%)
SweepPercent int
// NodeChangedCallback is called when a node is added or updated
NodeChangedCallback NodeChangedCallback
// Logger for debug messages
Logger logrus.FieldLogger
}
FlatTableConfig contains configuration for the flat table.
type IPLimiter ¶
type IPLimiter struct {
// contains filtered or unexported fields
}
IPLimiter tracks and enforces per-IP node limits.
This prevents sybil attacks where an attacker tries to fill the routing table with many nodes from the same IP address.
func NewIPLimiter ¶
NewIPLimiter creates a new IP limiter.
Parameters:
- maxNodesPerIP: Maximum nodes allowed per IP (0 = unlimited)
func (*IPLimiter) Add ¶
Add registers a node with the IP limiter.
This should be called when a node is added to the routing table. Returns false if the IP limit is exceeded.
func (*IPLimiter) CanAdd ¶
CanAdd checks if a node can be added without exceeding IP limits.
Returns true if the node can be added, false if the IP limit is exceeded.
func (*IPLimiter) GetNodeCountForIP ¶
GetNodeCountForIP returns the number of nodes for a given IP.
func (*IPLimiter) GetTotalRejections ¶
GetTotalRejections returns the total number of rejected nodes due to IP limits.
type IPStats ¶
type IPStats struct {
UniqueIPs int
TotalNodes int
MaxNodesPerIP int
Rejections int
IPDistribution map[string]int // IP -> node count
}
GetStats returns statistics about IP usage.
type NodeChangedCallback ¶
NodeChangedCallback is called when a node is added or updated in the table.