Skip to content

Commit

Permalink
[FAB-2213] Embed CONFIG_UPDATE tx in CONFIG
Browse files Browse the repository at this point in the history
https://jira.hyperledger.org/browse/FAB-2213

In order to support auditability on who submitted a config update
transaction, the full submitted envelope needs to be embedded into the
configuration, not just the config envelope.  This CR modifies the
configtx proto to accommodate this.

Change-Id: Id75b4206c3dff11ef71d9826e7e8e7b50dcb3700
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Feb 15, 2017
1 parent 6b78395 commit 02322a1
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 83 deletions.
4 changes: 2 additions & 2 deletions common/configtx/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ type Manager interface {
Resources

// Apply attempts to apply a configtx to become the new config
Apply(configtx *cb.ConfigUpdateEnvelope) error
Apply(configtx *cb.Envelope) error

// Validate attempts to validate a new configtx against the current config state
Validate(configtx *cb.ConfigUpdateEnvelope) error
Validate(configtx *cb.Envelope) error

// ConfigEnvelope returns the *cb.ConfigEnvelope from the last successful Apply
ConfigEnvelope() *cb.ConfigEnvelope
Expand Down
38 changes: 34 additions & 4 deletions common/configtx/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,16 +310,46 @@ func (cm *configManager) processConfig(configtx *cb.ConfigUpdateEnvelope) (map[s
return computedResult, nil
}

func envelopeToConfigUpdate(configtx *cb.Envelope) (*cb.ConfigUpdateEnvelope, error) {
payload, err := utils.UnmarshalPayload(configtx.Payload)
if err != nil {
return nil, err
}

if payload.Header == nil || payload.Header.ChannelHeader == nil {
return nil, fmt.Errorf("Envelope must have ChannelHeader")
}

if payload.Header == nil || payload.Header.ChannelHeader.Type != int32(cb.HeaderType_CONFIG_UPDATE) {
return nil, fmt.Errorf("Not a tx of type CONFIG_UPDATE")
}

configUpdateEnv, err := UnmarshalConfigUpdateEnvelope(payload.Data)
if err != nil {
return nil, fmt.Errorf("Error unmarshaling ConfigUpdateEnvelope: %s", err)
}

return configUpdateEnv, nil
}

// Validate attempts to validate a new configtx against the current config state
func (cm *configManager) Validate(configtx *cb.ConfigUpdateEnvelope) error {
_, err := cm.processConfig(configtx)
func (cm *configManager) Validate(configtx *cb.Envelope) error {
configUpdateEnv, err := envelopeToConfigUpdate(configtx)
if err != nil {
return err
}
_, err = cm.processConfig(configUpdateEnv)
cm.rollbackHandlers()
return err
}

// Apply attempts to apply a configtx to become the new config
func (cm *configManager) Apply(configtx *cb.ConfigUpdateEnvelope) error {
configMap, err := cm.processConfig(configtx)
func (cm *configManager) Apply(configtx *cb.Envelope) error {
configUpdateEnv, err := envelopeToConfigUpdate(configtx)
if err != nil {
return err
}
configMap, err := cm.processConfig(configUpdateEnv)
if err != nil {
cm.rollbackHandlers()
return err
Expand Down
17 changes: 13 additions & 4 deletions common/configtx/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func makeConfigEnvelope(chainID string, configPairs ...*configPair) *cb.ConfigEn
}
}

func makeConfigUpdateEnvelope(chainID string, configPairs ...*configPair) *cb.ConfigUpdateEnvelope {
func makeConfigUpdateEnvelope(chainID string, configPairs ...*configPair) *cb.Envelope {
values := make(map[string]*cb.ConfigValue)
for _, pair := range configPairs {
values[pair.key] = pair.value
Expand All @@ -84,8 +84,17 @@ func makeConfigUpdateEnvelope(chainID string, configPairs ...*configPair) *cb.Co
Values: values,
},
}
return &cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(config),
return &cb.Envelope{
Payload: utils.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: &cb.ChannelHeader{
Type: int32(cb.HeaderType_CONFIG_UPDATE),
},
},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(config),
}),
}),
}
}

Expand Down Expand Up @@ -274,7 +283,7 @@ func TestEmptyConfigUpdate(t *testing.T) {
t.Fatalf("Error constructing config manager: %s", err)
}

newConfig := &cb.ConfigUpdateEnvelope{}
newConfig := &cb.Envelope{}

