Skip to content

Commit

Permalink
FAB-5408 Missing channel update method.
Browse files Browse the repository at this point in the history
PS 3: No need wait on genesis / handled in seekBlock
PS 4: remove hardcoded 200 for retry wait time
PS 5: rename upgrade to update, fix some typos.
PS 6: Default logging to INFO
PS 7: Add configtxlator to docker-compose for testing update.
PS 8: Update READM.md for latest date
PS 10: Full update channel test.
PS 11: Clean up UpdateChannelIT add comments.
PS 12: Clean up. Use common method for channel updating.
PS 13: Clean up unnecessary logic

Change-Id: I1d45faed6bb9e0ceb7ab9bcb0b487bef11f8a90b
Signed-off-by: rickr <cr22rc@gmail.com>
  • Loading branch information
cr22rc committed Jul 25, 2017
1 parent 946e871 commit 7640986
Show file tree
Hide file tree
Showing 20 changed files with 772 additions and 138 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ You should use the following commit levels of the Hyperledger projects:

| Project | Commit level | Date |
|:---------------|:------------------------------------------:|---------------------------:|
| fabric | f56a82e36e040e1c1a986edfceac014ba1516571 | Jul 11 12:48:33 2017 -0700 |
| fabric-ca | 74f8f4d4c29e45a79a8849efb057dbd8de3ae8d0 | Jul 11 16:43:39 2017 +0200 |
| fabric | 3a4b1f2bce86daa86c025a9244a90106a58bb54b | Jul 22 18:18:25 2017 +0000 |
| fabric-ca | bc2b642f4a9ef2dcb393bf7da512ce43e1ec1a68 | Jul 23 03:38:20 2017 -0400 |

