network

package
v0.0.0-...-b78b3a4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 16, 2019 License: GPL-3.0 Imports: 19 Imported by: 0

README

Streaming

Streaming is a new protocol of the swarm bzz bundle of protocols. This protocol provides the basic logic for chunk-based data flow. It implements simple retrieve requests and delivery using priority queue. A data exchange stream is a directional flow of chunks between peers. The source of datachunks is the upstream, the receiver is called the downstream peer. Each streaming protocol defines an outgoing streamer and an incoming streamer, the former installing on the upstream, the latter on the downstream peer.

Subscribe on StreamerPeer launches an incoming streamer that sends a subscribe msg upstream. The streamer on the upstream peer handles the subscribe msg by installing the relevant outgoing streamer . The modules now engage in a process of upstream sending a sequence of hashes of chunks downstream (OfferedHashesMsg). The downstream peer evaluates which hashes are needed and get it delivered by sending back a msg (WantedHashesMsg).

Historical syncing is supported - currently not the right abstraction -- state kept across sessions by saving a series of intervals after their last batch actually arrived.

Live streaming is also supported, by starting session from the first item after the subscription.

Provable data exchange. In case a stream represents a swarm document's data layer or higher level chunks, streaming up to a certain index is always provable. It saves on sending intermediate chunks.

Using the streamer logic, various stream types are easy to implement:

  • light node requests:
    • url lookup with offset
    • document download
    • document upload
  • syncing
    • live session syncing
    • historical syncing
  • simple retrieve requests and deliveries
  • mutable resource updates streams
  • receipting for finger pointing

Syncing

Syncing is the process that makes sure storer nodes end up storing all and only the chunks that are requested from them.

Requirements

  • eventual consistency: so each chunk historical should be syncable
  • since the same chunk can and will arrive from many peers, (network traffic should be optimised, only one transfer of data per chunk)
  • explicit request deliveries should be prioritised higher than recent chunks received during the ongoing session which in turn should be higher than historical chunks.
  • insured chunks should get receipted for finger pointing litigation, the receipts storage should be organised efficiently, upstream peer should also be able to find these receipts for a deleted chunk easily to refute their challenge.
  • syncing should be resilient to cut connections, metadata should be persisted that keep track of syncing state across sessions, historical syncing state should survive restart
  • extra data structures to support syncing should be kept at minimum
  • syncing is organized separately for chunk types (resource update v content chunk)
  • various types of streams should have common logic abstracted

Syncing is now entirely mediated by the localstore, ie., no processes or memory leaks due to network contention. When a new chunk is stored, its chunk hash is index by proximity bin

peers syncronise by getting the chunks closer to the downstream peer than to the upstream one. Consequently peers just sync all stored items for the kad bin the receiving peer falls into. The special case of nearest neighbour sets is handled by the downstream peer indicating they want to sync all kademlia bins with proximity equal to or higher than their depth.

This sync state represents the initial state of a sync connection session. Retrieval is dictated by downstream peers simply using a special streamer protocol.

Syncing chunks created during the session by the upstream peer is called live session syncing while syncing of earlier chunks is historical syncing.

Once the relevant chunk is retrieved, downstream peer looks up all hash segments in its localstore and sends to the upstream peer a message with a a bitvector to indicate missing chunks (e.g., for chunk k, hash with chunk internal index which case ) new items. In turn upstream peer sends the relevant chunk data alongside their index.

On sending chunks there is a priority queue system. If during looking up hashes in its localstore, downstream peer hits on an open request then a retrieve request is sent immediately to the upstream peer indicating that no extra round of checks is needed. If another peers syncer hits the same open request, it is slightly unsafe to not ask that peer too: if the first one disconnects before delivering or fails to deliver and therefore gets disconnected, we should still be able to continue with the other. The minimum redundant traffic coming from such simultaneous eventualities should be sufficiently rare not to warrant more complex treatment.

Session syncing involves downstream peer to request a new state on a bin from upstream. using the new state, the range (of chunks) between the previous state and the new one are retrieved and chunks are requested identical to the historical case. After receiving all the missing chunks from the new hashes, downstream peer will request a new range. If this happens before upstream peer updates a new state, we say that session syncing is live or the two peers are in sync. In general the time interval passed since downstream peer request up to the current session cursor is a good indication of a permanent (probably increasing) lag.

