Skip to content

Commit

Permalink
[FAB-5497] Create 1.0.1 fabric release
Browse files Browse the repository at this point in the history
Single commit which squashes commits
from master for 1.0.1 release based
on FAB-5468

Change-Id: I4bb6c946d28ba2009c4074c76b4d1451b3d9a1ad
Signed-off-by: Gari Singh <[email protected]>

[FAB-5280] Fix git clone fabric-samples for Windows

This change expands the prerequisites documentation for Windows
to instruct users on setting git properly to ensure it handles
long filenames (required to successfully clone fabric-samples)
and end-of-lines (required for vagrant to work).

Change-Id: I8230f1980fedfb43d6e9cda8d2a2b4a65aa2434a
Signed-off-by: Arnaud J Le Hors <[email protected]>
(cherry picked from commit fc736ec)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5293] Log buffer overflow events

This commit adds a logging event when a message is dropped
due to overflow of the connection buffer to a remote peer

In case of data blocks, the message that is printed is:
2017-07-16 09:12:55.442 EDT [gossip/comm] send -> DEBU 0c1 Buffer to 9.37.220.210:38346 overflown, dropping message GossipMessage: Channel: [121 97 99 111 118], nonce: 0, tag: CHAN_AND_ORG Block message: {Data: 107690 bytes, seq: 2771}, Envelope: 107714 bytes, Signature: 0 bytes

Change-Id: Ibce121be0721a8c8a73f7805a051a28c213d64ba
Signed-off-by: yacovm <[email protected]>
(cherry picked from commit 28c8efd)
Signed-off-by: Gari Singh <[email protected]>

FAB-5331 Fix formatting of channel name

Historically, gossip keeps the channel name in messages
[]byte instead of in *string*s.

There is a String() method that formats complex messages
It would be beneficial to print instead a string,
for usability of log parsing.

Change-Id: I71351fa324d6e1ca583588dab089a9e887996f7f
Signed-off-by: yacovm <[email protected]>
(cherry picked from commit ca167ce)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5309] Set mod_policy for new channel policies

The current configtxgen creates a channel creation tx with policies of
Reader/Writer/Admin, where these each do not have a mod_policy set.
This makes it difficult to change these policies, because the policy
does not exist.

It is possible through a roundabout way to change these policies (by
removing and re-adding the policy with a different mod_policy), but this
is certainly not a painless procedure and requires assistance of the
orderer org.

This CR updates to configtx processing to validate mod_policy values
such that they are valid names.  This means that the policy is not
empty, and if the policy is path specified (ie using '/'), that each
component of the path can be described as a valid config element (does
not violate the config element naming rules).

This CR additionally sets the mod_policy on the policies generated by
configtxgen to "Admins".

For users of the old v1.0.0 configtxgen, channel creation will fail with
an error for v1.0.1 orderers.  However, v1.0.1 configtxgen users will
have their transaction appropriately consumed by v1.0.0 orderers.

So in summary, upgrading configtxgen without fabric is okay.  Upgrading
fabric without configtxgen will cause breakage for new channel creation.

An additional bug in the configtxgen output was discovered which was not
setting a mod_policy on the anchor peers element.  There was also an
error in the bddtests which mimic the missing policies for the
application level policies.

Change-Id: Ic2bc120cfb6170f3e4e6cbeac5be145363a64861
Signed-off-by: Jason Yellick <[email protected]>
(cherry picked from commit 3a2dd8e)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5340] Respect new max message size on reconf

Currently, the size filter only reads the max message size at
construction time.  This means that if this size is reconfigured, the
filter will not work correctly until restart.

This CR changes the sizefilter to re-read the size value each time.

Change-Id: Ib61c74dd8031fc61e107dc10ab9eba9d8b6b866e
Signed-off-by: Jason Yellick <[email protected]>
(cherry picked from commit 36b08c7)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5341] Solo should respect batchtimeout reconf

Solo currently only reads the batch timeout at startup.  This is a
problem, because the batch timeout may be changed dynamically through a
reconfiguration transaction.

