mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
swarm/pss, p2p/simulations/adapters: added pss routing peerpool
This commit is contained in:
parent
ebd6199dfc
commit
7341530f6f
5 changed files with 248 additions and 175 deletions
|
|
@ -86,6 +86,12 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
|
|||
//}
|
||||
//service := serviceFunc(id)
|
||||
|
||||
for _, service := range serviceFuncs[config.Service](id, nil) {
|
||||
for _, proto := range service.Protocols() {
|
||||
nodeprotos = append(nodeprotos, proto)
|
||||
}
|
||||
}
|
||||
|
||||
_, err := node.New(&node.Config{
|
||||
P2P: p2p.Config{
|
||||
PrivateKey: config.PrivateKey,
|
||||
|
|
@ -100,12 +106,6 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
for _, service := range serviceFuncs[config.Service](id, nil) {
|
||||
for _, proto := range service.Protocols() {
|
||||
nodeprotos = append(nodeprotos, proto)
|
||||
}
|
||||
}
|
||||
|
||||
simnode := &SimNode{
|
||||
Id: id,
|
||||
serviceFunc: serviceFuncs[config.Service],
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ const (
|
|||
addrLen = common.HashLength
|
||||
)
|
||||
|
||||
// implements p2p.Server
|
||||
// implements net.Conn
|
||||
type PssClient struct {
|
||||
localuri string
|
||||
remoteuri string
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
||||
"github.com/ethereum/go-ethereum/p2p/protocols"
|
||||
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
||||
"github.com/ethereum/go-ethereum/pot"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
|
|
@ -92,7 +92,6 @@ func NewPssEnvelope(addr []byte, topic PssTopic, payload []byte) *PssEnvelope {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func (msg *PssMsg) serialize() []byte {
|
||||
rlpdata, _ := rlp.EncodeToBytes(msg)
|
||||
/*buf := bytes.NewBuffer(nil)
|
||||
|
|
@ -103,7 +102,6 @@ func (msg *PssMsg) serialize() []byte {
|
|||
return rlpdata
|
||||
}
|
||||
|
||||
|
||||
var pssSpec = &protocols.Spec{
|
||||
Name: "pss",
|
||||
Version: 1,
|
||||
|
|
@ -145,7 +143,9 @@ type pssHandler func(msg []byte, p *p2p.Peer, from []byte) error
|
|||
// - a message cache to spot messages that previously have been forwarded
|
||||
type Pss struct {
|
||||
network.Overlay // we can get the overlayaddress from this
|
||||
//peerPool map[pot.Address]map[PssTopic]p2p.MsgReadWriter // keep track of all virtual p2p.Peers we are currently speaking to
|
||||
peerPool map[pot.Address]map[PssTopic]p2p.MsgReadWriter // keep track of all virtual p2p.Peers we are currently speaking to
|
||||
fwdPool map[pot.Address]*protocols.Peer // keep track of all peers sitting on the pssmsg routing layer
|
||||
handlers map[PssTopic]map[*pssHandler]bool // topic and version based pss payload handlers
|
||||
fwdcache map[pssDigest]pssCacheEntry // checksum of unique fields from pssmsg mapped to expiry, cache to determine whether to drop msg
|
||||
cachettl time.Duration // how long to keep messages in fwdcache
|
||||
|
|
@ -175,6 +175,7 @@ func NewPss(k network.Overlay, dpa *storage.DPA, params *PssParams) *Pss {
|
|||
return &Pss{
|
||||
Overlay: k,
|
||||
peerPool: make(map[pot.Address]map[PssTopic]p2p.MsgReadWriter, PssPeerCapacity),
|
||||
fwdPool: make(map[pot.Address]*protocols.Peer),
|
||||
handlers: make(map[PssTopic]map[*pssHandler]bool),
|
||||
fwdcache: make(map[pssDigest]pssCacheEntry),
|
||||
cachettl: params.Cachettl,
|
||||
|
|
@ -203,6 +204,9 @@ func (self *Pss) Protocols() []p2p.Protocol {
|
|||
|
||||
func (self *Pss) Run(p *p2p.Peer, rw p2p.MsgReadWriter) error {
|
||||
pp := protocols.NewPeer(p, rw, pssSpec)
|
||||
id := p.ID()
|
||||
h := pot.NewHashAddressFromBytes(network.ToOverlayAddr(id[:]))
|
||||
self.fwdPool[h.Address] = pp
|
||||
return pp.Run(self.handlePssMsg)
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +255,6 @@ func (self *Pss) deregister(topic *PssTopic, h *pssHandler) {
|
|||
// currently not in use as forwarder address is not known in the handler function hooked to the pss dispatcher.
|
||||
// it is included as a courtesy to custom transport layers that may want to implement this
|
||||
func (self *Pss) AddToCache(addr []byte, msg *PssMsg) error {
|
||||
//digest := self.hashMsg(msg)
|
||||
digest, err := self.storeMsg(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -376,17 +379,16 @@ func (self *Pss) Forward(msg *PssMsg) error {
|
|||
// send with kademlia
|
||||
// find the closest peer to the recipient and attempt to send
|
||||
self.Overlay.EachConn(msg.To, 256, func(op network.OverlayConn, po int, isproxbin bool) bool {
|
||||
p, ok := op.(senderPeer)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
//p, ok := op.(senderPeer)
|
||||
h := pot.NewHashAddressFromBytes(op.Address())
|
||||
pp := self.fwdPool[h.Address]
|
||||
addr := self.Overlay.BaseAddr()
|
||||
sendMsg := fmt.Sprintf("%x: msg to %x via %x", common.ByteLabel(addr), common.ByteLabel(msg.To), common.ByteLabel(p.Address()))
|
||||
if self.checkFwdCache(p.Address(), digest) {
|
||||
sendMsg := fmt.Sprintf("%x: msg to %x via %x", common.ByteLabel(addr), common.ByteLabel(msg.To), common.ByteLabel(op.Address()))
|
||||
if self.checkFwdCache(op.Address(), digest) {
|
||||
log.Info(fmt.Sprintf("%v: peer already forwarded to", sendMsg))
|
||||
return true
|
||||
}
|
||||
err := p.Send(msg)
|
||||
err := pp.Send(msg)
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("%v: failed forwarding: %v", sendMsg, err))
|
||||
return true
|
||||
|
|
@ -394,10 +396,10 @@ func (self *Pss) Forward(msg *PssMsg) error {
|
|||
log.Trace(fmt.Sprintf("%v: successfully forwarded", sendMsg))
|
||||
sent++
|
||||
// if equality holds, p is always the first peer given in the iterator
|
||||
if bytes.Equal(msg.To, p.Address()) || !isproxbin {
|
||||
if bytes.Equal(msg.To, op.Address()) || !isproxbin {
|
||||
return false
|
||||
}
|
||||
log.Trace(fmt.Sprintf("%x is in proxbin, keep forwarding", common.ByteLabel(p.Address())))
|
||||
log.Trace(fmt.Sprintf("%x is in proxbin, keep forwarding", common.ByteLabel(op.Address())))
|
||||
return true
|
||||
})
|
||||
|
||||
|
|
@ -511,7 +513,6 @@ func RegisterPssProtocol(pss *Pss, topic *PssTopic, spec *protocols.Spec, target
|
|||
spec: spec,
|
||||
}
|
||||
pss.Register(topic, pp.handle)
|
||||
//return pp
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -575,7 +576,6 @@ func NewTopic(s string, v int) (topic PssTopic) {
|
|||
return topic
|
||||
}
|
||||
|
||||
|
||||
func ToP2pMsg(msg []byte) (p2p.Msg, error) {
|
||||
payload := &PssProtocolMsg{}
|
||||
if err := rlp.DecodeBytes(msg, payload); err != nil {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -17,6 +18,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p/simulations"
|
||||
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
||||
p2ptest "github.com/ethereum/go-ethereum/p2p/testing"
|
||||
"github.com/ethereum/go-ethereum/pot"
|
||||
"github.com/ethereum/go-ethereum/swarm/network"
|
||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||
)
|
||||
|
|
@ -190,10 +192,13 @@ func TestPssSimpleLinear(t *testing.T) {
|
|||
}
|
||||
run := func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
|
||||
id := p.ID()
|
||||
pp := protocols.NewPeer(p, rw, pssSpec)
|
||||
bp := &testPssPeer{
|
||||
Peer: protocols.NewPeer(p, rw, pssSpec),
|
||||
Peer: pp,
|
||||
addr: network.ToOverlayAddr(id[:]),
|
||||
}
|
||||
h := pot.NewHashAddressFromBytes(bp.addr)
|
||||
ps.fwdPool[h.Address] = pp
|
||||
ps.Overlay.On(bp)
|
||||
defer ps.Overlay.Off(bp)
|
||||
log.Debug(fmt.Sprintf("%v", ps.Overlay))
|
||||
|
|
@ -244,6 +249,8 @@ func testPssFullRandom(t *testing.T, adapter adapters.NodeAdapter, nodecount int
|
|||
|
||||
trigger := make(chan *adapters.NodeId)
|
||||
ids := make([]*adapters.NodeId, nodeCount)
|
||||
fullids := ids[0:fullnodecount]
|
||||
fullpeers := [][]byte{}
|
||||
|
||||
for i := 0; i < nodeCount; i++ {
|
||||
nodeconfig := adapters.RandomNodeConfig()
|
||||
|
|
@ -261,6 +268,9 @@ func testPssFullRandom(t *testing.T, adapter adapters.NodeAdapter, nodecount int
|
|||
t.Fatal("error triggering checks for node %s: %s", node.ID().Label(), err)
|
||||
}
|
||||
ids[i] = node.ID()
|
||||
if i < fullnodecount {
|
||||
fullpeers = append(fullpeers, network.ToOverlayAddr(node.ID().Bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
// run a simulation which connects the 10 nodes in a ring and waits
|
||||
|
|
@ -295,15 +305,22 @@ func testPssFullRandom(t *testing.T, adapter adapters.NodeAdapter, nodecount int
|
|||
return false, fmt.Errorf("error getting node client: %s", err)
|
||||
}
|
||||
|
||||
log.Debug("in check", "node", id)
|
||||
|
||||
if lastid != nil {
|
||||
//msg := pssPingMsg{Created: time.Now(),}
|
||||
for _, fid := range fullids {
|
||||
if fid == id {
|
||||
fpeeridx := rand.Int() % (fullnodecount - 1)
|
||||
log.Debug(fmt.Sprintf("fpeeridx %d, fpeer len %d", fpeeridx, len(fullpeers)))
|
||||
if bytes.Equal(fullpeers[fpeeridx], network.ToOverlayAddr(fid.Bytes())) {
|
||||
fpeeridx++
|
||||
}
|
||||
msg := pssPingMsg{Created: time.Now()}
|
||||
code, _ := pssPingProtocol.GetCode(&pssPingMsg{})
|
||||
pmsg, _ := newProtocolMsg(code, msg)
|
||||
client.CallContext(context.Background(), nil, "pss_sendRaw", pssPingTopic, PssAPIMsg{
|
||||
Addr: lastid.Bytes(),
|
||||
Msg: []byte{1, 2, 3},
|
||||
Addr: fullpeers[fpeeridx],
|
||||
Msg: pmsg,
|
||||
})
|
||||
}
|
||||
}
|
||||
lastid = id
|
||||
|
||||
return true, nil
|
||||
|
|
@ -325,6 +342,36 @@ func testPssFullRandom(t *testing.T, adapter adapters.NodeAdapter, nodecount int
|
|||
t.Fatalf("simulation failed: %s", result.Error)
|
||||
}
|
||||
|
||||
trigger = make(chan *adapters.NodeId)
|
||||
|
||||
action = func(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
check = func(ctx context.Context, id *adapters.NodeId) (bool, error) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return false, ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
timeout = 5 * time.Second
|
||||
ctx, cancel = context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
result = simulations.NewSimulation(net).Run(ctx, &simulations.Step{
|
||||
Action: action,
|
||||
Trigger: trigger,
|
||||
Expect: &simulations.Expectation{
|
||||
Nodes: fullids,
|
||||
Check: check,
|
||||
},
|
||||
})
|
||||
if result.Error != nil {
|
||||
t.Fatalf("simulation failed: %s", result.Error)
|
||||
}
|
||||
|
||||
t.Log("Simulation Passed:")
|
||||
t.Logf("Duration: %s", result.FinishedAt.Sub(result.StartedAt))
|
||||
|
||||
|
|
@ -334,40 +381,57 @@ func testPssFullRandom(t *testing.T, adapter adapters.NodeAdapter, nodecount int
|
|||
// triggerChecks triggers a simulation step check whenever a peer is added or
|
||||
// removed from the given node
|
||||
func triggerChecks(trigger chan *adapters.NodeId, net *simulations.Network, id *adapters.NodeId) error {
|
||||
|
||||
gotpeer := make(map[*adapters.NodeId]bool)
|
||||
|
||||
node := net.GetNode(id)
|
||||
if node == nil {
|
||||
return fmt.Errorf("unknown node: %s", id)
|
||||
}
|
||||
go func() {
|
||||
time.Sleep(time.Second)
|
||||
trigger <- id
|
||||
}()
|
||||
/*
|
||||
client, err := node.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events := make(chan PssAPIMsg)
|
||||
sub, err := client.Subscribe(context.Background(), "pss", events, "newMsg", topic)
|
||||
|
||||
peerevents := make(chan *p2p.PeerEvent)
|
||||
peersub, err := client.Subscribe(context.Background(), "admin", peerevents, "peerEvents")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting peer events for node %v: %s", id, err)
|
||||
}
|
||||
|
||||
msgevents := make(chan PssAPIMsg)
|
||||
msgsub, err := client.Subscribe(context.Background(), "pss", msgevents, "newMsg", pssPingTopic)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting peer events for node %v: %s", id, err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer sub.Unsubscribe()
|
||||
defer msgsub.Unsubscribe()
|
||||
defer peersub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case msg := <-events:
|
||||
log.Warn("pss rpc got msg", "msg", msg)
|
||||
case event := <-peerevents:
|
||||
nid := adapters.NewNodeId(event.Peer[:])
|
||||
if event.Type == "add" && !gotpeer[nid] {
|
||||
trigger <- id
|
||||
case err := <-sub.Err():
|
||||
gotpeer[nid] = true
|
||||
}
|
||||
case <-msgevents:
|
||||
trigger <- id
|
||||
case err := <-peersub.Err():
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("error getting peer events for node %v", id), "err", err)
|
||||
}
|
||||
return
|
||||
|
||||
case err := <-msgsub.Err():
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("error getting msg for node %v", id), "err", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
*/
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -404,9 +468,20 @@ func newServices() adapters.Services {
|
|||
log.Error("local dpa creation failed", "error", err)
|
||||
return nil
|
||||
}
|
||||
pssp := NewPssParams()
|
||||
|
||||
return []node.Service{network.NewBzz(config, kademlia, adapters.NewSimStateStore()), NewPss(kademlia, dpa, pssp)}
|
||||
pssp := NewPssParams()
|
||||
ps := NewPss(kademlia, dpa, pssp)
|
||||
|
||||
ping := &pssPing{
|
||||
quitC: make(chan struct{}),
|
||||
}
|
||||
err = RegisterPssProtocol(ps, &pssPingTopic, pssPingProtocol, newPssPingProtocol(ping.pssPingHandler))
|
||||
if err != nil {
|
||||
log.Error("Couldnt register pss protocol", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return []node.Service{network.NewBzz(config, kademlia, adapters.NewSimStateStore()), ps}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ func (pssapi *PssAPI) NewMsg(ctx context.Context, topic PssTopic) (*rpc.Subscrip
|
|||
return psssub, nil
|
||||
}
|
||||
|
||||
// SendRaw sends the message (serialised into byte slice) to a peer with topic
|
||||
// SendRaw sends the message (serialized into byte slice) to a peer with topic
|
||||
func (pssapi *PssAPI) SendRaw(topic PssTopic, msg PssAPIMsg) error {
|
||||
err := pssapi.Pss.Send(msg.Addr, topic, msg.Msg)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in a new issue