Skip to content

Commit d21cd6d

Browse files
committed
[FAB-3530] Gossip - add block seq# validation
When a peer receives a data message (contains a block) it doesn't verify that the sequence of the block matches the sequence inside the marshaled block, and just calls VerifyBlock. The implementation already unmarshals the block, so there is no point in un-marshalling it outside. I extended the interface VerifyBlock to accept also a sequence number. Change-Id: I85c6c57f26f5e404fe8e7ece2abffa58eaded625 Signed-off-by: Yacov Manevich <[email protected]>
1 parent 1195f2f commit d21cd6d

17 files changed

+50
-36
lines changed

core/deliverservice/blocksprovider/blocksprovider.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func (b *blocksProviderImpl) DeliverBlocks() {
135135
logger.Errorf("Error serializing block with sequence number %d, due to %s", seqNum, err)
136136
continue
137137
}
138-
if err := b.mcs.VerifyBlock(gossipcommon.ChainID(b.chainID), marshaledBlock); err != nil {
138+
if err := b.mcs.VerifyBlock(gossipcommon.ChainID(b.chainID), seqNum, marshaledBlock); err != nil {
139139
logger.Errorf("Error verifying block with sequnce number %d, due to %s", seqNum, err)
140140
continue
141141
}

core/deliverservice/blocksprovider/blocksprovider_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (*mockMCS) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common2.PKIidT
3939
return common2.PKIidType("pkiID")
4040
}
4141