This CR simply causes solo to re-query the batch timeout from the config
each time the timer is initialized, rather than once at creation time.

Change-Id: I493fa4edddef40821336aa610ab242a3ffe97d26
Signed-off-by: Jason Yellick <[email protected]>
(cherry picked from commit b817672)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5339] Add missing nil check to extensions.go

There is a missing nil check, that might make the code
result in a null pointer panic.

For reference: IsDataMsg is:

func (m *GossipMessage) IsDataMsg() bool {
	return m.GetDataMsg() != nil
}

Change-Id: I5e20dee188e863b932312a7963f0ca73965c1457
Signed-off-by: yacovm <[email protected]>
(cherry picked from commit 3cde835)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5365] Fix bad error in peer CLI Deliver

The peer CLI currently attempts to print the error status returned by
the orderer's Deliver gRPC method.  However, the log statement
inappropriately uses the '%T' modifier, and prints the type of the
status, not the actual status code inside it.  Consequently, all deliver
errors read the same uninformative error message:

    Got Status:*orderer.DeliverResponse_Status

This CR fixes this log statement to include the status code instead, and
additionally enhances the other error messages with pertitent
information.

Change-Id: I5a3e1dec574bfab178550cf67bc96a66f1896d5b
Signed-off-by: Jason Yellick <[email protected]>
(cherry picked from commit 22e1299)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5342] spelling mistake in log: overflown

Change-Id: Iadf71f9c8b34716a8d785767e73ab154a249df78
Signed-off-by: Scott Zwierzynski <[email protected]>
(cherry picked from commit e3df726)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5330] Prevent payload buffer overpopulation

The state transfer module receives blocks from either the orderer
or other peers, and puts them into a payload buffer for reordering so
they would enter the ledger in-order.

In some cases:
- If the peer joined late and it receives blocks from peers starting from
  index i where the ledger is missing indices [j, i] for some j<i
  and the rate of block reception from peers is very fast
- If the ledger is "stuck" (i.e file system full, etc.) and cannot advance

This buffer would overpopulate.

This commit addresses this, and adds a maximum distance constant
that if the difference between the ledger height and the sequence
of the block that is received is greater than this constant,
the block is dropped.

Change-Id: Ia1ba8966ea6d211c5d1b7ddd84a4fad34af797d4
Signed-off-by: yacovm <[email protected]>
(cherry picked from commit ecda4c2)
Signed-off-by: Gari Singh <[email protected]>

FAB-5390 update chaintool URL

update chaintool version and URL to download chaintool binary
from nexus repository

Change-Id: I871eea4106a6e0c59a3a9660d475026d6d2e5481
Signed-off-by: rameshthoomu <[email protected]>
(cherry picked from commit 4223020)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5407] Fix issue with pubkey pkcs11 CKA_PRIVATE

According to PKCS11 standard:
CKA_PRIVATE - CK_BBOOL - TRUE if object is a private
object (vs. public object) (default FALSE)

Changing this to FALSE for public key pkcs11 attribute struct
fixed an issue we were having with our Thalas HSM: CKR_TEMPLATE_INCONSISTENT

Commenting out this line also works
(since there is no reason for it to be in the pubkey struct).
Please also vendor in this change to other projects using it,
such as Fabric-CA.

Change-Id: I87d363a89e34c39f438492123166ed59eb515c44
Signed-off-by: gbolo <[email protected]>
(cherry picked from commit c97a93a)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5413] Add initial execution in retry process.

Retry process should do an initial execution before starting
retry time ticker, otherwise there is a delay for each retry,
which accumulatively will cause slow start of kafka chain.

Change-Id: I9c2aafeb73e366b72d94e317088548e4754ee8c4
Signed-off-by: Jay Guo <[email protected]>
(cherry picked from commit 03afad8)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5418] Add prereq for npm on Windows

This change adds documentation on how to install the
Visual Studio C++ tools necessary to build the
Node.js native modules used in our samples.

