Skip to content

Commit

Permalink
BFT chain unit tests: successful tx propagation
Browse files Browse the repository at this point in the history
Signed-off-by: May Rosenbaum <[email protected]>
Signed-off-by: Emil Elizarov <[email protected]>
  • Loading branch information
MayRosenbaum committed Feb 29, 2024
1 parent 7424152 commit f1f0ef7
Show file tree
Hide file tree
Showing 15 changed files with 2,511 additions and 33 deletions.
29 changes: 11 additions & 18 deletions orderer/consensus/smartbft/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import (
"go.uber.org/zap"
)

//go:generate counterfeiter -o mocks/mock_blockpuller.go . BlockPuller
//go:generate mockery --dir . --name BlockPuller --case underscore --with-expecter=true --output mocks

// BlockPuller is used to pull blocks from other OSN
type BlockPuller interface {
Expand All @@ -53,6 +53,8 @@ type WALConfig struct {
}

// ConfigValidator interface
//
//go:generate mockery --dir . --name ConfigValidator --case underscore --with-expecter=true --output mocks
type ConfigValidator interface {
ValidateConfig(env *cb.Envelope) error
}
Expand All @@ -74,13 +76,13 @@ type BFTChain struct {
BlockPuller BlockPuller
clusterDialer *cluster.PredicateDialer // TODO Required by BFT-synchronizer
localConfigCluster localconfig.Cluster // TODO Required by BFT-synchronizer
Comm cluster.Communicator
Comm Communicator
SignerSerializer signerSerializer
PolicyManager policies.Manager
PolicyManager PolicyManager
Logger *flogging.FabricLogger
WALDir string
consensus *smartbft.Consensus
support consensus.ConsenterSupport
support ConsenterSupport
clusterService *cluster.ClusterService
verifier *Verifier
assembler *Assembler
Expand All @@ -105,12 +107,13 @@ func NewChain(
localConfigCluster localconfig.Cluster,
comm cluster.Communicator,
signerSerializer signerSerializer,
policyManager policies.Manager,
policyManager PolicyManager,
support consensus.ConsenterSupport,
metrics *Metrics,
metricsBFT *api.Metrics,
metricsWalBFT *wal.Metrics,
bccsp bccsp.BCCSP,
egressCommFactory EgressCommFactory,
) (*BFTChain, error) {
logger := flogging.MustGetLogger("orderer.consensus.smartbft.chain").With(zap.String("channel", support.ChannelID()))

Expand Down Expand Up @@ -166,7 +169,7 @@ func NewChain(
c.RuntimeConfig.Store(rtc)

c.verifier = buildVerifier(cv, c.RuntimeConfig, support, requestInspector, policyManager)
c.consensus = bftSmartConsensusBuild(c, requestInspector)
c.consensus = bftSmartConsensusBuild(c, requestInspector, egressCommFactory)

// Setup communication with list of remotes notes for the new channel
c.Comm.Configure(c.support.ChannelID(), rtc.RemoteNodes)
Expand All @@ -183,6 +186,7 @@ func NewChain(
func bftSmartConsensusBuild(
c *BFTChain,
requestInspector *RequestInspector,
egressCommFactory EgressCommFactory,
) *smartbft.Consensus {
var err error

Expand Down Expand Up @@ -275,18 +279,7 @@ func bftSmartConsensusBuild(
Assembler: c.assembler,
RequestInspector: requestInspector,
Synchronizer: sync,
Comm: &Egress{
RuntimeConfig: c.RuntimeConfig,
Channel: c.support.ChannelID(),
Logger: flogging.MustGetLogger("orderer.consensus.smartbft.egress").With(channelDecorator),
RPC: &cluster.RPC{
Logger: flogging.MustGetLogger("orderer.consensus.smartbft.rpc").With(channelDecorator),
Channel: c.support.ChannelID(),
StreamsByType: cluster.NewStreamsByType(),
Comm: c.Comm,
Timeout: 5 * time.Minute, // Externalize configuration
},
},
Comm: egressCommFactory(c.RuntimeConfig, c.Channel, c.Comm),
Scheduler: time.NewTicker(time.Second).C,
ViewChangerTicker: time.NewTicker(time.Second).C,
}
Expand Down
76 changes: 76 additions & 0 deletions orderer/consensus/smartbft/chain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright IBM Corp. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0

package smartbft_test

import (
"bytes"
"encoding/binary"
"testing"

cb "github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/msp"
"github.com/hyperledger/fabric/protoutil"
"github.com/stretchr/testify/require"
)

var (
nonce uint64 = 0
)

// Scenario:
// 1. Start a network of 4 nodes
// 2. Submit a TX
// 3. Wait for the TX to be received by all nodes
func TestSuccessfulTxPropagation(t *testing.T) {
dir := t.TempDir()
channelId := "testchannel"

networkSetupInfo := NewNetworkSetupInfo(t, channelId, dir)
nodeMap := networkSetupInfo.CreateNodes(4)
networkSetupInfo.StartAllNodes()

for _, node := range nodeMap {
node.State.WaitLedgerHeightToBe(1)
}

env := createEndorserTxEnvelope("TEST_MESSAGE #1", channelId)
err := networkSetupInfo.SendTxToAllAvailableNodes(env)
require.NoError(t, err)
for _, node := range nodeMap {
node.State.WaitLedgerHeightToBe(2)
}
}

func createEndorserTxEnvelope(message string, channelId string) *cb.Envelope {
return &cb.Envelope{
Payload: protoutil.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
Type: int32(cb.HeaderType_ENDORSER_TRANSACTION),
ChannelId: channelId,
}),
SignatureHeader: protoutil.MarshalOrPanic(&cb.SignatureHeader{
Creator: protoutil.MarshalOrPanic(&msp.SerializedIdentity{
Mspid: "mockMSP",
IdBytes: []byte("mockClient"),
}),
Nonce: generateNonce(),
}),
},
Data: []byte(message),
}),
Signature: []byte{1, 2, 3},
}
}

func generateNonce() []byte {
nonceBuf := new(bytes.Buffer)
err := binary.Write(nonceBuf, binary.LittleEndian, nonce)
if err != nil {
panic("Cannot generate nonce")
}
nonce++
return nonceBuf.Bytes()
}
27 changes: 24 additions & 3 deletions orderer/consensus/smartbft/consenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ import (
"encoding/pem"
"path"
"reflect"
"sync/atomic"
"time"

"github.com/hyperledger/fabric/orderer/consensus/smartbft/util"

"go.uber.org/zap"

"github.com/SmartBFT-Go/consensus/pkg/api"
"github.com/SmartBFT-Go/consensus/pkg/wal"
Expand All @@ -32,7 +38,6 @@ import (
"github.com/hyperledger/fabric/orderer/common/localconfig"
"github.com/hyperledger/fabric/orderer/common/multichannel"
"github.com/hyperledger/fabric/orderer/consensus"
"github.com/hyperledger/fabric/orderer/consensus/smartbft/util"
"github.com/hyperledger/fabric/protoutil"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
Expand Down Expand Up @@ -96,7 +101,7 @@ func New(
logger.Infof("WAL Directory is %s", walConfig.WALDir)

mpc := &MetricProviderConverter{
metricsProvider: metricsProvider,
MetricsProvider: metricsProvider,
}

consenter := &Consenter{
Expand Down Expand Up @@ -202,6 +207,22 @@ func (c *Consenter) HandleChain(support consensus.ConsenterSupport, metadata *cb
Logger: c.Logger,
}

egressCommFactory := func(runtimeConfig *atomic.Value, channelId string, comm Communicator) EgressComm {
channelDecorator := zap.String("channel", channelId)
return &Egress{
RuntimeConfig: runtimeConfig,
Channel: channelId,
Logger: flogging.MustGetLogger("orderer.consensus.smartbft.egress").With(channelDecorator),
RPC: &cluster.RPC{
Logger: flogging.MustGetLogger("orderer.consensus.smartbft.rpc").With(channelDecorator),
Channel: channelId,
StreamsByType: cluster.NewStreamsByType(),
Comm: comm,
Timeout: 5 * time.Minute, // Externalize configuration
},
}
}

chain, err := NewChain(
configValidator,
(uint64)(selfID),
Expand All @@ -218,7 +239,7 @@ func (c *Consenter) HandleChain(support consensus.ConsenterSupport, metadata *cb
c.MetricsBFT,
c.MetricsWalBFT,
c.BCCSP,
)
egressCommFactory)
if err != nil {
return nil, errors.Wrap(err, "failed creating a new BFTChain")
}
Expand Down
59 changes: 59 additions & 0 deletions orderer/consensus/smartbft/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package smartbft

import (
"sync/atomic"

protos "github.com/SmartBFT-Go/consensus/smartbftprotos"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/orderer/common/cluster"
"github.com/hyperledger/fabric/orderer/consensus"
)

//go:generate mockery --dir . --name ConsenterSupport --case underscore --with-expecter=true --output mocks

// ConsenterSupport provides the resources available to a Consenter implementation.
type ConsenterSupport interface {
consensus.ConsenterSupport
}

//go:generate mockery --dir . --name Communicator --case underscore --with-expecter=true --output mocks

// Communicator defines communication for a consenter
type Communicator interface {
cluster.Communicator
}

//go:generate mockery --dir . --name PolicyManager --case underscore --with-expecter=true --output mocks

// PolicyManager is a read only subset of the policy ManagerImpl
type PolicyManager interface {
policies.Manager
}

//go:generate mockery --dir . --name Policy --case underscore --with-expecter=true --output mocks

// Policy is used to determine if a signature is valid
type Policy interface {
policies.Policy
}

//go:generate mockery --dir . --name EgressComm --case underscore --with-expecter=true --output mocks

type EgressCommFactory func(runtimeConfig *atomic.Value, channelId string, comm Communicator) EgressComm

// Comm enables the communications between the nodes.
type EgressComm interface {
// SendConsensus sends the consensus protocol related message m to the node with id targetID.
SendConsensus(targetID uint64, m *protos.Message)
// SendTransaction sends the given client's request to the node with id targetID.
SendTransaction(targetID uint64, request []byte)
// Nodes returns a set of ids of participating nodes.
// In case you need to change or keep this slice, create a copy.
Nodes() []uint64
}
8 changes: 4 additions & 4 deletions orderer/consensus/smartbft/metrics_provider_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

type MetricProviderConverter struct {
metricsProvider metrics.Provider
MetricsProvider metrics.Provider
}

func (m *MetricProviderConverter) NewCounter(opts api.CounterOpts) api.Counter {
Expand All @@ -26,7 +26,7 @@ func (m *MetricProviderConverter) NewCounter(opts api.CounterOpts) api.Counter {
StatsdFormat: opts.StatsdFormat,
}
return &CounterConverter{
counter: m.metricsProvider.NewCounter(o),
counter: m.MetricsProvider.NewCounter(o),
}
}

Expand All @@ -41,7 +41,7 @@ func (m *MetricProviderConverter) NewGauge(opts api.GaugeOpts) api.Gauge {
StatsdFormat: opts.StatsdFormat,
}
return &GaugeConverter{
gauge: m.metricsProvider.NewGauge(o),
gauge: m.MetricsProvider.NewGauge(o),
}
}

Expand All @@ -57,7 +57,7 @@ func (m *MetricProviderConverter) NewHistogram(opts api.HistogramOpts) api.Histo
Buckets: opts.Buckets,
}
return &HistogramConverter{
histogram: m.metricsProvider.NewHistogram(o),
histogram: m.MetricsProvider.NewHistogram(o),
}
}

Expand Down
Loading

0 comments on commit f1f0ef7

Please sign in to comment.