42-
func (m *mockMCS) VerifyBlock(chainID common2.ChainID, signedBlock []byte) error {
42+
func (m *mockMCS) VerifyBlock(chainID common2.ChainID, seqNum uint64, signedBlock []byte) error {
4343
args := m.Called()
4444
if args.Get(0) != nil {
4545
return args.Get(0).(error)

core/deliverservice/deliveryclient_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (*mockMCS) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidTy
6060
return common.PKIidType("pkiID")
6161
}
6262

63-
func (*mockMCS) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
63+
func (*mockMCS) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
6464
return nil
6565
}
6666

gossip/api/crypto.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ type MessageCryptoService interface {
3333
// This validation is supposed to be done appropriately during the execution flow.
3434
GetPKIidOfCert(peerIdentity PeerIdentityType) common.PKIidType
3535

36-
// VerifyBlock returns nil if the block is properly signed,
36+
// VerifyBlock returns nil if the block is properly signed, and the claimed seqNum is the
37+
// sequence number that the block's header contains.
3738
// else returns error
38-
VerifyBlock(chainID common.ChainID, signedBlock []byte) error
39+
VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error
3940

4041
// Sign signs msg with this peer's signing key and outputs
4142
// the signature if no error occurred.

gossip/comm/comm_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (*naiveSecProvider) GetPKIidOfCert(peerIdentity api.PeerIdentityType) commo
7272

7373
// VerifyBlock returns nil if the block is properly signed,
7474
// else returns error
75-
func (*naiveSecProvider) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
75+
func (*naiveSecProvider) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
7676
return nil
7777
}
7878

gossip/gossip/channel/channel.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -522,11 +522,14 @@ func (gc *gossipChannel) verifyBlock(msg *proto.GossipMessage, sender common.PKI
522522
gc.logger.Warning("Received from ", sender, "a DataUpdate message that contains a non-block GossipMessage:", msg)
523523
return false
524524
}
525-
if msg.GetDataMsg().Payload == nil {
525+
payload := msg.GetDataMsg().Payload
526+
if payload == nil {
526527
gc.logger.Warning("Received empty payload from", sender)
527528
return false
528529
}
529-
err := gc.mcs.VerifyBlock(msg.Channel, msg.GetDataMsg().Payload.Data)
530+
seqNum := payload.SeqNum
531+
rawBlock := payload.Data
532+
err := gc.mcs.VerifyBlock(msg.Channel, seqNum, rawBlock)
530533
if err != nil {
531534
gc.logger.Warning("Received fabricated block from", sender, "in DataUpdate:", err)
532535
return false

gossip/gossip/channel/channel_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func (cs *cryptoService) VerifyByChannel(channel common.ChainID, identity api.Pe
125125
return args.Get(0).(error)
126126
}
127127

128-
func (cs *cryptoService) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
128+
func (cs *cryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
129129
args := cs.Called(signedBlock)
130130
if args.Get(0) == nil {
131131
return nil

gossip/gossip/gossip_impl.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,9 @@ func (g *gossipServiceImpl) validateMsg(msg proto.ReceivedMessage) bool {
431431
return true
432432
}
433433

434-
if err := g.mcs.VerifyBlock(msg.GetGossipMessage().Channel, blockMsg.Payload.Data); err != nil {
434+
seqNum := blockMsg.Payload.SeqNum
435+
rawBlock := blockMsg.Payload.Data
436+
if err := g.mcs.VerifyBlock(msg.GetGossipMessage().Channel, seqNum, rawBlock); err != nil {
435437
g.logger.Warning("Could not verify block", blockMsg.Payload.SeqNum, ":", err)
436438
return false
437439
}

gossip/gossip/gossip_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func (*naiveCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) com
158158

159159
// VerifyBlock returns nil if the block is properly signed,
160160
// else returns error
161-
func (*naiveCryptoService) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
161+
func (*naiveCryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
162162
return nil
163163
}
164164

gossip/gossip/orgs_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (*configurableCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityTy
7777

7878
// VerifyBlock returns nil if the block is properly signed,
7979
// else returns error
80-
func (*configurableCryptoService) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
80+
func (*configurableCryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
8181
return nil
8282
}
8383

gossip/identity/identity_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (*naiveCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) com
5454

5555
// VerifyBlock returns nil if the block is properly signed,
5656
// else returns error
57-
func (*naiveCryptoService) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
57+
func (*naiveCryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
5858
return nil
5959
}
6060

gossip/integration/integration_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func (s *cryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common
119119
return common.PKIidType(peerIdentity)
120120
}
121121

122-
func (s *cryptoService) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
122+
func (s *cryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
123123
return nil
124124
}
125125

gossip/service/gossip_service_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ func (*naiveCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) gos
673673

674674
// VerifyBlock returns nil if the block is properly signed,
675675
// else returns error
676-
func (*naiveCryptoService) VerifyBlock(chainID gossipCommon.ChainID, signedBlock []byte) error {
676+
func (*naiveCryptoService) VerifyBlock(chainID gossipCommon.ChainID, seqNum uint64, signedBlock []byte) error {
677677
return nil
678678
}
679679

gossip/state/state.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ func (s *GossipStateProviderImpl) handleStateResponse(msg proto.ReceivedMessage)
366366
}
367367
for _, payload := range response.GetPayloads() {
368368
logger.Debugf("Received payload with sequence number %d.", payload.SeqNum)
369-
if err := s.mcs.VerifyBlock(common2.ChainID(s.chainID), payload.Data); err != nil {
369+
if err := s.mcs.VerifyBlock(common2.ChainID(s.chainID), payload.SeqNum, payload.Data); err != nil {
370370
logger.Warningf("Error verifying block with sequence number %d, due to %s", payload.SeqNum, err)
371371
return uint64(0), err
372372
}

gossip/state/state_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (*cryptoServiceMock) GetPKIidOfCert(peerIdentity api.PeerIdentityType) comm
106106

107107
// VerifyBlock returns nil if the block is properly signed,
108108
// else returns error
109-
func (*cryptoServiceMock) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
109+
func (*cryptoServiceMock) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
110110
return nil
111111
}
112112

peer/gossip/mcs.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,10 @@ func (s *mspMessageCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityTy
113113
return digest
114114
}
115115

116-
// VerifyBlock returns nil if the block is properly signed,
116+
// VerifyBlock returns nil if the block is properly signed, and the claimed seqNum is the
117+
// sequence number that the block's header contains.
117118
// else returns error
118-
func (s *mspMessageCryptoService) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
119+
func (s *mspMessageCryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
119120
// - Convert signedBlock to common.Block.
120121
block, err := utils.GetBlockFromBlockBytes(signedBlock)
121122
if err != nil {
@@ -126,6 +127,11 @@ func (s *mspMessageCryptoService) VerifyBlock(chainID common.ChainID, signedBloc
126127
return fmt.Errorf("Invalid Block on channel [%s]. Header must be different from nil.", chainID)
127128
}
128129

130+
blockSeqNum := block.Header.Number
131+
if seqNum != blockSeqNum {
132+
return fmt.Errorf("Claimed seqNum is [%d] but actual seqNum inside block is [%d]", seqNum, blockSeqNum)
133+
}
134+
129135
// - Extract channelID and compare with chainID
130136
channelID, err := utils.GetChainIDFromBlock(block)
131137
if err != nil {

peer/gossip/mcs_test.go

+19-17
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@ limitations under the License.
1717
package gossip
1818

1919
import (
20-
"fmt"
21-
"testing"
22-
2320
"reflect"
21+
"testing"
2422

2523
"github.com/golang/protobuf/proto"
2624
"github.com/hyperledger/fabric/bccsp"
@@ -152,7 +150,7 @@ func TestVerify(t *testing.T) {
152150
assert.NoError(t, err)
153151
err = msgCryptoService.Verify(api.PeerIdentityType("Dave"), sigma, msg)
154152
assert.Error(t, err)
155-
assert.Contains(t, fmt.Sprintf("%v", err), "Could not acquire policy manager")
153+
assert.Contains(t, err.Error(), "Could not acquire policy manager")
156154

157155
// Check invalid args
158156
assert.Error(t, msgCryptoService.Verify(nil, sigma, msg))
@@ -182,34 +180,38 @@ func TestVerifyBlock(t *testing.T) {
182180
)
183181

184182
// - Prepare testing valid block, Alice signs it.
185-
blockRaw, msg := mockBlock(t, "C", aliceSigner, nil)
183+
blockRaw, msg := mockBlock(t, "C", 42, aliceSigner, nil)
186184
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
187-
blockRaw2, msg2 := mockBlock(t, "D", aliceSigner, nil)
185+
blockRaw2, msg2 := mockBlock(t, "D", 42, aliceSigner, nil)
188186
policyManagerGetter.Managers["D"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg2
189187

190188
// - Verify block
191-
assert.NoError(t, msgCryptoService.VerifyBlock([]byte("C"), blockRaw))
189+
assert.NoError(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRaw))
190+
// Wrong sequence number claimed
191+
err := msgCryptoService.VerifyBlock([]byte("C"), 43, blockRaw)
192+
assert.Error(t, err)
193+
assert.Contains(t, err.Error(), "but actual seqNum inside block is")
192194
delete(policyManagerGetter.Managers, "D")
193-
nilPolMgrErr := msgCryptoService.VerifyBlock([]byte("D"), blockRaw2)
194-
assert.Contains(t, fmt.Sprintf("%v", nilPolMgrErr), "Could not acquire policy manager")
195+
nilPolMgrErr := msgCryptoService.VerifyBlock([]byte("D"), 42, blockRaw2)
196+
assert.Contains(t, nilPolMgrErr.Error(), "Could not acquire policy manager")
195197
assert.Error(t, nilPolMgrErr)
196-
assert.Error(t, msgCryptoService.VerifyBlock([]byte("A"), blockRaw))
197-
assert.Error(t, msgCryptoService.VerifyBlock([]byte("B"), blockRaw))
198+
assert.Error(t, msgCryptoService.VerifyBlock([]byte("A"), 42, blockRaw))
199+
assert.Error(t, msgCryptoService.VerifyBlock([]byte("B"), 42, blockRaw))
198200

199201
// - Prepare testing invalid block (wrong data has), Alice signs it.
200-
blockRaw, msg = mockBlock(t, "C", aliceSigner, []byte{0})
202+
blockRaw, msg = mockBlock(t, "C", 42, aliceSigner, []byte{0})
201203
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
202204

203205
// - Verify block
204-
assert.Error(t, msgCryptoService.VerifyBlock([]byte("C"), blockRaw))
206+
assert.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRaw))
205207

206208
// Check invalid args
207-
assert.Error(t, msgCryptoService.VerifyBlock([]byte("C"), []byte{0, 1, 2, 3, 4}))
208-
assert.Error(t, msgCryptoService.VerifyBlock([]byte("C"), nil))
209+
assert.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, []byte{0, 1, 2, 3, 4}))
210+
assert.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, nil))
209211
}
210212

211-
func mockBlock(t *testing.T, channel string, localSigner crypto.LocalSigner, dataHash []byte) ([]byte, []byte) {
212-
block := common.NewBlock(0, nil)
213+
func mockBlock(t *testing.T, channel string, seqNum uint64, localSigner crypto.LocalSigner, dataHash []byte) ([]byte, []byte) {
214+
block := common.NewBlock(seqNum, nil)
213215

214216
// Add a fake transaction to the block referring channel "C"
215217
sProp, _ := utils.MockSignedEndorserProposalOrPanic(channel, &protospeer.ChaincodeSpec{}, []byte("transactor"), []byte("transactor's signature"))

0 commit comments

Comments
 (0)