Change-Id: I78277d937bcb5e697620b122061c6050d2570448
Signed-off-by: Arnaud J Le Hors <[email protected]>
(cherry picked from commit 7de02d2)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5421] Add configtxlator to fabric-tools image

Add configtxlator 2 fabric-tools docker image

Change-Id: I36bd4677a393216e05d866aedac8a8f7206a96f3
Signed-off-by: rickr <[email protected]>
(cherry picked from commit 210598f)
Signed-off-by: Gari Singh <[email protected]>

FAB-5422 make "Still have questions" prominent

Change-Id: I46ab194a467dd5633b132f63e77505fe33f60a62
Signed-off-by: Christopher Ferris <[email protected]>
(cherry picked from commit fbb84cc)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5353]: Qualify sys. failure vs validation error

Currently as stated in [FAB-5353], there is no clear separation during
transaction validation during block commmit, between invalid transaction
and some system failure which migh lead to inability to validate the
transaction. For example db is down or file system is unavailable. This
might lead to inconsistency of the state accross peers, therefore this
commit takes care to distinguish between real case of invalid
transaction versus system failure, later the error propagated down to
the committer and forces peer to stop with panic, so admin will be able
to take manual control and fix the problem therefore preventing peer
state to diverge.

Change-Id: I384e16d37e2f2b0fe144d504f566e0b744a5095c
Signed-off-by: Artem Barger <[email protected]>
(cherry picked from commit 0cf4c35)
Signed-off-by: Gari Singh <[email protected]>

FAB-5154 update prereqs to Docker 17.03.0-ce

Change-Id: I34d23137eebfd9d5697061c1bf813b83543bcd05
Signed-off-by: Christopher Ferris <[email protected]>
(cherry picked from commit 15c3bbe)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5313] Leader election yield if deliver unavailable

This commit makes the peer relinquish its leadership if it can't
connect to the ordering service.

Change-Id: I5fe679d5f23e539828fea4a9398c7dd4d9fd0f93
Signed-off-by: yacovm <[email protected]>
(cherry picked from commit 6962ee3)
Signed-off-by: Gari Singh <[email protected]>

FAB-5422 fix syntax error

Change-Id: Ied54138605d42b2c7687dc0f80a5a0eb3befca34
Signed-off-by: Christopher Ferris <[email protected]>
(cherry picked from commit f80789d)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5446] Fix orderer metadata local test

The orderer metadata test only works if the development environment is
setup to set common.Version, because if this is not set, the version is
returned as "development version" and compared to the unset empty
string.

This is very annoying when trying to do development locally as this test
always fails.

This CR simply overrides the common.Version value for the purpose of
testing this package.

Change-Id: I6bc7a1de5a2730f4dd3fe17f1e5c7ff6bd81d4af
Signed-off-by: Jason Yellick <[email protected]>
(cherry picked from commit 7d59d5a)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5391]Prevent concurrent invokes launching cc cont

This CR prevents concurrent invokes from launching a chaincode
container at the same time (e.g. during performance testing). The first
invoke should succeed (and launch the container) while subsequent
invokes should fail until the container has finished launching.

Note: This does not change any behavior as subsequent invokes should
have failed but it now sends a clear error message that the chaincode
container is already launching.

Change-Id: Ic1772a5f25dd0e4c34278e6e7bdb8507f16269c8
Signed-off-by: Will Lahti <[email protected]>
(cherry picked from commit 2232d0e)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5459] Recompute configmap instead of updating

The configtx validation code works by transforming the ConfigGroup tree
structure into a map, where each config element has a fully qualified
key like:

  [Groups] /Channel/Application

or

  [Policy] /Channel/Application/Readers

This flattened structure makes it easier to check which elements have
been modified, as the maps may simply be iterated over, rather than
walking the config tree.

After applying a config update, the current config map is copied, and
the elements which were updated are overlayed onto the old config.  This
map is then converted back into a tree structure and serialized to be
the new config tree.

The current code adopts the updated config map as the current config
map.  However, this produces the bug described in 5459.  Because the
updated config map is the overlay of the new config onto the old
config, the updated config may contain orphaned nodes which appear in
the map, but which do not appear in the config tree.

