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

Follower: check if join block different from fetched block #4265

Merged
merged 1 commit into from
Jun 8, 2023
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
69 changes: 36 additions & 33 deletions cmd/osnadmin/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var _ = Describe("osnadmin", func() {

BeforeEach(func() {
var err error
tempDir, err = ioutil.TempDir("", "osnadmin")
tempDir, err = os.MkdirTemp("", "osnadmin")
Expect(err).NotTo(HaveOccurred())

generateCertificates(tempDir)
Expand Down Expand Up @@ -782,46 +782,49 @@ func generateCertificates(tempDir string) {
}

func blockWithGroups(groups map[string]*cb.ConfigGroup, channelID string) *cb.Block {
return &cb.Block{
Data: &cb.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&cb.Envelope{
Payload: protoutil.MarshalOrPanic(&cb.Payload{
Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{
Config: &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: groups,
Values: map[string]*cb.ConfigValue{
"HashingAlgorithm": {
Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{
Name: bccsp.SHA256,
}),
},
"BlockDataHashingStructure": {
Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{
Width: math.MaxUint32,
}),
},
"OrdererAddresses": {
Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{
Addresses: []string{"localhost"},
}),
},
block := protoutil.NewBlock(0, []byte{})
block.Data = &cb.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&cb.Envelope{
Payload: protoutil.MarshalOrPanic(&cb.Payload{
Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{
Config: &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: groups,
Values: map[string]*cb.ConfigValue{
"HashingAlgorithm": {
Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{
Name: bccsp.SHA256,
}),
},
"BlockDataHashingStructure": {
Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{
Width: math.MaxUint32,
}),
},
"OrdererAddresses": {
Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{
Addresses: []string{"localhost"},
}),
},
},
},
}),
Header: &cb.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
Type: int32(cb.HeaderType_CONFIG),
ChannelId: channelID,
}),
},
}),
Header: &cb.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
Type: int32(cb.HeaderType_CONFIG),
ChannelId: channelID,
}),
},
}),
},
}),
},
}
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
protoutil.InitBlockMetadata(block)

return block
}

