diff --git a/pom.xml b/pom.xml index 512f7d00..a97c7891 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ fabric-sdk-java-1.0 - 1.14.0 + 1.15.0 3.6.1 1.60 4.5.6 diff --git a/src/main/java/org/hyperledger/fabric/sdk/Channel.java b/src/main/java/org/hyperledger/fabric/sdk/Channel.java index a408711d..b86e486a 100644 --- a/src/main/java/org/hyperledger/fabric/sdk/Channel.java +++ b/src/main/java/org/hyperledger/fabric/sdk/Channel.java @@ -139,6 +139,7 @@ public class Channel implements Serializable { private static final long serialVersionUID = -3266164166893832538L; private static final Log logger = LogFactory.getLog(Channel.class); private static final boolean IS_DEBUG_LEVEL = logger.isDebugEnabled(); + private static final boolean IS_WARN_LEVEL = logger.isWarnEnabled(); private static final boolean IS_TRACE_LEVEL = logger.isTraceEnabled(); private static final Config config = Config.getConfig(); @@ -5663,7 +5664,7 @@ boolean sweepMe() { // Sweeps DO NOT fire future. user needs to put timeout on t final boolean ret = sweepTime < System.currentTimeMillis() || fired.get() || future.isDone(); - if (IS_DEBUG_LEVEL && ret) { + if (IS_WARN_LEVEL && ret) { StringBuilder sb = new StringBuilder(10000); sb.append("Non reporting event hubs:"); @@ -5683,11 +5684,10 @@ boolean sweepMe() { // Sweeps DO NOT fire future. user needs to put timeout on t sep = ","; } - logger.debug(format("Force removing transaction listener after %d ms for transaction %s. %s" + + logger.warn(format("Force removing transaction listener after %d ms for transaction %s. %s" + ". sweep timeout: %b, fired: %b, future done:%b", System.currentTimeMillis() - createTime, txID, sb.toString(), sweepTime < System.currentTimeMillis(), fired.get(), future.isDone())); - } return ret; diff --git a/src/main/java/org/hyperledger/fabric/sdk/ChannelConfiguration.java b/src/main/java/org/hyperledger/fabric/sdk/ChannelConfiguration.java index 189def04..4eca4bae 100644 --- a/src/main/java/org/hyperledger/fabric/sdk/ChannelConfiguration.java +++ b/src/main/java/org/hyperledger/fabric/sdk/ChannelConfiguration.java @@ -20,11 +20,19 @@ import java.io.InputStream; import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hyperledger.fabric.sdk.exception.InvalidArgumentException; + +import static java.lang.String.format; +import static org.hyperledger.fabric.sdk.helper.Utils.toHexString; /** * A wrapper for the Hyperledger Channel configuration */ public class ChannelConfiguration { + private static final Log logger = LogFactory.getLog(ChannelConfiguration.class); + private static final boolean IS_TRACE_LEVEL = logger.isTraceEnabled(); private byte[] configBytes = null; /** @@ -41,9 +49,15 @@ public ChannelConfiguration() { * @param configFile The file containing the channel configuration. * @throws IOException */ - public ChannelConfiguration(File configFile) throws IOException { - InputStream is = new FileInputStream(configFile); - configBytes = IOUtils.toByteArray(is); + public ChannelConfiguration(File configFile) throws IOException, InvalidArgumentException { + if (configFile == null) { + throw new InvalidArgumentException("ChannelConfiguration configFile must be non-null"); + } + logger.trace(format("Creating ChannelConfiguration from file %s", configFile.getAbsolutePath())); + + try (InputStream is = new FileInputStream(configFile)) { + configBytes = IOUtils.toByteArray(is); + } } /** @@ -51,7 +65,11 @@ public ChannelConfiguration(File configFile) throws IOException { * * @param configAsBytes the byte array containing the serialized channel configuration */ - public ChannelConfiguration(byte[] configAsBytes) { + public ChannelConfiguration(byte[] configAsBytes) throws InvalidArgumentException { + if (configAsBytes == null) { + throw new InvalidArgumentException("ChannelConfiguration configAsBytes must be non-null"); + } + logger.trace("Creating ChannelConfiguration from bytes"); this.configBytes = configAsBytes; } @@ -60,7 +78,11 @@ public ChannelConfiguration(byte[] configAsBytes) { * * @param channelConfigurationAsBytes the byte array containing the serialized channel configuration */ - public void setChannelConfiguration(byte[] channelConfigurationAsBytes) { + public void setChannelConfiguration(byte[] channelConfigurationAsBytes) throws InvalidArgumentException { + if (channelConfigurationAsBytes == null) { + throw new InvalidArgumentException("ChannelConfiguration channelConfigurationAsBytes must be non-null"); + } + logger.trace("Creating setChannelConfiguration from bytes"); this.configBytes = channelConfigurationAsBytes; } @@ -68,6 +90,11 @@ public void setChannelConfiguration(byte[] channelConfigurationAsBytes) { * @return the channel configuration serialized per protobuf and ready for inclusion into channel configuration */ public byte[] getChannelConfigurationAsBytes() { - return this.configBytes; + if (configBytes == null) { + logger.error("ChannelConfiguration configBytes is null!"); + } else if (IS_TRACE_LEVEL) { + logger.trace(format("getChannelConfigurationAsBytes: %s", toHexString(configBytes))); + } + return configBytes; } } diff --git a/src/main/java/org/hyperledger/fabric/sdk/UpdateChannelConfiguration.java b/src/main/java/org/hyperledger/fabric/sdk/UpdateChannelConfiguration.java index f9504f29..69bec76d 100644 --- a/src/main/java/org/hyperledger/fabric/sdk/UpdateChannelConfiguration.java +++ b/src/main/java/org/hyperledger/fabric/sdk/UpdateChannelConfiguration.java @@ -22,11 +22,20 @@ import java.io.InputStream; import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hyperledger.fabric.sdk.exception.InvalidArgumentException; + +import static java.lang.String.format; +import static org.hyperledger.fabric.sdk.helper.Utils.toHexString; /** * A wrapper for the Hyperledger Channel update configuration */ public class UpdateChannelConfiguration { + private static final Log logger = LogFactory.getLog(UpdateChannelConfiguration.class); + private static final boolean IS_TRACE_LEVEL = logger.isTraceEnabled(); + private byte[] configBytes = null; /** @@ -43,9 +52,15 @@ public UpdateChannelConfiguration() { * @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); + public UpdateChannelConfiguration(File configFile) throws IOException, InvalidArgumentException { + if (configFile == null) { + throw new InvalidArgumentException("UpdateChannelConfiguration configFile must be non-null"); + } + logger.trace(format("Creating UpdateChannelConfiguration from file %s", configFile.getAbsolutePath())); + + try (InputStream is = new FileInputStream(configFile)) { + configBytes = IOUtils.toByteArray(is); + } } /** @@ -53,8 +68,12 @@ public UpdateChannelConfiguration(File configFile) throws IOException { * * @param configAsBytes the byte array containing the serialized channel configuration */ - public UpdateChannelConfiguration(byte[] configAsBytes) { - this.configBytes = configAsBytes; + public UpdateChannelConfiguration(byte[] configAsBytes) throws InvalidArgumentException { + if (configAsBytes == null) { + throw new InvalidArgumentException("UpdateChannelConfiguration configAsBytes must be non-null"); + } + logger.trace("Creating UpdateChannelConfiguration from bytes"); + configBytes = configAsBytes; } /** @@ -62,14 +81,23 @@ public UpdateChannelConfiguration(byte[] configAsBytes) { * * @param updateChannelConfigurationAsBytes the byte array containing the serialized channel configuration */ - public void setUpdateChannelConfiguration(byte[] updateChannelConfigurationAsBytes) { - this.configBytes = updateChannelConfigurationAsBytes; + public void setUpdateChannelConfiguration(byte[] updateChannelConfigurationAsBytes) throws InvalidArgumentException { + if (updateChannelConfigurationAsBytes == null) { + throw new InvalidArgumentException("UpdateChannelConfiguration updateChannelConfigurationAsBytes must be non-null"); + } + logger.trace("Creating setUpdateChannelConfiguration from bytes"); + configBytes = updateChannelConfigurationAsBytes; } /** * @return the channel configuration serialized per protobuf and ready for inclusion into channel configuration */ public byte[] getUpdateChannelConfigurationAsBytes() { - return this.configBytes; + if (configBytes == null) { + logger.error("UpdateChannelConfiguration configBytes is null!"); + } else if (IS_TRACE_LEVEL) { + logger.trace(format("getUpdateChannelConfigurationAsBytes: %s", toHexString(configBytes))); + } + return configBytes; } } diff --git a/src/main/java/org/hyperledger/fabric/sdk/transaction/ProtoUtils.java b/src/main/java/org/hyperledger/fabric/sdk/transaction/ProtoUtils.java index d8e27f63..00703f0b 100644 --- a/src/main/java/org/hyperledger/fabric/sdk/transaction/ProtoUtils.java +++ b/src/main/java/org/hyperledger/fabric/sdk/transaction/ProtoUtils.java @@ -196,7 +196,7 @@ public static ByteString getSignatureHeaderAsByteString(User user, TransactionCo Enrollment enrollment = user.getEnrollment(); String cert = enrollment.getCert(); - logger.debug(format(" User: %s Certificate:\n%s", user.getName(), cert)); + logger.debug(format(" User: %s Certificate: %s", user.getName(), cert == null ? "null" : toHexString(cert.getBytes(UTF_8)))); if (enrollment instanceof X509Enrollment) { if (null == suite) { diff --git a/src/test/cirun.sh b/src/test/cirun.sh index 238350e5..08d132c0 100755 --- a/src/test/cirun.sh +++ b/src/test/cirun.sh @@ -31,6 +31,8 @@ export ORG_HYPERLEDGER_FABRIC_SDKTEST_INVOKEWAITTIME=300000 export ORG_HYPERLEDGER_FABRIC_SDKTEST_DEPLOYWAITTIME=1300000 export ORG_HYPERLEDGER_FABRIC_SDKTEST_PROPOSALWAITTIME=300000 +export ORG_HYPERLEDGER_FABRIC_SDKTEST_RUNIDEMIXMTTEST=true + ORG_HYPERLEDGER_FABRIC_SDKTEST_VERSION=${ORG_HYPERLEDGER_FABRIC_SDKTEST_VERSION:-} if [ "$ORG_HYPERLEDGER_FABRIC_SDKTEST_VERSION" == "1.0.0" ]; then diff --git a/src/test/fixture/meta-infs/end2endit/META-INF/statedb/couchdb/indexes/IndexA.json b/src/test/fixture/meta-infs/end2endit/META-INF/statedb/couchdb/indexes/IndexA.json new file mode 100644 index 00000000..03367ced --- /dev/null +++ b/src/test/fixture/meta-infs/end2endit/META-INF/statedb/couchdb/indexes/IndexA.json @@ -0,0 +1,10 @@ +{ + "ddoc": "indexADDoc", + "index": { + "fields": [ + "a" + ] + }, + "name": "indexA", + "type": "json" +} \ No newline at end of file diff --git a/src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/build-artifacts.sh b/src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/build-artifacts.sh deleted file mode 100755 index fe6f91cc..00000000 --- a/src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/build-artifacts.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -configtxgen -outputBlock orderer.block -profile TwoOrgsOrdererGenesis_v13 -configtxgen -outputCreateChannelTx foo.tx -profile TwoOrgsChannel_v13 -channelID foo -configtxgen -outputCreateChannelTx bar.tx -profile TwoOrgsChannel_v13 -channelID bar diff --git a/src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/configtx.yaml b/src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/configtx.yaml index 8f8e41d6..e5929ccb 100644 --- a/src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/configtx.yaml +++ b/src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/configtx.yaml @@ -78,12 +78,6 @@ Organizations: msptype: idemix mspdir: crypto-config/peerOrganizations/org3.example.com - anchorpeers: - # anchorpeers defines the location of peers which can be used - # for cross org gossip communication. note, this value is only - # encoded in the genesis block in the application section context - - host: peer0.org3.example.com - port: 7051 - &Org2Idemix # defaultorg defines the organization which is used in the sampleconfig @@ -96,12 +90,6 @@ Organizations: msptype: idemix mspdir: crypto-config/peerOrganizations/org4.example.com - anchorpeers: - # anchorpeers defines the location of peers which can be used - # for cross org gossip communication. note, this value is only - # encoded in the genesis block in the application section context - - host: peer0.org4.example.com - port: 8051 ################################################################################ # # ORDERER diff --git a/src/test/java/org/hyperledger/fabric/sdk/ChannelConfigurationTest.java b/src/test/java/org/hyperledger/fabric/sdk/ChannelConfigurationTest.java index 9e60f016..fe7a26e0 100644 --- a/src/test/java/org/hyperledger/fabric/sdk/ChannelConfigurationTest.java +++ b/src/test/java/org/hyperledger/fabric/sdk/ChannelConfigurationTest.java @@ -22,7 +22,7 @@ public class ChannelConfigurationTest { private static final String TEST_BYTES_2 = "00112233445566778899"; @Test - public void testChannelConfigurationByeArray() { + public void testChannelConfigurationByeArray() throws Exception { // Test empty constructor new ChannelConfiguration(); diff --git a/src/test/java/org/hyperledger/fabric/sdk/idemix/IdemixTest.java b/src/test/java/org/hyperledger/fabric/sdk/idemix/IdemixTest.java index 8ea21bd9..9d37086e 100644 --- a/src/test/java/org/hyperledger/fabric/sdk/idemix/IdemixTest.java +++ b/src/test/java/org/hyperledger/fabric/sdk/idemix/IdemixTest.java @@ -24,11 +24,13 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; + import org.apache.milagro.amcl.FP256BN.BIG; import org.apache.milagro.amcl.FP256BN.ECP; import org.apache.milagro.amcl.RAND; import org.hyperledger.fabric.protos.idemix.Idemix; import org.hyperledger.fabric.sdk.exception.CryptoException; +import org.hyperledger.fabric.sdk.testutils.TestConfig; import org.junit.Test; import static org.junit.Assert.assertFalse; @@ -46,8 +48,11 @@ public class IdemixTest { @Test public void idemixTest() throws ExecutionException, InterruptedException { - ExecutorService serviceSingleTask = Executors.newFixedThreadPool(THREAD_POOL); - ExecutorService serviceMultiTask = Executors.newFixedThreadPool(THREAD_POOL); + if (!TestConfig.getConfig().getRunIdemixMTTest()) { + return; + } + ExecutorService serviceSingleTask = Executors.newFixedThreadPool(THREAD_POOL); + ExecutorService serviceMultiTask = Executors.newFixedThreadPool(THREAD_POOL); // Select attribute names and generate a Idemix Setup String[] attributeNames = {"Attr1", "Attr2", "Attr3", "Attr4", "Attr5"}; @@ -64,7 +69,7 @@ public void idemixTest() throws ExecutionException, InterruptedException { IdemixTask taskM = new IdemixTask(setup); results.add(serviceMultiTask.submit(taskM)); } - for (Future f: results) { + for (Future f : results) { assertTrue(f.get()); } } @@ -190,7 +195,7 @@ private void test() throws CryptoException { assertFalse(signature.verify(disclosure, setup.key.getIpk(), msg, setup.attrs, 0, setup.revocationKeyPair.getPublic(), epoch)); // test signature verification with different issuer public key - assertFalse(signature.verify(disclosure2, new IdemixIssuerKey(new String[]{"Attr1, Attr2, Attr3, Attr4, Attr5"}).getIpk(), msg, setup.attrs, 0, setup.revocationKeyPair.getPublic(), epoch)); + assertFalse(signature.verify(disclosure2, new IdemixIssuerKey(new String[] {"Attr1, Attr2, Attr3, Attr4, Attr5"}).getIpk(), msg, setup.attrs, 0, setup.revocationKeyPair.getPublic(), epoch)); // test signature verification with different message byte[] msg2 = {1, 1, 1}; diff --git a/src/test/java/org/hyperledger/fabric/sdk/testutils/TestConfig.java b/src/test/java/org/hyperledger/fabric/sdk/testutils/TestConfig.java index d7b6ce06..3611cf3b 100644 --- a/src/test/java/org/hyperledger/fabric/sdk/testutils/TestConfig.java +++ b/src/test/java/org/hyperledger/fabric/sdk/testutils/TestConfig.java @@ -62,6 +62,7 @@ public class TestConfig { private static final String INVOKEWAITTIME = PROPBASE + "InvokeWaitTime"; private static final String DEPLOYWAITTIME = PROPBASE + "DeployWaitTime"; private static final String PROPOSALWAITTIME = PROPBASE + "ProposalWaitTime"; + private static final String RUNIDEMIXMTTEST = PROPBASE + "RunIdemixMTTest"; // org.hyperledger.fabric.sdktest.RunIdemixMTTest ORG_HYPERLEDGER_FABRIC_SDKTEST_RUNIDEMIXMTTEST private static final String INTEGRATIONTESTS_ORG = PROPBASE + "integrationTests.org."; private static final Pattern orgPat = Pattern.compile("^" + Pattern.quote(INTEGRATIONTESTS_ORG) + "([^\\.]+)\\.mspid$"); @@ -120,6 +121,7 @@ private TestConfig() { defaultProperty(INVOKEWAITTIME, "32000"); defaultProperty(DEPLOYWAITTIME, "120000"); defaultProperty(PROPOSALWAITTIME, "120000"); + defaultProperty(RUNIDEMIXMTTEST, "false"); ////// defaultProperty(INTEGRATIONTESTS_ORG + "peerOrg1.mspid", "Org1MSP"); @@ -328,6 +330,10 @@ public long getProposalWaitTime() { return Integer.parseInt(getProperty(PROPOSALWAITTIME)); } + public boolean getRunIdemixMTTest() { + return Boolean.valueOf(getProperty(RUNIDEMIXMTTEST)); + } + public Collection getIntegrationTestsSampleOrgs() { return Collections.unmodifiableCollection(sampleOrgs.values()); } diff --git a/src/test/java/org/hyperledger/fabric/sdkintegration/End2endIT.java b/src/test/java/org/hyperledger/fabric/sdkintegration/End2endIT.java index 8b17c14d..b157d872 100644 --- a/src/test/java/org/hyperledger/fabric/sdkintegration/End2endIT.java +++ b/src/test/java/org/hyperledger/fabric/sdkintegration/End2endIT.java @@ -410,9 +410,19 @@ class ChaincodeEventCapture { //A test class to capture chaincode events ////For GO language and serving just a single user, chaincodeSource is mostly likely the users GOPATH installProposalRequest.setChaincodeSourceLocation(Paths.get(TEST_FIXTURES_PATH, CHAIN_CODE_FILEPATH).toFile()); + + if (testConfig.isFabricVersionAtOrAfter("1.1")) { // Fabric 1.1 added support for META-INF in the chaincode image. + + //This sets an index on the variable a in the chaincode // see http://hyperledger-fabric.readthedocs.io/en/master/couchdb_as_state_database.html#using-couchdb-from-chaincode + // The file IndexA.json as part of the META-INF will be packaged with the source to create the index. + installProposalRequest.setChaincodeMetaInfLocation(new File("src/test/fixture/meta-infs/end2endit")); + } } else { // On bar chain install from an input stream. + // For inputstream if indicies are desired the application needs to make sure the META-INF is provided in the stream. + // The SDK does not change anything in the stream. + if (CHAIN_CODE_LANG.equals(Type.GO_LANG)) { installProposalRequest.setChaincodeInputStream(Util.generateTarGzInputStream( @@ -488,29 +498,29 @@ policy OR(Org1MSP.member, Org2MSP.member) meaning 1 signature from someone in ei successful.clear(); failed.clear(); - if (isFooChain) { //Send responses both ways with specifying peers and by using those on the channel. - responses = channel.sendInstantiationProposal(instantiateProposalRequest, channel.getPeers()); + if (isFooChain) { //Send responses both ways with specifying peers and by using those on the channel. + responses = channel.sendInstantiationProposal(instantiateProposalRequest, channel.getPeers()); + } else { + responses = channel.sendInstantiationProposal(instantiateProposalRequest); + } + for (ProposalResponse response : responses) { + if (response.isVerified() && response.getStatus() == ProposalResponse.Status.SUCCESS) { + successful.add(response); + out("Succesful instantiate proposal response Txid: %s from peer %s", response.getTransactionID(), response.getPeer().getName()); } else { - responses = channel.sendInstantiationProposal(instantiateProposalRequest); + failed.add(response); } - for (ProposalResponse response : responses) { - if (response.isVerified() && response.getStatus() == ProposalResponse.Status.SUCCESS) { - successful.add(response); - out("Succesful instantiate proposal response Txid: %s from peer %s", response.getTransactionID(), response.getPeer().getName()); - } else { - failed.add(response); - } - } - out("Received %d instantiate proposal responses. Successful+verified: %d . Failed: %d", responses.size(), successful.size(), failed.size()); - if (failed.size() > 0) { - for (ProposalResponse fail : failed) { + } + out("Received %d instantiate proposal responses. Successful+verified: %d . Failed: %d", responses.size(), successful.size(), failed.size()); + if (failed.size() > 0) { + for (ProposalResponse fail : failed) { - out("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + fail.getMessage() + ", on peer" + fail.getPeer()); + out("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + fail.getMessage() + ", on peer" + fail.getPeer()); - } - ProposalResponse first = failed.iterator().next(); - fail("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + first.getMessage() + ". Was verified:" + first.isVerified()); } + ProposalResponse first = failed.iterator().next(); + fail("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + first.getMessage() + ". Was verified:" + first.isVerified()); + } /////////////// /// Send instantiate transaction to orderer out("Sending instantiateTransaction to orderer with a and b set to 100 and %s respectively", "" + (200 + delta));