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

Chan.Part.API: Onboarding and follower CFT IT #2094

Merged
merged 1 commit into from
Nov 17, 2020
Merged
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
1 change: 0 additions & 1 deletion integration/channelparticipation/channel_participation.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ func getBody(client *http.Client, url string) func() string {
return func() string {
resp, err := client.Get(url)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
bodyBytes, err := ioutil.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
resp.Body.Close()
Expand Down
331 changes: 243 additions & 88 deletions integration/raft/channel_participation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"github.com/hyperledger/fabric-config/configtx"
"github.com/hyperledger/fabric-config/configtx/orderer"
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/common/ledger/blockledger/fileledger"
"github.com/hyperledger/fabric/common/metrics/disabled"
"github.com/hyperledger/fabric/integration/channelparticipation"
conftx "github.com/hyperledger/fabric/integration/configtx"
"github.com/hyperledger/fabric/integration/nwo"
Expand Down Expand Up @@ -84,8 +86,7 @@ var _ = Describe("ChannelParticipation", func() {
ordererRunner := network.OrdererRunner(o)
ordererProcess := ifrit.Invoke(ordererRunner)
Eventually(ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed())
Eventually(ordererRunner.Err(), network.EventuallyTimeout).Should(gbytes.Say(
"Registrar initializing without a system channel, number of application channels: 0, with 0 consensus.Chain\\(s\\) and 0 follower.Chain\\(s\\)"))
Eventually(ordererRunner.Err(), network.EventuallyTimeout).Should(gbytes.Say("Registrar initializing without a system channel"))
ordererProcesses = append(ordererProcesses, ordererProcess)
ordererRunners = append(ordererRunners, ordererRunner)
}
Expand Down Expand Up @@ -459,106 +460,260 @@ var _ = Describe("ChannelParticipation", func() {
})
})

It("joins application channels with join-block as follower via channel participation api", func() {
orderer1 := network.Orderer("orderer1")
orderer2 := network.Orderer("orderer2")
orderer3 := network.Orderer("orderer3")
orderers := []*nwo.Orderer{orderer1, orderer2}
peer := network.Peer("Org1", "peer0")
Context("joining application channels with join-block as follower via channel participation api", func() {
var (
orderer1, orderer2, orderer3 *nwo.Orderer
orderers []*nwo.Orderer
peer *nwo.Peer
genesisBlock, configBlock *common.Block
)

By("starting two orderers")
for _, o := range orderers {
startOrderer(o)
cl := channelparticipation.List(network, o)
Expect(cl).To(Equal(channelparticipation.ChannelList{}))
}
BeforeEach(func() {
orderer1 = network.Orderer("orderer1")
orderer2 = network.Orderer("orderer2")
orderer3 = network.Orderer("orderer3")
orderers = []*nwo.Orderer{orderer1, orderer2}
peer = network.Peer("Org1", "peer0")

By("starting two orderers")
for _, o := range orderers {
startOrderer(o)
cl := channelparticipation.List(network, o)
Expect(cl).To(Equal(channelparticipation.ChannelList{}))
}

genesisBlock = applicationChannelGenesisBlock(network, orderers, []*nwo.Peer{peer}, "participation-trophy")
expectedChannelInfoPT := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 1,
}

By("joining orderer1 and orderer2 to the channel with a genesis block")
for _, o := range orderers {
By("joining " + o.Name + " to channel as a consenter")
channelparticipation.Join(network, o, "participation-trophy", genesisBlock, expectedChannelInfoPT)
channelInfo := channelparticipation.ListOne(network, o, "participation-trophy")
Expect(channelInfo).To(Equal(expectedChannelInfoPT))
}

submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 2,
})

genesisBlock := applicationChannelGenesisBlock(network, orderers, []*nwo.Peer{peer}, "participation-trophy")
expectedChannelInfoPT := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 1,
}
submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 3,
})

for _, o := range orderers {
By("joining " + o.Name + " to channel as a consenter")
channelparticipation.Join(network, o, "participation-trophy", genesisBlock, expectedChannelInfoPT)
channelInfo := channelparticipation.ListOne(network, o, "participation-trophy")
Expect(channelInfo).To(Equal(expectedChannelInfoPT))
}
By("submitting a channel config update")
channelConfig := nwo.GetConfig(network, peer, orderer1, "participation-trophy")
c := configtx.New(channelConfig)
err := c.Orderer().AddCapability("V1_1")
Expect(err).NotTo(HaveOccurred())
computeSignSubmitConfigUpdate(network, orderer1, peer, c, "participation-trophy")

submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 2,
})
currentBlockNumber := nwo.CurrentConfigBlockNumber(network, peer, orderer1, "participation-trophy")
Expect(currentBlockNumber).To(BeNumerically(">", 1))

submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 3,
By("getting the updated config block")
configBlock = nwo.GetConfigBlock(network, peer, orderer2, "participation-trophy")
})

By("submitting a channel config update")
channelConfig := nwo.GetConfig(network, peer, orderer1, "participation-trophy")
c := configtx.New(channelConfig)
err := c.Orderer().AddCapability("V1_1")
Expect(err).NotTo(HaveOccurred())
computeSignSubmitConfigUpdate(network, orderer1, peer, c, "participation-trophy")
It("joins the channel as a follower using a config block", func() {
By("starting third orderer")
startOrderer(orderer3)
cl := channelparticipation.List(network, orderer3)
Expect(cl).To(Equal(channelparticipation.ChannelList{}))

currentBlockNumber := nwo.CurrentConfigBlockNumber(network, peer, orderer1, "participation-trophy")
Expect(currentBlockNumber).To(BeNumerically(">", 1))
By("joining orderer3 to the channel as a follower")
// make sure we can join using a config block from one of the other orderers
expectedChannelInfoPTFollower := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "onboarding",
ConsensusRelation: "follower",
Height: 0,
}
channelparticipation.Join(network, orderer3, "participation-trophy", configBlock, expectedChannelInfoPTFollower)

By("ensuring orderer3 completes onboarding successfully")
expectedChannelInfoPTFollower.Status = "active"
expectedChannelInfoPTFollower.Height = 4
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPTFollower))

By("adding orderer3 to the consenters set")
channelConfig := nwo.GetConfig(network, peer, orderer1, "participation-trophy")
c := configtx.New(channelConfig)
err := c.Orderer().AddConsenter(consenterChannelConfig(network, orderer3))
Expect(err).NotTo(HaveOccurred())
computeSignSubmitConfigUpdate(network, orderer1, peer, c, "participation-trophy")

By("ensuring orderer3 transitions from follower to consenter")
// config update above added a block
expectedChannelInfoPT := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 5,
}
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPT))

By("starting third orderer")
startOrderer(orderer3)
cl := channelparticipation.List(network, orderer3)
Expect(cl).To(Equal(channelparticipation.ChannelList{}))
submitPeerTxn(orderer3, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 6,
})
})

By("joining orderer3 to the channel as a follower")
// make sure we can join using a config block from one of the other orderers
configBlockPT := nwo.GetConfigBlock(network, peer, orderer2, "participation-trophy")
expectedChannelInfoPTFollower := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "onboarding",
ConsensusRelation: "follower",
Height: 0,
}
channelparticipation.Join(network, orderer3, "participation-trophy", configBlockPT, expectedChannelInfoPTFollower)
It("recovers from a crash after the join block is written to the pendingops file repo", func() {
By("simulating the filesystem state at crash")
joinBlockFileRepoPath := filepath.Join(network.OrdererDir(orderer3), "system", "pendingops", "join")
err := os.MkdirAll(joinBlockFileRepoPath, 0755)
Expect(err).NotTo(HaveOccurred())
blockPath := filepath.Join(joinBlockFileRepoPath, "participation-trophy.join")
configBlockBytes, err := proto.Marshal(configBlock)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(blockPath, configBlockBytes, 0600)
Expect(err).NotTo(HaveOccurred())

By("starting third orderer")
startOrderer(orderer3)

By("ensuring orderer3 completes onboarding successfully")
expectedChannelInfoPTFollower := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "follower",
Height: 4,
}
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPTFollower))
})

By("ensuring orderer3 completes onboarding successfully")
expectedChannelInfoPTFollower.Status = "active"
expectedChannelInfoPTFollower.Height = 4
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPTFollower))
It("recovers from a crash after the join block is written to the pendingops file repo and the ledger directory (but not the ledger) has been created", func() {
By("simulating the filesystem state at crash")
joinBlockFileRepoPath := filepath.Join(network.OrdererDir(orderer3), "system", "pendingops", "join")
err := os.MkdirAll(joinBlockFileRepoPath, 0755)
Expect(err).NotTo(HaveOccurred())
blockPath := filepath.Join(joinBlockFileRepoPath, "participation-trophy.join")
configBlockBytes, err := proto.Marshal(configBlock)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(blockPath, configBlockBytes, 0600)
Expect(err).NotTo(HaveOccurred())

// create the ledger directory
ledgerPath := filepath.Join(network.OrdererDir(orderer3), "system", "chains", "participation-trophy")
err = os.MkdirAll(ledgerPath, 0755)
Expect(err).NotTo(HaveOccurred())

By("starting third orderer")
startOrderer(orderer3)

By("ensuring orderer3 completes onboarding successfully")
expectedChannelInfoPTFollower := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "follower",
Height: 4,
}
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPTFollower))
})

By("adding orderer3 to the consenters set")
channelConfig = nwo.GetConfig(network, peer, orderer1, "participation-trophy")
c = configtx.New(channelConfig)
err = c.Orderer().AddConsenter(consenterChannelConfig(network, orderer3))
Expect(err).NotTo(HaveOccurred())
computeSignSubmitConfigUpdate(network, orderer1, peer, c, "participation-trophy")
It("recovers from a crash after the join block is written to the pendingops file repo and the ledger has been created", func() {
By("simulating the filesystem state at crash")
joinBlockFileRepoPath := filepath.Join(network.OrdererDir(orderer3), "system", "pendingops", "join")
err := os.MkdirAll(joinBlockFileRepoPath, 0755)
Expect(err).NotTo(HaveOccurred())
blockPath := filepath.Join(joinBlockFileRepoPath, "participation-trophy.join")
configBlockBytes, err := proto.Marshal(configBlock)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(blockPath, configBlockBytes, 0600)
Expect(err).NotTo(HaveOccurred())

// create the ledger and add the genesis block
ledgerDir := filepath.Join(network.OrdererDir(orderer3), "system")
lf, err := fileledger.New(ledgerDir, &disabled.Provider{})
Expect(err).NotTo(HaveOccurred())
ledger, err := lf.GetOrCreate("participation-trophy")
Expect(err).NotTo(HaveOccurred())
err = ledger.Append(genesisBlock)
Expect(err).NotTo(HaveOccurred())
lf.Close()

By("starting third orderer")
startOrderer(orderer3)

By("ensuring orderer3 completes onboarding successfully")
expectedChannelInfoPTFollower := channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "follower",
Height: 4,
}
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPTFollower))

By("ensuring orderer3 transitions from follower to consenter")
// config update above added a block
expectedChannelInfoPT.Height = 5
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPT))
By("killing orderer3")
ordererProcesses[2].Signal(syscall.SIGKILL)
Eventually(ordererProcesses[2].Wait(), network.EventuallyTimeout).Should(Receive(MatchError("exit status 137")))

submitPeerTxn(orderer3, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 6,
By("submitting transactions while orderer3 is down")
submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 5,
})

submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "consenter",
Height: 6,
})

By("restarting orderer3 (follower) and ensuring it catches up to the blocks it missed")
ordererRunner := network.OrdererRunner(orderer3)
ordererProcess := ifrit.Invoke(ordererRunner)
Eventually(ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed())
ordererProcesses[2] = ordererProcess
ordererRunners[2] = ordererRunner
expectedChannelInfoPTFollower = channelparticipation.ChannelInfo{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
Status: "active",
ConsensusRelation: "follower",
Height: 6,
}
Eventually(func() channelparticipation.ChannelInfo {
return channelparticipation.ListOne(network, orderer3, "participation-trophy")
}, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPTFollower))
})
})

Expand Down