Consequently, when a subsequent update arrives, it is validated not
only against the current config, but also against the orphaned nodes
which are still in the updated config map.

This CR changes the logic to discard the updated config map (which may
contain this orphaned nodes) and instead has the config map recomputed
every time a new config is adopted.  This is more obviously
deterministic and mimics the way a new ordering node would initialize
the config after being restarted.

Note: There is no accompanying test case with this.  I had originally
written a test case which demonstrated that nodes were orphaned in the
updated config.  However, this is expected and not a useful test case.
Similarly, forcing the update config map to have updated nodes, then
testing that that map is not adopted does not provide a valuable test
case.

So, instead of a test, this CR opts for some code comments and this
lengthly commit explaining the change.

Change-Id: Idc847cd5e237531e4a8b978f3465e30a909eb94f
Signed-off-by: Jason Yellick <[email protected]>
(cherry picked from commit 6eab9cf)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5458] wrong type check in validator

Validator is sending peer.TxValidationCode_INVALID_OTHER_REASON instead of
peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE due to a wrong type check.

Added UT to cover the switch and ensure correct tx flag been assigned.

Change-Id: I7abe8828323780d527b24905f54d9a06e5f70b4e
Signed-off-by: Srinivasan Muralidharan <[email protected]>
Signed-off-by: Artem Barger <[email protected]>
(cherry picked from commit e7b20bd)
Signed-off-by: Gari Singh <[email protected]>

FAB-5474 add links to godoc resources

Change-Id: I13af4e7452cac28d0708ab4ba996af05f3fc8614
Signed-off-by: Christopher Ferris <[email protected]>
(cherry picked from commit 65730c8)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5329] Able to instantiate on a taken chaincode ID

This fix appends a hash of the Docker image name to the image name
to ensure a chaincode with different capitalization does not override
the container of an already instantiated chaincode. This problem was
introduced by the need to convert all Docker image names to lowercase.
The Docker container name will retain its capitalization as that
restriction only applies to the image name.

Change-Id: I854f80b2f0e0269d9bbc60725f82b7e5a804b6fd
Signed-off-by: Will Lahti <[email protected]>
(cherry picked from commit 36e5140)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5484] Fixes documentation for Windows users

With this change the documentation instructs Windows users
to work within the Docker Quickstart Terminal rather than
Git Bash which does not work for Windows 10.
This change also adds a note to the first curl command to
address the recurrent problem with Windows users reporting
failure due to using an outdated version of curl.

Patch-set hyperledger#2: added a piece about installing npm grpc based
on users reporting this was necessary.

Change-Id: I95e7caeddc43e48f107955018aced112893ca540
Signed-off-by: Arnaud J Le Hors <[email protected]>
(cherry picked from commit 1b6820a)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5498] Missing RLock in onStatusChangeFactory

There is a map access that isn't protected by a lock
that was introduced in a recent commit.

Change-Id: I31f884f76aaf0ba4a6b547c66830d8cd652f3c4e
Signed-off-by: yacovm <[email protected]>
(cherry picked from commit 201a814)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5525] Fix configtx memory allocation bug

The configtx code uses an 'append(...)' against a slice, and records the
new slice address when computing the config map.  Through sheer dumb
luck, this code works for config groups which are only nested 2 levels
deep, because the append call triggers a true new memory allocation.
However, for config groups 3 levels deep (such as consortium groups),
the append call actually re-uses the underlying memory for the slice.

This causes the path to be corrupted internally for the consortium group
items, and cause the wrong policy to be resolved when checking for a
policy which has been specified relatively.

This fix manually allocates new memory, copies it, and then appends the
element.

Change-Id: I0f4df619e006cdfebba60173156bda597d42a544
Signed-off-by: Jason Yellick <[email protected]>
(cherry picked from commit b3c1430)
Signed-off-by: Gari Singh <[email protected]>

[FAB-5529] Missing check at endorser

There is a missing check in the endorser code for a nil chaincodeID.
Added a test.