func createBlockFile(tempDir string, configBlock *cb.Block) string {
Expand Down
69 changes: 36 additions & 33 deletions integration/raft/channel_participation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1040,46 +1040,49 @@ func multiNodeEtcdRaftTwoChannels() *nwo.Config {
}

func createJoinBlockDefineSystemChannel(channelID string) *common.Block {
return &common.Block{
Data: &common.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&common.Envelope{
Payload: protoutil.MarshalOrPanic(&common.Payload{
Data: protoutil.MarshalOrPanic(&common.ConfigEnvelope{
Config: &common.Config{
ChannelGroup: &common.ConfigGroup{
Groups: map[string]*common.ConfigGroup{
"Consortiums": {},
block := protoutil.NewBlock(0, []byte{})
block.Data = &common.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&common.Envelope{
Payload: protoutil.MarshalOrPanic(&common.Payload{
Data: protoutil.MarshalOrPanic(&common.ConfigEnvelope{
Config: &common.Config{
ChannelGroup: &common.ConfigGroup{
Groups: map[string]*common.ConfigGroup{
"Consortiums": {},
},
Values: map[string]*common.ConfigValue{
"HashingAlgorithm": {
Value: protoutil.MarshalOrPanic(&common.HashingAlgorithm{
Name: bccsp.SHA256,
}),
},
"BlockDataHashingStructure": {
Value: protoutil.MarshalOrPanic(&common.BlockDataHashingStructure{
Width: math.MaxUint32,
}),
},
Values: map[string]*common.ConfigValue{
"HashingAlgorithm": {
Value: protoutil.MarshalOrPanic(&common.HashingAlgorithm{
Name: bccsp.SHA256,
}),
},
"BlockDataHashingStructure": {
Value: protoutil.MarshalOrPanic(&common.BlockDataHashingStructure{
Width: math.MaxUint32,
}),
},
"OrdererAddresses": {
Value: protoutil.MarshalOrPanic(&common.OrdererAddresses{
Addresses: []string{"localhost"},
}),
},
"OrdererAddresses": {
Value: protoutil.MarshalOrPanic(&common.OrdererAddresses{
Addresses: []string{"localhost"},
}),
},
},
},
}),
Header: &common.Header{
ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
Type: int32(common.HeaderType_CONFIG),
ChannelId: channelID,
}),
},
}),
Header: &common.Header{
ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
Type: int32(common.HeaderType_CONFIG),
ChannelId: channelID,
}),
},
}),
},
}),
},
}
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
protoutil.InitBlockMetadata(block)

return block
}
1 change: 1 addition & 0 deletions integration/raft/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ var _ = Describe("EndToEnd reconfiguration and onboarding", func() {
Expect(err).NotTo(HaveOccurred())
genesisBlock.Data.Data[0], err = protoutil.Marshal(envelope)
Expect(err).NotTo(HaveOccurred())
genesisBlock.Header.DataHash = protoutil.BlockDataHash(genesisBlock.Data)
genesisBlockBytes, err := protoutil.Marshal(genesisBlock)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(network.OutputBlockPath("testchannel"), genesisBlockBytes, 0o644)
Expand Down
10 changes: 10 additions & 0 deletions orderer/common/channelparticipation/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
package channelparticipation

import (
"bytes"

cb "github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/common/channelconfig"
Expand All @@ -25,6 +27,14 @@ func ValidateJoinBlock(configBlock *cb.Block) (channelID string, err error) {
return "", errors.New("block is not a config block")
}

if configBlock.Metadata == nil || len(configBlock.Metadata.Metadata) == 0 {
return "", errors.New("invalid block: does not have metadata")
}

if !bytes.Equal(protoutil.BlockDataHash(configBlock.Data), configBlock.Header.DataHash) {
return "", errors.New("invalid block: Header.DataHash is different from Hash(block.Data)")
}

envelope, err := protoutil.ExtractEnvelope(configBlock, 0)
if err != nil {
return "", err
Expand Down
139 changes: 84 additions & 55 deletions orderer/common/channelparticipation/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"math"
"testing"

"github.com/golang/protobuf/proto"
cb "github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/orderer/common/channelparticipation"
Expand All @@ -19,12 +20,45 @@ import (
)

func TestValidateJoinBlock(t *testing.T) {
validJoinBlock := blockWithGroups(
map[string]*cb.ConfigGroup{
"Application": {},
},
"my-channel",
)

tests := []struct {
testName string
joinBlock *cb.Block
expectedChannelID string
expectedErr error
}{
{
testName: "Valid application channel join block",
joinBlock: validJoinBlock,
expectedChannelID: "my-channel",
expectedErr: nil,
},
{
testName: "Invalid block data hash",
joinBlock: func() *cb.Block {
b := proto.Clone(validJoinBlock).(*cb.Block)
b.Header.DataHash = []byte("bogus")
return b
}(),
expectedChannelID: "",
expectedErr: errors.New("invalid block: Header.DataHash is different from Hash(block.Data)"),
},
{
testName: "Invalid block metadata",
joinBlock: func() *cb.Block {
b := proto.Clone(validJoinBlock).(*cb.Block)
b.Metadata = nil
return b
}(),
expectedChannelID: "",
expectedErr: errors.New("invalid block: does not have metadata"),
},
{
testName: "Not supported: system channel join block",
joinBlock: blockWithGroups(
Expand All @@ -36,17 +70,6 @@ func TestValidateJoinBlock(t *testing.T) {
expectedChannelID: "",
expectedErr: errors.New("invalid config: contains consortiums: system channel not supported"),
},
{
testName: "Valid application channel join block",
joinBlock: blockWithGroups(
map[string]*cb.ConfigGroup{
"Application": {},
},
"my-channel",
),
expectedChannelID: "my-channel",
expectedErr: nil,
},
{
testName: "Join block not a config block",
joinBlock: nonConfigBlock(),
Expand Down Expand Up @@ -100,62 +123,68 @@ func TestValidateJoinBlock(t *testing.T) {
}

func blockWithGroups(groups map[string]*cb.ConfigGroup, channelID string) *cb.Block {
return &cb.Block{
Data: &cb.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&cb.Envelope{
Payload: protoutil.MarshalOrPanic(&cb.Payload{
Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{
Config: &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: groups,
Values: map[string]*cb.ConfigValue{
"HashingAlgorithm": {
Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{
Name: bccsp.SHA256,
}),
},
"BlockDataHashingStructure": {
Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{
Width: math.MaxUint32,
}),
},
"OrdererAddresses": {
Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{
Addresses: []string{"localhost"},
}),
},
block := protoutil.NewBlock(0, []byte{})
block.Data = &cb.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&cb.Envelope{
Payload: protoutil.MarshalOrPanic(&cb.Payload{
Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{
Config: &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: groups,
Values: map[string]*cb.ConfigValue{
"HashingAlgorithm": {
Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{
Name: bccsp.SHA256,
}),
},
"BlockDataHashingStructure": {
Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{
Width: math.MaxUint32,
}),
},
"OrdererAddresses": {
Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{
Addresses: []string{"localhost"},
}),
},
},
},
}),
Header: &cb.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
Type: int32(cb.HeaderType_CONFIG),
ChannelId: channelID,
}),
},
}),
Header: &cb.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
Type: int32(cb.HeaderType_CONFIG),
ChannelId: channelID,
}),
},
}),
},
}),
},
}
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
protoutil.InitBlockMetadata(block)

return block
}

func nonConfigBlock() *cb.Block {
return &cb.Block{
Data: &cb.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&cb.Envelope{
Payload: protoutil.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
Type: int32(cb.HeaderType_ENDORSER_TRANSACTION),
}),
},
}),
block := protoutil.NewBlock(0, []byte{})
block.Data = &cb.BlockData{
Data: [][]byte{
protoutil.MarshalOrPanic(&cb.Envelope{
Payload: protoutil.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
Type: int32(cb.HeaderType_ENDORSER_TRANSACTION),
}),
},
}),
},
}),
},
}
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
protoutil.InitBlockMetadata(block)

return block
}
Loading