Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cbp latest #692

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ clean:
rm -rf ./cmd/fsccli/cmd
rm -rf ./samples/fabric/iou/cmd

.PHONY: clean-fabric-peer-images
clean-fabric-peer-images:
docker images -a | grep "_peer_" | awk '{print $3}' | xargs docker rmi

.PHONY: fsccli
fsccli:
@go install ./cmd/fsccli
23 changes: 20 additions & 3 deletions docs/core-fabric.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ fabric:

# TBD: idemix-folder, bccsp-folder

# define the default values for the tls connections
tls:
# Species the fabric network requires TLS or not
enabled: true
Expand All @@ -291,18 +292,25 @@ fabric:
interval: 60s
# If not provided, the default is 20 seconds
timeout: 600s
# If not provided, the default is 10 seconds
connectionTimeout: 10s
tlsEnabled: true

ordering:
# number of retries to attempt to send a transaction to an orderer
# If not specified or set to 0, it will default to 3 retries
numRetries: 3
# retryInternal specifies the amount of time to wait before retrying a connection to the ordering service, it has no default and must be specified
retryInterval: 3s
# here is possible to disable tls just for the ordering service.
# if this key is not specified, then the `tls` section is used.
tlsEnabled: true
# here is possible to enable tls client-side authentication just for the ordering service
# if this key is not specified, then the `tls` section is used.
tlsClientAuthRequired: false

# List of orderers on top of those discovered in the channel
# This is optional and as such it should be left to those orderers discovered on the channel
# tls configuration is governed by the `tls` section, if not otherwise specified in the `ordering` section
orderers:
# address of orderer
- address: 'orderer0:7050'
Expand All @@ -312,9 +320,14 @@ fabric:
tlsRootCertFile: /path/to/ordererorg/ca.crt
# server name override if tls cert SANS doesn't match address
serverNameOverride:
# it is possible to customize per orderer the TLS behaviour, by using the following attributes
tlsClientSideAuth: true
tlsDisabled: true
tlsEnabled: false

# List of trusted peers this node can connect to.
# usually this will be the fabric peers in the same organisation as the FSC node
# usually this will be the fabric peers in the same organisation as the FSC node.
# tls configuration is governed by the `tls` section.
peers:
# address of orderer
- address: 'peer2:7051'
Expand All @@ -323,8 +336,12 @@ fabric:
# path to peer org's ca cert if tls is enabled
tlsRootCertFile: /path/to/peerorg/ca.crt
serverNameOverride:
# it is possible to customize per peer the TLS behaviour, by using the following attributes
tlsClientSideAuth: true
tlsDisabled: true
tlsEnabled: false

# List of channels and deployed chaincode
# List of channels and deployed chaincode
channels:
- name: mychannel
# whether this is the default channel or not
Expand Down
6 changes: 3 additions & 3 deletions docs/fabric/fabricdev/core/fabricdev/channelprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/delivery"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/finality"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/membership"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/peer"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/rwset"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/services"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/transaction"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/driver"
driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver"
Expand Down Expand Up @@ -90,7 +90,7 @@ func (p *provider) NewChannel(nw driver.FabricNetworkService, channelName string
envelopeService := transaction.NewEnvelopeService(p.kvss, nw.Name(), channelName)
transactionService := transaction.NewEndorseTransactionService(p.kvss, nw.Name(), channelName)
metadataService := transaction.NewMetadataService(p.kvss, nw.Name(), channelName)
peerService := peer.NewService(nw.ConfigService(), nw.LocalMembership().DefaultSigningIdentity())
peerService := services.NewClientFactory(nw.ConfigService(), nw.LocalMembership().DefaultSigningIdentity())

// Fabric finality
fabricFinality, err := finality.NewFabricFinality(
Expand Down Expand Up @@ -193,7 +193,7 @@ func (p *provider) NewChannel(nw driver.FabricNetworkService, channelName string
ChannelMembershipService: channelMembershipService,
ChaincodeManagerService: chaincodeManagerService,
CommitterService: committerService,
PeerManager: peerService,
PeerService: peerService,
}
if err := c.Init(); err != nil {
return nil, errors.WithMessagef(err, "failed initializing Channel [%s]", channelName)
Expand Down
44 changes: 30 additions & 14 deletions integration/fabric/iou/iou_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,41 @@ import (

var _ = Describe("EndToEnd", func() {
Describe("IOU Life Cycle With LibP2P", func() {
s := NewTestSuite(fsc.LibP2P, integration.NoReplication)
s := NewTestSuite(fsc.LibP2P, integration.NoReplication, true)
BeforeEach(s.Setup)
AfterEach(s.TearDown)
It("succeeded", s.TestSucceeded)
})

Describe("IOU Life Cycle With Websockets", func() {
s := NewTestSuite(fsc.WebSocket, integration.NoReplication)
s := NewTestSuite(fsc.WebSocket, integration.NoReplication, true)
BeforeEach(s.Setup)
AfterEach(s.TearDown)
It("succeeded", s.TestSucceeded)
})

Describe("IOU Life Cycle With Websockets and no TLS", func() {
s := NewTestSuite(fsc.WebSocket, integration.NoReplication, false)
BeforeEach(s.Setup)
AfterEach(s.TearDown)
It("succeeded", s.TestSucceeded)
})

Describe("IOU Life Cycle With Websockets and replicas", func() {
s := NewTestSuite(fsc.WebSocket, &integration.ReplicationOptions{
ReplicationFactors: map[string]int{
"borrower": 3,
"lender": 2,
},
SQLConfigs: map[string]*postgres.ContainerConfig{
"borrower": postgres.DefaultConfig("borrower-db"),
"lender": postgres.DefaultConfig("lender-db"),
s := NewTestSuite(
fsc.WebSocket,
&integration.ReplicationOptions{
ReplicationFactors: map[string]int{
"borrower": 3,
"lender": 2,
},
SQLConfigs: map[string]*postgres.ContainerConfig{
"borrower": postgres.DefaultConfig("borrower-db"),
"lender": postgres.DefaultConfig("lender-db"),
},
},
})
true,
)
BeforeEach(s.Setup)
AfterEach(s.TearDown)
It("succeeded", s.TestSucceededWithReplicas)
Expand All @@ -50,9 +61,14 @@ type TestSuite struct {
*integration.TestSuite
}

func NewTestSuite(commType fsc.P2PCommunicationType, nodeOpts *integration.ReplicationOptions) *TestSuite {
return &TestSuite{integration.NewTestSuiteWithSQL(nodeOpts.SQLConfigs, func() (*integration.Infrastructure, error) {
return integration.Generate(StartPort(), true, integration.ReplaceTemplate(iou.Topology(&iou.SDK{}, commType, nodeOpts))...)
func NewTestSuite(commType fsc.P2PCommunicationType, nodeOpts *integration.ReplicationOptions, tlsEnabled bool) *TestSuite {
return &TestSuite{TestSuite: integration.NewTestSuiteWithSQL(nodeOpts.SQLConfigs, func() (*integration.Infrastructure, error) {
return integration.Generate(StartPort(), true, integration.ReplaceTemplate(iou.Topology(&iou.Opts{
SDK: &iou.SDK{},
CommType: commType,
ReplicationOpts: nodeOpts,
TLSEnabled: tlsEnabled,
}))...)
})}
}

Expand Down
24 changes: 16 additions & 8 deletions integration/fabric/iou/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,38 @@ import (
"github.com/hyperledger-labs/fabric-smart-client/platform/view/sdk/tracing"
)

func Topology(sdk api2.SDK, commType fsc.P2PCommunicationType, replicationOpts *integration.ReplicationOptions) []api.Topology {
type Opts struct {
SDK api2.SDK
CommType fsc.P2PCommunicationType
ReplicationOpts *integration.ReplicationOptions
TLSEnabled bool
}

func Topology(opts *Opts) []api.Topology {
// Define a Fabric topology with:
// 1. Three organization: Org1, Org2, and Org3
// 2. A namespace whose changes can be endorsed by Org1.
fabricTopology := fabric.NewDefaultTopology()
fabricTopology.AddOrganizationsByName("Org1", "Org2", "Org3")
fabricTopology.SetNamespaceApproverOrgs("Org1")
fabricTopology.AddNamespaceWithUnanimity("iou", "Org1")
fabricTopology.TLSEnabled = opts.TLSEnabled

// Define an FSC topology with 3 FCS nodes.
// One for the approver, one for the borrower, and one for the lender.
fscTopology := fsc.NewTopology()
fscTopology.P2PCommunicationType = commType
fscTopology.P2PCommunicationType = opts.CommType
fscTopology.EnablePrometheusMetrics()

//fscTopology.SetLogging("debug", "")
// fscTopology.SetLogging("debug", "")
fscTopology.EnableTracing(tracing.Otpl)

// Add the approver FSC node.
fscTopology.AddNodeByName("approver1").
// This option equips the approver's FSC node with an identity belonging to Org1.
// Therefore, the approver is an endorser of the Fabric namespace we defined above.
AddOptions(fabric.WithOrganization("Org1")).
AddOptions(replicationOpts.For("approver1")...).
AddOptions(opts.ReplicationOpts.For("approver1")...).
RegisterResponder(&views.ApproverView{}, &views.CreateIOUView{}).
RegisterResponder(&views.ApproverView{}, &views.UpdateIOUView{}).
RegisterViewFactory("init", &views.ApproverInitViewFactory{})
Expand All @@ -50,23 +58,23 @@ func Topology(sdk api2.SDK, commType fsc.P2PCommunicationType, replicationOpts *
// This option equips the approver's FSC node with an identity belonging to Org1.
// Therefore, the approver is an endorser of the Fabric namespace we defined above.
AddOptions(fabric.WithOrganization("Org1")).
AddOptions(replicationOpts.For("approver2")...).
AddOptions(opts.ReplicationOpts.For("approver2")...).
RegisterResponder(&views.ApproverView{}, &views.CreateIOUView{}).
RegisterResponder(&views.ApproverView{}, &views.UpdateIOUView{}).
RegisterViewFactory("init", &views.ApproverInitViewFactory{})

// Add the borrower's FSC node
fscTopology.AddNodeByName("borrower").
AddOptions(fabric.WithOrganization("Org2")).
AddOptions(replicationOpts.For("borrower")...).
AddOptions(opts.ReplicationOpts.For("borrower")...).
RegisterViewFactory("create", &views.CreateIOUViewFactory{}).
RegisterViewFactory("update", &views.UpdateIOUViewFactory{}).
RegisterViewFactory("query", &views.QueryViewFactory{})

// Add the lender's FSC node
fscTopology.AddNodeByName("lender").
AddOptions(fabric.WithOrganization("Org3")).
AddOptions(replicationOpts.For("lender")...).
AddOptions(opts.ReplicationOpts.For("lender")...).
RegisterResponder(&views.CreateIOUResponderView{}, &views.CreateIOUView{}).
RegisterResponder(&views.UpdateIOUResponderView{}, &views.UpdateIOUView{}).
RegisterViewFactory("query", &views.QueryViewFactory{})
Expand All @@ -77,7 +85,7 @@ func Topology(sdk api2.SDK, commType fsc.P2PCommunicationType, replicationOpts *
monitoringTopology.EnableOPTL()

// Add Fabric SDK to FSC Nodes
fscTopology.AddSDK(sdk)
fscTopology.AddSDK(opts.SDK)

return []api.Topology{
fabricTopology,
Expand Down
86 changes: 73 additions & 13 deletions integration/nwo/fabric/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,111 @@ SPDX-License-Identifier: Apache-2.0
package fabric

import (
"context"
"fmt"
"strings"
"time"

"github.com/hyperledger-labs/fabric-smart-client/integration/nwo/common/docker"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
healthgrpc "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/status"
)

const CCEnvDefaultImage = "hyperledger/fabric-ccenv:latest"

var RequiredImages = []string{CCEnvDefaultImage}
type Docker struct {
NetworkID string
RequiredImages []string
}

func (p *Platform) setupDocker() error {
func (d *Docker) Setup() error {
// getting our docker helper, check required images exists and launch a docker network
d, err := docker.GetInstance()
client, err := docker.GetInstance()
if err != nil {
return errors.Wrapf(err, "failed to get docker helper")
return fmt.Errorf("failed to get docker helper: %w", err)
}

// check if all docker images we need are available
err = d.CheckImagesExist(RequiredImages...)
err = client.CheckImagesExist(d.RequiredImages...)
if err != nil {
return errors.Wrapf(err, "check failed; Require the following container images: %s", RequiredImages)
return errors.Wrapf(err, "check failed; Require the following container images: %s", d.RequiredImages)
}

// create a container network associated with our platform networkID
err = d.CreateNetwork(p.Network.NetworkID)
err = client.CreateNetwork(d.NetworkID)
if err != nil {
return errors.Wrapf(err, "creating network '%s' failed", p.Network.NetworkID)
return errors.Wrapf(err, "creating network '%s' failed", d.NetworkID)
}

return nil
}

func (p *Platform) cleanupDocker() error {
func (d *Docker) Cleanup() error {
dockerClient, err := docker.GetInstance()
if err != nil {
return err
}

// remove all container components
if err := dockerClient.Cleanup(p.Network.NetworkID, func(name string) bool {
return strings.HasPrefix(name, "/"+p.Network.NetworkID)
if err := dockerClient.Cleanup(d.NetworkID, func(name string) bool {
return strings.HasPrefix(name, "/"+d.NetworkID)
}); err != nil {
return errors.Wrapf(err, "cleanup failed")
}

return nil
}

func WaitUntilReady(ctx context.Context, grpcEndpoint string) error {
logger.Infof("Wait until read")

startWaitingAt := time.Now()

serviceConfig := `{
"healthCheckConfig": {
"serviceName": ""
},
"methodConfig": [{
"name": [{"service": ""}],
"waitForReady": true,
"retryPolicy": {
"MaxAttempts": 5,
"InitialBackoff": ".1s",
"MaxBackoff": "1s",
"BackoffMultiplier": 2.0,
"RetryableStatusCodes": [ "UNAVAILABLE" ]
}
}]
}`

options := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultServiceConfig(serviceConfig),
}

conn, err := grpc.NewClient(grpcEndpoint, options...)
if err != nil {
return fmt.Errorf("grpc Dial(%q) failed: %w", grpcEndpoint, err)
}
defer conn.Close()

healthClient := healthgrpc.NewHealthClient(conn)
res, err := healthClient.Check(ctx, &healthgrpc.HealthCheckRequest{
Service: "",
})
if status.Code(err) == codes.Canceled {
return fmt.Errorf("healthcheck canceled: %w", err)
}
if err != nil {
return fmt.Errorf("healthcheck failed: %w", err)
}

if res.Status != healthgrpc.HealthCheckResponse_SERVING {
return fmt.Errorf("invalid status .... %s", res)
}

logger.Infof("Ready! (t=%s)", time.Since(startWaitingAt))
return nil
}
Loading