If there is no historical backlog, and downstream peer has an acceptable 'last synced' tag, then it is said to be fully synced with the upstream peer. If a peer is fully synced with all its storer peers, it can advertise itself as globally fully synced.

The downstream peer persists the record of the last synced offset. When the two peers disconnect and reconnect syncing can start from there. This situation however can also happen while historical syncing is not yet complete. Effectively this means that the peer needs to persist a record of an arbitrary array of offset ranges covered.

Delivery requests

once the appropriate ranges of the hashstream are retrieved and buffered, downstream peer just scans the hashes, looks them up in localstore, if not found, create a request entry. The range is referenced by the chunk index. Alongside the name (indicating the stream, e.g., content chunks for bin 6) and the range downstream peer sends a 128 long bitvector indicating which chunks are needed. Newly created requests are satisfied bound together in a waitgroup which when done, will promptt sending the next one. to be able to do check and storage concurrently, we keep a buffer of one, we start with two batches of hashes. If there is nothing to give, upstream peers SetNextBatch is blocking. Subscription ends with an unsubscribe. which removes the syncer from the map.

Canceling requests (for instance the late chunks of an erasure batch) should be a chan closed on the request

Simple request is also a subscribe different streaming protocols are different p2p protocols with same message types. the constructor is the Run function itself. which takes a streamerpeer as argument

provable streams

The swarm hash over the hash stream has many advantages. It implements a provable data transfer and provide efficient storage for receipts in the form of inclusion proofs useable for finger pointing litigation. When challenged on a missing chunk, upstream peer will provide an inclusion proof of a chunk hash against the state of the sync stream. In order to be able to generate such an inclusion proof, upstream peer needs to store the hash index (counting consecutive hash-size segments) alongside the chunk data and preserve it even when the chunk data is deleted until the chunk is no longer insured. if there is no valid insurance on the files the entry may be deleted. As long as the chunk is preserved, no takeover proof will be needed since the node can respond to any challenge. However, once the node needs to delete an insured chunk for capacity reasons, a receipt should be available to refute the challenge by finger pointing to a downstream peer. As part of the deletion protocol then, hashes of insured chunks to be removed are pushed to an infinite stream for every bin.

Downstream peer on the other hand needs to make sure that they can only be finger pointed about a chunk they did receive and store. For this the check of a state should be exhaustive. If historical syncing finishes on one state, all hashes before are covered, no surprises. In other words historical syncing this process is self verifying. With session syncing however, it is not enough to check going back covering the range from old offset to new. Continuity (i.e., that the new state is extension of the old) needs to be verified: after downstream peer reads the range into a buffer, it appends the buffer the last known state at the last known offset and verifies the resulting hash matches the latest state. Past intervals of historical syncing are checked via the the session root. Upstream peer signs the states, downstream peers can use as handover proofs. Downstream peers sign off on a state together with an initial offset.

Once historical syncing is complete and the session does not lag, downstream peer only preserves the latest upstream state and store the signed version.

Upstream peer needs to keep the latest takeover states: each deleted chunk's hash should be covered by takeover proof of at least one peer. If historical syncing is complete, upstream peer typically will store only the latest takeover proof from downstream peer. Crucially, the structure is totally independent of the number of peers in the bin, so it scales extremely well.

implementation

The simplest protocol just involves upstream peer to prefix the key with the kademlia proximity order (say 0-15 or 0-31) and simply iterate on index per bin when syncing with a peer.

priority queues are used for sending chunks so that user triggered requests should be responded to first, session syncing second, and historical with lower priority. The request on chunks remains implemented as a dataless entry in the memory store. The lifecycle of this object should be more carefully thought through, ie., when it fails to retrieve it should be removed.

Documentation

Index

Constants

View Source
const (
	DefaultNetworkID = 3
	//protocolmaxmsgsize允许的最大消息大小
	ProtocolMaxMsgSize = 10 * 1024 * 1024
)

Variables

View Source
var BzzSpec = &protocols.Spec{
	Name:       "bzz",
	Version:    6,
	MaxMsgSize: 10 * 1024 * 1024,
	Messages: []interface{}{
		HandshakeMsg{},
	},
}

bzzspec是通用群握手的规范

View Source
var DiscoverySpec = &protocols.Spec{
	Name:       "hive",
	Version:    5,
	MaxMsgSize: 10 * 1024 * 1024,
	Messages: []interface{}{
		peersMsg{},
		subPeersMsg{},
	},
}