You can clone these projects by going to the [Hyperledger repository](https://gerrit.hyperledger.org/r/#/admin/projects/).

Expand Down Expand Up @@ -111,14 +111,15 @@ environment. For non Vagrant envrionment, the steps would be the same as below
config.vm.network :forwarded_port, guest: 8054, host: 8054
config.vm.network :forwarded_port, guest: 8056, host: 8056
config.vm.network :forwarded_port, guest: 8058, host: 8058
config.vm.network :forwarded_port, guest: 7059, host: 7059
```

Add to your Vagrant file a folder for referencing the sdkintegration folder between the lines below:

config.vm.synced_folder "..", "/opt/gopath/src/github.com/hyperledger/fabric"</br>

`config.vm.synced_folder "/home/<<user>>/fabric-sdk-java/src/test/fixture/sdkintegration", "/opt/gopath/src/github.com/hyperledger/fabric/sdkintegration`</br>
`config.vm.synced_folder "/home/<<user>>/fabric-sdk-java/src/test/fixture/sdkintegration", "/opt/gopath/src/github.com/hyperledger/fabric/sdkintegration"`</br>

config.vm.synced_folder ENV.fetch('LOCALDEVDIR', ".."), "#{LOCALDEV}"</br>

Expand Down
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@
<version>${httpclient.version}</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${httpclient.version}</version>
<scope>test</scope>
</dependency>


<!-- https://mvnrepository.com/artifact/org.glassfish/javax.json -->
<dependency>
<groupId>org.glassfish</groupId>
Expand Down
382 changes: 296 additions & 86 deletions src/main/java/org/hyperledger/fabric/sdk/Channel.java

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions src/main/java/org/hyperledger/fabric/sdk/HFClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,24 @@ public byte[] getChannelConfigurationSignature(ChannelConfiguration channelConfi

}

/**
* Get signature for update channel configuration
*
* @param updateChannelConfiguration
* @param signer
* @return byte array with the signature
* @throws InvalidArgumentException
*/

public byte[] getUpdateChannelConfigurationSignature(UpdateChannelConfiguration updateChannelConfiguration, User signer) throws InvalidArgumentException {

clientCheck();

Channel systemChannel = Channel.newSystemChannel(this);
return systemChannel.getUpdateChannelConfigurationSignature(updateChannelConfiguration, signer);

}

/**
* Send install chaincode request proposal to peers.
*
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/hyperledger/fabric/sdk/Orderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ void setChannel(Channel channel) throws InvalidArgumentException {
}

this.channel = channel;

}

void unsetChannel() {

channel = null;

}

private Channel channel;
Expand Down
33 changes: 16 additions & 17 deletions src/main/java/org/hyperledger/fabric/sdk/OrdererClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ class OrdererClient {
ordererWaitTimeMilliSecs = tempOrdererWaitTimeMilliSecs;
}


}

synchronized void shutdown(boolean force) {
Expand Down Expand Up @@ -165,21 +164,21 @@ public void onCompleted() {

nso.onNext(envelope);

try {
if (!finishLatch.await(ordererWaitTimeMilliSecs, TimeUnit.MILLISECONDS)) {
TransactionException ste = new TransactionException(format("Channel %s, send transactions failed on orderer %s. Reason: timeout after %d ms.",
channelName, name, ordererWaitTimeMilliSecs));
logger.error("sendTransaction error " + ste.getMessage(), ste);
throw ste;
}
if (throwable[0] != null) {
//get full stack trace
TransactionException ste = new TransactionException(format("Channel %s, send transaction failed on orderer %s. Reason: %s",
channelName, name, throwable[0].getMessage()), throwable[0]);
logger.error("sendTransaction error " + ste.getMessage(), ste);
throw ste;
}
logger.debug("Done waiting for reply! Got:" + ret[0]);
try {
if (!finishLatch.await(ordererWaitTimeMilliSecs, TimeUnit.MILLISECONDS)) {
TransactionException ste = new TransactionException(format("Channel %s, send transactions failed on orderer %s. Reason: timeout after %d ms.",
channelName, name, ordererWaitTimeMilliSecs));
logger.error("sendTransaction error " + ste.getMessage(), ste);
throw ste;
}
if (throwable[0] != null) {
//get full stack trace
TransactionException ste = new TransactionException(format("Channel %s, send transaction failed on orderer %s. Reason: %s",
channelName, name, throwable[0].getMessage()), throwable[0]);
logger.error("sendTransaction error " + ste.getMessage(), ste);
throw ste;
}
logger.debug("Done waiting for reply! Got:" + ret[0]);

} catch (InterruptedException e) {
logger.error(e);
Expand Down Expand Up @@ -269,7 +268,7 @@ public void onError(Throwable t) {

@Override
public void onCompleted() {
logger.warn("onCompleted");
logger.trace("onCompleted");
finishLatch.countDown();
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
*
* Copyright 2016,2017 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.hyperledger.fabric.sdk;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;

/**
* A wrapper for the Hyperledger Channel update configuration
*/
public class UpdateChannelConfiguration {
private byte[] configBytes = null;

/**
* The constructor for the UpdateChannelConfiguration wrapper. You will
* need to use the {@link Channel#updateChannelConfiguration(UpdateChannelConfiguration, byte[]...)} method to
* populate the update channel configuration
*/
public UpdateChannelConfiguration() {
}

/**
* constructs a UpdateChannelConfiguration object with the actual configuration gotten from the file system
*
* @param configFile The file containing the channel configuration.
* @throws IOException
*/
public UpdateChannelConfiguration(File configFile) throws IOException {
InputStream is = new FileInputStream(configFile);
configBytes = IOUtils.toByteArray(is);
}

/**
* constructs a UpdateChannelConfiguration object
*
* @param configAsBytes the byte array containing the serialized channel configuration
*/
public UpdateChannelConfiguration(byte[] configAsBytes) {
this.configBytes = configAsBytes;
}

/**
* sets the UpdateChannelConfiguration from a byte array
*
* @param updateChannelConfigurationAsBytes the byte array containing the serialized channel configuration
*/
public void setUpdateChannelConfiguration(byte[] updateChannelConfigurationAsBytes) {
this.configBytes = updateChannelConfigurationAsBytes;
}

/**
* @return the channel configuration serialized per protobuf and ready for inclusion into channel configuration
*/
public byte[] getUpdateChannelConfigurationAsBytes() {
return this.configBytes;
}
}
22 changes: 22 additions & 0 deletions src/main/java/org/hyperledger/fabric/sdk/helper/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public class Config {
public static final String HASH_ALGORITHM = "org.hyperledger.fabric.sdk.hash_algorithm";
public static final String CACERTS = "org.hyperledger.fabric.sdk.cacerts";
public static final String PROPOSAL_WAIT_TIME = "org.hyperledger.fabric.sdk.proposal.wait.time";
public static final String CHANNEL_CONFIG_WAIT_TIME = "org.hyperledger.fabric.sdk.channelconfig.wait_time";
public static final String ORDERER_RETRY_WAIT_TIME = "org.hyperledger.fabric.sdk.orderer_retry.wait_time";
public static final String PROPOSAL_CONSISTENCY_VALIDATION = "org.hyperledger.fabric.sdk.proposal.consistency_validation";
public static final String GENESISBLOCK_WAIT_TIME = "org.hyperledger.fabric.sdk.channel.genesisblock_wait_time";
public static final String ASYMMETRIC_KEY_TYPE = "org.hyperledger.fabric.sdk.crypto.asymmetric_key_type";
Expand Down Expand Up @@ -98,6 +100,8 @@ private Config() {
defaultProperty(EXTRALOGLEVEL, "0");
defaultProperty(LOGGERLEVEL, null);
defaultProperty(DIAGNOTISTIC_FILE_DIRECTORY, null);
defaultProperty(CHANNEL_CONFIG_WAIT_TIME, "10000");
defaultProperty(ORDERER_RETRY_WAIT_TIME, "200");


final String inLogLevel = sdkProperties.getProperty(LOGGERLEVEL);
Expand Down Expand Up @@ -236,6 +240,24 @@ public long getGenesisBlockWaitTime() {
return Long.parseLong(getProperty(GENESISBLOCK_WAIT_TIME));
}

/**
* Time to wait for channel to be configured.
*
* @return
*/
public long getChannelConfigWaitTime() {
return Long.parseLong(getProperty(CHANNEL_CONFIG_WAIT_TIME));
}

/**
* Time to wait before retrying an operation.
*
* @return
*/
public long getOrdererRetryWaitTime() {
return Long.parseLong(getProperty(ORDERER_RETRY_WAIT_TIME));
}

public String getAsymmetricKeyType() {
return getProperty(ASYMMETRIC_KEY_TYPE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,18 @@ private boolean cantWrite() {
return null == directory || !directory.exists() || !directory.isDirectory() || !directory.canWrite();
}

public String createDiagnosticFile(byte[] byteString, String prefix, String ext) {
public String createDiagnosticFile(byte[] bytes) {

return createDiagnosticFile(bytes, null, null);

}

public String createDiagnosticFile(byte[] bytes, String prefix, String ext) {
String fileName = "";
if (cantWrite()) {
return "Missing dump directory or can not write: " + (dirAbsolutePath);
}
if (null != byteString) {
if (null != bytes) {
if (null == prefix) {
prefix = "diagnostic_";
}
Expand All @@ -100,7 +106,7 @@ public String createDiagnosticFile(byte[] byteString, String prefix, String ext)
+ "_" + counter.addAndGet(1) + "." + ext;
fileName = fileName.replaceAll("\\:", "-"); // colon is bad for windows.

new QueEntry(fileName, byteString); //Add to Que let process by async thread.
new QueEntry(fileName, bytes); //Add to Que let process by async thread.

}
return fileName;
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/commons-logging.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ example.SimpleSample.level=FINE

# FileHandler options - can also be set to the ConsoleHandler
# FileHandler level can be set to override the global level:
java.util.logging.FileHandler.level=DEBUG
java.util.logging.FileHandler.level=INFO

# log file name for the File Handler
java.util.logging.FileHandler.pattern=java-chaincode%u.log
Expand Down
2 changes: 1 addition & 1 deletion src/resources/commons-logging.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ handlers=java.util.logging.ConsoleHandler

# FileHandler options - can also be set to the ConsoleHandler
# FileHandler level can be set to override the global level:
java.util.logging.FileHandler.level=DEBUG
java.util.logging.FileHandler.level=INFO
java.util.logging.ConsoleHandler.level=ALL

# log file name for the File Handler
Expand Down
7 changes: 7 additions & 0 deletions src/test/fixture/sdkintegration/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,12 @@ services:
- orderer.example.com
- peer0.org2.example.com

configtxlator:
image: hyperledger/fabric-tools${IMAGE_TAG_FABRIC}
ports:
- "7059:7059"
command: /usr/local/bin/configtxlator start
container_name: configtxlator

ccenv:
image: hyperledger/fabric-ccenv${IMAGE_TAG_FABRIC}
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ private Properties getEndPointProperties(final String type, final String name) {

final String domainName = getDomainName(name);

File cert = Paths.get(getTestChannlePath(), "crypto-config/ordererOrganizations".replace("orderer", type), domainName, type + "s",
File cert = Paths.get(getTestChannelPath(), "crypto-config/ordererOrganizations".replace("orderer", type), domainName, type + "s",
name, "tls/server.crt").toFile();
if (!cert.exists()) {
throw new RuntimeException(String.format("Missing cert file for: %s. Could not find at location: %s", name,
Expand All @@ -313,8 +313,7 @@ public Properties getEventHubProperties(String name) {

}


public String getTestChannlePath() {
public String getTestChannelPath() {

return "src/test/fixture/sdkintegration/e2e-2Orgs/channel";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ public void setup() {
//Persistence is not part of SDK. Sample file store is for demonstration purposes only!
// MUST be replaced with more robust application implementation (Database, LDAP)
File sampleStoreFile = new File(System.getProperty("java.io.tmpdir") + "/HFCSampletest.properties");
sampleStoreFile.deleteOnExit();

final SampleStore sampleStore = new SampleStore(sampleStoreFile);

Expand Down
20 changes: 2 additions & 18 deletions src/test/java/org/hyperledger/fabric/sdkintegration/End2endIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ public void setup() {
// src/test/fixture/sdkintegration/e2e-2Orgs/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/

SampleUser peerOrgAdmin = sampleStore.getMember(sampleOrgName + "Admin", sampleOrgName, sampleOrg.getMSPID(),
findFileSk(Paths.get(testConfig.getTestChannlePath(), "crypto-config/peerOrganizations/",
Util.findFileSk(Paths.get(testConfig.getTestChannelPath(), "crypto-config/peerOrganizations/",
sampleOrgDomainName, format("/users/Admin@%s/msp/keystore", sampleOrgDomainName)).toFile()),
Paths.get(testConfig.getTestChannlePath(), "crypto-config/peerOrganizations/", sampleOrgDomainName,
Paths.get(testConfig.getTestChannelPath(), "crypto-config/peerOrganizations/", sampleOrgDomainName,
format("/users/Admin@%s/msp/signcerts/Admin@%s-cert.pem", sampleOrgDomainName, sampleOrgDomainName)).toFile());

sampleOrg.setPeerAdmin(peerOrgAdmin); //A special user that can create channels, join peers and install chaincode
Expand Down Expand Up @@ -640,22 +640,6 @@ private void waitOnFabric(int additional) {
// }
}

File findFileSk(File directory) {

File[] matches = directory.listFiles((dir, name) -> name.endsWith("_sk"));

if (null == matches) {
throw new RuntimeException(format("Matches returned null does %s directory exist?", directory.getAbsoluteFile().getName()));
}

if (matches.length != 1) {
throw new RuntimeException(format("Expected in %s only 1 sk file but found %d", directory.getAbsoluteFile().getName(), matches.length));
}

return matches[0];

}

private static final Map<String, String> TX_EXPECTED;

static {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@RunWith (Suite.class)

@Suite.SuiteClasses({
End2endIT.class,
End2endAndBackAgainIT.class,
UpdateChannelIT.class,
HFCAClientIT.class
})
public class IntegrationSuite {
Expand Down
Loading

0 comments on commit 7640986

Please sign in to comment.