github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/integration/configtx/configtx_test.go (about)

     1  /*
     2  Copyright hechain All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package configtx
     8  
     9  import (
    10  	"crypto"
    11  	"crypto/x509"
    12  	"encoding/pem"
    13  	"io/ioutil"
    14  	"os"
    15  	"syscall"
    16  	"time"
    17  
    18  	docker "github.com/fsouza/go-dockerclient"
    19  	"github.com/golang/protobuf/proto"
    20  	"github.com/hechain20/hechain/integration/nwo"
    21  	"github.com/hechain20/hechain/integration/nwo/commands"
    22  	"github.com/hechain20/hechain/integration/ordererclient"
    23  	"github.com/hyperledger/fabric-config/configtx"
    24  	"github.com/hyperledger/fabric-protos-go/common"
    25  	"github.com/tedsuo/ifrit"
    26  
    27  	. "github.com/onsi/ginkgo"
    28  	. "github.com/onsi/gomega"
    29  )
    30  
    31  var _ = Describe("ConfigTx", func() {
    32  	var (
    33  		client  *docker.Client
    34  		testDir string
    35  		network *nwo.Network
    36  		process ifrit.Process
    37  	)
    38  
    39  	BeforeEach(func() {
    40  		var err error
    41  		testDir, err = ioutil.TempDir("", "configtx")
    42  		Expect(err).NotTo(HaveOccurred())
    43  
    44  		client, err = docker.NewClientFromEnv()
    45  		Expect(err).NotTo(HaveOccurred())
    46  
    47  		network = nwo.New(nwo.BasicSolo(), testDir, client, StartPort(), components)
    48  
    49  		// Generate config
    50  		network.GenerateConfigTree()
    51  
    52  		// bootstrap the network
    53  		network.Bootstrap()
    54  
    55  		networkRunner := network.NetworkGroupRunner()
    56  		process = ifrit.Invoke(networkRunner)
    57  		Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
    58  	})
    59  
    60  	AfterEach(func() {
    61  		if process != nil {
    62  			process.Signal(syscall.SIGTERM)
    63  			Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
    64  		}
    65  		if network != nil {
    66  			network.Cleanup()
    67  		}
    68  
    69  		os.RemoveAll(testDir)
    70  	})
    71  
    72  	It("creates channels and updates them using fabric-config/configtx", func() {
    73  		orderer := network.Orderer("orderer")
    74  		org1peer0 := network.Peer("Org1", "peer0")
    75  
    76  		By("setting up the channel")
    77  		channel := configtx.Channel{
    78  			Consortium: "SampleConsortium",
    79  			Application: configtx.Application{
    80  				Organizations: []configtx.Organization{
    81  					{
    82  						Name: "Org1",
    83  					},
    84  					{
    85  						Name: "Org2",
    86  					},
    87  				},
    88  				Capabilities: []string{"V1_3"},
    89  				ACLs:         map[string]string{"event/Block": "/Channel/Application/Readers"},
    90  				Policies: map[string]configtx.Policy{
    91  					configtx.ReadersPolicyKey: {
    92  						Type: configtx.ImplicitMetaPolicyType,
    93  						Rule: "ANY Readers",
    94  					},
    95  					configtx.WritersPolicyKey: {
    96  						Type: configtx.ImplicitMetaPolicyType,
    97  						Rule: "ANY Writers",
    98  					},
    99  					configtx.AdminsPolicyKey: {
   100  						Type: configtx.ImplicitMetaPolicyType,
   101  						Rule: "MAJORITY Admins",
   102  					},
   103  					configtx.EndorsementPolicyKey: {
   104  						Type: configtx.ImplicitMetaPolicyType,
   105  						Rule: "MAJORITY Endorsement",
   106  					},
   107  					configtx.LifecycleEndorsementPolicyKey: {
   108  						Type: configtx.ImplicitMetaPolicyType,
   109  						Rule: "MAJORITY Endorsement",
   110  					},
   111  				},
   112  			},
   113  		}
   114  
   115  		channelID := "testchannel"
   116  		createChannelUpdate, err := configtx.NewMarshaledCreateChannelTx(channel, channelID)
   117  		Expect(err).NotTo(HaveOccurred())
   118  
   119  		envelope, err := configtx.NewEnvelope(createChannelUpdate)
   120  		Expect(err).NotTo(HaveOccurred())
   121  		envBytes, err := proto.Marshal(envelope)
   122  		Expect(err).NotTo(HaveOccurred())
   123  		channelCreateTxPath := network.CreateChannelTxPath("testchannel")
   124  		err = ioutil.WriteFile(channelCreateTxPath, envBytes, 0o644)
   125  		Expect(err).NotTo(HaveOccurred())
   126  
   127  		By("creating the channel")
   128  		createChannel := func() int {
   129  			sess, err := network.PeerAdminSession(org1peer0, commands.ChannelCreate{
   130  				ChannelID:   "testchannel",
   131  				Orderer:     network.OrdererAddress(orderer, nwo.ListenPort),
   132  				File:        channelCreateTxPath,
   133  				OutputBlock: "/dev/null",
   134  				ClientAuth:  network.ClientAuthRequired,
   135  			})
   136  			Expect(err).NotTo(HaveOccurred())
   137  			return sess.Wait(network.EventuallyTimeout).ExitCode()
   138  		}
   139  		Eventually(createChannel, network.EventuallyTimeout).Should(Equal(0))
   140  
   141  		By("joining all peers to the channel")
   142  		testPeers := network.PeersWithChannel("testchannel")
   143  		network.JoinChannel("testchannel", orderer, testPeers...)
   144  
   145  		By("getting the current channel config")
   146  		org2peer0 := network.Peer("Org2", "peer0")
   147  		channelConfig := nwo.GetConfig(network, org2peer0, orderer, "testchannel")
   148  		c := configtx.New(channelConfig)
   149  
   150  		By("updating orderer channel configuration")
   151  		o := c.Orderer()
   152  		oConfig, err := o.Configuration()
   153  		Expect(err).NotTo(HaveOccurred())
   154  		oConfig.BatchTimeout = 2 * time.Second
   155  		err = o.SetConfiguration(oConfig)
   156  		Expect(err).NotTo(HaveOccurred())
   157  		host, port := OrdererHostPort(network, orderer)
   158  		err = o.Organization(orderer.Organization).SetEndpoint(configtx.Address{Host: host, Port: port + 1})
   159  		Expect(err).NotTo(HaveOccurred())
   160  
   161  		By("computing the config update")
   162  		configUpdate, err := c.ComputeMarshaledUpdate("testchannel")
   163  		Expect(err).NotTo(HaveOccurred())
   164  
   165  		By("creating a detached signature for the orderer")
   166  		signingIdentity := configtx.SigningIdentity{
   167  			Certificate: parseCertificate(network.OrdererUserCert(orderer, "Admin")),
   168  			PrivateKey:  parsePrivateKey(network.OrdererUserKey(orderer, "Admin")),
   169  			MSPID:       network.Organization(orderer.Organization).MSPID,
   170  		}
   171  		signature, err := signingIdentity.CreateConfigSignature(configUpdate)
   172  		Expect(err).NotTo(HaveOccurred())
   173  
   174  		By("creating a signed config update envelope with the orderer's detached signature")
   175  		configUpdateEnvelope, err := configtx.NewEnvelope(configUpdate, signature)
   176  		Expect(err).NotTo(HaveOccurred())
   177  		err = signingIdentity.SignEnvelope(configUpdateEnvelope)
   178  		Expect(err).NotTo(HaveOccurred())
   179  
   180  		currentBlockNumber := nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel")
   181  
   182  		By("submitting the channel config update")
   183  		resp, err := ordererclient.Broadcast(network, orderer, configUpdateEnvelope)
   184  		Expect(err).NotTo(HaveOccurred())
   185  		Expect(resp.Status).To(Equal(common.Status_SUCCESS))
   186  
   187  		ccb := func() uint64 { return nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel") }
   188  		Eventually(ccb, network.EventuallyTimeout).Should(BeNumerically(">", currentBlockNumber))
   189  
   190  		By("ensuring the active channel config matches the submitted config")
   191  		updatedChannelConfig := nwo.GetConfig(network, org2peer0, orderer, "testchannel")
   192  		Expect(proto.Equal(c.UpdatedConfig(), updatedChannelConfig)).To(BeTrue())
   193  
   194  		By("checking the current application capabilities")
   195  		c = configtx.New(updatedChannelConfig)
   196  		a := c.Application()
   197  		capabilities, err := a.Capabilities()
   198  		Expect(err).NotTo(HaveOccurred())
   199  		Expect(capabilities).To(HaveLen(1))
   200  		Expect(capabilities).To(ContainElement("V1_3"))
   201  
   202  		By("enabling V2_0 application capabilities")
   203  		err = a.AddCapability("V2_0")
   204  		Expect(err).NotTo(HaveOccurred())
   205  
   206  		By("checking the application capabilities after update")
   207  		capabilities, err = a.Capabilities()
   208  		Expect(err).NotTo(HaveOccurred())
   209  		Expect(capabilities).To(HaveLen(2))
   210  		Expect(capabilities).To(ContainElements("V1_3", "V2_0"))
   211  
   212  		By("computing the config update")
   213  		configUpdate, err = c.ComputeMarshaledUpdate("testchannel")
   214  		Expect(err).NotTo(HaveOccurred())
   215  
   216  		By("creating detached signatures for each peer")
   217  		signingIdentities := make([]configtx.SigningIdentity, len(testPeers))
   218  		signatures := make([]*common.ConfigSignature, len(testPeers))
   219  		for i, p := range testPeers {
   220  			signingIdentity := configtx.SigningIdentity{
   221  				Certificate: parseCertificate(network.PeerUserCert(p, "Admin")),
   222  				PrivateKey:  parsePrivateKey(network.PeerUserKey(p, "Admin")),
   223  				MSPID:       network.Organization(p.Organization).MSPID,
   224  			}
   225  			signingIdentities[i] = signingIdentity
   226  			signature, err := signingIdentity.CreateConfigSignature(configUpdate)
   227  			Expect(err).NotTo(HaveOccurred())
   228  			signatures[i] = signature
   229  		}
   230  
   231  		By("creating a signed config update envelope with the detached peer signatures")
   232  		configUpdateEnvelope, err = configtx.NewEnvelope(configUpdate, signatures...)
   233  		Expect(err).NotTo(HaveOccurred())
   234  		err = signingIdentities[0].SignEnvelope(configUpdateEnvelope)
   235  		Expect(err).NotTo(HaveOccurred())
   236  
   237  		currentBlockNumber = nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel")
   238  
   239  		By("submitting the channel config update")
   240  		resp, err = ordererclient.Broadcast(network, orderer, configUpdateEnvelope)
   241  		Expect(err).NotTo(HaveOccurred())
   242  		Expect(resp.Status).To(Equal(common.Status_SUCCESS))
   243  
   244  		ccb = func() uint64 { return nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel") }
   245  		Eventually(ccb, network.EventuallyTimeout).Should(BeNumerically(">", currentBlockNumber))
   246  
   247  		By("ensuring the active channel config matches the submitted config")
   248  		updatedChannelConfig = nwo.GetConfig(network, org2peer0, orderer, "testchannel")
   249  		Expect(proto.Equal(c.UpdatedConfig(), updatedChannelConfig)).To(BeTrue())
   250  
   251  		By("adding the anchor peer for each org")
   252  		for _, peer := range network.AnchorsForChannel("testchannel") {
   253  			By("getting the current channel config")
   254  			channelConfig = nwo.GetConfig(network, peer, orderer, "testchannel")
   255  			c = configtx.New(channelConfig)
   256  			peerOrg := c.Application().Organization(peer.Organization)
   257  
   258  			By("adding the anchor peer for " + peer.Organization)
   259  			host, port := PeerHostPort(network, peer)
   260  			err = peerOrg.AddAnchorPeer(configtx.Address{Host: host, Port: port})
   261  			Expect(err).NotTo(HaveOccurred())
   262  
   263  			By("computing the config update")
   264  			configUpdate, err = c.ComputeMarshaledUpdate("testchannel")
   265  			Expect(err).NotTo(HaveOccurred())
   266  
   267  			By("creating a detached signature")
   268  			signingIdentity := configtx.SigningIdentity{
   269  				Certificate: parseCertificate(network.PeerUserCert(peer, "Admin")),
   270  				PrivateKey:  parsePrivateKey(network.PeerUserKey(peer, "Admin")),
   271  				MSPID:       network.Organization(peer.Organization).MSPID,
   272  			}
   273  			signature, err := signingIdentity.CreateConfigSignature(configUpdate)
   274  			Expect(err).NotTo(HaveOccurred())
   275  
   276  			By("creating a signed config update envelope with the detached peer signature")
   277  			configUpdateEnvelope, err = configtx.NewEnvelope(configUpdate, signature)
   278  			Expect(err).NotTo(HaveOccurred())
   279  			err = signingIdentity.SignEnvelope(configUpdateEnvelope)
   280  			Expect(err).NotTo(HaveOccurred())
   281  
   282  			currentBlockNumber = nwo.CurrentConfigBlockNumber(network, peer, orderer, "testchannel")
   283  
   284  			By("submitting the channel config update for " + peer.Organization)
   285  			resp, err = ordererclient.Broadcast(network, orderer, configUpdateEnvelope)
   286  			Expect(err).NotTo(HaveOccurred())
   287  			Expect(resp.Status).To(Equal(common.Status_SUCCESS))
   288  
   289  			ccb = func() uint64 { return nwo.CurrentConfigBlockNumber(network, peer, orderer, "testchannel") }
   290  			Eventually(ccb, network.EventuallyTimeout).Should(BeNumerically(">", currentBlockNumber))
   291  
   292  			By("ensuring the active channel config matches the submitted config")
   293  			updatedChannelConfig = nwo.GetConfig(network, peer, orderer, "testchannel")
   294  			Expect(proto.Equal(c.UpdatedConfig(), updatedChannelConfig)).To(BeTrue())
   295  		}
   296  	})
   297  })
   298  
   299  // parsePrivateKey loads the PEM-encoded private key at the specified path.
   300  func parsePrivateKey(path string) crypto.PrivateKey {
   301  	pkBytes, err := ioutil.ReadFile(path)
   302  	Expect(err).NotTo(HaveOccurred())
   303  	pemBlock, _ := pem.Decode(pkBytes)
   304  	privateKey, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
   305  	Expect(err).NotTo(HaveOccurred())
   306  	return privateKey
   307  }
   308  
   309  // parseCertificate loads the PEM-encoded x509 certificate at the specified
   310  // path.
   311  func parseCertificate(path string) *x509.Certificate {
   312  	certBytes, err := ioutil.ReadFile(path)
   313  	Expect(err).NotTo(HaveOccurred())
   314  	pemBlock, _ := pem.Decode(certBytes)
   315  	cert, err := x509.ParseCertificate(pemBlock.Bytes)
   316  	Expect(err).NotTo(HaveOccurred())
   317  	return cert
   318  }