go_study/fabric-main/internal/peer/gossip/mcs_test.go

665 lines
25 KiB
Go

/*
Copyright IBM Corp. 2017 All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package gossip
import (
"crypto/sha256"
"errors"
"reflect"
"strings"
"testing"
"time"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-protos-go/common"
pmsp "github.com/hyperledger/fabric-protos-go/msp"
protospeer "github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/bccsp/sw"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/gossip/api"
"github.com/hyperledger/fabric/internal/peer/gossip/mocks"
"github.com/hyperledger/fabric/internal/pkg/identity"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/msp/mgmt"
"github.com/hyperledger/fabric/protoutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
//go:generate counterfeiter -o mocks/policy_manager.go -fake-name PolicyManager . policyManager
type policyManager interface {
policies.Manager
}
//go:generate counterfeiter -o mocks/signer_serializer.go --fake-name SignerSerializer . signerSerializer
type signerSerializer interface {
identity.SignerSerializer
}
//go:generate counterfeiter -o mocks/resources.go --fake-name Resources . resources
type resources interface {
channelconfig.Resources
}
//go:generate counterfeiter -o mocks/orderer.go --fake-name Orderer . orderer
type orderer interface {
channelconfig.Orderer
}
//go:generate counterfeiter -o mocks/channel.go --fake-name Channel . channel
type channel interface {
channelconfig.Channel
}
//go:generate counterfeiter -o mocks/channel_capabilities.go --fake-name ChannelCapabilities . channelCapabilities
type channelCapabilities interface {
channelconfig.ChannelCapabilities
}
func TestPKIidOfCert(t *testing.T) {
deserializersManager := &mocks.DeserializersManager{
LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
}
signer := &mocks.SignerSerializer{}
signer.SerializeReturns([]byte("Alice"), nil)
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
msgCryptoService := NewMCS(
&mocks.ChannelPolicyManagerGetterWithManager{},
signer,
deserializersManager,
cryptoProvider,
mockChannelConfigGetter,
)
peerIdentity := []byte("Alice")
pkid := msgCryptoService.GetPKIidOfCert(peerIdentity)
// Check pkid is not nil
require.NotNil(t, pkid, "PKID must be different from nil")
// Check that pkid is correctly computed
id, err := deserializersManager.Deserialize(peerIdentity)
require.NoError(t, err, "Failed getting validated identity from [% x]", []byte(peerIdentity))
idRaw := append([]byte(id.Mspid), id.IdBytes...)
require.NoError(t, err, "Failed marshalling identity identifier [% x]: [%s]", peerIdentity, err)
h := sha256.New()
h.Write(idRaw)
digest := h.Sum(nil)
require.Equal(t, digest, []byte(pkid), "PKID must be the SHA2-256 of peerIdentity")
// The PKI-ID is calculated by concatenating the MspId with IdBytes.
// Ensure that additional fields haven't been introduced in the code
v := reflect.Indirect(reflect.ValueOf(id)).Type()
fieldsThatStartWithXXX := 0
for i := 0; i < v.NumField(); i++ {
if strings.Index(v.Field(i).Name, "XXX_") == 0 {
fieldsThatStartWithXXX++
}
}
require.Equal(t, 2+fieldsThatStartWithXXX, v.NumField())
}
func TestPKIidOfNil(t *testing.T) {
signer := &mocks.SignerSerializer{}
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
localMSP := mgmt.GetLocalMSP(cryptoProvider)
msgCryptoService := NewMCS(
&mocks.ChannelPolicyManagerGetter{},
signer,
NewDeserializersManager(localMSP),
cryptoProvider,
mockChannelConfigGetter,
)
pkid := msgCryptoService.GetPKIidOfCert(nil)
// Check pkid is not nil
require.Nil(t, pkid, "PKID must be nil")
}
func TestValidateIdentity(t *testing.T) {
deserializersManager := &mocks.DeserializersManager{
LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
ChannelDeserializers: map[string]msp.IdentityDeserializer{
"A": &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}},
},
}
signer := &mocks.SignerSerializer{}
signer.SerializeReturns([]byte("Charlie"), nil)
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
msgCryptoService := NewMCS(
&mocks.ChannelPolicyManagerGetterWithManager{},
signer,
deserializersManager,
cryptoProvider,
mockChannelConfigGetter,
)
err = msgCryptoService.ValidateIdentity([]byte("Alice"))
require.NoError(t, err)
err = msgCryptoService.ValidateIdentity([]byte("Bob"))
require.NoError(t, err)
err = msgCryptoService.ValidateIdentity([]byte("Charlie"))
require.Error(t, err)
err = msgCryptoService.ValidateIdentity(nil)
require.Error(t, err)
// Now, pretend the identities are not well formed
deserializersManager.ChannelDeserializers["A"].(*mocks.IdentityDeserializer).On("IsWellFormed", mock.Anything).Return(errors.New("invalid form"))
err = msgCryptoService.ValidateIdentity([]byte("Bob"))
require.Error(t, err)
require.Equal(t, "identity is not well formed: invalid form", err.Error())
deserializersManager.LocalDeserializer.(*mocks.IdentityDeserializer).On("IsWellFormed", mock.Anything).Return(errors.New("invalid form"))
err = msgCryptoService.ValidateIdentity([]byte("Alice"))
require.Error(t, err)
require.Equal(t, "identity is not well formed: invalid form", err.Error())
}
func TestSign(t *testing.T) {
signer := &mocks.SignerSerializer{}
signer.SignReturns([]byte("signature"), nil)
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
localMSP := mgmt.GetLocalMSP(cryptoProvider)
msgCryptoService := NewMCS(
&mocks.ChannelPolicyManagerGetter{},
signer,
NewDeserializersManager(localMSP),
cryptoProvider,
mockChannelConfigGetter,
)
msg := []byte("Hello World!!!")
sigma, err := msgCryptoService.Sign(msg)
require.NoError(t, err, "Failed generating signature")
require.NotNil(t, sigma, "Signature must be different from nil")
}
func TestVerify(t *testing.T) {
signer := &mocks.SignerSerializer{}
signer.SerializeReturns([]byte("Alice"), nil)
signer.SignReturns([]byte("msg1"), nil)
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
msgCryptoService := NewMCS(
&mocks.ChannelPolicyManagerGetterWithManager{
Managers: map[string]policies.Manager{
"A": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}}},
},
"B": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}}},
},
"C": nil,
},
},
signer,
&mocks.DeserializersManager{
LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
ChannelDeserializers: map[string]msp.IdentityDeserializer{
"A": &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}},
"B": &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}},
"C": &mocks.IdentityDeserializer{Identity: []byte("Dave"), Msg: []byte("msg4"), Mock: mock.Mock{}},
},
},
cryptoProvider,
mockChannelConfigGetter,
)
msg := []byte("msg1")
sigma, err := msgCryptoService.Sign(msg)
require.NoError(t, err, "Failed generating signature")
err = msgCryptoService.Verify(api.PeerIdentityType("Alice"), sigma, msg)
require.NoError(t, err, "Alice should verify the signature")
err = msgCryptoService.Verify(api.PeerIdentityType("Bob"), sigma, msg)
require.Error(t, err, "Bob should not verify the signature")
err = msgCryptoService.Verify(api.PeerIdentityType("Charlie"), sigma, msg)
require.Error(t, err, "Charlie should not verify the signature")
sigma, err = msgCryptoService.Sign(msg)
require.NoError(t, err)
err = msgCryptoService.Verify(api.PeerIdentityType("Dave"), sigma, msg)
require.Error(t, err)
require.Contains(t, err.Error(), "Could not acquire policy manager")
// Check invalid args
require.Error(t, msgCryptoService.Verify(nil, sigma, msg))
}
func TestVerifyBlock(t *testing.T) {
aliceSigner := &mocks.SignerSerializer{}
aliceSigner.SerializeReturns([]byte("Alice"), nil)
policyManagerGetter := &mocks.ChannelPolicyManagerGetterWithManager{
Managers: map[string]policies.Manager{
"A": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}}},
},
"B": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}}},
},
"C": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}}},
},
"D": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}}},
},
},
}
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
msgCryptoService := NewMCS(
policyManagerGetter,
aliceSigner,
&mocks.DeserializersManager{
LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
ChannelDeserializers: map[string]msp.IdentityDeserializer{
"A": &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}},
"B": &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}},
},
},
cryptoProvider,
mockChannelConfigGetter,
)
// - Prepare testing valid block, Alice signs it.
blockRaw, msg := mockBlock(t, "C", 42, aliceSigner, nil)
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
blockRaw2, msg2 := mockBlock(t, "D", 42, aliceSigner, nil)
policyManagerGetter.Managers["D"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg2
t.Run("verify block", func(t *testing.T) {
require.NoError(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRaw))
// Wrong sequence number claimed
err = msgCryptoService.VerifyBlock([]byte("C"), 43, blockRaw)
require.Error(t, err)
require.Contains(t, err.Error(), "but actual seqNum inside block is")
delete(policyManagerGetter.Managers, "D")
nilPolMgrErr := msgCryptoService.VerifyBlock([]byte("D"), 42, blockRaw2)
require.Contains(t, nilPolMgrErr.Error(), "Could not acquire policy manager")
require.Error(t, nilPolMgrErr)
require.Error(t, msgCryptoService.VerifyBlock([]byte("A"), 42, blockRaw))
require.Error(t, msgCryptoService.VerifyBlock([]byte("B"), 42, blockRaw))
// - Prepare testing invalid block (wrong data has), Alice signs it.
blockRawInvalid, msgInvalid := mockBlock(t, "C", 42, aliceSigner, []byte{0})
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msgInvalid
defer func() {
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
}()
// - Verify block
require.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRawInvalid))
// Check invalid args
require.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, &common.Block{}))
})
t.Run("verify block attestation", func(t *testing.T) {
// An attestation is a signed block with block.Data = nil
attestation := blockRaw
attestation.Data = nil
attestation2 := blockRaw2
attestation2.Data = nil
assert.NoError(t, msgCryptoService.VerifyBlockAttestation("C", attestation))
delete(policyManagerGetter.Managers, "D")
nilPolMgrErr := msgCryptoService.VerifyBlockAttestation("D", attestation2)
assert.Contains(t, nilPolMgrErr.Error(), "Could not acquire policy manager")
assert.Error(t, nilPolMgrErr)
assert.Error(t, msgCryptoService.VerifyBlockAttestation("A", attestation))
assert.Error(t, msgCryptoService.VerifyBlockAttestation("B", attestation))
// - Prepare testing invalid attestation (wrong data has), Alice signs it.
// - Prepare testing invalid attestation (wrong data has), Alice signs it.
_, msgInvalid := mockBlock(t, "C", 42, aliceSigner, []byte{0})
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msgInvalid
defer func() {
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
}()
// - Verify attestation
assert.Error(t, msgCryptoService.VerifyBlockAttestation("C", attestation))
// Check invalid args
attestation.Header.DataHash = []byte{0, 1, 2, 3, 4}
assert.Error(t, msgCryptoService.VerifyBlockAttestation("C", attestation))
attestation.Metadata = nil
assert.Error(t, msgCryptoService.VerifyBlockAttestation("C", attestation))
attestation.Header = nil
assert.Error(t, msgCryptoService.VerifyBlockAttestation("C", attestation))
assert.Error(t, msgCryptoService.VerifyBlockAttestation("C", nil))
})
}
func TestVerifyBlockBFT(t *testing.T) {
aliceSigner := &mocks.SignerSerializer{}
consenters := mockConsenters()
aliceID := protoutil.MarshalOrPanic(&pmsp.SerializedIdentity{
Mspid: consenters[0].MspId,
IdBytes: consenters[0].Identity,
})
bobID := protoutil.MarshalOrPanic(&pmsp.SerializedIdentity{
Mspid: consenters[1].MspId,
IdBytes: consenters[1].Identity,
})
charlieID := protoutil.MarshalOrPanic(&pmsp.SerializedIdentity{
Mspid: consenters[2].MspId,
IdBytes: consenters[2].Identity,
})
aliceSigner.SerializeReturns(aliceID, nil)
policyManagerGetter := &mocks.ChannelPolicyManagerGetterWithManager{
Managers: map[string]policies.Manager{
"A": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: bobID, Msg: []byte("msg2"), Mock: mock.Mock{}}},
},
"B": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: charlieID, Msg: []byte("msg3"), Mock: mock.Mock{}}},
},
"C": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: aliceID, Msg: []byte("msg1"), Mock: mock.Mock{}}},
},
"D": &mocks.ChannelPolicyManager{
Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: aliceID, Msg: []byte("msg1"), Mock: mock.Mock{}}},
},
},
}
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
msgCryptoService := NewMCS(
policyManagerGetter,
aliceSigner,
&mocks.DeserializersManager{
LocalDeserializer: &mocks.IdentityDeserializer{Identity: aliceID, Msg: []byte("msg1"), Mock: mock.Mock{}},
ChannelDeserializers: map[string]msp.IdentityDeserializer{
"A": &mocks.IdentityDeserializer{Identity: bobID, Msg: []byte("msg2"), Mock: mock.Mock{}},
"B": &mocks.IdentityDeserializer{Identity: charlieID, Msg: []byte("msg3"), Mock: mock.Mock{}},
},
},
cryptoProvider,
mockChannelConfigGetterBFT,
)
// - Prepare testing valid block, Alice signs it.
blockRaw, msg := mockBlockBFT(t, "C", 42, aliceSigner, nil)
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
blockRaw2, msg2 := mockBlockBFT(t, "D", 42, aliceSigner, nil)
policyManagerGetter.Managers["D"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg2
t.Run("verify block", func(t *testing.T) {
// - Verify block
require.NoError(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRaw))
// Wrong sequence number claimed
err = msgCryptoService.VerifyBlock([]byte("C"), 43, blockRaw)
require.Error(t, err)
require.Contains(t, err.Error(), "but actual seqNum inside block is")
delete(policyManagerGetter.Managers, "D")
nilPolMgrErr := msgCryptoService.VerifyBlock([]byte("D"), 42, blockRaw2)
require.Contains(t, nilPolMgrErr.Error(), "Could not acquire policy manager")
require.Error(t, nilPolMgrErr)
require.Error(t, msgCryptoService.VerifyBlock([]byte("A"), 42, blockRaw))
require.Error(t, msgCryptoService.VerifyBlock([]byte("B"), 42, blockRaw))
// - Prepare testing invalid block (wrong data has), Alice signs it.
blockRawInvalid, msgInvalid := mockBlockBFT(t, "C", 42, aliceSigner, []byte{0})
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msgInvalid
defer func() {
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
}()
// - Verify block
require.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRawInvalid))
// Check invalid args
require.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, &common.Block{}))
})
t.Run("verify block attestation", func(t *testing.T) {
// An attestation is a signed block with block.Data = nil
attestation := blockRaw
attestation.Data = nil
attestation2 := blockRaw2
attestation2.Data = nil
// - Verify block
require.NoError(t, msgCryptoService.VerifyBlockAttestation("C", attestation))
nilPolMgrErr := msgCryptoService.VerifyBlockAttestation("D", attestation2)
require.Contains(t, nilPolMgrErr.Error(), "Could not acquire policy manager")
require.Error(t, nilPolMgrErr)
require.Error(t, msgCryptoService.VerifyBlockAttestation("A", attestation))
require.Error(t, msgCryptoService.VerifyBlockAttestation("B", attestation))
// - Prepare testing invalid block (has wrong data), Alice signs it.
_, msgInvalid := mockBlockBFT(t, "C", 42, aliceSigner, []byte{0})
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msgInvalid
defer func() {
policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
}()
// - Verify block
require.Error(t, msgCryptoService.VerifyBlockAttestation("C", attestation))
})
}
func mockBlock(t *testing.T, channel string, seqNum uint64, localSigner *mocks.SignerSerializer, dataHash []byte) (*common.Block, []byte) {
block := protoutil.NewBlock(seqNum, nil)
// Add a fake transaction to the block referring channel "C"
sProp, _ := protoutil.MockSignedEndorserProposalOrPanic(channel, &protospeer.ChaincodeSpec{}, []byte("transactor"), []byte("transactor's signature"))
sPropRaw, err := protoutil.Marshal(sProp)
require.NoError(t, err, "Failed marshalling signed proposal")
block.Data.Data = [][]byte{sPropRaw}
// Compute hash of block.Data and put into the Header
if len(dataHash) != 0 {
block.Header.DataHash = dataHash
} else {
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
}
// Add signer's signature to the block
shdr, err := protoutil.NewSignatureHeader(localSigner)
require.NoError(t, err, "Failed generating signature header")
blockSignature := &common.MetadataSignature{
SignatureHeader: protoutil.MarshalOrPanic(shdr),
}
// Note, this value is intentionally nil, as this metadata is only about the signature, there is no additional metadata
// information required beyond the fact that the metadata item is signed.
blockSignatureValue := []byte(nil)
msg := util.ConcatenateBytes(blockSignatureValue, blockSignature.SignatureHeader, protoutil.BlockHeaderBytes(block.Header))
localSigner.SignReturns(msg, nil)
blockSignature.Signature, err = localSigner.Sign(msg)
require.NoError(t, err, "Failed signing block")
block.Metadata.Metadata[common.BlockMetadataIndex_SIGNATURES] = protoutil.MarshalOrPanic(&common.Metadata{
Value: blockSignatureValue,
Signatures: []*common.MetadataSignature{
blockSignature,
},
})
return block, msg
}
func mockBlockBFT(t *testing.T, channel string, seqNum uint64, localSigner *mocks.SignerSerializer, dataHash []byte) (*common.Block, []byte) {
block := protoutil.NewBlock(seqNum, nil)
// Add a fake transaction to the block referring channel "C"
sProp, _ := protoutil.MockSignedEndorserProposalOrPanic(channel, &protospeer.ChaincodeSpec{}, []byte("transactor"), []byte("transactor's signature"))
sPropRaw, err := protoutil.Marshal(sProp)
require.NoError(t, err, "Failed marshalling signed proposal")
block.Data.Data = [][]byte{sPropRaw}
// Compute hash of block.Data and put into the Header
if len(dataHash) != 0 {
block.Header.DataHash = dataHash
} else {
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
}
ihdr := &common.IdentifierHeader{
Identifier: 1,
}
blockSignature := &common.MetadataSignature{
IdentifierHeader: protoutil.MarshalOrPanic(ihdr),
}
// Note, this value is intentionally nil, as this metadata is only about the signature, there is no additional metadata
// information required beyond the fact that the metadata item is signed.
blockSignatureValue := []byte(nil)
msg := util.ConcatenateBytes(blockSignatureValue, blockSignature.IdentifierHeader, protoutil.BlockHeaderBytes(block.Header))
localSigner.SignReturns(msg, nil)
blockSignature.Signature, err = localSigner.Sign(msg)
require.NoError(t, err, "Failed signing block")
block.Metadata.Metadata[common.BlockMetadataIndex_SIGNATURES] = protoutil.MarshalOrPanic(&common.Metadata{
Value: blockSignatureValue,
Signatures: []*common.MetadataSignature{
blockSignature,
},
})
return block, msg
}
func TestExpiration(t *testing.T) {
expirationDate := time.Now().Add(time.Minute)
id1 := &pmsp.SerializedIdentity{
Mspid: "X509BasedMSP",
IdBytes: []byte("X509BasedIdentity"),
}
x509IdentityBytes, _ := proto.Marshal(id1)
id2 := &pmsp.SerializedIdentity{
Mspid: "nonX509BasedMSP",
IdBytes: []byte("nonX509RawIdentity"),
}
nonX509IdentityBytes, _ := proto.Marshal(id2)
deserializersManager := &mocks.DeserializersManager{
LocalDeserializer: &mocks.IdentityDeserializer{
Identity: []byte{1, 2, 3},
Msg: []byte{1, 2, 3},
},
ChannelDeserializers: map[string]msp.IdentityDeserializer{
"X509BasedMSP": &mocks.IdentityDeserializerWithExpiration{
Expiration: expirationDate,
IdentityDeserializer: &mocks.IdentityDeserializer{
Identity: x509IdentityBytes,
Msg: []byte("x509IdentityBytes"),
},
},
"nonX509BasedMSP": &mocks.IdentityDeserializer{
Identity: nonX509IdentityBytes,
Msg: []byte("nonX509IdentityBytes"),
},
},
}
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
msgCryptoService := NewMCS(
&mocks.ChannelPolicyManagerGetterWithManager{},
&mocks.SignerSerializer{},
deserializersManager,
cryptoProvider,
mockChannelConfigGetter,
)
// Green path I check the expiration date is as expected
exp, err := msgCryptoService.Expiration(x509IdentityBytes)
require.NoError(t, err)
require.Equal(t, expirationDate.Second(), exp.Second())
// Green path II - a non-x509 identity has a zero expiration time
exp, err = msgCryptoService.Expiration(nonX509IdentityBytes)
require.NoError(t, err)
require.Zero(t, exp)
// Bad path I - corrupt the x509 identity and make sure error is returned
x509IdentityBytes = append(x509IdentityBytes, 0, 0, 0, 0, 0, 0)
exp, err = msgCryptoService.Expiration(x509IdentityBytes)
require.Error(t, err)
require.Contains(t, err.Error(), "No MSP found able to do that")
require.Zero(t, exp)
}
func mockChannelConfigGetter(cid string) channelconfig.Resources {
o := &mocks.Orderer{}
o.ConsentersReturns([]*common.Consenter{})
cap := &mocks.ChannelCapabilities{}
cap.ConsensusTypeBFTReturns(false)
c := &mocks.Channel{}
c.CapabilitiesReturns(cap)
res := &mocks.Resources{}
res.OrdererConfigReturns(o, false)
res.ChannelConfigReturns(c)
return res
}
func mockChannelConfigGetterBFT(cid string) channelconfig.Resources {
o := &mocks.Orderer{}
o.ConsentersReturns(mockConsenters())
cap := &mocks.ChannelCapabilities{}
cap.ConsensusTypeBFTReturns(true)
c := &mocks.Channel{}
c.CapabilitiesReturns(cap)
res := &mocks.Resources{}
res.OrdererConfigReturns(o, true)
res.ChannelConfigReturns(c)
return res
}
func mockConsenters() []*common.Consenter {
return []*common.Consenter{
{
Id: 1,
Host: "host1",
Port: 8001,
MspId: "msp1",
Identity: []byte("identity1"),
},
{
Id: 2,
Host: "host2",
Port: 8002,
MspId: "msp2",
Identity: []byte("identity2"),
},
{
Id: 3,
Host: "host3",
Port: 8003,
MspId: "msp3",
Identity: []byte("identity3"),
},
}
}