Skip to content

Commit

Permalink
[FAB-1698] Add block data hashing structure config
Browse files Browse the repository at this point in the history
https://jira.hyperledger.org/browse/FAB-1698

This commit adds a proto message for BlockDataHashingStructure which
dictates the width of the Merkle tree to use when computing the
BlockData hash.

It also adds this value to the chainconfig Reader, although no one
currently consumes this.

Change-Id: I17c4b13a30df8da0c39310be9c0f2a32a76ce859
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Jan 17, 2017
1 parent e057af8 commit 522c040
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 47 deletions.
26 changes: 25 additions & 1 deletion common/chainconfig/chainconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import (
const (
// HashingAlgorithmKey is the cb.ConfigurationItem type key name for the HashingAlgorithm message
HashingAlgorithmKey = "HashingAlgorithm"

// BlockDataHashingStructureKey is the cb.ConfigurationItem type key name for the BlockDataHashingStructure message
BlockDataHashingStructureKey = "BlockDataHashingStructure"
)

// Hashing algorithm types
Expand All @@ -48,10 +51,15 @@ type Descriptor interface {
// HashingAlgorithm returns the default algorithm to be used when hashing
// such as computing block hashes, and CreationPolicy digests
HashingAlgorithm() func(input []byte) []byte

// BlockDataHashingStructureWidth returns the width to use when constructing the
// Merkle tree to compute the BlockData hash
BlockDatahashingStructureWidth() int
}

type chainConfig struct {
hashingAlgorithm func(input []byte) []byte
hashingAlgorithm func(input []byte) []byte
blockDataHashingStructureWidth uint32
}

// DescriptorImpl is an implementation of Manager and configtx.ConfigHandler
Expand All @@ -73,6 +81,11 @@ func (pm *DescriptorImpl) HashingAlgorithm() func(input []byte) []byte {
return pm.config.hashingAlgorithm
}

// BlockDataHashingStructure returns the width to use when forming the block data hashing structure
func (pm *DescriptorImpl) BlockDataHashingStructureWidth() uint32 {
return pm.config.blockDataHashingStructureWidth
}

// BeginConfig is used to start a new configuration proposal
func (pm *DescriptorImpl) BeginConfig() {
if pm.pendingConfig != nil {
Expand Down Expand Up @@ -113,6 +126,17 @@ func (pm *DescriptorImpl) ProposeConfig(configItem *cb.ConfigurationItem) error
default:
return fmt.Errorf("Unknown hashing algorithm type: %s", hashingAlgorithm.Name)
}
case BlockDataHashingStructureKey:
blockDataHashingStructure := &cb.BlockDataHashingStructure{}
if err := proto.Unmarshal(configItem.Value, blockDataHashingStructure); err != nil {
return fmt.Errorf("Unmarshaling error for BlockDataHashingStructure: %s", err)
}

if blockDataHashingStructure.Width == 0 {
return fmt.Errorf("BlockDataHashStructure width must not be zero")
}

pm.pendingConfig.blockDataHashingStructureWidth = blockDataHashingStructure.Width
default:
logger.Warningf("Uknown Chain configuration item with key %s", configItem.Key)
}
Expand Down
43 changes: 43 additions & 0 deletions common/chainconfig/chainconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,46 @@ func TestHashingAlgorithm(t *testing.T) {
t.Fatalf("Should have set default hashing algorithm")
}
}

func TestBlockDataHashingStructure(t *testing.T) {
expectedWidth := uint32(7)
invalidMessage :=
&cb.ConfigurationItem{
Type: cb.ConfigurationItem_Chain,
Key: BlockDataHashingStructureKey,
Value: []byte("Garbage Data"),
}
invalidWidth := &cb.ConfigurationItem{
Type: cb.ConfigurationItem_Chain,
Key: BlockDataHashingStructureKey,
Value: utils.MarshalOrPanic(&cb.BlockDataHashingStructure{Width: 0}),
}
validWidth := &cb.ConfigurationItem{
Type: cb.ConfigurationItem_Chain,
Key: BlockDataHashingStructureKey,
Value: utils.MarshalOrPanic(&cb.BlockDataHashingStructure{Width: expectedWidth}),
}
m := NewDescriptorImpl()
m.BeginConfig()

err := m.ProposeConfig(invalidMessage)
if err == nil {
t.Fatalf("Should have failed on invalid message")
}

err = m.ProposeConfig(invalidWidth)
if err == nil {
t.Fatalf("Should have failed on invalid width")
}

err = m.ProposeConfig(validWidth)
if err != nil {
t.Fatalf("Error applying valid config: %s", err)
}

m.CommitConfig()

if newWidth := m.BlockDataHashingStructureWidth(); newWidth != expectedWidth {
t.Fatalf("Unexpected width, got %d expected %d", newWidth, expectedWidth)
}
}
1 change: 1 addition & 0 deletions protos/common/common.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

104 changes: 60 additions & 44 deletions protos/common/configuration.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions protos/common/configuration.proto
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,17 @@ message SignaturePolicy {
}


// HashingAlgorithm is encoded into the configuration transaction as a configuration item of type CHAIN
// with a Key of "HashingAlgorithm" as marshaled protobuf bytes
// HashingAlgorithm is encoded into the configuration transaction as a configuration item of type Chain
// with a Key of "HashingAlgorithm" and a Value of HashingAlgorithm as marshaled protobuf bytes
message HashingAlgorithm {
// Currently supported algorithms are: SHAKE256
string name = 1;
}

// BlockDataHashingStructure is encoded into the configuration transaction as a configuration item of
// type Chain with a Key of "BlockDataHashingStructure" and a Value of HashingAlgorithm as marshaled protobuf bytes
message BlockDataHashingStructure {
// width specifies the width of the Merkle tree to use when computing the BlockDataHash
// in order to replicate flat hashing, set this width to MAX_UINT32
uint32 width = 1;
}

0 comments on commit 522c040

Please sign in to comment.