diff --git a/internal/util/util.go b/internal/util/util.go index 9c9de56..acce3d7 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -1,5 +1,13 @@ package util +import ( + "errors" + + "github.com/hyperledger/fabric-admin-sdk/internal/protoutil" + "github.com/hyperledger/fabric-admin-sdk/pkg/identity" + cb "github.com/hyperledger/fabric-protos-go-apiv2/common" +) + func Concatenate[T any](slices ...[]T) []T { size := 0 for _, slice := range slices { @@ -15,3 +23,55 @@ func Concatenate[T any](slices ...[]T) []T { return result } + +const ( + msgVersion = int32(0) + epoch = 0 +) + +func SignConfigTx(channelID string, envConfigUpdate *cb.Envelope, signer identity.SigningIdentity) (*cb.Envelope, error) { + payload, err := protoutil.UnmarshalPayload(envConfigUpdate.GetPayload()) + if err != nil { + return nil, errors.New("bad payload") + } + + if payload.GetHeader() == nil || payload.Header.ChannelHeader == nil { + return nil, errors.New("bad header") + } + + ch, err := protoutil.UnmarshalChannelHeader(payload.GetHeader().GetChannelHeader()) + if err != nil { + return nil, errors.New("could not unmarshall channel header") + } + + if ch.GetType() != int32(cb.HeaderType_CONFIG_UPDATE) { + return nil, errors.New("bad type") + } + + if ch.GetChannelId() == "" { + return nil, errors.New("empty channel id") + } + + configUpdateEnv, err := protoutil.UnmarshalConfigUpdateEnvelope(payload.GetData()) + if err != nil { + return nil, errors.New("bad config update env") + } + + sigHeader, err := protoutil.NewSignatureHeader(signer) + if err != nil { + return nil, err + } + + configSig := &cb.ConfigSignature{ + SignatureHeader: protoutil.MarshalOrPanic(sigHeader), + } + + configSig.Signature, err = signer.Sign(Concatenate(configSig.GetSignatureHeader(), configUpdateEnv.GetConfigUpdate())) + if err != nil { + return nil, err + } + + configUpdateEnv.Signatures = append(configUpdateEnv.Signatures, configSig) + + return protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, channelID, signer, configUpdateEnv, msgVersion, epoch) +} diff --git a/pkg/channel/channel.go b/pkg/channel/channel.go index db1bdf8..7ace768 100644 --- a/pkg/channel/channel.go +++ b/pkg/channel/channel.go @@ -9,10 +9,14 @@ import ( "io" "net/http" + "github.com/hyperledger/fabric-admin-sdk/internal/configtxgen/encoder" + "github.com/hyperledger/fabric-admin-sdk/internal/configtxgen/genesisconfig" "github.com/hyperledger/fabric-admin-sdk/internal/osnadmin" "github.com/hyperledger/fabric-admin-sdk/internal/protoutil" + "github.com/hyperledger/fabric-admin-sdk/internal/util" "github.com/hyperledger/fabric-admin-sdk/pkg/identity" "github.com/hyperledger/fabric-admin-sdk/pkg/internal/proposal" + "github.com/hyperledger/fabric-protos-go-apiv2/orderer" "github.com/hyperledger/fabric-protos-go-apiv2/peer" cb "github.com/hyperledger/fabric-protos-go-apiv2/common" @@ -110,3 +114,54 @@ func ListChannelOnPeer(ctx context.Context, connection grpc.ClientConnInterface, } return channelQueryResponse.GetChannels(), nil } + +func UpdateChannelConfig(ctx context.Context, channelID string, updateEnvelope []byte, ordererConnection grpc.ClientConnInterface, signers []identity.SigningIdentity) (*orderer.BroadcastResponse, error) { + + envConfigUpdate, err := protoutil.UnmarshalEnvelope(updateEnvelope) + if err != nil { + return nil, err + } + + for _, signer := range signers { + envConfigUpdate, err = util.SignConfigTx(channelID, envConfigUpdate, signer) + if err != nil { + return nil, err + } + } + + ordererClient, err := orderer.NewAtomicBroadcastClient(ordererConnection).Broadcast(ctx) + if err != nil { + return nil, err + } + + defer func(ordererClient orderer.AtomicBroadcast_BroadcastClient) { + _ = ordererClient.CloseSend() + }(ordererClient) + + err = ordererClient.Send(envConfigUpdate) + if err != nil { + return nil, err + } + + response, err := ordererClient.Recv() + return response, err + +} + +func CreateGenesisBlock(profileType string, profilePath string, channelID string) (*cb.Block, error) { + + var profile *genesisconfig.Profile + var err error + profile, err = genesisconfig.Load(profileType, profilePath) + if err != nil { + return nil, err + } + + pgen, err := encoder.NewBootstrapper(profile) + if err != nil { + return nil, err + } + genesisBlock := pgen.GenesisBlockForChannel(channelID) + return genesisBlock, nil + +} diff --git a/test/channel_test.go b/test/channel_test.go index b1baf88..d9749e8 100644 --- a/test/channel_test.go +++ b/test/channel_test.go @@ -8,9 +8,6 @@ import ( "log" "os" - "github.com/hyperledger/fabric-admin-sdk/internal/protoutil" - "github.com/hyperledger/fabric-protos-go-apiv2/orderer" - "github.com/hyperledger/fabric-admin-sdk/pkg/channel" "github.com/hyperledger/fabric-admin-sdk/pkg/identity" "github.com/hyperledger/fabric-admin-sdk/pkg/network" @@ -163,16 +160,6 @@ var _ = Describe("channel", func() { // get update config file, see https://hyperledger-fabric.readthedocs.io/en/release-2.4/channel_update_tutorial.html#add-the-org3-crypto-material updateEnvelope, err := os.ReadFile("./org3_update_in_envelope.pb") Expect(err).NotTo(HaveOccurred()) - envelope, err := protoutil.UnmarshalEnvelope(updateEnvelope) - Expect(err).NotTo(HaveOccurred()) - - // Peer1 sign - envelope, err = SignConfigTx(channelID, envelope, signer) - Expect(err).NotTo(HaveOccurred()) - - // Peer2 sign - envelope, err = SignConfigTx(channelID, envelope, signer2) - Expect(err).NotTo(HaveOccurred()) ordererNode := network.Node{ Addr: OrdererAddr, @@ -182,14 +169,7 @@ var _ = Describe("channel", func() { Expect(err).NotTo(HaveOccurred()) ordererConnection, err := network.DialConnection(ordererNode) Expect(err).NotTo(HaveOccurred()) - ordererClient, err := orderer.NewAtomicBroadcastClient(ordererConnection).Broadcast(context.Background()) - Expect(err).NotTo(HaveOccurred()) - defer func(ordererClient orderer.AtomicBroadcast_BroadcastClient) { - _ = ordererClient.CloseSend() - }(ordererClient) - err = ordererClient.Send(envelope) - Expect(err).NotTo(HaveOccurred()) - response, err := ordererClient.Recv() + response, err := channel.UpdateChannelConfig(context.Background(), channelID, updateEnvelope, ordererConnection, []identity.SigningIdentity{signer, signer2}) Expect(err).NotTo(HaveOccurred()) log.Println("response: ", response.String()) }) diff --git a/test/e2e_suite_test.go b/test/e2e_suite_test.go index 1d0d3f3..34b8f71 100644 --- a/test/e2e_suite_test.go +++ b/test/e2e_suite_test.go @@ -1,25 +1,13 @@ package test import ( - "errors" "os" "testing" - "github.com/hyperledger/fabric-admin-sdk/internal/configtxgen/encoder" - "github.com/hyperledger/fabric-admin-sdk/internal/configtxgen/genesisconfig" - "github.com/hyperledger/fabric-admin-sdk/internal/protoutil" - "github.com/hyperledger/fabric-admin-sdk/internal/util" - "github.com/hyperledger/fabric-admin-sdk/pkg/identity" - cb "github.com/hyperledger/fabric-protos-go-apiv2/common" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) -const ( - msgVersion = int32(0) - epoch = 0 -) - func TestE2e(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "e2e Suite") @@ -34,60 +22,3 @@ var _ = BeforeSuite(func() { var _ = AfterSuite(func() { _ = os.RemoveAll(tmpDir) }) - -// ConfigTxGen based on Profile return block -func ConfigTxGen(config *genesisconfig.Profile, channelID string) (*cb.Block, error) { - pgen, err := encoder.NewBootstrapper(config) - if err != nil { - return nil, err - } - genesisBlock := pgen.GenesisBlockForChannel(channelID) - return genesisBlock, nil -} - -func SignConfigTx(channelID string, envConfigUpdate *cb.Envelope, signer identity.SigningIdentity) (*cb.Envelope, error) { - payload, err := protoutil.UnmarshalPayload(envConfigUpdate.GetPayload()) - if err != nil { - return nil, errors.New("bad payload") - } - - if payload.GetHeader() == nil || payload.Header.ChannelHeader == nil { - return nil, errors.New("bad header") - } - - ch, err := protoutil.UnmarshalChannelHeader(payload.GetHeader().GetChannelHeader()) - if err != nil { - return nil, errors.New("could not unmarshall channel header") - } - - if ch.GetType() != int32(cb.HeaderType_CONFIG_UPDATE) { - return nil, errors.New("bad type") - } - - if ch.GetChannelId() == "" { - return nil, errors.New("empty channel id") - } - - configUpdateEnv, err := protoutil.UnmarshalConfigUpdateEnvelope(payload.GetData()) - if err != nil { - return nil, errors.New("bad config update env") - } - - sigHeader, err := protoutil.NewSignatureHeader(signer) - if err != nil { - return nil, err - } - - configSig := &cb.ConfigSignature{ - SignatureHeader: protoutil.MarshalOrPanic(sigHeader), - } - - configSig.Signature, err = signer.Sign(util.Concatenate(configSig.GetSignatureHeader(), configUpdateEnv.GetConfigUpdate())) - if err != nil { - return nil, err - } - - configUpdateEnv.Signatures = append(configUpdateEnv.Signatures, configSig) - - return protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, channelID, signer, configUpdateEnv, msgVersion, epoch) -} diff --git a/test/e2e_test.go b/test/e2e_test.go index 9b81728..20c1ab0 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -14,7 +14,6 @@ import ( "sync" "time" - "github.com/hyperledger/fabric-admin-sdk/internal/configtxgen/genesisconfig" "github.com/hyperledger/fabric-admin-sdk/pkg/chaincode" "github.com/hyperledger/fabric-admin-sdk/pkg/channel" "github.com/hyperledger/fabric-admin-sdk/pkg/discovery" @@ -22,6 +21,7 @@ import ( "github.com/hyperledger/fabric-admin-sdk/pkg/network" "github.com/hyperledger/fabric-admin-sdk/pkg/snapshot" "github.com/hyperledger/fabric-gateway/pkg/client" + cb "github.com/hyperledger/fabric-protos-go-apiv2/common" gatewaypb "github.com/hyperledger/fabric-protos-go-apiv2/gateway" . "github.com/onsi/ginkgo/v2" @@ -149,23 +149,15 @@ var _ = Describe("e2e", func() { //genesis block createChannel, ok := os.LookupEnv("CREATE_CHANNEL") if createChannel == "create_channel" && ok { - var profile *genesisconfig.Profile - var err error - profile, err = genesisconfig.Load("ChannelUsingRaft", "./") - Expect(err).NotTo(HaveOccurred()) - Expect(profile).ToNot(BeNil()) - Expect(profile.Orderer.BatchSize.MaxMessageCount).To(Equal(uint32(10))) - IsBFT, check := os.LookupEnv("CONSENSUS") + var block *cb.Block if IsBFT == "BFT" && check { - profile, err = genesisconfig.Load("ChannelUsingBFT", "./bft") + block, err = channel.CreateGenesisBlock("ChannelUsingBFT", "./bft", channelName) + Expect(err).NotTo(HaveOccurred()) + } else { + block, err = channel.CreateGenesisBlock("ChannelUsingRaft", "./", channelName) Expect(err).NotTo(HaveOccurred()) - Expect(profile).ToNot(BeNil()) - Expect(profile.Orderer.BatchSize.MaxMessageCount).To(Equal(uint32(10))) } - - block, err := ConfigTxGen(profile, channelName) - Expect(err).NotTo(HaveOccurred()) Expect(block).ToNot(BeNil()) //create channel