Change-Id: I10cb58ddb49cb9768aa2cdb9e9dc0b24808a5fbc
Signed-off-by: yacovm <[email protected]>
(cherry picked from commit 9b37c12)
Signed-off-by: Gari Singh <[email protected]>
  • Loading branch information
mastersingh24 committed Jul 30, 2017
1 parent d9c3202 commit 2cab745
Show file tree
Hide file tree
Showing 53 changed files with 1,205 additions and 179 deletions.
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ PKGNAME = github.com/$(PROJECT_NAME)
CGO_FLAGS = CGO_CFLAGS=" "
ARCH=$(shell uname -m)
MARCH=$(shell go env GOOS)-$(shell go env GOARCH)
CHAINTOOL_RELEASE=v0.10.3
CHAINTOOL_RELEASE=1.0.0
BASEIMAGE_RELEASE=$(shell cat ./.baseimage-release)

# defined in common/metadata/metadata.go
Expand All @@ -65,7 +65,7 @@ GO_LDFLAGS = $(patsubst %,-X $(PKGNAME)/common/metadata.%,$(METADATA_VAR))

GO_TAGS ?=

CHAINTOOL_URL ?= https://github.com/hyperledger/fabric-chaintool/releases/download/$(CHAINTOOL_RELEASE)/chaintool
CHAINTOOL_URL ?= https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric/chaintool-$(CHAINTOOL_RELEASE)/hyperledger-fabric-chaintool-$(CHAINTOOL_RELEASE).jar

export GO_LDFLAGS

Expand Down Expand Up @@ -187,7 +187,7 @@ linter: buildenv
%/chaintool: Makefile
@echo "Installing chaintool"
@mkdir -p $(@D)
curl -L $(CHAINTOOL_URL) > $@
curl -fL $(CHAINTOOL_URL) > $@
chmod +x $@

# We (re)build a package within a docker context but persist the $GOPATH/pkg
Expand Down Expand Up @@ -255,6 +255,7 @@ build/image/couchdb/payload: images/couchdb/docker-entrypoint.sh \
images/couchdb/vm.args
build/image/tools/payload: build/docker/bin/cryptogen \
build/docker/bin/configtxgen \
build/docker/bin/configtxlator \
build/docker/bin/peer \
build/sampleconfig.tar.bz2

Expand Down
2 changes: 1 addition & 1 deletion bccsp/pkcs11/pkcs11.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func (csp *impl) generateECKey(curve asn1.ObjectIdentifier, ephemeral bool) (ski
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral),
pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, marshaledOID),
pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, false),

pkcs11.NewAttribute(pkcs11.CKA_ID, publabel),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, publabel),
Expand Down
2 changes: 1 addition & 1 deletion bddtests/steps/bootstrap_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@ def create_channel_config_update(system_channel_version, channel_id, consortium_
Policy(type=typeImplicitMeta, value=IMP(
rule=ruleMajority, sub_policy=BootstrapHelper.KEY_POLICY_ADMINS).SerializeToString()))
write_set.groups[ApplicationGroup].mod_policy = "Admins"
for k, v in write_set.groups[ApplicationGroup].groups.iteritems():
for k, v in write_set.groups[ApplicationGroup].policies.iteritems():
v.mod_policy=BootstrapHelper.KEY_POLICY_ADMINS
config_update = common_dot_configtx_pb2.ConfigUpdate(channel_id=channel_id,
read_set=read_set,
Expand Down
4 changes: 3 additions & 1 deletion common/configtx/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ func recurseConfig(result map[string]comparable, path []string, group *cb.Config
}

for key, group := range group.Groups {
nextPath := append(path, key)
nextPath := make([]string, len(path)+1)
copy(nextPath, path)
nextPath[len(nextPath)-1] = key
if err := recurseConfig(result, nextPath, group); err != nil {
return err
}
Expand Down
15 changes: 15 additions & 0 deletions common/configtx/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@ func TestBadKey(t *testing.T) {
"Should have errored on key with illegal characters")
}

func TestConfigMapMultiGroup(t *testing.T) {
config := cb.NewConfigGroup()
config.Groups["0"] = cb.NewConfigGroup()
config.Groups["0"].Groups["1"] = cb.NewConfigGroup()
config.Groups["0"].Groups["1"].Groups["2.1"] = cb.NewConfigGroup()
config.Groups["0"].Groups["1"].Groups["2.1"].Values["Value"] = &cb.ConfigValue{}
config.Groups["0"].Groups["1"].Groups["2.2"] = cb.NewConfigGroup()
config.Groups["0"].Groups["1"].Groups["2.2"].Values["Value"] = &cb.ConfigValue{}

confMap, err := MapConfig(config)
assert.NoError(t, err)
assert.Equal(t, []string{"Channel", "0", "1", "2.1"}, confMap["[Values] /Channel/0/1/2.1/Value"].path)
assert.Equal(t, []string{"Channel", "0", "1", "2.2"}, confMap["[Values] /Channel/0/1/2.2/Value"].path)
}

func TestConfigMap(t *testing.T) {
config := cb.NewConfigGroup()
config.Groups["0DeepGroup"] = cb.NewConfigGroup()
Expand Down
34 changes: 22 additions & 12 deletions common/configtx/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,49 +204,49 @@ func (cm *configManager) proposeConfigUpdate(configtx *cb.Envelope) (*cb.ConfigE
}, nil
}

func (cm *configManager) prepareApply(configEnv *cb.ConfigEnvelope) (map[string]comparable, *configResult, error) {
func (cm *configManager) prepareApply(configEnv *cb.ConfigEnvelope) (*configResult, error) {
if configEnv == nil {
return nil, nil, fmt.Errorf("Attempted to apply config with nil envelope")
return nil, fmt.Errorf("Attempted to apply config with nil envelope")
}

if configEnv.Config == nil {
return nil, nil, fmt.Errorf("Config cannot be nil")
return nil, fmt.Errorf("Config cannot be nil")
}

if configEnv.Config.Sequence != cm.current.sequence+1 {
return nil, nil, fmt.Errorf("Config at sequence %d, cannot prepare to update to %d", cm.current.sequence, configEnv.Config.Sequence)
return nil, fmt.Errorf("Config at sequence %d, cannot prepare to update to %d", cm.current.sequence, configEnv.Config.Sequence)
}

configUpdateEnv, err := envelopeToConfigUpdate(configEnv.LastUpdate)
if err != nil {
return nil, nil, err
return nil, err
}

configMap, err := cm.authorizeUpdate(configUpdateEnv)
if err != nil {
return nil, nil, err
return nil, err
}

channelGroup, err := configMapToConfig(configMap)
if err != nil {
return nil, nil, fmt.Errorf("Could not turn configMap back to channelGroup: %s", err)
return nil, fmt.Errorf("Could not turn configMap back to channelGroup: %s", err)
}

if !reflect.DeepEqual(channelGroup, configEnv.Config.ChannelGroup) {
return nil, nil, fmt.Errorf("ConfigEnvelope LastUpdate did not produce the supplied config result")
return nil, fmt.Errorf("ConfigEnvelope LastUpdate did not produce the supplied config result")
}

result, err := cm.processConfig(channelGroup)
if err != nil {
return nil, nil, err
return nil, err
}

return configMap, result, nil
return result, nil
}

// Validate simulates applying a ConfigEnvelope to become the new config
func (cm *configManager) Validate(configEnv *cb.ConfigEnvelope) error {
_, result, err := cm.prepareApply(configEnv)
result, err := cm.prepareApply(configEnv)
if err != nil {
return err
}
Expand All @@ -258,7 +258,17 @@ func (cm *configManager) Validate(configEnv *cb.ConfigEnvelope) error {

// Apply attempts to apply a ConfigEnvelope to become the new config
func (cm *configManager) Apply(configEnv *cb.ConfigEnvelope) error {
configMap, result, err := cm.prepareApply(configEnv)
// Note, although prepareApply will necessarilly compute a config map
// for the updated config, this config map will possibly contain unreachable
// elements from a config graph perspective. Therefore, it is not safe to use
// as the config map after application. Instead, we compute the config map
// just like we would at startup.
configMap, err := MapConfig(configEnv.Config.ChannelGroup)
if err != nil {
return err
}

result, err := cm.prepareApply(configEnv)
if err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions common/configtx/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,11 @@ func (cct *channelCreationTemplate) Envelope(channelID string) (*cb.ConfigUpdate

wSet.Groups[config.ApplicationGroupKey].ModPolicy = configmsp.AdminsPolicyKey
wSet.Groups[config.ApplicationGroupKey].Policies[configmsp.AdminsPolicyKey] = policies.ImplicitMetaPolicyWithSubPolicy(configmsp.AdminsPolicyKey, cb.ImplicitMetaPolicy_MAJORITY)
wSet.Groups[config.ApplicationGroupKey].Policies[configmsp.AdminsPolicyKey].ModPolicy = configmsp.AdminsPolicyKey
wSet.Groups[config.ApplicationGroupKey].Policies[configmsp.WritersPolicyKey] = policies.ImplicitMetaPolicyWithSubPolicy(configmsp.WritersPolicyKey, cb.ImplicitMetaPolicy_ANY)
wSet.Groups[config.ApplicationGroupKey].Policies[configmsp.WritersPolicyKey].ModPolicy = configmsp.AdminsPolicyKey
wSet.Groups[config.ApplicationGroupKey].Policies[configmsp.ReadersPolicyKey] = policies.ImplicitMetaPolicyWithSubPolicy(configmsp.ReadersPolicyKey, cb.ImplicitMetaPolicy_ANY)
wSet.Groups[config.ApplicationGroupKey].Policies[configmsp.ReadersPolicyKey].ModPolicy = configmsp.AdminsPolicyKey
wSet.Groups[config.ApplicationGroupKey].Version = 1

return &cb.ConfigUpdateEnvelope{
Expand Down
6 changes: 5 additions & 1 deletion common/configtx/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"testing"

"github.com/hyperledger/fabric/common/config"
configmsp "github.com/hyperledger/fabric/common/config/msp"
mmsp "github.com/hyperledger/fabric/common/mocks/msp"
cb "github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/utils"
Expand Down Expand Up @@ -144,8 +145,11 @@ func TestNewChainTemplate(t *testing.T) {
assert.Len(t, configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups, len(orgs))

for _, org := range orgs {
_, ok := configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org]
group, ok := configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org]
assert.True(t, ok, "Expected to find %s but did not", org)
for _, policy := range group.Policies {
assert.Equal(t, configmsp.AdminsPolicyKey, policy.ModPolicy)
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions common/configtx/tool/configtxgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func doOutputAnchorPeersUpdate(conf *genesisconfig.Profile, channelID string, ou
}

configGroup := config.TemplateAnchorPeers(org.Name, anchorPeers)
configGroup.Groups[config.ApplicationGroupKey].Groups[org.Name].Values[config.AnchorPeersKey].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate := &cb.ConfigUpdate{
ChannelId: channelID,
WriteSet: configGroup,
Expand All @@ -132,6 +133,7 @@ func doOutputAnchorPeersUpdate(conf *genesisconfig.Profile, channelID string, ou
// Add all the existing config to the readset
configUpdate.ReadSet.Groups[config.ApplicationGroupKey] = cb.NewConfigGroup()
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Version = 1
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name] = cb.NewConfigGroup()
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Values[config.MSPKey] = &cb.ConfigValue{}
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.ReadersPolicyKey] = &cb.ConfigPolicy{}
Expand All @@ -140,7 +142,9 @@ func doOutputAnchorPeersUpdate(conf *genesisconfig.Profile, channelID string, ou

// Add all the existing at the same versions to the writeset
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Version = 1
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Version = 1
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Values[config.MSPKey] = &cb.ConfigValue{}
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.ReadersPolicyKey] = &cb.ConfigPolicy{}
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.WritersPolicyKey] = &cb.ConfigPolicy{}
Expand Down
25 changes: 25 additions & 0 deletions common/configtx/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package configtx

import (
"fmt"
"strings"

"github.com/hyperledger/fabric/common/policies"
cb "github.com/hyperledger/fabric/protos/common"
Expand Down Expand Up @@ -54,12 +55,36 @@ func ComputeDeltaSet(readSet, writeSet map[string]comparable) map[string]compara
return result
}

func validateModPolicy(modPolicy string) error {
if modPolicy == "" {
return fmt.Errorf("mod_policy not set")
}

trimmed := modPolicy
if modPolicy[0] == '/' {
trimmed = modPolicy[1:]
}

for i, pathElement := range strings.Split(trimmed, PathSeparator) {
err := validateConfigID(pathElement)
if err != nil {
return fmt.Errorf("path element at %d is invalid: %s", i, err)
}
}
return nil

}

func (cm *configManager) verifyDeltaSet(deltaSet map[string]comparable, signedData []*cb.SignedData) error {
if len(deltaSet) == 0 {
return fmt.Errorf("Delta set was empty. Update would have no effect.")
}

for key, value := range deltaSet {
if err := validateModPolicy(value.modPolicy()); err != nil {
return fmt.Errorf("invalid mod_policy for element %s: %s", key, err)
}

existing, ok := cm.current.configMap[key]
if !ok {
if value.version() != 0 {
Expand Down
34 changes: 30 additions & 4 deletions common/configtx/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,39 @@ func TestVerifyDeltaSet(t *testing.T) {
t.Run("Green path", func(t *testing.T) {
deltaSet := make(map[string]comparable)

deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}}
deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}}

assert.NoError(t, cm.verifyDeltaSet(deltaSet, nil), "Good update")
})

t.Run("Bad mod policy", func(t *testing.T) {
deltaSet := make(map[string]comparable)

deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}}

assert.Regexp(t, "invalid mod_policy for element", cm.verifyDeltaSet(deltaSet, nil))
})

t.Run("Big Skip", func(t *testing.T) {
deltaSet := make(map[string]comparable)

deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 2}}
deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 2, ModPolicy: "foo"}}

assert.Error(t, cm.verifyDeltaSet(deltaSet, nil), "Version skip from 0 to 2")
})

t.Run("New item high version", func(t *testing.T) {
deltaSet := make(map[string]comparable)

deltaSet["bar"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}}
deltaSet["bar"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}}

assert.Error(t, cm.verifyDeltaSet(deltaSet, nil), "New key not at version 0")
})

t.Run("Policy evalaution to false", func(t *testing.T) {
deltaSet := make(map[string]comparable)

deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}}
deltaSet["foo"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1, ModPolicy: "foo"}}
cm.Resources.(*mockconfigtx.Resources).PolicyManagerVal.Policy = &mockpolicies.Policy{Err: fmt.Errorf("Err")}

assert.Error(t, cm.verifyDeltaSet(deltaSet, nil), "Policy evaluation should have failed")
Expand Down Expand Up @@ -182,3 +190,21 @@ func TestPolicyForItem(t *testing.T) {
assert.True(t, ok)
assert.Equal(t, policy, fooPolicy, "Should have found relative foo policy for foo group")
}

func TestValidateModPolicy(t *testing.T) {
t.Run("Valid", func(t *testing.T) {
assert.Nil(t, validateModPolicy("/foo/bar"))
})
t.Run("Empty", func(t *testing.T) {
assert.Regexp(t, "mod_policy not set", validateModPolicy(""))
})
t.Run("InvalidFirstChar", func(t *testing.T) {
assert.Regexp(t, "path element at 0 is invalid", validateModPolicy("^foo"))
})
t.Run("InvalidRootPath", func(t *testing.T) {
assert.Regexp(t, "path element at 0 is invalid", validateModPolicy("/"))
})
t.Run("InvalidSubPath", func(t *testing.T) {
assert.Regexp(t, "path element at 1 is invalid", validateModPolicy("foo//bar"))
})
}
Loading

0 comments on commit 2cab745

Please sign in to comment.