Proficient in Filecoin: Hello protocol of Filecoin source code
start
method of the Filecoin full node is called to start the full node, the New
method of the hello protocol is called. The processing of this method is as follows:
- Generate a Hello object.
hello := &Handler{ host: h, genesis: gen, chainSyncCB: syncCallback, getHeaviestTipSet: getHeaviestTipSet, net: net, commitSha: commitSha, }
The
host
object is theHost
object provided by the underlying libp2;genesis
is the CID of thegenesis
block;chainSyncCB
is thesyncCallBack
function of the full node object for synchronizing blocks from remote nodes;getHeaviestTipSet
is theChainHead
method of theporcelain.API
object Inherited fromplumbing.API
object, theChainHead
method is defined in the latter), used to return the tipset of the blockchain head;net
represents the current network environment, such as the test network, the official network; - Call the
SetStreamHandler
method of thehost
object and set its ownhandleNewStream
method as the handler for the/fil/hello/1.0.0
protocol.h.SetStreamHandler(protocol, hello.handleNewStream)
When the connection is established, the notifier registered later calls the
sayHello
method, in which a hello protocol stream is opened and a hello message is sent. - Call the
Notify
method of the host object's network object (that is, the swarm object), and register itself as the notified party on the network object.h.Network().Notify((*helloNotify)(hello))
In this step, by calling the
Network
method of thehost
object, the underlying swarm object is returned, then thehello
object is converted into ahelloNotify
object, and finally theNotify
method of the swarm object is called, so that thehelloNotify
object will be notified when any event occurs on the underlying swarm object (Ie thehello
object).
In the Hello protocol, we only care about the connection establishment event, so the helloNotify
type only implements this method, and the other methods are implemented as empty, as follows:
type helloNotify Handler
func (hn * helloNotify) hello () * Handler {
return (* Handler) (hn)
}
- Getting started with blockchain | What can blockchain do in agriculture?
- In Africa, I see the future of digital assets
- Ethereum token evolution: how will it develop in the future?
const helloTimeout = time.Second * 10
func (hn * helloNotify) Connected (n net.Network, c net.Conn) {
go func () {
ctx, cancel: = context.WithTimeout (context.Background (), helloTimeout)
defer cancel ()
p: = c.RemotePeer ()
if err: = hn.hello (). sayHello (ctx, p); err! = nil {
log.Warningf ("failed to send hello handshake to peer% s:% s", p, err)
}
} ()
}
When a node acts as a client and dials up to connect to a remote peer, the underlying swarm object will call its notifyAll
method to notify all Notify objects that connections have been opened, that is, call the Connected
methods of all Notify objects, including the ones we registered earlier Notification object. When the Connected
method of the helloNotify
object is called, this method internally calls its own hello
method, which returns itself and is coerced to the Handler
type, and then calls its sayHello
method to say hello to the remote we are currently connected to.
At the same time, when a remote node acts as a server and receives a connection request from us to generate a connection, its swarm object will also notify all its Notify objects, and thus also its previously registered notification objects, which call the server vendor's Connected
method, thus calling its sayHello
method to send us the block situation; because in the second step, we registered the handleNewStream
method of the Hello object as the processor of the Hello protocol, so when the node receives the remote node to send the block situation This method will be called for processing, and this method will call the syncCallBack
method of the full node for block synchronization processing. In general, the Hello protocol handleNewStream
block synchronization through sayHello
and handleNewStream
. The former sends its own block situation to a remote node, and the latter handles the block situation sent by the remote node.
sayHello
method is processed as follows:
- Call the
NewStream
Host object to generate a stream object that handles the Hello protocol.s, err := h.host.NewStream(ctx, p, protocol) if err != nil { return err } defer s.Close() // nolint: errcheck
- Call your own
getOurHelloMessage
method to get the top information of your owngetOurHelloMessage
.msg := h.getOurHelloMessage()
The internal execution flow of this method is as follows:
- Call your own
getHeaviestTipSet
method to get the top information of theChainHead
. This method is a reference to theplumbing.API
objectChainHead
method. - Using the obtained blockchain information, a message object
Message
generated and returned.
- Call your own
- Send block information to remote nodes via streaming.
handleNewStream
method is processed as follows:
- Generate a message object
Message
and read from the stream the content sent by the remote peer node into the message object.var hello Message if err := cbu.NewMsgReader(s).ReadMsg(&hello); err != nil { log.Debugf("bad hello message from peer %s: %s", from, err) helloMsgErrCt.Inc(context.TODO(), 1) s.Conn().Close() // nolint: errcheck return }
- Call its own
processHelloMessage
method to process messages sent by remote nodes. The method code is as follows:func (h *Handler) processHelloMessage(from peer.ID, msg *Message) error { if !msg.GenesisHash.Equals(h.genesis) { return ErrBadGenesis } if (h.net == "devnet-test" || h.net == "devnet-user") && msg.CommitSha != h.commitSha { return ErrWrongVersion }
h.chainSyncCB(from, msg.HeaviestTipSetCids, msg.HeaviestTipSetHeight) return nil
}
Its processing logic is relatively simple:
- First, check if the genesis block hash sent by the remote node is equal to its genesis block hash. If not, return an error directly.
- Then, check the network type.
- Finally, it calls its own
chainSyncCB
method to process the block information sent by the remote node. This synchronization callback method object is generated in the start methodStart
of the full node. Its main generation is to generate a typetypes/SortedCidSet
object based on the top-level information of thetypes/SortedCidSet
sent by the remote node, and then call theHandleNewTipset
method inchain/syncer.go
to process the remotely sent block information.
- Different processing is performed according to the result of the previous processing message.
switch err := h.processHelloMessage(from, &hello); err { case ErrBadGenesis: log.Debugf("genesis cid: %s does not match: %s, disconnecting from peer: %s", &hello.GenesisHash, h.genesis, from) genesisErrCt.Inc(context.TODO(), 1) s.Conn().Close() // nolint: errcheck return case ErrWrongVersion: log.Debugf("code not at same version: peer has version %s, daemon has version %s, disconnecting from peer: %s", hello.CommitSha, h.commitSha, from) versionErrCt.Inc(context.TODO(), 1) s.Conn().Close() // nolint: errcheck return case nil: // ok, noop default: log.Error(err) }
We will continue to update Blocking; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles
- Yesterday, 340,000 ETH on the Upbit exchange was stolen, but this server was attacked …
- Former Director of the Central Bank on Digital Currency, Blockchain Application and Fintech Development
- Opinion: "Patent thinking" may destroy China's blockchain industry, and open source is the trend
- Ethereum Foundation: What is Phase 0 of Ethereum 2.0?
- Large-scale innovation of open financial applications on Ethereum, how does each application build this ecological space?
- Twitter CEO Jack Dorsey: Bitcoin's future will be in Africa
- Blockchain domain names: simpler, say goodbye to complex addresses