discovery spec是bzz discovery子协议的规范

Functions

func Label

func Label(e *entry) string

label是调试条目的短标记

func LogAddrs

func LogAddrs(nns [][]byte) string

func NewNodeIDFromAddr

func NewNodeIDFromAddr(addr Addr) discover.NodeID

newnodeidfromaddr将底层地址转换为adapters.nodeid

func NewPeerPotMap

func NewPeerPotMap(kadMinProxSize int, addrs [][]byte) map[string]*PeerPot

newpeerpotmap用键创建overlayaddr的pot记录的映射 作为地址的十六进制表示。

func NotifyDepth

func NotifyDepth(depth uint8, h Overlay)

func NotifyPeer

func NotifyPeer(p OverlayAddr, k Overlay)

func ToOverlayAddr

func ToOverlayAddr(id []byte) []byte

ToOverlayAddr从字节片创建覆盖地址

Types

type Addr

type Addr interface {
	OverlayPeer
	Over() []byte
	Under() []byte
	String() string
	Update(OverlayAddr) OverlayAddr
}

对等池所需的addr接口

type Bzz

type Bzz struct {
	*Hive
	NetworkID uint64
	LightNode bool
	// contains filtered or unexported fields
}

bzz是swarm协议包

func NewBzz

func NewBzz(config *BzzConfig, kad Overlay, store state.Store, streamerSpec *protocols.Spec, streamerRun func(*BzzPeer) error) *Bzz

Newzz是Swarm协议的构造者 争论 *BZZ配置 *覆盖驱动程序 *对等存储

func (*Bzz) APIs

func (b *Bzz) APIs() []rpc.API

API返回BZZ提供的API *蜂箱 bzz实现node.service接口

func (*Bzz) GetHandshake

func (b *Bzz) GetHandshake(peerID discover.NodeID) (*HandshakeMsg, bool)

gethandshake返回peerid远程对等机发送的bzz handshake

func (*Bzz) NodeInfo

func (b *Bzz) NodeInfo() interface{}

nodeinfo返回节点的覆盖地址

func (*Bzz) Protocols

func (b *Bzz) Protocols() []p2p.Protocol

协议返回Swarm提供的协议 bzz实现node.service接口 *握手/蜂窝 *发现

func (*Bzz) RunProtocol

func (b *Bzz) RunProtocol(spec *protocols.Spec, run func(*BzzPeer) error) func(*p2p.Peer, p2p.MsgReadWriter) error

runprotocol是swarm子协议的包装器 返回可分配给p2p.protocol run字段的p2p协议运行函数。 争论: *P2P协议规范 *以bzzpeer为参数运行函数 此运行函数用于在协议会话期间阻塞 返回时,会话终止,对等端断开连接。 协议等待BZZ握手被协商 bzzpeer上的覆盖地址是通过远程握手设置的。

func (*Bzz) UpdateLocalAddr

func (b *Bzz) UpdateLocalAddr(byteaddr []byte) *BzzAddr

updateLocalAddr更新正在运行的节点的参考底图地址

type BzzAddr

type BzzAddr struct {
	OAddr []byte
	UAddr []byte
}

bzzaddr实现peeraddr接口

func NewAddrFromNodeID

func NewAddrFromNodeID(id discover.NodeID) *BzzAddr

newAddrFromNodeID从discover.nodeID构造BzzAddr 覆盖地址是作为nodeid的散列派生的。

func NewAddrFromNodeIDAndPort

func NewAddrFromNodeIDAndPort(id discover.NodeID, host net.IP, port uint16) *BzzAddr

newaddrFromNodeAndPort从discover.nodeid和端口uint16构造bzzaddr 覆盖地址是作为nodeid的散列派生的。

func RandomAddr

func RandomAddr() *BzzAddr

randomaddr是从公钥生成地址的实用方法

func ToAddr

func ToAddr(pa OverlayPeer) *BzzAddr

func (*BzzAddr) Address

func (a *BzzAddr) Address() []byte

地址实现覆盖中要使用的覆盖对等接口

func (*BzzAddr) ID

func (a *BzzAddr) ID() discover.NodeID

id返回参考底图enode地址中的nodeid

func (*BzzAddr) Over

func (a *BzzAddr) Over() []byte

over返回覆盖地址

func (*BzzAddr) String

func (a *BzzAddr) String() string

