Skip to content

Commit

Permalink
[P2P] Add set hiddenPeer in config file
Browse files Browse the repository at this point in the history
- Full node set BP nodes to designante peer and hidden peer to hide block producer node from other public nodes.
- hidden peer is not visible in p2p AddressesResponse and RPC getpeers
  • Loading branch information
hayarobi committed Dec 24, 2018
1 parent efd2b9c commit 960aecb
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 14 deletions.
1 change: 1 addition & 0 deletions config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type P2PConfig struct {
NPCert string `mapstructure:"npcert" description:"Certificate file for N2N network"`
NPKey string `mapstructure:"npkey" description:"Private Key file for N2N network"`
NPAddPeers []string `mapstructure:"npaddpeers" description:"Add peers to connect with at startup"`
NPHiddenPeers []string `mapstructure:"nphiddenpeers" description:"List of peerids which will not show to other peers"`
NPMaxPeers int `mapstructure:"npmaxpeers" description:"Maximum number of remote peers to keep"`
NPPeerPool int `mapstructure:"nppeerpool" description:"Max peer pool size"`

Expand Down
1 change: 1 addition & 0 deletions message/p2pmsg.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ type GetPeers struct {
// GetPeersRsp contains peer meta information and current states.
type GetPeersRsp struct {
Peers []*types.PeerAddress
Hiddens []bool
// last received block notice
LastBlks []*types.NewBlockNotice
States []types.PeerState
Expand Down
23 changes: 15 additions & 8 deletions p2p/mockPeerManager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func (_m *MockPeerManager) GetPeers() []RemotePeer {
}

// GetPeerAddresses provides a mock function with given fields:
func (_m *MockPeerManager) GetPeerAddresses() ([]*types.PeerAddress, []*types.NewBlockNotice, []types.PeerState) {
func (_m *MockPeerManager) GetPeerAddresses() ([]*types.PeerAddress, []bool, []*types.NewBlockNotice, []types.PeerState) {
ret := _m.Called()

var r0 []*types.PeerAddress
Expand All @@ -266,21 +266,28 @@ func (_m *MockPeerManager) GetPeerAddresses() ([]*types.PeerAddress, []*types.Ne
}
}

var r1 []*types.NewBlockNotice
if rf, ok := ret.Get(1).(func() []*types.NewBlockNotice); ok {
var r1 []bool
if rf, ok := ret.Get(1).(func() []bool); ok {
r1 = rf()
} else {
r1 = ret.Get(1).([]*types.NewBlockNotice)
r1 = ret.Get(1).([]bool)
}

var r2 []types.PeerState
if rf, ok := ret.Get(1).(func() []types.PeerState); ok {
var r2 []*types.NewBlockNotice
if rf, ok := ret.Get(2).(func() []*types.NewBlockNotice); ok {
r2 = rf()
} else {
r2 = ret.Get(1).([]types.PeerState)
r2 = ret.Get(2).([]*types.NewBlockNotice)
}

var r3 []types.PeerState
if rf, ok := ret.Get(3).(func() []types.PeerState); ok {
r3 = rf()
} else {
r3 = ret.Get(3).([]types.PeerState)
}

return r0, r1, r2
return r0, r1, r2, r3
}

// GetStatus provides a mock function with given fields:
Expand Down
4 changes: 2 additions & 2 deletions p2p/p2p.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ func (p2ps *P2P) Receive(context actor.Context) {
// do nothing for now. just for prevent deadletter

case *message.GetPeers:
peers, lastBlks, states := p2ps.pm.GetPeerAddresses()
context.Respond(&message.GetPeersRsp{Peers: peers, LastBlks: lastBlks, States: states})
peers, hiddens, lastBlks, states := p2ps.pm.GetPeerAddresses()
context.Respond(&message.GetPeersRsp{Peers: peers, Hiddens:hiddens, LastBlks: lastBlks, States: states})
case *message.GetSyncAncestor:
p2ps.GetSyncAncestor(msg.ToWhom, msg.Hashes)

Expand Down
21 changes: 18 additions & 3 deletions p2p/peermanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type PeerManager interface {
// GetPeer return registered(handshaked) remote peer object
GetPeer(ID peer.ID) (RemotePeer, bool)
GetPeers() []RemotePeer
GetPeerAddresses() ([]*types.PeerAddress, []*types.NewBlockNotice, []types.PeerState)
GetPeerAddresses() ([]*types.PeerAddress, []bool, []*types.NewBlockNotice, []types.PeerState)
}

/**
Expand All @@ -60,6 +60,7 @@ type peerManager struct {
mm metric.MetricsManager

designatedPeers map[peer.ID]PeerMeta
hiddenPeerSet map[peer.ID]bool

remotePeers map[peer.ID]*remotePeerImpl
peerPool map[peer.ID]PeerMeta
Expand Down Expand Up @@ -104,6 +105,7 @@ func NewPeerManager(handlerFactory HandlerFactory, hsFactory HSHandlerFactory, i
mutex: &sync.Mutex{},

designatedPeers: make(map[peer.ID]PeerMeta, len(cfg.P2P.NPAddPeers)),
hiddenPeerSet: make(map[peer.ID]bool,len(cfg.P2P.NPHiddenPeers)),

remotePeers: make(map[peer.ID]*remotePeerImpl, p2pConf.NPMaxPeers),
peerPool: make(map[peer.ID]PeerMeta, p2pConf.NPPeerPool),
Expand Down Expand Up @@ -138,6 +140,14 @@ func (pm *peerManager) RegisterEventListener(listener PeerEventListener) {
func (pm *peerManager) init() {
// set designated peers
pm.initDesignatedPeerList()
// init hidden peers
for _, pidStr := range pm.conf.NPHiddenPeers {
pid, err := peer.IDB58Decode(pidStr)
if err != nil {
panic("Invalid pid in NPHiddenPeers : "+pidStr+" err "+err.Error())
}
pm.hiddenPeerSet[pid] = true
}
}

func (pm *peerManager) getProtocolAddrs() (protocolAddr net.IP, protocolPort int) {
Expand Down Expand Up @@ -518,21 +528,26 @@ func (pm *peerManager) GetPeers() []RemotePeer {
return pm.peerCache
}

func (pm *peerManager) GetPeerAddresses() ([]*types.PeerAddress, []*types.NewBlockNotice, []types.PeerState) {
func (pm *peerManager) GetPeerAddresses() ([]*types.PeerAddress, []bool, []*types.NewBlockNotice, []types.PeerState) {
peers := make([]*types.PeerAddress, 0, len(pm.remotePeers))
hiddens := make([]bool, 0, len(pm.remotePeers))
blks := make([]*types.NewBlockNotice, 0, len(pm.remotePeers))
states := make([]types.PeerState, 0, len(pm.remotePeers))
for _, aPeer := range pm.remotePeers {
addr := aPeer.meta.ToPeerAddress()
hiddens = append(hiddens, aPeer.meta.Hidden)
peers = append(peers, &addr)
blks = append(blks, aPeer.lastNotice)
states = append(states, aPeer.state)
}
return peers, blks, states
return peers, hiddens, blks, states
}

// this method should be called inside pm.mutex
func (pm *peerManager) insertPeer(ID peer.ID, peer *remotePeerImpl) {
if _,exist := pm.hiddenPeerSet[ID]; exist {
peer.meta.Hidden = true
}
pm.remotePeers[ID] = peer
pm.updatePeerCache()
}
Expand Down
3 changes: 2 additions & 1 deletion p2p/peermanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ func TestPeerManager_GetPeerAddresses(t *testing.T) {
pm.remotePeers[peer.ID()] = peer
}

actPeers, actBklNotices, actStates := pm.GetPeerAddresses()
actPeers, hiddens, actBklNotices, actStates := pm.GetPeerAddresses()
assert.Equal(t, peersLen, len(actPeers))
assert.Equal(t, peersLen, len(hiddens))
assert.Equal(t, peersLen, len(actBklNotices))
assert.Equal(t, peersLen, len(actStates))
})
Expand Down
4 changes: 4 additions & 0 deletions p2p/subprotocoladdrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ func (ph *addressesRequestHandler) handle(msg Message, msgBody proto.Message) {
if aPeer.ID() == peerID {
continue
}
if aPeer.Meta().Hidden {
continue
}

pAddr := aPeer.Meta().ToPeerAddress()
addrList = append(addrList, &pAddr)
addrCount++
Expand Down
122 changes: 122 additions & 0 deletions p2p/subprotocoladdrs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/**
* @file
* @copyright defined in aergo/LICENSE.txt
*/

package p2p

import (
"fmt"
"github.com/libp2p/go-libp2p-crypto"
"github.com/libp2p/go-libp2p-peer"
"github.com/stretchr/testify/mock"
"testing"

"github.com/aergoio/aergo/types"
"github.com/golang/protobuf/proto"
)

var samplePeers []RemotePeer

func init() {
samplePeers = make([]RemotePeer, 20)
for i := 0; i < 20; i++ {
_, pub, _ := crypto.GenerateKeyPair(crypto.Secp256k1, 256)
peerid, _ := peer.IDFromPublicKey(pub)
// first 10 are visible, others are hidden
meta := PeerMeta{ID: peerid, Hidden:i>=10}
samplePeer := &remotePeerImpl{meta:meta}
samplePeers[i] = samplePeer
}
fmt.Println("peers ",samplePeers)
}


func MakeSenderSlice(slis ...[]RemotePeer) []RemotePeer {
result := make([]RemotePeer, 0, 10)
for _, sli := range slis {
result = append(result, sli...)
}
return result
}

func Test_addressesRequestHandler_handle(t *testing.T) {
dummySender := &types.PeerAddress{PeerID:[]byte(dummyPeerID),Port:7845}
senderPeer := &remotePeerImpl{meta:PeerMeta{ID:dummyPeerID2}}
tests := []struct {
name string
gotPeers []RemotePeer
wantSize int
}{
{"TVisible",samplePeers[:10], 10},
{"THidden",samplePeers[10:], 0},
{"TMix",samplePeers[5:15], 5},
{"TVisibleWithSender",MakeSenderSlice(samplePeers[:10], []RemotePeer{senderPeer}), 10},
{"THiddenWithSender",MakeSenderSlice(samplePeers[10:], []RemotePeer{senderPeer}), 0},
{"TMixWithSender",MakeSenderSlice(samplePeers[5:15], []RemotePeer{senderPeer}), 5},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockPM := new(MockPeerManager)
mockPM .On("SelfNodeID").Return(dummyPeerID)
mockPM.On("GetPeers").Return(tt.gotPeers)
mockPeer := new(MockRemotePeer)
mockMF := new(MockMoFactory)
mockActor := new(MockActorService)
mockPeer.On("ID").Return(dummyPeerID2)
mockPeer.On("MF").Return(mockMF)
mockPeer.On("sendMessage", mock.Anything)
mockMF.On("newMsgResponseOrder", mock.Anything, AddressesResponse, mock.MatchedBy(
func(p0 *types.AddressesResponse) bool {
return len(p0.Peers) == tt.wantSize
})).Return(dummyMo)
ph := newAddressesReqHandler(mockPM, mockPeer, logger, mockActor)
dummyMsg := &V030Message{id:NewMsgID()}
msgBody := &types.AddressesRequest{Sender:dummySender, MaxSize:50}
ph.handle(dummyMsg, msgBody)


})
}
}

func Test_addressesResponseHandler_checkAndAddPeerAddresses(t *testing.T) {
type args struct {
peers []*types.PeerAddress
}
tests := []struct {
name string
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
})
}
}

func Test_addressesResponseHandler_handle(t *testing.T) {
type fields struct {
BaseMsgHandler BaseMsgHandler
}
type args struct {
msg Message
msgBody proto.Message
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ph := &addressesResponseHandler{
BaseMsgHandler: tt.fields.BaseMsgHandler,
}
ph.handle(tt.args.msg, tt.args.msgBody)
})
}
}
3 changes: 3 additions & 0 deletions rpc/grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,9 @@ func (rpc *AergoRPCService) GetPeers(ctx context.Context, in *types.Empty) (*typ

ret := &types.PeerList{Peers: []*types.Peer{}}
for i, state := range rsp.States {
if rsp.Hiddens[i] {
continue
}
peer := &types.Peer{Address: rsp.Peers[i], State: int32(state), Bestblock: rsp.LastBlks[i]}
ret.Peers = append(ret.Peers, peer)
}
Expand Down

0 comments on commit 960aecb

Please sign in to comment.