mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
p2p/simulations: Get peer events via RPC
Signed-off-by: Lewis Marshall <lewis@lmars.net>
This commit is contained in:
parent
a4b52df32c
commit
247e40a36a
14 changed files with 378 additions and 137 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
package adapters
|
package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -22,7 +23,7 @@ type DockerNode struct {
|
||||||
|
|
||||||
// NewDockerNode creates a new DockerNode, building the docker image if
|
// NewDockerNode creates a new DockerNode, building the docker image if
|
||||||
// necessary
|
// necessary
|
||||||
func NewDockerNode(id *NodeId, service string) (*DockerNode, error) {
|
func NewDockerNode(id *NodeId, key *ecdsa.PrivateKey, service string) (*DockerNode, error) {
|
||||||
if runtime.GOOS != "linux" {
|
if runtime.GOOS != "linux" {
|
||||||
return nil, fmt.Errorf("NewDockerNode can only be used on Linux as it uses the current binary (which must be a Linux binary)")
|
return nil, fmt.Errorf("NewDockerNode can only be used on Linux as it uses the current binary (which must be a Linux binary)")
|
||||||
}
|
}
|
||||||
|
|
@ -51,6 +52,7 @@ func NewDockerNode(id *NodeId, service string) (*DockerNode, error) {
|
||||||
ID: id,
|
ID: id,
|
||||||
Service: service,
|
Service: service,
|
||||||
Config: &conf,
|
Config: &conf,
|
||||||
|
key: key,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
node.newCmd = node.dockerCommand
|
node.newCmd = node.dockerCommand
|
||||||
|
|
@ -60,13 +62,13 @@ func NewDockerNode(id *NodeId, service string) (*DockerNode, error) {
|
||||||
// dockerCommand returns a command which exec's the binary in a docker
|
// dockerCommand returns a command which exec's the binary in a docker
|
||||||
// container.
|
// container.
|
||||||
//
|
//
|
||||||
// It uses a shell so that we can pass the _P2P_NODE_CONFIG environment
|
// It uses a shell so that we can pass the _P2P_NODE_CONFIG and _P2P_NODE_KEY
|
||||||
// variable to the container using the --env flag.
|
// environment variables to the container using the --env flag.
|
||||||
func (n *DockerNode) dockerCommand() *exec.Cmd {
|
func (n *DockerNode) dockerCommand() *exec.Cmd {
|
||||||
return exec.Command(
|
return exec.Command(
|
||||||
"sh", "-c",
|
"sh", "-c",
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
`exec docker run --interactive --env _P2P_NODE_CONFIG="${_P2P_NODE_CONFIG}" %s p2p-node %s %s`,
|
`exec docker run --interactive --env _P2P_NODE_CONFIG="${_P2P_NODE_CONFIG}" --env _P2P_NODE_KEY="${_P2P_NODE_KEY}" %s p2p-node %s %s`,
|
||||||
dockerImage, n.Service, n.ID.String(),
|
dockerImage, n.Service, n.ID.String(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -16,6 +18,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/reexec"
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
|
@ -55,11 +58,12 @@ type ExecNode struct {
|
||||||
|
|
||||||
client *rpc.Client
|
client *rpc.Client
|
||||||
newCmd func() *exec.Cmd
|
newCmd func() *exec.Cmd
|
||||||
|
key *ecdsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExecNode creates a new ExecNode which will run the given service using a
|
// NewExecNode creates a new ExecNode which will run the given service using a
|
||||||
// sub-directory of the given baseDir
|
// sub-directory of the given baseDir
|
||||||
func NewExecNode(id *NodeId, service, baseDir string) (*ExecNode, error) {
|
func NewExecNode(id *NodeId, key *ecdsa.PrivateKey, service, baseDir string) (*ExecNode, error) {
|
||||||
if _, exists := serviceFuncs[service]; !exists {
|
if _, exists := serviceFuncs[service]; !exists {
|
||||||
return nil, fmt.Errorf("unknown node service %q", service)
|
return nil, fmt.Errorf("unknown node service %q", service)
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +86,7 @@ func NewExecNode(id *NodeId, service, baseDir string) (*ExecNode, error) {
|
||||||
Service: service,
|
Service: service,
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Config: &conf,
|
Config: &conf,
|
||||||
|
key: key,
|
||||||
}
|
}
|
||||||
node.newCmd = node.execCommand
|
node.newCmd = node.execCommand
|
||||||
return node, nil
|
return node, nil
|
||||||
|
|
@ -99,9 +104,10 @@ func (n *ExecNode) Client() (*rpc.Client, error) {
|
||||||
return n.client, nil
|
return n.client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start exec's the node passing the ID and service as command line arguments
|
// Start exec's the node passing the ID and service as command line arguments,
|
||||||
// and the node config encoded as JSON in the _P2P_NODE_CONFIG environment
|
// the node config encoded as JSON in the _P2P_NODE_CONFIG environment
|
||||||
// variable
|
// variable and the node's private key hex-endoded in the _P2P_NODE_KEY
|
||||||
|
// environment variable
|
||||||
func (n *ExecNode) Start() (err error) {
|
func (n *ExecNode) Start() (err error) {
|
||||||
if n.Cmd != nil {
|
if n.Cmd != nil {
|
||||||
return errors.New("already started")
|
return errors.New("already started")
|
||||||
|
|
@ -119,6 +125,9 @@ func (n *ExecNode) Start() (err error) {
|
||||||
return fmt.Errorf("error generating node config: %s", err)
|
return fmt.Errorf("error generating node config: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// encode the private key
|
||||||
|
key := hex.EncodeToString(crypto.FromECDSA(n.key))
|
||||||
|
|
||||||
// create a net.Pipe for RPC communication over stdin / stdout
|
// create a net.Pipe for RPC communication over stdin / stdout
|
||||||
pipe1, pipe2 := net.Pipe()
|
pipe1, pipe2 := net.Pipe()
|
||||||
|
|
||||||
|
|
@ -127,7 +136,10 @@ func (n *ExecNode) Start() (err error) {
|
||||||
cmd.Stdin = pipe1
|
cmd.Stdin = pipe1
|
||||||
cmd.Stdout = pipe1
|
cmd.Stdout = pipe1
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Env = append(os.Environ(), fmt.Sprintf("_P2P_NODE_CONFIG=%s", conf))
|
cmd.Env = append(os.Environ(),
|
||||||
|
fmt.Sprintf("_P2P_NODE_CONFIG=%s", conf),
|
||||||
|
fmt.Sprintf("_P2P_NODE_KEY=%s", key),
|
||||||
|
)
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return fmt.Errorf("error starting node: %s", err)
|
return fmt.Errorf("error starting node: %s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -215,6 +227,17 @@ func execP2PNode() {
|
||||||
log.Crit("error decoding _P2P_NODE_CONFIG", "err", err)
|
log.Crit("error decoding _P2P_NODE_CONFIG", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decode the private key
|
||||||
|
keyEnv := os.Getenv("_P2P_NODE_KEY")
|
||||||
|
if keyEnv == "" {
|
||||||
|
log.Crit("missing _P2P_NODE_KEY")
|
||||||
|
}
|
||||||
|
key, err := hex.DecodeString(keyEnv)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("error decoding _P2P_NODE_KEY", "err", err)
|
||||||
|
}
|
||||||
|
conf.P2P.PrivateKey = crypto.ToECDSA(key)
|
||||||
|
|
||||||
// initialize the service
|
// initialize the service
|
||||||
serviceFunc, exists := serviceFuncs[serviceName]
|
serviceFunc, exists := serviceFuncs[serviceName]
|
||||||
if !exists {
|
if !exists {
|
||||||
|
|
@ -268,10 +291,22 @@ func startP2PNode(conf *node.Config, service node.Service) (*node.Node, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
constructor := func(ctx *node.ServiceContext) (node.Service, error) {
|
|
||||||
return service, nil
|
constructor := func(s node.Service) node.ServiceConstructor {
|
||||||
|
return func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
|
return s, nil
|
||||||
}
|
}
|
||||||
if err := stack.Register(constructor); err != nil {
|
}
|
||||||
|
|
||||||
|
// register the peer events API
|
||||||
|
//
|
||||||
|
// TODO: move this to node.PrivateAdminAPI once the following is merged:
|
||||||
|
// https://github.com/ethereum/go-ethereum/pull/13885
|
||||||
|
if err := stack.Register(constructor(&PeerAPI{stack.Server})); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := stack.Register(constructor(service)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := stack.Start(); err != nil {
|
if err := stack.Start(); err != nil {
|
||||||
|
|
@ -280,6 +315,65 @@ func startP2PNode(conf *node.Config, service node.Service) (*node.Node, error) {
|
||||||
return stack, nil
|
return stack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PeerAPI is used to expose peer events under the "eth" RPC namespace.
|
||||||
|
//
|
||||||
|
// TODO: move this to node.PrivateAdminAPI and expose under the "admin"
|
||||||
|
// namespace once the following is merged:
|
||||||
|
// https://github.com/ethereum/go-ethereum/pull/13885
|
||||||
|
type PeerAPI struct {
|
||||||
|
server func() p2p.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PeerAPI) Protocols() []p2p.Protocol {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PeerAPI) APIs() []rpc.API {
|
||||||
|
return []rpc.API{{
|
||||||
|
Namespace: "eth",
|
||||||
|
Version: "1.0",
|
||||||
|
Service: p,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PeerAPI) Start(p2p.Server) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PeerAPI) Stop() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerEvents creates an RPC sunscription which receives peer events from the
|
||||||
|
// underlying p2p.Server
|
||||||
|
func (p *PeerAPI) PeerEvents(ctx context.Context) (*rpc.Subscription, error) {
|
||||||
|
notifier, supported := rpc.NotifierFromContext(ctx)
|
||||||
|
if !supported {
|
||||||
|
return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcSub := notifier.CreateSubscription()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
events := make(chan *p2p.PeerEvent)
|
||||||
|
sub := p.server().SubscribePeers(events)
|
||||||
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event := <-events:
|
||||||
|
notifier.Notify(rpcSub.ID, event)
|
||||||
|
case <-rpcSub.Err():
|
||||||
|
return
|
||||||
|
case <-notifier.Closed():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return rpcSub, nil
|
||||||
|
}
|
||||||
|
|
||||||
// stdioConn wraps os.Stdin / os.Stdout with a nop Close method so we can
|
// stdioConn wraps os.Stdin / os.Stdout with a nop Close method so we can
|
||||||
// use them to handle RPC messages
|
// use them to handle RPC messages
|
||||||
type stdioConn struct {
|
type stdioConn struct {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
|
@ -59,6 +60,7 @@ type SimNode struct {
|
||||||
service node.Service
|
service node.Service
|
||||||
peerMap map[discover.NodeID]int
|
peerMap map[discover.NodeID]int
|
||||||
peers []*Peer
|
peers []*Peer
|
||||||
|
peerFeed event.Feed
|
||||||
client *rpc.Client
|
client *rpc.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,13 +117,20 @@ func (self *SimNode) startRPC() error {
|
||||||
return errors.New("RPC already started")
|
return errors.New("RPC already started")
|
||||||
}
|
}
|
||||||
|
|
||||||
// add SimAdminAPI so that the network can call the AddPeer
|
// add SimAdminAPI and PeerAPI so that the network can call the
|
||||||
// and RemovePeer RPC methods
|
// AddPeer, RemovePeer and PeerEvents RPC methods
|
||||||
apis := append(self.service.APIs(), rpc.API{
|
apis := append(self.service.APIs(), []rpc.API{
|
||||||
|
{
|
||||||
Namespace: "admin",
|
Namespace: "admin",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
Service: &SimAdminAPI{self},
|
Service: &SimAdminAPI{self},
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
Namespace: "eth",
|
||||||
|
Version: "1.0",
|
||||||
|
Service: &PeerAPI{func() p2p.Server { return self }},
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
|
||||||
// start the RPC handler
|
// start the RPC handler
|
||||||
handler := rpc.NewServer()
|
handler := rpc.NewServer()
|
||||||
|
|
@ -219,6 +228,10 @@ func (self *SimNode) AddPeer(node *discover.Node) {
|
||||||
self.RunProtocol(na.(*SimNode), rw, rrw, peer)
|
self.RunProtocol(na.(*SimNode), rw, rrw, peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *SimNode) SubscribePeers(ch chan *p2p.PeerEvent) event.Subscription {
|
||||||
|
return self.peerFeed.Subscribe(ch)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *SimNode) PeerCount() int {
|
func (self *SimNode) PeerCount() int {
|
||||||
self.lock.Lock()
|
self.lock.Lock()
|
||||||
defer self.lock.Unlock()
|
defer self.lock.Unlock()
|
||||||
|
|
@ -243,13 +256,13 @@ func (self *SimNode) RunProtocol(node *SimNode, rw, rrw p2p.MsgReadWriter, peer
|
||||||
log.Trace(fmt.Sprintf("protocol starting on peer %v (connection with %v)", self.Id, id))
|
log.Trace(fmt.Sprintf("protocol starting on peer %v (connection with %v)", self.Id, id))
|
||||||
p := p2p.NewPeer(id.NodeID, id.Label(), []p2p.Cap{})
|
p := p2p.NewPeer(id.NodeID, id.Label(), []p2p.Cap{})
|
||||||
go func() {
|
go func() {
|
||||||
self.network.DidConnect(self.Id, id)
|
self.peerFeed.Send(&p2p.PeerEvent{Type: p2p.PeerEventTypeAdd, Peer: id.NodeID})
|
||||||
err := protocol.Run(p, rw)
|
err := protocol.Run(p, rw)
|
||||||
<-peer.Readyc
|
<-peer.Readyc
|
||||||
self.RemovePeer(node.Node())
|
self.RemovePeer(node.Node())
|
||||||
peer.Errc <- err
|
peer.Errc <- err
|
||||||
log.Trace(fmt.Sprintf("protocol quit on peer %v (connection with %v broken: %v)", self.Id, id, err))
|
log.Trace(fmt.Sprintf("protocol quit on peer %v (connection with %v broken: %v)", self.Id, id, err))
|
||||||
self.network.DidDisconnect(self.Id, id)
|
self.peerFeed.Send(&p2p.PeerEvent{Type: p2p.PeerEventTypeDrop, Peer: id.NodeID})
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package adapters
|
package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
@ -79,22 +78,3 @@ type Reporter interface {
|
||||||
DidConnect(*NodeId, *NodeId) error
|
DidConnect(*NodeId, *NodeId) error
|
||||||
DidDisconnect(*NodeId, *NodeId) error
|
DidDisconnect(*NodeId, *NodeId) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandomNodeId() *NodeId {
|
|
||||||
key, err := crypto.GenerateKey()
|
|
||||||
if err != nil {
|
|
||||||
panic("unable to generate key")
|
|
||||||
}
|
|
||||||
var id discover.NodeID
|
|
||||||
pubkey := crypto.FromECDSAPub(&key.PublicKey)
|
|
||||||
copy(id[:], pubkey[1:])
|
|
||||||
return &NodeId{id}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RandomNodeIds(n int) []*NodeId {
|
|
||||||
var ids []*NodeId
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
ids = append(ids, RandomNodeId())
|
|
||||||
}
|
|
||||||
return ids
|
|
||||||
}
|
|
||||||
|
|
|
||||||
20
p2p/peer.go
20
p2p/peer.go
|
|
@ -60,6 +60,26 @@ type protoHandshake struct {
|
||||||
Rest []rlp.RawValue `rlp:"tail"`
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PeerEventType is the type of peer events emitted by a p2p.Server
|
||||||
|
type PeerEventType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PeerEventTypeAdd is the type of event emitted when a peer is added
|
||||||
|
// to a p2p.Server
|
||||||
|
PeerEventTypeAdd PeerEventType = "add"
|
||||||
|
|
||||||
|
// PeerEventTypeDrop is the type of event emitted when a peer is
|
||||||
|
// dropped from a p2p.Server
|
||||||
|
PeerEventTypeDrop PeerEventType = "drop"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PeerEvent is an event emitted when peers are either added or dropped from
|
||||||
|
// a p2p.Server
|
||||||
|
type PeerEvent struct {
|
||||||
|
Type PeerEventType
|
||||||
|
Peer discover.NodeID
|
||||||
|
}
|
||||||
|
|
||||||
// Peer represents a connected remote node.
|
// Peer represents a connected remote node.
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
rw *conn
|
rw *conn
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/adapters"
|
"github.com/ethereum/go-ethereum/p2p/adapters"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/simulations"
|
||||||
p2ptest "github.com/ethereum/go-ethereum/p2p/testing"
|
p2ptest "github.com/ethereum/go-ethereum/p2p/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -117,8 +118,8 @@ func newProtocol(pp *p2ptest.TestPeerPool) adapters.ProtoCall {
|
||||||
}
|
}
|
||||||
|
|
||||||
func protocolTester(t *testing.T, pp *p2ptest.TestPeerPool) *p2ptest.ProtocolTester {
|
func protocolTester(t *testing.T, pp *p2ptest.TestPeerPool) *p2ptest.ProtocolTester {
|
||||||
id := adapters.RandomNodeId()
|
conf := simulations.RandomNodeConfig()
|
||||||
return p2ptest.NewProtocolTester(t, id, 2, newProtocol(pp))
|
return p2ptest.NewProtocolTester(t, conf.Id, 2, newProtocol(pp))
|
||||||
}
|
}
|
||||||
|
|
||||||
func protoHandshakeExchange(id *adapters.NodeId, proto *protoHandshake) []p2ptest.Exchange {
|
func protoHandshakeExchange(id *adapters.NodeId, proto *protoHandshake) []p2ptest.Exchange {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discv5"
|
"github.com/ethereum/go-ethereum/p2p/discv5"
|
||||||
|
|
@ -141,6 +142,7 @@ type Server interface {
|
||||||
Stop() error
|
Stop() error
|
||||||
AddPeer(node *discover.Node)
|
AddPeer(node *discover.Node)
|
||||||
RemovePeer(node *discover.Node)
|
RemovePeer(node *discover.Node)
|
||||||
|
SubscribePeers(ch chan *PeerEvent) event.Subscription
|
||||||
PeerCount() int
|
PeerCount() int
|
||||||
NodeInfo() *NodeInfo
|
NodeInfo() *NodeInfo
|
||||||
PeersInfo() []*PeerInfo
|
PeersInfo() []*PeerInfo
|
||||||
|
|
@ -180,6 +182,7 @@ type server struct {
|
||||||
addpeer chan *conn
|
addpeer chan *conn
|
||||||
delpeer chan peerDrop
|
delpeer chan peerDrop
|
||||||
loopWG sync.WaitGroup // loop, listenLoop
|
loopWG sync.WaitGroup // loop, listenLoop
|
||||||
|
peerFeed event.Feed
|
||||||
}
|
}
|
||||||
|
|
||||||
type peerOpFunc func(map[discover.NodeID]*Peer)
|
type peerOpFunc func(map[discover.NodeID]*Peer)
|
||||||
|
|
@ -305,6 +308,11 @@ func (srv *server) RemovePeer(node *discover.Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubscribePeers subscribes the given channel to peer events
|
||||||
|
func (srv *server) SubscribePeers(ch chan *PeerEvent) event.Subscription {
|
||||||
|
return srv.peerFeed.Subscribe(ch)
|
||||||
|
}
|
||||||
|
|
||||||
// Self returns the local node's endpoint information.
|
// Self returns the local node's endpoint information.
|
||||||
func (srv *server) Self() *discover.Node {
|
func (srv *server) Self() *discover.Node {
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
|
|
@ -770,6 +778,11 @@ func (srv *server) runPeer(p *Peer) {
|
||||||
if srv.newPeerHook != nil {
|
if srv.newPeerHook != nil {
|
||||||
srv.newPeerHook(p)
|
srv.newPeerHook(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// broadcast peer add / drop events
|
||||||
|
srv.peerFeed.Send(&PeerEvent{Type: PeerEventTypeAdd, Peer: p.ID()})
|
||||||
|
defer srv.peerFeed.Send(&PeerEvent{Type: PeerEventTypeDrop, Peer: p.ID()})
|
||||||
|
|
||||||
remoteRequested, err := p.run()
|
remoteRequested, err := p.run()
|
||||||
// Note: run waits for existing peers to be sent on srv.delpeer
|
// Note: run waits for existing peers to be sent on srv.delpeer
|
||||||
// before returning, so this send should not select on srv.quit.
|
// before returning, so this send should not select on srv.quit.
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,8 @@ func MockEvents(eventer *event.TypeMux, ids []*adapters.NodeId, conf *MockerConf
|
||||||
var mustconnect []int
|
var mustconnect []int
|
||||||
for i := 0; len(offNodes) > 0 && i < nodesUp; i++ {
|
for i := 0; len(offNodes) > 0 && i < nodesUp; i++ {
|
||||||
c := rand.Intn(len(offNodes))
|
c := rand.Intn(len(offNodes))
|
||||||
sn := &Node{Id: offNodes[c]}
|
sn := &Node{}
|
||||||
|
sn.Id = offNodes[c]
|
||||||
err := eventer.Post(sn.EmitEvent(ControlEvent))
|
err := eventer.Post(sn.EmitEvent(ControlEvent))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,19 @@
|
||||||
package simulations
|
package simulations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/adapters"
|
"github.com/ethereum/go-ethereum/p2p/adapters"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
@ -176,9 +181,7 @@ func NewNodesController(net *Network) *ResourceController {
|
||||||
&ResourceHandlers{
|
&ResourceHandlers{
|
||||||
Create: &ResourceHandler{
|
Create: &ResourceHandler{
|
||||||
Handle: func(msg interface{}, parent *ResourceController) (interface{}, error) {
|
Handle: func(msg interface{}, parent *ResourceController) (interface{}, error) {
|
||||||
nodeid := adapters.RandomNodeId()
|
return net.NewNode()
|
||||||
net.NewNode(&NodeConfig{Id: nodeid})
|
|
||||||
return &NodeConfig{Id: nodeid}, nil
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Retrieve: &ResourceHandler{
|
Retrieve: &ResourceHandler{
|
||||||
|
|
@ -289,7 +292,7 @@ func (self *Network) Subscribe(eventer *event.TypeMux, types ...interface{}) {
|
||||||
|
|
||||||
func (self *Network) executeNodeEvent(ne *NodeControlEvent) {
|
func (self *Network) executeNodeEvent(ne *NodeControlEvent) {
|
||||||
if ne.Up {
|
if ne.Up {
|
||||||
err := self.NewNode(&NodeConfig{Id: ne.Node.Id})
|
err := self.NewNodeWithConfig(&ne.Node.NodeConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Trace(fmt.Sprintf("error execute event %v: %v", ne, err))
|
log.Trace(fmt.Sprintf("error execute event %v: %v", ne, err))
|
||||||
}
|
}
|
||||||
|
|
@ -370,9 +373,10 @@ type LiveEventer interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Id *adapters.NodeId `json:"id"`
|
NodeConfig
|
||||||
|
|
||||||
Up bool
|
Up bool
|
||||||
config *NodeConfig
|
|
||||||
na adapters.NodeAdapter
|
na adapters.NodeAdapter
|
||||||
controlFired bool
|
controlFired bool
|
||||||
}
|
}
|
||||||
|
|
@ -511,7 +515,55 @@ func (self *Node) Adapter() adapters.NodeAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeConfig struct {
|
type NodeConfig struct {
|
||||||
Id *adapters.NodeId `json:"Id"`
|
Id *adapters.NodeId
|
||||||
|
PrivateKey *ecdsa.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeConfigJSON struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
PrivateKey string `json:"private_key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NodeConfig) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(nodeConfigJSON{
|
||||||
|
n.Id.String(),
|
||||||
|
hex.EncodeToString(crypto.FromECDSA(n.PrivateKey)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NodeConfig) UnmarshalJSON(data []byte) error {
|
||||||
|
var confJSON nodeConfigJSON
|
||||||
|
if err := json.Unmarshal(data, &confJSON); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeID, err := discover.HexID(confJSON.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n.Id = &adapters.NodeId{NodeID: nodeID}
|
||||||
|
|
||||||
|
key, err := hex.DecodeString(confJSON.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n.PrivateKey = crypto.ToECDSA(key)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomNodeConfig() *NodeConfig {
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
panic("unable to generate key")
|
||||||
|
}
|
||||||
|
var id discover.NodeID
|
||||||
|
pubkey := crypto.FromECDSAPub(&key.PublicKey)
|
||||||
|
copy(id[:], pubkey[1:])
|
||||||
|
return &NodeConfig{
|
||||||
|
Id: &adapters.NodeId{NodeID: id},
|
||||||
|
PrivateKey: key,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ignored for now
|
// TODO: ignored for now
|
||||||
|
|
@ -530,9 +582,18 @@ type Know struct {
|
||||||
// swap balance
|
// swap balance
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNode adds a new node to the network
|
// NewNode adds a new node to the network with a random ID
|
||||||
|
func (self *Network) NewNode() (*NodeConfig, error) {
|
||||||
|
conf := RandomNodeConfig()
|
||||||
|
if err := self.NewNodeWithConfig(conf); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNodeWithConfig adds a new node to the network with the given config
|
||||||
// errors if a node by the same id already exist
|
// errors if a node by the same id already exist
|
||||||
func (self *Network) NewNode(conf *NodeConfig) error {
|
func (self *Network) NewNodeWithConfig(conf *NodeConfig) error {
|
||||||
self.lock.Lock()
|
self.lock.Lock()
|
||||||
defer self.lock.Unlock()
|
defer self.lock.Unlock()
|
||||||
id := conf.Id
|
id := conf.Id
|
||||||
|
|
@ -544,8 +605,7 @@ func (self *Network) NewNode(conf *NodeConfig) error {
|
||||||
self.nodeMap[id.NodeID] = len(self.Nodes)
|
self.nodeMap[id.NodeID] = len(self.Nodes)
|
||||||
na := self.naf(conf)
|
na := self.naf(conf)
|
||||||
node := &Node{
|
node := &Node{
|
||||||
Id: conf.Id,
|
NodeConfig: *conf,
|
||||||
config: conf,
|
|
||||||
na: na,
|
na: na,
|
||||||
}
|
}
|
||||||
self.Nodes = append(self.Nodes, node)
|
self.Nodes = append(self.Nodes, node)
|
||||||
|
|
@ -603,9 +663,49 @@ func (self *Network) Start(id *adapters.NodeId) error {
|
||||||
log.Info(fmt.Sprintf("started node %v: %v", id, node.Up))
|
log.Info(fmt.Sprintf("started node %v: %v", id, node.Up))
|
||||||
|
|
||||||
self.events.Post(node.EmitEvent(ControlEvent))
|
self.events.Post(node.EmitEvent(ControlEvent))
|
||||||
|
|
||||||
|
// subscribe to peer events
|
||||||
|
client, err := node.Adapter().Client()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting rpc client for node %v: %s", id, err)
|
||||||
|
}
|
||||||
|
events := make(chan *p2p.PeerEvent)
|
||||||
|
sub, err := client.EthSubscribe(context.Background(), events, "peerEvents")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting peer events for node %v: %s", id, err)
|
||||||
|
}
|
||||||
|
go self.watchPeerEvents(id, events, sub)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Network) watchPeerEvents(id *adapters.NodeId, events chan *p2p.PeerEvent, sub event.Subscription) {
|
||||||
|
defer sub.Unsubscribe()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event, ok := <-events:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
peer := &adapters.NodeId{NodeID: event.Peer}
|
||||||
|
switch event.Type {
|
||||||
|
case p2p.PeerEventTypeAdd:
|
||||||
|
if err := self.DidConnect(id, peer); err != nil {
|
||||||
|
log.Error(fmt.Sprintf("error generating connection up event %s => %s", id.Label(), peer.Label()), "err", err)
|
||||||
|
}
|
||||||
|
case p2p.PeerEventTypeDrop:
|
||||||
|
if err := self.DidDisconnect(id, peer); err != nil {
|
||||||
|
log.Error(fmt.Sprintf("error generating connection down event %s => %s", id.Label(), peer.Label()), "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case err := <-sub.Err():
|
||||||
|
if err != nil {
|
||||||
|
log.Error(fmt.Sprintf("error getting peer events for node %v", id), "err", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stop(id) shuts down the node (relevant only for instance with own p2p or remote)
|
// Stop(id) shuts down the node (relevant only for instance with own p2p or remote)
|
||||||
func (self *Network) Stop(id *adapters.NodeId) error {
|
func (self *Network) Stop(id *adapters.NodeId) error {
|
||||||
node := self.GetNode(id)
|
node := self.GetNode(id)
|
||||||
|
|
@ -629,6 +729,7 @@ func (self *Network) Stop(id *adapters.NodeId) error {
|
||||||
// calling the node's nodadapters Connect method
|
// calling the node's nodadapters Connect method
|
||||||
// connection is established (as if) the first node dials out to the other
|
// connection is established (as if) the first node dials out to the other
|
||||||
func (self *Network) Connect(oneId, otherId *adapters.NodeId) error {
|
func (self *Network) Connect(oneId, otherId *adapters.NodeId) error {
|
||||||
|
log.Debug(fmt.Sprintf("connecting %s to %s", oneId, otherId))
|
||||||
conn, err := self.GetOrCreateConn(oneId, otherId)
|
conn, err := self.GetOrCreateConn(oneId, otherId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -808,6 +909,7 @@ func (self *Network) getConn(oneId, otherId *adapters.NodeId) *Conn {
|
||||||
func (self *Network) Shutdown() {
|
func (self *Network) Shutdown() {
|
||||||
// disconnect all nodes
|
// disconnect all nodes
|
||||||
for _, conn := range self.Conns {
|
for _, conn := range self.Conns {
|
||||||
|
log.Debug(fmt.Sprintf("disconnecting %s from %s", conn.One.Label(), conn.Other.Label()))
|
||||||
if err := self.Disconnect(conn.One, conn.Other); err != nil {
|
if err := self.Disconnect(conn.One, conn.Other); err != nil {
|
||||||
log.Warn(fmt.Sprintf("error disconnecting %s from %s", conn.One.Label(), conn.Other.Label()), "err", err)
|
log.Warn(fmt.Sprintf("error disconnecting %s from %s", conn.One.Label(), conn.Other.Label()), "err", err)
|
||||||
}
|
}
|
||||||
|
|
@ -815,6 +917,7 @@ func (self *Network) Shutdown() {
|
||||||
|
|
||||||
// stop all nodes
|
// stop all nodes
|
||||||
for _, node := range self.Nodes {
|
for _, node := range self.Nodes {
|
||||||
|
log.Debug(fmt.Sprintf("stopping node %s", node.Id.Label()))
|
||||||
if err := node.na.Stop(); err != nil {
|
if err := node.na.Stop(); err != nil {
|
||||||
log.Warn(fmt.Sprintf("error stopping node %s", node.Id.Label()), "err", err)
|
log.Warn(fmt.Sprintf("error stopping node %s", node.Id.Label()), "err", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func NewProtocolTester(t *testing.T, id *adapters.NodeId, n int, run func(*p2p.P
|
||||||
}
|
}
|
||||||
net.SetNaf(naf)
|
net.SetNaf(naf)
|
||||||
|
|
||||||
if err := net.NewNode(&simulations.NodeConfig{Id: id}); err != nil {
|
if err := net.NewNodeWithConfig(&simulations.NodeConfig{Id: id}); err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
if err := net.Start(id); err != nil {
|
if err := net.Start(id); err != nil {
|
||||||
|
|
@ -36,30 +36,35 @@ func NewProtocolTester(t *testing.T, id *adapters.NodeId, n int, run func(*p2p.P
|
||||||
}
|
}
|
||||||
|
|
||||||
node := net.GetNodeAdapter(id).(*adapters.SimNode)
|
node := net.GetNodeAdapter(id).(*adapters.SimNode)
|
||||||
ids := adapters.RandomNodeIds(n)
|
peers := make([]*simulations.NodeConfig, n)
|
||||||
ps := NewProtocolSession(node, ids)
|
peerIDs := make([]*adapters.NodeId, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
peers[i] = simulations.RandomNodeConfig()
|
||||||
|
peerIDs[i] = peers[i].Id
|
||||||
|
}
|
||||||
|
ps := NewProtocolSession(node, peerIDs)
|
||||||
self := &ProtocolTester{
|
self := &ProtocolTester{
|
||||||
ProtocolSession: ps,
|
ProtocolSession: ps,
|
||||||
network: net,
|
network: net,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.Connect(id, ids...)
|
self.Connect(id, peers...)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ProtocolTester) Connect(selfId *adapters.NodeId, ids ...*adapters.NodeId) {
|
func (self *ProtocolTester) Connect(selfId *adapters.NodeId, peers ...*simulations.NodeConfig) {
|
||||||
for _, id := range ids {
|
for _, peer := range peers {
|
||||||
log.Trace(fmt.Sprintf("start node %v", id))
|
log.Trace(fmt.Sprintf("start node %v", peer.Id))
|
||||||
if err := self.network.NewNode(&simulations.NodeConfig{Id: id}); err != nil {
|
if err := self.network.NewNodeWithConfig(peer); err != nil {
|
||||||
panic(fmt.Sprintf("error starting peer %v: %v", id, err))
|
panic(fmt.Sprintf("error starting peer %v: %v", peer.Id, err))
|
||||||
}
|
}
|
||||||
if err := self.network.Start(id); err != nil {
|
if err := self.network.Start(peer.Id); err != nil {
|
||||||
panic(fmt.Sprintf("error starting peer %v: %v", id, err))
|
panic(fmt.Sprintf("error starting peer %v: %v", peer.Id, err))
|
||||||
}
|
}
|
||||||
log.Trace(fmt.Sprintf("connect to %v", id))
|
log.Trace(fmt.Sprintf("connect to %v", peer.Id))
|
||||||
if err := self.network.Connect(selfId, id); err != nil {
|
if err := self.network.Connect(selfId, peer.Id); err != nil {
|
||||||
panic(fmt.Sprintf("error connecting to peer %v: %v", id, err))
|
panic(fmt.Sprintf("error connecting to peer %v: %v", peer.Id, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ func TestRegisterAndConnect(t *testing.T) {
|
||||||
},
|
},
|
||||||
ticker: make(chan time.Time),
|
ticker: make(chan time.Time),
|
||||||
}
|
}
|
||||||
//pp.Start(tc.connect, tc.ping)
|
|
||||||
pp.Start(s.TestNodeAdapter, tc.ping)
|
pp.Start(s.TestNodeAdapter, tc.ping)
|
||||||
defer pp.Stop()
|
defer pp.Stop()
|
||||||
tc.ticker <- time.Now()
|
tc.ticker <- time.Now()
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ func (n *pssTestNode) triggerCheck() {
|
||||||
//go func() { n.trigger <- n.id }()
|
//go func() { n.trigger <- n.id }()
|
||||||
go func() { n.trigger <- adapters.NewNodeId(n.Addr()) }()
|
go func() { n.trigger <- adapters.NewNodeId(n.Addr()) }()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func (n *pssTestNode) RunProtocol(id *adapters.NodeId, rw, rrw p2p.MsgReadWriter, peer *adapters.Peer) error {
|
func (n *pssTestNode) RunProtocol(id *adapters.NodeId, rw, rrw p2p.MsgReadWriter, peer *adapters.Peer) error {
|
||||||
return n.NodeAdapter.(adapters.ProtocolRunner).RunProtocol(id, rw, rrw, peer)
|
return n.NodeAdapter.(adapters.ProtocolRunner).RunProtocol(id, rw, rrw, peer)
|
||||||
|
|
@ -686,11 +687,13 @@ func newPssSimulationTester(t *testing.T, numnodes int, numfullnodes int, net *s
|
||||||
//svcs[conf.Id] = testservice
|
//svcs[conf.Id] = testservice
|
||||||
return node.SimNode
|
return node.SimNode
|
||||||
})
|
})
|
||||||
ids := adapters.RandomNodeIds(numnodes)
|
configs := make([]*simulations.NodeConfig, numnodes)
|
||||||
i := 0
|
for i := 0; i < numnodes; i++ {
|
||||||
for _, id := range ids {
|
configs[i] = simulations.RandomNodeConfig()
|
||||||
addr := NewPeerAddrFromNodeId(id)
|
}
|
||||||
psss[id] = makePss(addr.OverlayAddr())
|
for i, conf := range configs {
|
||||||
|
addr := NewPeerAddrFromNodeId(conf.Id)
|
||||||
|
psss[conf.Id] = makePss(addr.OverlayAddr())
|
||||||
if i < numfullnodes {
|
if i < numfullnodes {
|
||||||
tp := &pssTestPeer{
|
tp := &pssTestPeer{
|
||||||
Peer: &protocols.Peer{
|
Peer: &protocols.Peer{
|
||||||
|
|
@ -699,24 +702,23 @@ func newPssSimulationTester(t *testing.T, numnodes int, numfullnodes int, net *s
|
||||||
successC: make(chan bool),
|
successC: make(chan bool),
|
||||||
resultC: make(chan int),
|
resultC: make(chan int),
|
||||||
}
|
}
|
||||||
testpeers[id] = tp
|
testpeers[conf.Id] = tp
|
||||||
targetprotocol := makeCustomProtocol(name, version, vct, testpeers[id])
|
targetprotocol := makeCustomProtocol(name, version, vct, testpeers[conf.Id])
|
||||||
pssprotocol := NewPssProtocol(psss[id], &topic, vct, targetprotocol)
|
pssprotocol := NewPssProtocol(psss[conf.Id], &topic, vct, targetprotocol)
|
||||||
psss[id].Register(topic, pssprotocol.GetHandler())
|
psss[conf.Id].Register(topic, pssprotocol.GetHandler())
|
||||||
}
|
}
|
||||||
|
|
||||||
net.NewNode(&simulations.NodeConfig{Id: id})
|
net.NewNodeWithConfig(conf)
|
||||||
if err := net.Start(id); err != nil {
|
if err := net.Start(conf.Id); err != nil {
|
||||||
t.Fatalf("error starting node %s: %s", id.Label(), err)
|
t.Fatalf("error starting node %s: %s", conf.Id.Label(), err)
|
||||||
}
|
}
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
//return svcs
|
//return svcs
|
||||||
}
|
}
|
||||||
|
|
||||||
type pssTestService struct{
|
type pssTestService struct {
|
||||||
node *pssTestNode // get addrs from this
|
node *pssTestNode // get addrs from this
|
||||||
msgFunc func(interface{}) error
|
msgFunc func(interface{}) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ func TestDiscoverySimulationDockerAdapter(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
net.SetNaf(func(conf *simulations.NodeConfig) adapters.NodeAdapter {
|
net.SetNaf(func(conf *simulations.NodeConfig) adapters.NodeAdapter {
|
||||||
node, err := adapters.NewDockerNode(conf.Id, serviceName)
|
node, err := adapters.NewDockerNode(conf.Id, conf.PrivateKey, serviceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ func TestDiscoverySimulationExecAdapter(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
net.SetNaf(func(conf *simulations.NodeConfig) adapters.NodeAdapter {
|
net.SetNaf(func(conf *simulations.NodeConfig) adapters.NodeAdapter {
|
||||||
node, err := adapters.NewExecNode(conf.Id, serviceName, baseDir)
|
node, err := adapters.NewExecNode(conf.Id, conf.PrivateKey, serviceName, baseDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -118,12 +118,16 @@ func testDiscoverySimulation(t *testing.T, setup func(net *simulations.Network,
|
||||||
})
|
})
|
||||||
defer net.Shutdown()
|
defer net.Shutdown()
|
||||||
setup(net, trigger)
|
setup(net, trigger)
|
||||||
ids := adapters.RandomNodeIds(nodeCount)
|
ids := make([]*adapters.NodeId, nodeCount)
|
||||||
for _, id := range ids {
|
for i := 0; i < nodeCount; i++ {
|
||||||
net.NewNode(&simulations.NodeConfig{Id: id})
|
conf, err := net.NewNode()
|
||||||
if err := net.Start(id); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error starting node %s: %s", id.Label(), err)
|
t.Fatalf("error starting node %s: %s", conf.Id.Label(), err)
|
||||||
}
|
}
|
||||||
|
if err := net.Start(conf.Id); err != nil {
|
||||||
|
t.Fatalf("error starting node %s: %s", conf.Id.Label(), err)
|
||||||
|
}
|
||||||
|
ids[i] = conf.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
// run a simulation which connects the 10 nodes in a ring and waits
|
// run a simulation which connects the 10 nodes in a ring and waits
|
||||||
|
|
|
||||||
|
|
@ -118,11 +118,16 @@ func nethook(conf *simulations.NetworkConfig) (simulations.NetworkControl, *simu
|
||||||
conf.Backend = true
|
conf.Backend = true
|
||||||
net := NewNetwork(simulations.NewNetwork(conf))
|
net := NewNetwork(simulations.NewNetwork(conf))
|
||||||
|
|
||||||
//ids := p2ptest.RandomNodeIds(10)
|
ids := make([]*adapters.NodeId, 10)
|
||||||
ids := adapters.RandomNodeIds(10)
|
for i := 0; i < 10; i++ {
|
||||||
|
conf, err := net.NewNode()
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
ids[i] = conf.Id
|
||||||
|
}
|
||||||
|
|
||||||
for i, id := range ids {
|
for i, id := range ids {
|
||||||
net.NewNode(&simulations.NodeConfig{Id: id})
|
|
||||||
var peerId *adapters.NodeId
|
var peerId *adapters.NodeId
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
peerId = ids[len(ids)-1]
|
peerId = ids[len(ids)-1]
|
||||||
|
|
@ -138,7 +143,6 @@ func nethook(conf *simulations.NetworkConfig) (simulations.NetworkControl, *simu
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
n := rand.Intn(1000)
|
n := rand.Intn(1000)
|
||||||
time.Sleep(time.Duration(n) * time.Millisecond)
|
time.Sleep(time.Duration(n) * time.Millisecond)
|
||||||
net.NewNode(&simulations.NodeConfig{Id: id})
|
|
||||||
net.Start(id)
|
net.Start(id)
|
||||||
log.Debug(fmt.Sprintf("node %v starting up", id))
|
log.Debug(fmt.Sprintf("node %v starting up", id))
|
||||||
// time.Sleep(1000 * time.Millisecond)
|
// time.Sleep(1000 * time.Millisecond)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue