Skip to content

Commit

Permalink
Backport PR 4011 to release-2.4
Browse files Browse the repository at this point in the history
PR 4011 addressed a bug (#3998) in IsChannelMember that manifested itself in the test

`integration/raft/cft_test.go` use-case: "disregards certificate renewal if only the validity period changed"

after it was converted to run without the system channel.

Here we
- Backport the fix (in etcdraft/consenter.go)
- Add the same test case which runs without the system channel (w/o the fix this test case fails).
- Backport some test infrastructure that helps running tests without the system channel.

Signed-off-by: Yoav Tock <tock@il.ibm.com>
Change-Id: I7205dbe264248c4ad534499955bb22710d07444d
  • Loading branch information
tock-ibm authored and denyeart committed Mar 1, 2023
1 parent 782f239 commit 1e35107
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 31 deletions.
58 changes: 49 additions & 9 deletions integration/channelparticipation/channel_participation.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"mime/multipart"
"net/http"

Expand All @@ -25,11 +25,20 @@ import (
func Join(n *nwo.Network, o *nwo.Orderer, channel string, block *common.Block, expectedChannelInfo ChannelInfo) {
blockBytes, err := proto.Marshal(block)
Expect(err).NotTo(HaveOccurred())
url := fmt.Sprintf("https://127.0.0.1:%d/participation/v1/channels", n.OrdererPort(o, nwo.AdminPort))

protocol := "http"
if n.TLSEnabled {
protocol = "https"
}
url := fmt.Sprintf("%s://127.0.0.1:%d/participation/v1/channels", protocol, n.OrdererPort(o, nwo.AdminPort))
req := GenerateJoinRequest(url, channel, blockBytes)
authClient, _ := nwo.OrdererOperationalClients(n, o)
authClient, unauthClient := nwo.OrdererOperationalClients(n, o)

body := doBody(authClient, req)
client := unauthClient
if n.TLSEnabled {
client = authClient
}
body := doBody(client, req)
c := &ChannelInfo{}
err = json.Unmarshal(body, c)
Expect(err).NotTo(HaveOccurred())
Expand All @@ -56,7 +65,7 @@ func doBody(client *http.Client, req *http.Request) []byte {
resp, err := client.Do(req)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusCreated))
bodyBytes, err := ioutil.ReadAll(resp.Body)
bodyBytes, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
resp.Body.Close()

Expand All @@ -75,7 +84,12 @@ type ChannelInfoShort struct {

func List(n *nwo.Network, o *nwo.Orderer) ChannelList {
authClient, _ := nwo.OrdererOperationalClients(n, o)
listChannelsURL := fmt.Sprintf("https://127.0.0.1:%d/participation/v1/channels", n.OrdererPort(o, nwo.AdminPort))

protocol := "http"
if n.TLSEnabled {
protocol = "https"
}
listChannelsURL := fmt.Sprintf("%s://127.0.0.1:%d/participation/v1/channels", protocol, n.OrdererPort(o, nwo.AdminPort))

body := getBody(authClient, listChannelsURL)()
list := &ChannelList{}
Expand All @@ -89,7 +103,7 @@ func getBody(client *http.Client, url string) func() string {
return func() string {
resp, err := client.Get(url)
Expect(err).NotTo(HaveOccurred())
bodyBytes, err := ioutil.ReadAll(resp.Body)
bodyBytes, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
resp.Body.Close()
return string(bodyBytes)
Expand All @@ -106,7 +120,12 @@ type ChannelInfo struct {

func ListOne(n *nwo.Network, o *nwo.Orderer, channel string) ChannelInfo {
authClient, _ := nwo.OrdererOperationalClients(n, o)
listChannelURL := fmt.Sprintf("https://127.0.0.1:%d/participation/v1/channels/%s", n.OrdererPort(o, nwo.AdminPort), channel)

protocol := "http"
if n.TLSEnabled {
protocol = "https"
}
listChannelURL := fmt.Sprintf("%s://127.0.0.1:%d/participation/v1/channels/%s", protocol, n.OrdererPort(o, nwo.AdminPort), channel)

body := getBody(authClient, listChannelURL)()
c := &ChannelInfo{}
Expand All @@ -117,7 +136,12 @@ func ListOne(n *nwo.Network, o *nwo.Orderer, channel string) ChannelInfo {

func Remove(n *nwo.Network, o *nwo.Orderer, channel string) {
authClient, _ := nwo.OrdererOperationalClients(n, o)
url := fmt.Sprintf("https://127.0.0.1:%d/participation/v1/channels/%s", n.OrdererPort(o, nwo.AdminPort), channel)

protocol := "http"
if n.TLSEnabled {
protocol = "https"
}
url := fmt.Sprintf("%s://127.0.0.1:%d/participation/v1/channels/%s", protocol, n.OrdererPort(o, nwo.AdminPort), channel)

req, err := http.NewRequest(http.MethodDelete, url, nil)
Expect(err).NotTo(HaveOccurred())
Expand Down Expand Up @@ -158,3 +182,19 @@ func channelInfoShortMatcher(channel string) types.GomegaMatcher {
"URL": Equal(fmt.Sprintf("/participation/v1/channels/%s", channel)),
})
}

// JoinOrderersAppChannelCluster Joins a set of orderers to a channel for which the genesis block was created by the network
// bootstrap. It assumes a channel with one or more orderers (a cluster).
func JoinOrderersAppChannelCluster(network *nwo.Network, channelID string, orderers ...*nwo.Orderer) {
appGenesisBlock := network.LoadAppChannelGenesisBlock(channelID)
for _, orderer := range orderers {
expectedChannelInfo := ChannelInfo{
Name: channelID,
URL: fmt.Sprintf("/participation/v1/channels/%s", channelID),
Status: "active",
ConsensusRelation: "consenter",
Height: 1,
}
Join(network, orderer, channelID, appGenesisBlock, expectedChannelInfo)
}
}
60 changes: 45 additions & 15 deletions integration/nwo/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import (
"text/template"
"time"

"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/protoutil"

docker "github.com/fsouza/go-dockerclient"
"github.com/hyperledger/fabric/integration/nwo/commands"
"github.com/hyperledger/fabric/integration/nwo/fabricconfig"
Expand Down Expand Up @@ -286,7 +289,9 @@ func (n *Network) AddOrg(o *Organization, peers ...*Peer) {
}

n.Organizations = append(n.Organizations, o)
n.Consortiums[0].Organizations = append(n.Consortiums[0].Organizations, o.Name)
if n.Consortiums != nil {
n.Consortiums[0].Organizations = append(n.Consortiums[0].Organizations, o.Name)
}
}

// ConfigTxPath returns the path to the generated configtxgen configuration
Expand Down Expand Up @@ -787,22 +792,38 @@ func (n *Network) Bootstrap() {

n.bootstrapIdemix()

sess, err = n.ConfigTxGen(commands.OutputBlock{
ChannelID: n.SystemChannel.Name,
Profile: n.SystemChannel.Profile,
ConfigPath: n.RootDir,
OutputBlock: n.OutputBlockPath(n.SystemChannel.Name),
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
if n.SystemChannel != nil {
sess, err = n.ConfigTxGen(commands.OutputBlock{
ChannelID: n.SystemChannel.Name,
Profile: n.SystemChannel.Profile,
ConfigPath: n.RootDir,
OutputBlock: n.OutputBlockPath(n.SystemChannel.Name),
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))

for _, c := range n.Channels {
sess, err := n.ConfigTxGen(commands.CreateChannelTx{
ChannelID: c.Name,
Profile: c.Profile,
BaseProfile: c.BaseProfile,
ConfigPath: n.RootDir,
OutputCreateChannelTx: n.CreateChannelTxPath(c.Name),
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
}

n.ConcatenateTLSCACertificates()
return
}

for _, c := range n.Channels {
sess, err := n.ConfigTxGen(commands.CreateChannelTx{
ChannelID: c.Name,
Profile: c.Profile,
BaseProfile: c.BaseProfile,
ConfigPath: n.RootDir,
OutputCreateChannelTx: n.CreateChannelTxPath(c.Name),
sess, err := n.ConfigTxGen(commands.OutputBlock{
ChannelID: c.Name,
Profile: c.Profile,
ConfigPath: n.RootDir,
OutputBlock: n.OutputBlockPath(c.Name),
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expand Down Expand Up @@ -2006,3 +2027,12 @@ func (n *Network) GenerateCoreConfig(p *Peer) {
err = t.Execute(io.MultiWriter(core, pw), n)
Expect(err).NotTo(HaveOccurred())
}

func (n *Network) LoadAppChannelGenesisBlock(channelID string) *common.Block {
appGenesisPath := n.OutputBlockPath(channelID)
appGenesisBytes, err := ioutil.ReadFile(appGenesisPath)
Expect(err).NotTo(HaveOccurred())
appGenesisBlock, err := protoutil.UnmarshalBlock(appGenesisBytes)
Expect(err).NotTo(HaveOccurred())
return appGenesisBlock
}
108 changes: 108 additions & 0 deletions integration/nwo/standard_networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,111 @@ func MultiNodeEtcdRaft() *Config {
}}
return config
}

// === configurations for testing without the system channel ===

// BasicConfig is a configuration with two organizations and one peer per org.
// This configuration does not specify a consensus type.
func BasicConfig() *Config {
return &Config{
Organizations: []*Organization{{
Name: "OrdererOrg",
MSPID: "OrdererMSP",
Domain: "example.com",
EnableNodeOUs: false,
Users: 0,
CA: &CA{Hostname: "ca"},
}, {
Name: "Org1",
MSPID: "Org1MSP",
Domain: "org1.example.com",
EnableNodeOUs: true,
Users: 2,
CA: &CA{Hostname: "ca"},
}, {
Name: "Org2",
MSPID: "Org2MSP",
Domain: "org2.example.com",
EnableNodeOUs: true,
Users: 2,
CA: &CA{Hostname: "ca"},
}},
Consortiums: []*Consortium{{
Name: "SampleConsortium",
Organizations: []string{
"Org1",
"Org2",
},
}},
Consensus: &Consensus{
BootstrapMethod: "file",
},
SystemChannel: &SystemChannel{
Name: "systemchannel",
Profile: "TwoOrgsOrdererGenesis",
},
Orderers: []*Orderer{
{Name: "orderer", Organization: "OrdererOrg"},
},
Channels: []*Channel{
{Name: "testchannel", Profile: "TwoOrgsChannel"},
},
Peers: []*Peer{{
Name: "peer0",
Organization: "Org1",
Channels: []*PeerChannel{
{Name: "testchannel", Anchor: true},
},
}, {
Name: "peer0",
Organization: "Org2",
Channels: []*PeerChannel{
{Name: "testchannel", Anchor: true},
},
}},
Profiles: []*Profile{
{
Name: "TwoOrgsOrdererGenesis",
Orderers: []string{"orderer"},
},
{
Name: "TwoOrgsChannel",
Consortium: "SampleConsortium",
Organizations: []string{"Org1", "Org2"},
},
},
}
}

func BasicEtcdRaftNoSysChan() *Config {
config := BasicConfig()

config.Consensus.Type = "etcdraft"
config.Profiles = []*Profile{
{
Name: "TwoOrgsAppChannelEtcdRaft",
Consortium: "SampleConsortium",
Orderers: []string{"orderer"},
Organizations: []string{"Org1", "Org2"},
},
}
config.SystemChannel = nil
config.Consensus.ChannelParticipationEnabled = true
config.Consensus.BootstrapMethod = "none"
config.Consortiums = nil
config.Channels = []*Channel{{Name: "testchannel", Profile: "TwoOrgsAppChannelEtcdRaft"}}

return config
}

func MultiNodeEtcdRaftNoSysChan() *Config {
config := BasicEtcdRaftNoSysChan()
config.Orderers = []*Orderer{
{Name: "orderer1", Organization: "OrdererOrg"},
{Name: "orderer2", Organization: "OrdererOrg"},
{Name: "orderer3", Organization: "OrdererOrg"},
}
config.Profiles[0].Orderers = []string{"orderer1", "orderer2", "orderer3"}

return config
}
2 changes: 2 additions & 0 deletions integration/nwo/template/orderer_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ General:
ServerInterval: 7200s
ServerTimeout: 20s
BootstrapMethod: {{ .Consensus.BootstrapMethod }}
{{- if eq $w.Consensus.BootstrapMethod "file" }}
BootstrapFile: {{ .RootDir }}/{{ .SystemChannel.Name }}_block.pb
{{- end }}
LocalMSPDir: {{ $w.OrdererLocalMSPDir Orderer }}
LocalMSPID: {{ ($w.Organization Orderer.Organization).MSPID }}
Profile:
Expand Down
Loading

0 comments on commit 1e35107

Please sign in to comment.