err = cm.Validate(newConfig)
if err == nil {
Expand Down
12 changes: 11 additions & 1 deletion common/configtx/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,17 @@ func MakeChainCreationTransaction(creationPolicy string, chainID string, signer
Header: configUpdate.Header,
Channel: configUpdate.WriteSet,
},
LastUpdate: newConfigUpdateEnv,
LastUpdate: &cb.Envelope{
Payload: utils.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: &cb.ChannelHeader{
ChannelId: chainID,
Type: int32(cb.HeaderType_CONFIG_UPDATE),
},
},
Data: utils.MarshalOrPanic(newConfigUpdateEnv),
}),
},
}

payloadChannelHeader := utils.MakeChannelHeader(cb.HeaderType_CONFIG, msgVersion, chainID, epoch)
Expand Down
10 changes: 10 additions & 0 deletions common/configtx/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ func UnmarshalConfigUpdate(data []byte) (*cb.ConfigUpdate, error) {
return configUpdate, nil
}

// UnmarshalConfigUpdateEnvelope attempts to unmarshal bytes to a *cb.ConfigUpdate
func UnmarshalConfigUpdateEnvelope(data []byte) (*cb.ConfigUpdateEnvelope, error) {
configUpdateEnvelope := &cb.ConfigUpdateEnvelope{}
err := proto.Unmarshal(data, configUpdateEnvelope)
if err != nil {
return nil, err
}
return configUpdateEnvelope, nil
}

// UnmarshalConfigEnvelope attempts to unmarshal bytes to a *cb.ConfigEnvelope
func UnmarshalConfigEnvelope(data []byte) (*cb.ConfigEnvelope, error) {
configEnv := &cb.ConfigEnvelope{}
Expand Down
6 changes: 3 additions & 3 deletions common/mocks/configtx/configtx.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ type Manager struct {
ApplyVal error

// AppliedConfigUpdateEnvelope is set by Apply
AppliedConfigUpdateEnvelope *cb.ConfigUpdateEnvelope
AppliedConfigUpdateEnvelope *cb.Envelope

// ValidateVal is returned by Validate
ValidateVal error
Expand All @@ -142,12 +142,12 @@ func (cm *Manager) Sequence() uint64 {
}

// Apply returns ApplyVal
func (cm *Manager) Apply(configtx *cb.ConfigUpdateEnvelope) error {
func (cm *Manager) Apply(configtx *cb.Envelope) error {
cm.AppliedConfigUpdateEnvelope = configtx
return cm.ApplyVal
}

// Validate returns ValidateVal
func (cm *Manager) Validate(configtx *cb.ConfigUpdateEnvelope) error {
func (cm *Manager) Validate(configtx *cb.Envelope) error {
return cm.ValidateVal
}
2 changes: 1 addition & 1 deletion core/committer/txvalidator/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type Support interface {
MSPManager() msp.MSPManager

// Apply attempts to apply a configtx to become the new config
Apply(configtx *common.ConfigUpdateEnvelope) error
Apply(configtx *common.Envelope) error
}

//Validator interface which defines API to validate block transactions
Expand Down
2 changes: 1 addition & 1 deletion core/mocks/txvalidator/support.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ func (ms *Support) MSPManager() msp.MSPManager {
}

// Apply returns ApplyVal
func (ms *Support) Apply(configtx *common.ConfigUpdateEnvelope) error {
func (ms *Support) Apply(configtx *common.Envelope) error {
return ms.ApplyVal
}
17 changes: 7 additions & 10 deletions orderer/common/configtxfilter/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ package configtxfilter
import (
"fmt"

"github.com/hyperledger/fabric/common/configtx"
"github.com/hyperledger/fabric/common/configtx/api"
"github.com/hyperledger/fabric/orderer/common/filter"
cb "github.com/hyperledger/fabric/protos/common"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/protos/utils"
)

type configFilter struct {
Expand All @@ -39,7 +39,7 @@ func NewFilter(manager api.Manager) filter.Rule {

type configCommitter struct {
manager api.Manager
configEnvelope *cb.ConfigUpdateEnvelope
configEnvelope *cb.Envelope
}

func (cc *configCommitter) Commit() {
Expand All @@ -55,9 +55,7 @@ func (cc *configCommitter) Isolated() bool {

// Apply applies the rule to the given Envelope, replying with the Action to take for the message
func (cf *configFilter) Apply(message *cb.Envelope) (filter.Action, filter.Committer) {
msgData := &cb.Payload{}

err := proto.Unmarshal(message.Payload, msgData)
msgData, err := utils.UnmarshalPayload(message.Payload)
if err != nil {
return filter.Forward, nil
}
Expand All @@ -66,19 +64,18 @@ func (cf *configFilter) Apply(message *cb.Envelope) (filter.Action, filter.Commi
return filter.Forward, nil
}

config := &cb.ConfigEnvelope{}
err = proto.Unmarshal(msgData.Data, config)
configEnvelope, err := configtx.UnmarshalConfigEnvelope(msgData.Data)
if err != nil {
return filter.Reject, nil
}

err = cf.configManager.Validate(config.LastUpdate)
err = cf.configManager.Validate(configEnvelope.LastUpdate)
if err != nil {
return filter.Reject, nil
}

return filter.Accept, &configCommitter{
manager: cf.configManager,
configEnvelope: config.LastUpdate,
configEnvelope: configEnvelope.LastUpdate,
}
}
22 changes: 15 additions & 7 deletions orderer/common/configtxfilter/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,19 @@ func TestAcceptGoodConfig(t *testing.T) {
configUpdateEnv := &cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(configGroup),
}
configEnvBytes := utils.MarshalOrPanic(&cb.ConfigEnvelope{
LastUpdate: configUpdateEnv,
})
configEnv := &cb.ConfigEnvelope{
LastUpdate: &cb.Envelope{
Payload: utils.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: &cb.ChannelHeader{
Type: int32(cb.HeaderType_CONFIG_UPDATE),
},
},
Data: utils.MarshalOrPanic(configUpdateEnv),
}),
},
}
configEnvBytes := utils.MarshalOrPanic(configEnv)
configBytes := utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: &cb.ChannelHeader{Type: int32(cb.HeaderType_CONFIG)}}, Data: configEnvBytes})
configEnvelope := &cb.Envelope{
Payload: configBytes,
Expand All @@ -63,12 +73,10 @@ func TestAcceptGoodConfig(t *testing.T) {
t.Fatal("Config transactions should be isolated to their own block")
}

t.Logf("%+v", committer.(*configCommitter).configEnvelope)

committer.Commit()

if !reflect.DeepEqual(mcm.AppliedConfigUpdateEnvelope, configUpdateEnv) {
t.Fatalf("Should have applied new config on commit got %+v and %+v", mcm.AppliedConfigUpdateEnvelope, configUpdateEnv)
if !reflect.DeepEqual(mcm.AppliedConfigUpdateEnvelope, configEnv.LastUpdate) {
t.Fatalf("Should have applied new config on commit got %+v and %+v", mcm.AppliedConfigUpdateEnvelope, configEnv.LastUpdate)
}
}

Expand Down
18 changes: 15 additions & 3 deletions orderer/multichain/systemchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/hyperledger/fabric/orderer/common/filter"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
"github.com/hyperledger/fabric/protos/utils"

"github.com/golang/protobuf/proto"
)
Expand Down Expand Up @@ -155,8 +156,19 @@ func (sc *systemChain) authorize(configEnvelope *cb.ConfigEnvelope) cb.Status {
return cb.Status_BAD_REQUEST
}

configNext := &cb.ConfigUpdate{}
err := proto.Unmarshal(configEnvelope.LastUpdate.ConfigUpdate, configNext)
configEnvEnvPayload, err := utils.UnmarshalPayload(configEnvelope.LastUpdate.Payload)
if err != nil {
logger.Debugf("Failing to validate chain creation because of payload unmarshaling error: %s", err)
return cb.Status_BAD_REQUEST
}

configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(configEnvEnvPayload.Data)
if err != nil {
logger.Debugf("Failing to validate chain creation because of config update envelope unmarshaling error: %s", err)
return cb.Status_BAD_REQUEST
}

configNext, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
if err != nil {
logger.Debugf("Failing to validate chain creation because of unmarshaling error: %s", err)
return cb.Status_BAD_REQUEST
Expand Down Expand Up @@ -200,7 +212,7 @@ func (sc *systemChain) authorize(configEnvelope *cb.ConfigEnvelope) cb.Status {
return cb.Status_INTERNAL_SERVER_ERROR
}

signedData, err := configEnvelope.LastUpdate.AsSignedData()
signedData, err := configUpdateEnv.AsSignedData()
if err != nil {
logger.Debugf("Failed to validate chain creation because config envelope could not be converted to signed data: %s", err)
return cb.Status_BAD_REQUEST
Expand Down
12 changes: 11 additions & 1 deletion orderer/multichain/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,17 @@ func makeConfigTxFromConfigUpdateEnvelope(chainID string, configUpdateEnv *cb.Co
Header: configUpdate.Header,
Channel: configUpdate.WriteSet,
},
LastUpdate: configUpdateEnv,
LastUpdate: &cb.Envelope{
Payload: utils.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: &cb.ChannelHeader{
Type: int32(cb.HeaderType_CONFIG_UPDATE),
ChannelId: chainID,
},
},
Data: utils.MarshalOrPanic(configUpdateEnv),
}),
},
}),
}
return &cb.Envelope{
Expand Down
Loading

0 comments on commit 02322a1

Please sign in to comment.