Skip to content

Commit 15c301b

Browse files
committed
Connect MSP-components-for gossip with gossip
The gossip layer uses 2 interfaces for identity and cryptographic capabilities, which are implemented using the various MSP managers (either local or channel-based). The 2 interfaces are found under gossip/api and they are called MessageCryptoService and SecurityAdvisor. They were implemented using the MSP, and this commit connects their implementation to the gossip layer, and removes the fake/dummy implementations that were used as placeholders. - This test also fixes a bug that is related to parsing the certificate of anchor peers. - It also now makes the default anchor peer (if non specified) to be peer0 with the certificate of msp/sampleconfig - And it also fixes a small bug was introduced by a commit a few days ago that was caused by passing a certificate instead of a PKI-ID into the gossip identity mapper, when validating a channel state-info message. How was this tested? I ran 4 instances of peers, in 2 different orgs, but with rootCAs of all orgs in all peer local MSP configurations, and with peer0 as a bootstrap peer for the rest 3 peers, and made sure that the gossip communication logs in all 4 peers send messages to 3 other peers. This proves that they are able to authenticate and exchange membership information about each other. Then I created a channel, and made peers join it, and saw that they send one another channel related messages and no warnings/errors were seen in the logs. Signed-off-by: Yacov Manevich <[email protected]> Change-Id: Id8b5e7e9400b7c58302e4396c04209f917bbde70
1 parent 886f6bc commit 15c301b

File tree

10 files changed

+85
-97
lines changed

10 files changed

+85
-97
lines changed

core/peer/peer_test.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
ccp "github.com/hyperledger/fabric/core/common/ccprovider"
3131
"github.com/hyperledger/fabric/core/mocks/ccprovider"
3232
"github.com/hyperledger/fabric/gossip/service"
33+
"github.com/hyperledger/fabric/msp/mgmt"
3334
)
3435

3536
func TestInitialize(t *testing.T) {
@@ -57,7 +58,11 @@ func TestCreateChainFromBlock(t *testing.T) {
5758
assert.NoError(t, err)
5859
go grpcServer.Serve(socket)
5960
defer grpcServer.Stop()
60-
service.InitGossipService("localhost:13611", grpcServer)
61+
62+
mgmt.LoadFakeSetupWithLocalMspAndTestChainMsp("../../msp/sampleconfig")
63+
64+
identity, _ := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
65+
service.InitGossipService(identity, "localhost:13611", grpcServer)
6166

6267
err = CreateChainFromBlock(block)
6368
if err != nil {

core/scc/cscc/configer_test.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
3434
"github.com/hyperledger/fabric/core/peer"
3535
"github.com/hyperledger/fabric/gossip/service"
36+
"github.com/hyperledger/fabric/msp/mgmt"
3637
"github.com/hyperledger/fabric/protos/common"
3738
pb "github.com/hyperledger/fabric/protos/peer"
3839
"github.com/hyperledger/fabric/protos/utils"
@@ -116,7 +117,11 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) {
116117
assert.NoError(t, err)
117118
go grpcServer.Serve(socket)
118119
defer grpcServer.Stop()
119-
service.InitGossipService("localhost:13611", grpcServer)
120+
121+
mgmt.LoadFakeSetupWithLocalMspAndTestChainMsp("../../../msp/sampleconfig")
122+
identity, _ := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
123+
124+
service.InitGossipService(identity, "localhost:13611", grpcServer)
120125

121126
// Successful path for JoinChain
122127
blockBytes := mockConfigBlock()

gossip/gossip/gossip_impl.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,11 @@ func (g *gossipServiceImpl) getOrgOfPeer(PKIID common.PKIidType) api.OrgIdentity
869869

870870
func (g *gossipServiceImpl) validateStateInfoMsg(msg *proto.GossipMessage) error {
871871
verifier := func(identity []byte, signature, message []byte) error {
872-
return g.idMapper.Verify(identity, signature, message)
872+
pkiID := g.idMapper.GetPKIidOfCert(api.PeerIdentityType(identity))
873+
if pkiID == nil {
874+
return fmt.Errorf("PKI-ID not found in identity mapper")
875+
}
876+
return g.idMapper.Verify(pkiID, signature, message)
873877
}
874878
identity, err := g.idMapper.Get(msg.GetStateInfo().PkiID)
875879
if err != nil {

gossip/integration/integration.go

+6-66
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,18 @@ limitations under the License.
1717
package integration
1818

1919
import (
20-
"bytes"
21-
"fmt"
2220
"strconv"
2321
"strings"
2422
"time"
2523

26-
"github.com/hyperledger/fabric/gossip/api"
27-
"github.com/hyperledger/fabric/gossip/common"
2824
"github.com/hyperledger/fabric/gossip/gossip"
25+
"github.com/hyperledger/fabric/peer/gossip/mcs"
26+
"github.com/hyperledger/fabric/peer/gossip/sa"
2927
"google.golang.org/grpc"
3028
)
3129

3230
// This file is used to bootstrap a gossip instance for integration/demo purposes ONLY
3331

34-
// TODO: This is a temporary fix to make gossip multi-channel work
35-
// because we don't support cross-organization gossip yet.
36-
// this will be removed once we support gossip across orgs.
37-
var orgId = []byte("ORG1")
38-
3932
func newConfig(selfEndpoint string, bootPeers ...string) *gossip.Config {
4033
port, err := strconv.ParseInt(strings.Split(selfEndpoint, ":")[1], 10, 64)
4134
if err != nil {
@@ -61,62 +54,9 @@ func newConfig(selfEndpoint string, bootPeers ...string) *gossip.Config {
6154
}
6255

6356
// NewGossipComponent creates a gossip component that attaches itself to the given gRPC server
64-
func NewGossipComponent(endpoint string, s *grpc.Server, dialOpts []grpc.DialOption, bootPeers ...string) gossip.Gossip {
57+
func NewGossipComponent(identity []byte, endpoint string, s *grpc.Server, dialOpts []grpc.DialOption, bootPeers ...string) gossip.Gossip {
6558
conf := newConfig(endpoint, bootPeers...)
66-
return gossip.NewGossipService(conf, s, &orgCryptoService{}, &naiveCryptoService{}, []byte(endpoint), dialOpts...)
67-
}
68-
69-
type naiveCryptoService struct {
70-
}
71-
72-
// ValidateIdentity validates the given identity.
73-
// Returns error on failure, nil on success
74-
func (*naiveCryptoService) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
75-
return nil
76-
}
77-
78-
// GetPKIidOfCert returns the PKI-ID of a peer's identity
79-
func (*naiveCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
80-
return common.PKIidType(peerIdentity)
81-
}
82-
83-
// VerifyBlock returns nil if the block is properly signed,
84-
// else returns error
85-
func (*naiveCryptoService) VerifyBlock(chainID common.ChainID, signedBlock api.SignedBlock) error {
86-
return nil
87-
}
88-
89-
// Sign signs msg with this peer's signing key and outputs
90-
// the signature if no error occurred.
91-
func (*naiveCryptoService) Sign(msg []byte) ([]byte, error) {
92-
return msg, nil
93-
}
94-
95-
// VerifyByChannel verifies a peer's signature on a message in the context
96-
// of a specific channel
97-
func (*naiveCryptoService) VerifyByChannel(_ common.ChainID, _ api.PeerIdentityType, _, _ []byte) error {
98-
return nil
99-
}
100-
101-
// Verify verifies a signature on a message that came from a peer with a certain vkID
102-
func (cs *naiveCryptoService) Verify(vkID api.PeerIdentityType, signature, message []byte) error {
103-
if !bytes.Equal(signature, message) {
104-
return fmt.Errorf("Invalid signature")
105-
}
106-
return nil
107-
}
108-
109-
type orgCryptoService struct {
110-
}
111-
112-
// OrgByPeerIdentity returns the OrgIdentityType
113-
// of a given peer identity
114-
func (*orgCryptoService) OrgByPeerIdentity(identity api.PeerIdentityType) api.OrgIdentityType {
115-
return orgId
116-
}
117-
118-
// Verify verifies a JoinChannelMessage, returns nil on success,
119-
// and an error on failure
120-
func (*orgCryptoService) Verify(joinChanMsg api.JoinChannelMessage) error {
121-
return nil
59+
cryptSvc := mcs.NewMessageCryptoService()
60+
secAdv := sa.NewSecurityAdvisor()
61+
return gossip.NewGossipService(conf, s, secAdv, cryptSvc, identity, dialOpts...)
12262
}

gossip/integration/integration_test.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"testing"
2323
"time"
2424

25+
"github.com/hyperledger/fabric/msp/mgmt"
2526
"google.golang.org/grpc"
2627
)
2728

@@ -39,9 +40,12 @@ func TestNewGossipCryptoService(t *testing.T) {
3940
endpoint2 := "localhost:5612"
4041
endpoint3 := "localhost:5613"
4142

42-
g1 := NewGossipComponent(endpoint1, s1, []grpc.DialOption{grpc.WithInsecure()})
43-
g2 := NewGossipComponent(endpoint2, s2, []grpc.DialOption{grpc.WithInsecure()}, endpoint1)
44-
g3 := NewGossipComponent(endpoint3, s3, []grpc.DialOption{grpc.WithInsecure()}, endpoint1)
43+
mgmt.LoadFakeSetupWithLocalMspAndTestChainMsp("../../msp/sampleconfig")
44+
identity, _ := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
45+
46+
g1 := NewGossipComponent(identity, endpoint1, s1, []grpc.DialOption{grpc.WithInsecure()})
47+
g2 := NewGossipComponent(identity, endpoint2, s2, []grpc.DialOption{grpc.WithInsecure()}, endpoint1)
48+
g3 := NewGossipComponent(identity, endpoint3, s3, []grpc.DialOption{grpc.WithInsecure()}, endpoint1)
4549
go s1.Serve(ll1)
4650
go s2.Serve(ll2)
4751
go s3.Serve(ll3)

gossip/service/gossip_service.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (jcm *joinChannelMessage) AnchorPeers() []api.AnchorPeer {
7676
var logger = logging.MustGetLogger("gossipService")
7777

7878
// InitGossipService initialize gossip service
79-
func InitGossipService(endpoint string, s *grpc.Server, bootPeers ...string) {
79+
func InitGossipService(identity []byte, endpoint string, s *grpc.Server, bootPeers ...string) {
8080
once.Do(func() {
8181
logger.Info("Initialize gossip with endpoint", endpoint, "and bootstrap set", bootPeers)
8282
dialOpts := []grpc.DialOption{}
@@ -86,7 +86,7 @@ func InitGossipService(endpoint string, s *grpc.Server, bootPeers ...string) {
8686
dialOpts = append(dialOpts, grpc.WithInsecure())
8787
}
8888

89-
gossip := integration.NewGossipComponent(endpoint, s, dialOpts, bootPeers...)
89+
gossip := integration.NewGossipComponent(identity, endpoint, s, dialOpts, bootPeers...)
9090
gossipServiceInstance = &gossipServiceImpl{
9191
gossipSvc: gossip,
9292
chains: make(map[string]state.GossipStateProvider),

gossip/service/gossip_service_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"testing"
2424

2525
"github.com/hyperledger/fabric/gossip/api"
26+
"github.com/hyperledger/fabric/msp/mgmt"
2627
"github.com/stretchr/testify/assert"
2728
"google.golang.org/grpc"
2829
)
@@ -36,11 +37,14 @@ func TestInitGossipService(t *testing.T) {
3637
go grpcServer.Serve(socket)
3738
defer grpcServer.Stop()
3839

40+
mgmt.LoadFakeSetupWithLocalMspAndTestChainMsp("../../msp/sampleconfig")
41+
identity, _ := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
42+
3943
wg := sync.WaitGroup{}
4044
wg.Add(10)
4145
for i := 0; i < 10; i++ {
4246
go func() {
43-
InitGossipService("localhost:5611", grpcServer)
47+
InitGossipService(identity, "localhost:5611", grpcServer)
4448
wg.Done()
4549
}()
4650
}

msp/identities.go

+15
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,21 @@ func (id *identity) GetOrganizationUnits() string {
7777
return "dunno"
7878
}
7979

80+
// NewSerializedIdentity returns a serialized identity
81+
// having as content the passed mspID and x509 certificate in PEM format.
82+
// This method does not check the validity of certificate nor
83+
// any consistency of the mspID with it.
84+
func NewSerializedIdentity(mspID string, certPEM []byte) ([]byte, error) {
85+
// We serialize identities by prepending the MSPID
86+
// and appending the x509 cert in PEM format
87+
sId := &SerializedIdentity{Mspid: mspID, IdBytes: certPEM}
88+
raw, err := proto.Marshal(sId)
89+
if err != nil {
90+
return nil, fmt.Errorf("Failed serializing identity [%s][% X]: [%s]", mspID, certPEM, err)
91+
}
92+
return raw, nil
93+
}
94+
8095
// Verify checks against a signature and a message
8196
// to determine whether this identity produced the
8297
// signature; it returns nil if so or an error otherwise

peer/common/anchors.go

+25-21
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"strconv"
2626
"strings"
2727

28+
"github.com/hyperledger/fabric/msp"
2829
"github.com/hyperledger/fabric/protos/peer"
2930
)
3031

@@ -112,34 +113,37 @@ func anchorPeerFromFile(filename string) (*peer.AnchorPeer, error) {
112113
if err != nil {
113114
return nil, fmt.Errorf("Anchor peer certificate is not a valid PEM certificate: %v", err)
114115
}
116+
117+
// TODO: this MSP-ID isn't going to stay like that in the future,
118+
// but right now, it's the same for everyone.
119+
identity, err := msp.NewSerializedIdentity("DEFAULT", rawPEM)
120+
if err != nil {
121+
return nil, err
122+
}
123+
115124
ap := &peer.AnchorPeer{
116125
Host: hostname,
117126
Port: int32(port),
118-
Cert: block.Bytes,
127+
Cert: identity,
119128
}
120129
return ap, nil
121130
}
122131

123-
const defaultAnchorPeerFile = `anchorpeer
132+
const defaultAnchorPeerFile = `peer0
124133
7051
125134
-----BEGIN CERTIFICATE-----
126-
MIIDZzCCAk+gAwIBAgIJAKSntkwsYDPhMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNV
127-
BAYTAklMMQ8wDQYDVQQIDAZJc3JhZWwxDjAMBgNVBAcMBUhhaWZhMQwwCgYDVQQK
128-
DANJQk0xDDAKBgNVBAsMA0lCTTAeFw0xNzAxMjcwMzUzMjdaFw0xODAxMjcwMzUz
129-
MjdaMEoxCzAJBgNVBAYTAklMMQ8wDQYDVQQIDAZJc3JhZWwxDjAMBgNVBAcMBUhh
130-
aWZhMQwwCgYDVQQKDANJQk0xDDAKBgNVBAsMA0lCTTCCASIwDQYJKoZIhvcNAQEB
131-
BQADggEPADCCAQoCggEBAL0KUiuuZFfs+BN7+FnDKoeiVGCkayQVrPrdeO8Mwu/n
132-
928T9lhmBI6wFnmkdeEjYTi1M5dks8hEal2AP8ykREc+LTmMH5JAJ8kktnoNQteO
133-
rdFqnBpzA0IdiDnaLLLU3QD22VT47TPxWnfqZ3Z+fEJkmxc+tNmJJ5/0eCxXC4v4
134-
875wQZP8CEeI1EpkljL6AILLNCUN4qpug2R2CCBRvGaqA81TM8NKxvWgN90iSAiv
135-
vrQIc3/aelIpaJN457JEqLWgAcWw982rFUn5+D3u63pUq99lWH16VU4vRdUFzqi1
136-
E3mBbGNTcNBzrBYswj5KhMFHLBpzIwQQX+Tvjh70cwkCAwEAAaNQME4wHQYDVR0O
137-
BBYEFNHpTtXPDggAIavkdxLh+ttFH+HCMB8GA1UdIwQYMBaAFNHpTtXPDggAIavk
138-
dxLh+ttFH+HCMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADuYrb0h
139-
eXepdpkUSZ6t5mk6R4vyaGDQAHCUltL5Q2qhL8f5sWxMBqke/JhbB02+pQCsvj8P
140-
SIVSXuCXgFbzP0O3gNWqGhGn9atgN/j81hGyXtpAl5U5hyqcaFATX++Rdv58TKty
141-
WnjzYUtnrG2W6c5uK/XPmoUHoNHxkgj1HrlmuahdrxzFXkdcND7UIfW8U2K0Cz4V
142-
gJyAC5yIOs+kakE2gwjJI8SqREgegfO1JIbBfnUCkDJj1TLu2eUkBgnVLeJrcbXq
143-
AbiMV4MFfj5KFA51Tp8QltKbsPPm1Vx3+CRVWNnMgqVWygIQF+8h4H/CcETU4XCV
144-
4LqJvYfKwy27YUA=
135+
MIICjDCCAjKgAwIBAgIUBEVwsSx0TmqdbzNwleNBBzoIT0wwCgYIKoZIzj0EAwIw
136+
fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh
137+
biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK
138+
BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMTYxMTExMTcwNzAw
139+
WhcNMTcxMTExMTcwNzAwWjBjMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGgg
140+
Q2Fyb2xpbmExEDAOBgNVBAcTB1JhbGVpZ2gxGzAZBgNVBAoTEkh5cGVybGVkZ2Vy
141+
IEZhYnJpYzEMMAoGA1UECxMDQ09QMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
142+
HBuKsAO43hs4JGpFfiGMkB/xsILTsOvmN2WmwpsPHZNL6w8HWe3xCPQtdG/XJJvZ
143+
+C756KEsUBM3yw5PTfku8qOBpzCBpDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw
144+
FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFOFC
145+
dcUZ4es3ltiCgAVDoyLfVpPIMB8GA1UdIwQYMBaAFBdnQj2qnoI/xMUdn1vDmdG1
146+
nEgQMCUGA1UdEQQeMByCCm15aG9zdC5jb22CDnd3dy5teWhvc3QuY29tMAoGCCqG
147+
SM49BAMCA0gAMEUCIDf9Hbl4xn3z4EwNKmilM9lX2Fq4jWpAaRVB97OmVEeyAiEA
148+
25aDPQHGGq2AvhKT0wvt08cX1GTGCIbfmuLpMwKQj38=
145149
-----END CERTIFICATE-----`

peer/node/start.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/hyperledger/fabric/core/scc"
4040
"github.com/hyperledger/fabric/events/producer"
4141
"github.com/hyperledger/fabric/gossip/service"
42+
"github.com/hyperledger/fabric/msp/mgmt"
4243
"github.com/hyperledger/fabric/peer/common"
4344
pb "github.com/hyperledger/fabric/protos/peer"
4445
"github.com/spf13/cobra"
@@ -169,7 +170,13 @@ func serve(args []string) error {
169170

170171
// Initialize gossip component
171172
bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")
172-
service.InitGossipService(peerEndpoint.Address, grpcServer, bootstrap...)
173+
174+
serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
175+
if err != nil {
176+
panic(fmt.Sprintf("Failed serializing self identity: %v", err))
177+
}
178+
179+
service.InitGossipService(serializedIdentity, peerEndpoint.Address, grpcServer, bootstrap...)
173180
defer service.GetGossipService().Stop()
174181

175182
//initialize the env for chainless startup

0 commit comments

Comments
 (0)