字符串漂亮地打印地址

func (*BzzAddr) Under

func (a *BzzAddr) Under() []byte

在下面返回参考底图地址

func (*BzzAddr) Update

func (a *BzzAddr) Update(na OverlayAddr) OverlayAddr

更新更新更新对等记录的底层地址

type BzzConfig

type BzzConfig struct {
	OverlayAddr  []byte //覆盖网络的基址
	UnderlayAddr []byte //节点的参考底图地址
	HiveParams   *HiveParams
	NetworkID    uint64
	LightNode    bool
}

bzzconfig捕获配置单元使用的配置参数

type BzzPeer

type BzzPeer struct {
	*protocols.Peer //表示联机对等机的连接

	*BzzAddr //远程地址->实现addr interface=protocols.peer

	LightNode bool
	// contains filtered or unexported fields
}

bzz peer是协议的bzz协议视图。peer(本身是p2p.peer的扩展) 实现对等接口和所有接口对等实现:addr、overlaypeer

func NewBzzTestPeer

func NewBzzTestPeer(p *protocols.Peer, addr *BzzAddr) *BzzPeer

func (*BzzPeer) LastActive

func (p *BzzPeer) LastActive() time.Time

LastActive返回上次激活对等机的时间

func (*BzzPeer) Off

func (p *BzzPeer) Off() OverlayAddr

off返回脱机持久性的覆盖对等记录

type Conn

type Conn interface {
	ID() discover.NodeID                                                                  //唯一标识对等池节点的键
	Handshake(context.Context, interface{}, func(interface{}) error) (interface{}, error) //可以发送消息
	Send(context.Context, interface{}) error                                              //
	Drop(error)                                                                           //
	Run(func(context.Context, interface{}) error) error                                   //
	Off() OverlayAddr
}

conn接口表示活动对等连接

type HandshakeMsg

type HandshakeMsg struct {
	Version   uint64
	NetworkID uint64
	Addr      *BzzAddr
	LightNode bool
	// contains filtered or unexported fields
}

func (*HandshakeMsg) String

func (bh *HandshakeMsg) String() string

字符串漂亮地打印了握手

type Health

type Health struct {
	KnowNN     bool     //节点是否知道所有最近的邻居
	GotNN      bool     //节点是否连接到其所有最近的邻居
	CountNN    int      //连接到的最近邻居的数量
	CulpritsNN [][]byte //哪些已知的nns丢失了
	Full       bool     //节点在每个kademlia bin中是否有一个对等点(如果有这样的对等点)
	Hive       string
}

卡德米利亚的健康状况

type Hive

type Hive struct {
	*HiveParams             //
	Overlay                 //
	Store       state.Store //
	// contains filtered or unexported fields
}

func NewHive

func NewHive(params *HiveParams, overlay Overlay, store state.Store) *Hive

func (*Hive) NodeInfo

func (h *Hive) NodeInfo() interface{}

func (*Hive) PeerInfo

func (h *Hive) PeerInfo(id discover.NodeID) interface{}

func (*Hive) Run

func (h *Hive) Run(p *BzzPeer) error

func (*Hive) Start

func (h *Hive) Start(server *p2p.Server) error

func (*Hive) Stop

func (h *Hive) Stop() error

type HiveParams

type HiveParams struct {
	Discovery             bool  //
	PeersBroadcastSetSize uint8 //
	MaxPeersPerRequest    uint8 //
	KeepAliveInterval     time.Duration
}

func NewHiveParams

func NewHiveParams() *HiveParams

type KadParams

type KadParams struct {
	// 可调参数
	MaxProxDisplay int   //表显示的行数
	MinProxBinSize int   //最近邻核最小基数
	MinBinSize     int   //一行中的最小对等数
	MaxBinSize     int   //修剪前一行中的最大对等数
	RetryInterval  int64 //对等机首次重新拨号前的初始间隔
	RetryExponent  int   //用指数乘以重试间隔
	MaxRetries     int   //重拨尝试的最大次数
	//制裁或阻止建议同伴的职能
	Reachable func(OverlayAddr) bool
}

kadparams保存kademlia的配置参数

func NewKadParams

func NewKadParams() *KadParams

newkadparams返回带有默认值的params结构

type Kademlia

type Kademlia struct {
	*KadParams //Kademlia配置参数
	// contains filtered or unexported fields
}

