Skip to content

Commit

Permalink
smart BFT GRPC forwarding invalid message test (#4429)
Browse files Browse the repository at this point in the history
Signed-off-by: Emil Elizarov <emil.elizarov@ibm.com>
Co-authored-by: Emil Elizarov <emil.elizarov@ibm.com>
  • Loading branch information
semil and Emil Elizarov authored Sep 8, 2023
1 parent cc9f229 commit f895ea2
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 11 deletions.
43 changes: 36 additions & 7 deletions integration/nwo/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ package nwo
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"net"
Expand Down Expand Up @@ -1408,9 +1410,11 @@ func (n *Network) PeerUserSession(p *Peer, user string, command Command) (*gexec
// services. The client connection should be closed when the tests are done
// using it.
func (n *Network) PeerClientConn(p *Peer) *grpc.ClientConn {
return n.newClientConn(
return n.NewClientConn(
n.PeerAddress(p, ListenPort),
filepath.Join(n.PeerLocalTLSDir(p), "ca.crt"),
"",
"",
)
}

Expand All @@ -1419,24 +1423,49 @@ func (n *Network) PeerClientConn(p *Peer) *grpc.ClientConn {
// orderer services. The client connection should be closed when the tests are
// done using it.
func (n *Network) OrdererClientConn(o *Orderer) *grpc.ClientConn {
return n.newClientConn(
return n.NewClientConn(
n.OrdererAddress(o, ListenPort),
filepath.Join(n.OrdererLocalTLSDir(o), "ca.crt"),
"",
"",
)
}

func (n *Network) newClientConn(address, ca string) *grpc.ClientConn {
fingerprint := "grpc::" + address + "::" + ca
func (n *Network) NewClientConn(address, caCertPath string, clientCertPath string, clientKeyPath string) *grpc.ClientConn {
fingerprint := "grpc::" + address + "::" + caCertPath
if d := n.throttleDuration(fingerprint); d > 0 {
time.Sleep(d)
}

var creds credentials.TransportCredentials
var err error
if clientCertPath == "" || clientKeyPath == "" {
creds, err = credentials.NewClientTLSFromFile(caCertPath, "")
Expect(err).NotTo(HaveOccurred())
} else {
// read ca's cert
caCert, err := os.ReadFile(caCertPath)
Expect(err).NotTo(HaveOccurred())

// create cert pool and append ca's cert
certPool := x509.NewCertPool()
Expect(certPool.AppendCertsFromPEM(caCert)).To(BeTrue())

// read client cert
clientCert, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
Expect(err).NotTo(HaveOccurred())

config := &tls.Config{
Certificates: []tls.Certificate{clientCert},
RootCAs: certPool,
}

creds = credentials.NewTLS(config)
}

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

creds, err := credentials.NewClientTLSFromFile(ca, "")
Expect(err).NotTo(HaveOccurred())

conn, err := grpc.DialContext(
ctx,
address,
Expand Down
124 changes: 120 additions & 4 deletions integration/smartbft/smartbft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"context"
"crypto/x509"
"encoding/pem"
"fmt"
Expand All @@ -24,12 +25,14 @@ import (
"syscall"
"time"

"github.com/hyperledger/fabric/orderer/common/cluster"

docker "github.com/fsouza/go-dockerclient"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-config/configtx"
"github.com/hyperledger/fabric-config/configtx/orderer"
"github.com/hyperledger/fabric-protos-go/common"
protosOrderer "github.com/hyperledger/fabric-protos-go/orderer"
ordererProtos "github.com/hyperledger/fabric-protos-go/orderer"
"github.com/hyperledger/fabric/integration/channelparticipation"
conftx "github.com/hyperledger/fabric/integration/configtx"
"github.com/hyperledger/fabric/integration/nwo"
Expand Down Expand Up @@ -1131,7 +1134,7 @@ var _ = Describe("EndToEnd Smart BFT configuration test", func() {

By("Changing the batch max bytes to 1MB")
updateBatchSize(network, peer, orderer1, channel,
func(batchSize *protosOrderer.BatchSize) {
func(batchSize *ordererProtos.BatchSize) {
batchSize.AbsoluteMaxBytes = uint32(newAbsoluteMaxBytes)
})

Expand Down Expand Up @@ -1304,6 +1307,119 @@ var _ = Describe("EndToEnd Smart BFT configuration test", func() {

assertBlockReception(map[string]int{"testchannel1": 8}, network.Orderers[1:], peer, network)
})

It("smartbft forwarding errorous message to leader", func() {
networkConfig := nwo.MultiNodeSmartBFT()
networkConfig.Channels = nil
channel := "testchannel1"

network = nwo.New(networkConfig, testDir, client, StartPort(), components)
network.GenerateConfigTree()
network.Bootstrap()

var ordererRunners []*ginkgomon.Runner
for _, orderer := range network.Orderers {
runner := network.OrdererRunner(orderer)
runner.Command.Env = append(runner.Command.Env, "FABRIC_LOGGING_SPEC=orderer.consensus.smartbft=debug:grpc=debug:policies=debug")
ordererRunners = append(ordererRunners, runner)
proc := ifrit.Invoke(runner)
ordererProcesses = append(ordererProcesses, proc)
Eventually(proc.Ready(), network.EventuallyTimeout).Should(BeClosed())
}

joinChannel(network, channel)

By("Waiting for followers to see the leader")
Eventually(ordererRunners[1].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say("Message from 1"))
Eventually(ordererRunners[2].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say("Message from 1"))
Eventually(ordererRunners[3].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say("Message from 1"))

leader := network.Orderers[0]
follower := network.Orderers[1]

By("Create a GRPC")
grpcConn := network.NewClientConn(
network.OrdererAddress(leader, nwo.ClusterPort),
filepath.Join(network.OrdererLocalTLSDir(leader), "ca.crt"),
filepath.Join(network.OrdererLocalTLSDir(follower), "server.crt"),
filepath.Join(network.OrdererLocalTLSDir(follower), "server.key"),
)
defer grpcConn.Close()

By("Create a step client")
clusterNodeServiceClient := ordererProtos.NewClusterNodeServiceClient(grpcConn)
stepClient, err := clusterNodeServiceClient.Step(context.Background())
Expect(err).NotTo(HaveOccurred())

signer := &nwo.SigningIdentity{
CertPath: network.OrdererSignCert(follower),
KeyPath: filepath.Join(
network.OrdererLocalCryptoDir(follower, "msp"),
"keystore",
"priv_sk",
),
MSPID: network.Organization(follower.Organization).MSPID,
}

client := &cluster.NodeClientStream{
Version: 0,
StepClient: stepClient,
SourceNodeID: uint64(follower.Id),
DestinationNodeID: uint64(leader.Id),
Signer: signer,
Channel: channel,
}

By("Create an envelope with invalid signature")
env, err := protoutil.CreateSignedEnvelope(
common.HeaderType_ENDORSER_TRANSACTION,
channel,
signer,
&common.Envelope{Payload: []byte("TEST_MESSAGE")},
0,
0,
)
Expect(err).NotTo(HaveOccurred())
env.Signature = []byte{}

By("Authenticate to the leader step service")
err = client.Auth()
Expect(err).NotTo(HaveOccurred())

By("Send the request")
req := &ordererProtos.StepRequest{
Payload: &ordererProtos.StepRequest_SubmitRequest{
SubmitRequest: &ordererProtos.SubmitRequest{
Channel: channel,
LastValidationSeq: 0,
Payload: env,
},
},
}

By("Expect an error")
Expect(client.Send(req)).NotTo(HaveOccurred())
requestErrMessage := "SigFilter evaluation failed: implicit policy evaluation failed - 0 sub-policies were satisfied"
Eventually(ordererRunners[0].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say(requestErrMessage))

By("Send valid message")
env, err = protoutil.CreateSignedEnvelope(
common.HeaderType_ENDORSER_TRANSACTION,
channel,
signer,
&common.Envelope{Payload: []byte("TEST_MESSAGE_2")},
0,
0,
)
Expect(err).NotTo(HaveOccurred())

By("Should not be an error")
req.Payload.(*ordererProtos.StepRequest_SubmitRequest).SubmitRequest.Payload = env
Expect(client.Send(req)).NotTo(HaveOccurred())
<-time.After(time.Second)
Eventually(ordererRunners[0].Err(), time.Second).ShouldNot(gbytes.Say(requestErrMessage))
Eventually(ordererRunners[0].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say("writing block 1 with 1 transactions and metadata"))
})
})
})

Expand Down Expand Up @@ -1688,11 +1804,11 @@ func updateBatchSize(
peer *nwo.Peer,
orderer *nwo.Orderer,
channel string,
batchSizeMutator func(batchSize *protosOrderer.BatchSize)) {
batchSizeMutator func(batchSize *ordererProtos.BatchSize)) {
config := nwo.GetConfig(network, peer, orderer, channel)
updatedConfig := proto.Clone(config).(*common.Config)
batchSizeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["BatchSize"]
batchSizeValue := &protosOrderer.BatchSize{}
batchSizeValue := &ordererProtos.BatchSize{}
Expect(proto.Unmarshal(batchSizeConfigValue.Value, batchSizeValue)).To(Succeed())
batchSizeMutator(batchSizeValue)
updatedConfig.ChannelGroup.Groups["Orderer"].Values["BatchSize"] = &common.ConfigValue{
Expand Down

0 comments on commit f895ea2

Please sign in to comment.