neo-go/pkg/peer/readme.md
2019-02-25 22:44:14 +00:00

67 lines
No EOL
2.9 KiB
Markdown

# Package - Peer
## Responsibility
Once a connection has been made. The connection will represent a established peer to the localNode. Since a connection and the `Wire` is a golang primitive, that we cannot do much with. The peer package will encapsulate both, while adding extra functionality.
## Features
- The handshake protocol is automatically executed and handled by the peer package. If a Version/Verack is received twice, the peer will be disconnected.
- IdleTimeouts: If a Message is not received from the peer within a set period of time, the peer will be disconnected.
- StallTimeouts: For Example, If a GetHeaders, is sent to the Peer and a Headers Response is not received within a certain period of time, then the peer is disconnected.
- Concurrency Model: The concurrency model used is similar to Actor model, with a few changes. Messages can be sent to a peer asynchronously or synchronously. An example of an synchornous message send is the `RequestHeaders` method, where the channel blocks until an error value is received. The `OnHeaders` message is however asynchronously called. Furthermore, all methods passed through the config, are wrapped inside of an additional `Peers` method, this is to lay the ground work to capturing statistics regarding a specific command. These are also used so that we can pass behaviour to be executed down the channel.
- Configuration: Each Peer will have a config struct passed to it, with information about the Local Peer and functions that will encapsulate the behaviour of what the peer should do, given a request. This way, the peer is not dependent on any other package.
## Usage
conn, err := net.Dial("tcp", "seed2.neo.org:10333")
if err != nil {
fmt.Println("Error dialing connection", err.Error())
return
}
config := peer.LocalConfig{
Net: protocol.MainNet,
UserAgent: "NEO-G",
Services: protocol.NodePeerService,
Nonce: 1200,
ProtocolVer: 0,
Relay: false,
Port: 10332,
StartHeight: LocalHeight,
OnHeader: OnHeader,
}
p := peer.NewPeer(conn, false, config)
err = p.Run()
hash, err := util.Uint256DecodeString(chainparams.GenesisHash)
// hash2, err := util.Uint256DecodeString("ff8fe95efc5d1cc3a22b17503aecaf289cef68f94b79ddad6f613569ca2342d8")
err = p.RequestHeaders(hash)
func OnHeader(peer *peer.Peer, msg *payload.HeadersMessage) {
// This function is passed to peer
// and the peer will execute it on receiving a header
}
func LocalHeight() uint32 {
// This will be a function from the object that handles the block heights
return 10
}
### Notes
Should we follow the actor model for Peers? Each Peer will have a ID, which we can take as the PID or if
we launch a go-routine for each peer, then we can use that as an implicit PID.
Peer information should be stored into a database, if no db exists, we should get it from an initial peers file.
We can use this to periodically store information about a peer.