Kademlia是一个活动对等端表和一个已知对等端数据库(节点记录)

func NewKademlia

func NewKademlia(addr []byte, params *KadParams) *Kademlia

newkademlia为基地址addr创建一个kademlia表 参数与参数相同 如果params为nil,则使用默认值

func (*Kademlia) AddrCountC

func (k *Kademlia) AddrCountC() <-chan int

addrCountc返回发送新的 每次更改的地址计数值。 不从返回通道接收将阻止寄存器功能 地址计数值更改时。

func (*Kademlia) BaseAddr

func (k *Kademlia) BaseAddr() []byte

baseaddr返回kademlia基地址

func (*Kademlia) EachAddr

func (k *Kademlia) EachAddr(base []byte, o int, f func(OverlayAddr, int, bool) bool)

用(base,po,f)调用的eachaddr是一个迭代器,将f应用于每个已知的对等端 从基地测量,接近订单为po或更低 如果基为零,则使用Kademlia基地址

func (*Kademlia) EachBin

func (k *Kademlia) EachBin(base []byte, pof pot.Pof, o int, eachBinFunc func(conn OverlayConn, po int) bool)

func (*Kademlia) EachConn

func (k *Kademlia) EachConn(base []byte, o int, f func(OverlayConn, int, bool) bool)

eachconn是一个带有args(base、po、f)的迭代器,将f应用于每个活动对等端 从基地测量,接近订单为po或更低 如果基为零,则使用Kademlia基地址

func (*Kademlia) Healthy

func (k *Kademlia) Healthy(pp *PeerPot) *Health

健康报告Kademlia连接性的健康状态 返回健康结构

func (*Kademlia) NeighbourhoodDepthC

func (k *Kademlia) NeighbourhoodDepthC() <-chan int

Neighbourhooddepthc返回发送新Kademlia的频道 每一次变化的邻里深度。 不从返回通道接收将阻塞功能 当邻近深度改变时。

func (*Kademlia) Off

func (k *Kademlia) Off(p OverlayConn)

关闭从活动对等中删除对等

func (*Kademlia) On

func (k *Kademlia) On(p OverlayConn) (uint8, bool)

在上,将对等机作为Kademlia对等机插入活动对等机

func (*Kademlia) Register

func (k *Kademlia) Register(peers []OverlayAddr) error

寄存器将每个overlayaddr作为kademlia对等记录输入 已知对等地址数据库

func (*Kademlia) String

func (k *Kademlia) String() string

字符串返回用ASCII显示的kademlia表+kaddb表

func (*Kademlia) SuggestPeer

func (k *Kademlia) SuggestPeer() (a OverlayAddr, o int, want bool)

suggestpeer返回的最低接近箱的已知对等 深度以下的最低料位计数 当然,如果有一个空行,它将返回该行的对等方

type Overlay

type Overlay interface {
	//
	SuggestPeer() (OverlayAddr, int, bool)
	//
	On(OverlayConn) (depth uint8, changed bool)
	Off(OverlayConn)
	//
	Register([]OverlayAddr) error
	//
	EachConn([]byte, int, func(OverlayConn, int, bool) bool)
	//
	EachAddr([]byte, int, func(OverlayAddr, int, bool) bool)
	//
	String() string
	//
	BaseAddr() []byte
	//
	Healthy(*PeerPot) *Health
}

type OverlayAddr

type OverlayAddr interface {
	OverlayPeer
	Update(OverlayAddr) OverlayAddr //返回原始版本的更新版本
}

overlayAddr表示Kademlia对等记录

type OverlayConn

type OverlayConn interface {
	OverlayPeer
	Drop(error)       //调用以指示应删除对等项
	Off() OverlayAddr //调用以返回Persistant OverlayAddr
}

overlayconn表示连接的对等机

type OverlayPeer

type OverlayPeer interface {
	Address() []byte
}

覆盖对等接口从覆盖中捕获对等视图的公共方面 拓扑驱动程序

type Peer

type Peer interface {
	Addr                   //对等机的地址
	Conn                   //实时连接(protocols.peer)
	LastActive() time.Time //上次激活时间
}

对等接口表示实时对等连接

type PeerPot

type PeerPot struct {
	NNSet     [][]byte
	EmptyBins []int
}

Peerpot保存预期最近邻居和空箱子的信息 仅用于测试

Directories

Path Synopsis
simulations

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL