go_study/fabric-main/integration/e2e/chaincode_server_test.go

190 lines
6.3 KiB
Go

/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package e2e
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"syscall"
"time"
"github.com/hyperledger/fabric/common/crypto/tlsgen"
"github.com/hyperledger/fabric/core/container/externalbuilder"
"github.com/hyperledger/fabric/integration/channelparticipation"
"github.com/hyperledger/fabric/integration/nwo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/tedsuo/ifrit"
ginkgomon "github.com/tedsuo/ifrit/ginkgomon_v2"
)
var _ = Describe("ChaincodeAsExternalServer", func() {
var (
testDir string
network *nwo.Network
chaincode nwo.Chaincode
chaincodeServerAddress string
assetDir string
ordererRunner *ginkgomon.Runner
ordererProcess, peerProcess ifrit.Process
ccserver ifrit.Process
)
BeforeEach(func() {
var err error
testDir, err = ioutil.TempDir("", "external-chaincode-server")
Expect(err).NotTo(HaveOccurred())
network = nwo.New(nwo.BasicEtcdRaft(), testDir, nil, StartPort(), components)
network.GenerateConfigTree()
network.Bootstrap()
// Create the configuration
chaincodeServerAddress = fmt.Sprintf("127.0.0.1:%d", network.ReservePort())
connData, serverKeyPair := generateChaincodeConfig(chaincodeServerAddress)
// Create directory for configuration files
assetDir, err = ioutil.TempDir(testDir, "assets")
Expect(err).NotTo(HaveOccurred())
// Write the config files
connJSON, err := json.Marshal(connData)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(assetDir, "connection.json"), connJSON, 0o644)
Expect(err).NotTo(HaveOccurred())
configJSON, err := json.Marshal(serverKeyPair)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(assetDir, "config.json"), configJSON, 0o644)
Expect(err).NotTo(HaveOccurred())
// Setup the network
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", network.Orderer("orderer"), ordererRunner)
nwo.EnableCapabilities(
network,
"testchannel",
"Application", "V2_0",
network.Orderer("orderer"),
network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"),
)
// set to use the 'ccaas' builder rathern than binary
// binary build remains as an example of a scripted approach
chaincode = nwo.Chaincode{
Name: "mycc",
Version: "0.0",
Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/server"),
Lang: "ccaas",
PackageFile: filepath.Join(testDir, "server.tar.gz"),
Ctor: `{"Args":["init","a","100","b","200"]}`,
InitRequired: true,
SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
Sequence: "1",
Label: "my_server_chaincode",
CodeFiles: map[string]string{
filepath.Join(assetDir, "connection.json"): "connection.json",
filepath.Join(assetDir, "config.json"): "config.json",
},
}
})
AfterEach(func() {
if ccserver != nil {
ccserver.Signal(syscall.SIGTERM)
Eventually(ccserver.Wait(), network.EventuallyTimeout).Should(Receive())
}
if peerProcess != nil {
peerProcess.Signal(syscall.SIGTERM)
Eventually(peerProcess.Wait(), network.EventuallyTimeout).Should(Receive())
}
if ordererProcess != nil {
ordererProcess.Signal(syscall.SIGTERM)
Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
}
if network != nil {
network.Cleanup()
}
os.RemoveAll(testDir)
})
It("executes a basic etcdraft network with 2 orgs and external chaincode server", func() {
orderer := network.Orderer("orderer")
peer := network.Peer("Org1", "peer0")
peers := network.PeersWithChannel("testchannel")
By("packaging and installing the chaincode")
nwo.PackageAndInstallChaincode(network, chaincode, peers...)
chaincode.SetPackageIDFromPackageFile()
By("approving and committing the chaincode")
nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, peers...)
nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), peers...)
nwo.CommitChaincode(network, "testchannel", orderer, chaincode, peer, peers...)
By("starting the chaincode server")
ccserver = ifrit.Invoke(ginkgomon.New(ginkgomon.Config{
Name: chaincode.PackageID,
Command: &exec.Cmd{
Path: chaincode.Path,
Args: []string{chaincode.Path, chaincode.PackageID, chaincodeServerAddress},
Dir: assetDir,
},
StartCheck: `Starting chaincode ` + chaincode.PackageID + ` at ` + chaincodeServerAddress,
StartCheckTimeout: 15 * time.Second,
}))
Eventually(ccserver.Ready(), network.EventuallyTimeout).Should(BeClosed())
By("exercising the chaincode")
nwo.InitChaincode(network, "testchannel", orderer, chaincode, network.PeersWithChannel("testchannel")...)
RunQueryInvokeQuery(network, orderer, peer, "testchannel")
RunRespondWith(network, orderer, peer, "testchannel")
})
})
type chaincodeConfig struct {
ListenAddress string `json:"listen_address,omitempty"`
Key string `json:"key,omitempty"` // PEM encoded key
Cert string `json:"cert,omitempty"` // PEM encoded certificate
CA string `json:"ca,omitempty"` // PEM encode CA certificate
}
func generateChaincodeConfig(chaincodeAddress string) (externalbuilder.ChaincodeServerUserData, chaincodeConfig) {
tlsCA, err := tlsgen.NewCA()
Expect(err).NotTo(HaveOccurred())
serverPair, err := tlsCA.NewServerCertKeyPair("127.0.0.1")
Expect(err).NotTo(HaveOccurred())
clientPair, err := tlsCA.NewClientCertKeyPair()
Expect(err).NotTo(HaveOccurred())
config := chaincodeConfig{
ListenAddress: chaincodeAddress,
Key: string(serverPair.Key),
Cert: string(serverPair.Cert),
CA: string(tlsCA.CertBytes()),
}
connData := externalbuilder.ChaincodeServerUserData{
Address: chaincodeAddress,
DialTimeout: externalbuilder.Duration(10 * time.Second),
TLSRequired: true,
ClientAuthRequired: true,
ClientKey: string(clientPair.Key),
ClientCert: string(clientPair.Cert),
RootCert: string(tlsCA.CertBytes()),
}
return connData, config
}