Unverified Commit 104ec7c1 authored by Jason Yellick's avatar Jason Yellick Committed by Artem Barger
Browse files

FAB-14057 Specify tx base profile in configtxgen



In order to support altering ordering parameters at channel creation
time, we add support for specifying a base orderer system channel
configuration profile.  The expected usage is:

 configtxgen -outputChannelCreateTx my.pb.tx \
             -channelCreateTxBaseProfile sysChannelProfile

Change-Id: I191bb730251178241b57f7ec10a7810bc76b66bd
Signed-off-by: default avatarJason Yellick <jyellick@us.ibm.com>
Signed-off-by: default avatarArtem Barger <bartem@il.ibm.com>
parent 28b11ed4
......@@ -48,10 +48,16 @@ func doOutputBlock(config *genesisconfig.Profile, channelID string, outputBlock
return nil
}
func doOutputChannelCreateTx(conf *genesisconfig.Profile, channelID string, outputChannelCreateTx string) error {
func doOutputChannelCreateTx(conf, baseProfile *genesisconfig.Profile, channelID string, outputChannelCreateTx string) error {
logger.Info("Generating new channel configtx")
configtx, err := encoder.MakeChannelCreationTransaction(channelID, nil, conf)
var configtx *cb.Envelope
var err error
if baseProfile == nil {
configtx, err = encoder.MakeChannelCreationTransaction(channelID, nil, conf)
} else {
configtx, err = encoder.MakeChannelCreationTransactionWithSystemChannelContext(channelID, nil, conf, baseProfile)
}
if err != nil {
return err
}
......@@ -207,11 +213,12 @@ func doPrintOrg(t *genesisconfig.TopLevel, printOrg string) error {
}
func main() {
var outputBlock, outputChannelCreateTx, profile, configPath, channelID, inspectBlock, inspectChannelCreateTx, outputAnchorPeersUpdate, asOrg, printOrg string
var outputBlock, outputChannelCreateTx, channelCreateTxBaseProfile, profile, configPath, channelID, inspectBlock, inspectChannelCreateTx, outputAnchorPeersUpdate, asOrg, printOrg string
flag.StringVar(&outputBlock, "outputBlock", "", "The path to write the genesis block to (if set)")
flag.StringVar(&channelID, "channelID", "", "The channel ID to use in the configtx")
flag.StringVar(&outputChannelCreateTx, "outputCreateChannelTx", "", "The path to write a channel creation configtx to (if set)")
flag.StringVar(&channelCreateTxBaseProfile, "channelCreateTxBaseProfile", "", "Specifies a profile to consider as the orderer system channel current state to allow modification of non-application parameters during channel create tx generation. Only valid in conjuction with 'outputCreateChannelTx'.")
flag.StringVar(&profile, "profile", genesisconfig.SampleInsecureSoloProfile, "The profile from configtx.yaml to use for generation.")
flag.StringVar(&configPath, "configPath", "", "The path containing the configuration to use (if set)")
flag.StringVar(&inspectBlock, "inspectBlock", "", "Prints the configuration contained in the block at the specified path")
......@@ -271,6 +278,18 @@ func main() {
topLevelConfig = genesisconfig.LoadTopLevel()
}
var baseProfile *genesisconfig.Profile
if channelCreateTxBaseProfile != "" {
if outputChannelCreateTx == "" {
logger.Warning("Specified 'channelCreateTxBaseProfile', but did not specify 'outputChannelCreateTx', 'channelCreateTxBaseProfile' will not affect output.")
}
if configPath != "" {
baseProfile = genesisconfig.Load(channelCreateTxBaseProfile, configPath)
} else {
baseProfile = genesisconfig.Load(channelCreateTxBaseProfile)
}
}
if outputBlock != "" {
if err := doOutputBlock(profileConfig, channelID, outputBlock); err != nil {
logger.Fatalf("Error on outputBlock: %s", err)
......@@ -278,7 +297,7 @@ func main() {
}
if outputChannelCreateTx != "" {
if err := doOutputChannelCreateTx(profileConfig, channelID, outputChannelCreateTx); err != nil {
if err := doOutputChannelCreateTx(profileConfig, baseProfile, channelID, outputChannelCreateTx); err != nil {
logger.Fatalf("Error on outputChannelCreateTx: %s", err)
}
}
......
......@@ -81,7 +81,7 @@ func TestMissingConsortiumValue(t *testing.T) {
config := configtxgentest.Load(genesisconfig.SampleSingleMSPChannelProfile)
config.Consortium = ""
assert.Error(t, doOutputChannelCreateTx(config, "foo", configTxDest), "Missing Consortium value in Application Profile definition")
assert.Error(t, doOutputChannelCreateTx(config, nil, "foo", configTxDest), "Missing Consortium value in Application Profile definition")
}
func TestMissingApplicationValue(t *testing.T) {
......@@ -90,7 +90,7 @@ func TestMissingApplicationValue(t *testing.T) {
config := configtxgentest.Load(genesisconfig.SampleSingleMSPChannelProfile)
config.Application = nil
assert.Error(t, doOutputChannelCreateTx(config, "foo", configTxDest), "Missing Application value in Application Profile definition")
assert.Error(t, doOutputChannelCreateTx(config, nil, "foo", configTxDest), "Missing Application value in Application Profile definition")
}
func TestInspectMissingConfigTx(t *testing.T) {
......@@ -102,7 +102,7 @@ func TestInspectConfigTx(t *testing.T) {
config := configtxgentest.Load(genesisconfig.SampleSingleMSPChannelProfile)
assert.NoError(t, doOutputChannelCreateTx(config, "foo", configTxDest), "Good outputChannelCreateTx generation request")
assert.NoError(t, doOutputChannelCreateTx(config, nil, "foo", configTxDest), "Good outputChannelCreateTx generation request")
assert.NoError(t, doInspectChannelCreateTx(configTxDest), "Good configtx inspection request")
}
......@@ -148,6 +148,7 @@ func TestConfigTxFlags(t *testing.T) {
os.Args = []string{
"cmd",
"-outputCreateChannelTx=" + configTxDest,
"-channelCreateTxBaseProfile=" + genesisconfig.SampleSingleMSPSoloProfile,
"-profile=" + genesisconfig.SampleSingleMSPChannelProfile,
"-configPath=" + devConfigDir,
"-inspectChannelCreateTx=" + configTxDest,
......
......@@ -81,6 +81,17 @@ var _ = Describe("EndToEnd", func() {
network = nwo.New(nwo.BasicSolo(), testDir, client, BasePort(), components)
network.MetricsProvider = "statsd"
network.StatsdEndpoint = datagramReader.Address()
network.Profiles = append(network.Profiles, &nwo.Profile{
Name: "TwoOrgsBaseProfileChannel",
Consortium: "SampleConsortium",
Orderers: []string{"orderer"},
Organizations: []string{"Org1", "Org2"},
})
network.Channels = append(network.Channels, &nwo.Channel{
Name: "baseprofilechannel",
Profile: "TwoOrgsBaseProfileChannel",
BaseProfile: "TwoOrgsOrdererGenesis",
})
network.GenerateConfigTree()
network.Bootstrap()
......@@ -120,6 +131,10 @@ var _ = Describe("EndToEnd", func() {
CheckPeerStatsdMetrics(datagramReader.String(), "org1_peer0")
CheckPeerStatsdMetrics(datagramReader.String(), "org2_peer1")
CheckOrdererStatsdMetrics(datagramReader.String(), "ordererorg_orderer")
By("setting up a channel from a base profile")
additionalPeer := network.Peer("Org2", "peer1")
network.CreateChannel("baseprofilechannel", orderer, peer, additionalPeer)
})
})
......
......@@ -31,6 +31,7 @@ type CreateChannelTx struct {
Profile string
ConfigPath string
OutputCreateChannelTx string
BaseProfile string
}
func (c CreateChannelTx) SessionName() string {
......@@ -43,6 +44,7 @@ func (c CreateChannelTx) Args() []string {
"-profile", c.Profile,
"-configPath", c.ConfigPath,
"-outputCreateChannelTx", c.OutputCreateChannelTx,
"-channelCreateTxBaseProfile", c.BaseProfile,
}
}
......
......@@ -61,14 +61,8 @@ Channel: &ChannelDefaults
Profiles:{{ range .Profiles }}
{{ .Name }}:
{{- if .Orderers }}
<<: *ChannelDefaults
Consortiums:{{ range $w.Consortiums }}
{{ .Name }}:
Organizations:{{ range .Organizations }}
- *{{ ($w.Organization .).MSPID }}
{{- end }}
{{- end }}
{{- if .Orderers }}
Orderer:
OrdererType: {{ $w.Consensus.Type }}
Addresses:{{ range .Orderers }}{{ with $w.Orderer . }}
......@@ -118,7 +112,9 @@ Profiles:{{ range .Profiles }}
BlockValidation:
Type: ImplicitMeta
Rule: ANY Writers
{{- else }}
{{- end }}
{{- if .Consortium }}
Consortium: {{ .Consortium }}
Application:
Capabilities:
V1_3: true
......@@ -136,7 +132,19 @@ Profiles:{{ range .Profiles }}
Admins:
Type: ImplicitMeta
Rule: MAJORITY Admins
Consortium: {{ .Consortium }}
LifecycleEndorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Endorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
{{- else }}
Consortiums:{{ range $w.Consortiums }}
{{ .Name }}:
Organizations:{{ range .Organizations }}
- *{{ ($w.Organization .).MSPID }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{ end }}
......
......@@ -73,8 +73,9 @@ type SystemChannel struct {
// Channel associates a channel name with a configtxgen profile name.
type Channel struct {
Name string `yaml:"name,omitempty"`
Profile string `yaml:"profile,omitempty"`
Name string `yaml:"name,omitempty"`
Profile string `yaml:"profile,omitempty"`
BaseProfile string `yaml:"baseprofile,omitempty"`
}
// Orderer defines an orderer instance and its owning organization.
......@@ -581,6 +582,7 @@ func (n *Network) Bootstrap() {
sess, err := n.ConfigTxGen(commands.CreateChannelTx{
ChannelID: c.Name,
Profile: c.Profile,
BaseProfile: c.BaseProfile,
ConfigPath: n.RootDir,
OutputCreateChannelTx: n.CreateChannelTxPath(c.Name),
})
......@@ -720,21 +722,32 @@ func (n *Network) UpdateChannelAnchors(o *Orderer, channelName string) {
// CreateChannel will submit an existing create channel transaction to the
// specified orderer. The channel transaction must exist at the location
// returned by CreateChannelTxPath.
// returned by CreateChannelTxPath. Optionally, additional signers may be
// included in the case where the channel creation tx modifies other
// aspects of the channel config for the new channel.
//
// The orderer must be running when this is called.
func (n *Network) CreateChannel(channelName string, o *Orderer, p *Peer) {
func (n *Network) CreateChannel(channelName string, o *Orderer, p *Peer, additionalSigners ...*Peer) {
channelCreateTxPath := n.CreateChannelTxPath(channelName)
for _, signer := range additionalSigners {
sess, err := n.PeerAdminSession(signer, commands.SignConfigTx{
File: channelCreateTxPath,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
}
createChannel := func() int {
sess, err := n.PeerAdminSession(p, commands.ChannelCreate{
ChannelID: channelName,
Orderer: n.OrdererAddress(o, ListenPort),
File: n.CreateChannelTxPath(channelName),
File: channelCreateTxPath,
OutputBlock: "/dev/null",
})
Expect(err).NotTo(HaveOccurred())
return sess.Wait(n.EventuallyTimeout).ExitCode()
}
Eventually(createChannel, n.EventuallyTimeout).Should(Equal(0))
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment