diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst
index 6a6122c2ca..2fbf6b40e3 100644
--- a/docs/source/changelog.rst
+++ b/docs/source/changelog.rst
@@ -8,6 +8,8 @@ Unreleased
==========
* Introduced a hierarchy of ``DatabaseMigrationException``s, allowing ``NodeStartup`` to gracefully inform users of problems related to database migrations before exiting with a non-zero code.
+* Removed -xmx VM argument from Explorer's Capsule setup. This helps avoiding out of memory errors.
+
* Shell now kills an ongoing flow when CTRL+C is pressed in the terminal.
* ``ServiceHub`` and ``CordaRPCOps`` can now safely be used from multiple threads without incurring in database transaction problems.
diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst
index 0baf3c6efc..04becd16b5 100644
--- a/docs/source/contributing.rst
+++ b/docs/source/contributing.rst
@@ -130,16 +130,20 @@ Merging the changes back into Corda
1. Create a pull request from your fork to the ``master`` branch of the Corda repo
-2. In the PR comments box, complete the pull-request checklist:
+2. In the PR comments box:
- * [ ] Have you run the unit, integration and smoke tests as described here? https://docs.corda.net/head/testing.html
- * [ ] If you added/changed public APIs, did you write/update the JavaDocs?
- * [ ] If the changes are of interest to application developers, have you added them to the changelog, and potentially
- release notes?
- * [ ] If you are contributing for the first time, please read the agreement in CONTRIBUTING.md now and add to this
- Pull Request that you agree to it.
+ * Complete the pull-request checklist:
-3. In the PR comments box, also add a clear description of the purpose for the PR
+ * [ ] Have you run the unit, integration and smoke tests as described here? https://docs.corda.net/head/testing.html
+ * [ ] If you added/changed public APIs, did you write/update the JavaDocs?
+ * [ ] If the changes are of interest to application developers, have you added them to the changelog, and potentially
+ release notes?
+ * [ ] If you are contributing for the first time, please read the agreement in CONTRIBUTING.md now and add to this
+ Pull Request that you agree to it.
+
+ * Add a clear description of the purpose of the PR
+
+ * Add the following statement to confirm that your contribution is your own original work: "I hereby certify that my contribution is in accordance with the Developer Certificate of Origin (https://github.com/corda/corda/blob/master/CONTRIBUTING.md#developer-certificate-of-origin)."
4. Request a review from a member of the Corda platform team via the `#design channel `_
diff --git a/docs/source/corda-configuration-file.rst b/docs/source/corda-configuration-file.rst
index 2332f3dba9..0a72d42c6a 100644
--- a/docs/source/corda-configuration-file.rst
+++ b/docs/source/corda-configuration-file.rst
@@ -145,6 +145,9 @@ absolute path to the node's base directory.
:validating: Boolean to determine whether the notary is a validating or non-validating one.
+ :serviceLegalName: If the node is part of a distributed cluster, specify the legal name of the cluster. At runtime, Corda
+ checks whether this name matches the name of the certificate of the notary cluster.
+
:raft: If part of a distributed Raft cluster specify this config object, with the following settings:
:nodeAddress: The host and port to which to bind the embedded Raft server. Note that the Raft cluster uses a
diff --git a/docs/source/setting-up-a-corda-network.rst b/docs/source/setting-up-a-corda-network.rst
index 492bc4e24a..ce0d70a8b6 100644
--- a/docs/source/setting-up-a-corda-network.rst
+++ b/docs/source/setting-up-a-corda-network.rst
@@ -44,6 +44,7 @@ The most important fields regarding network configuration are:
* ``rpcAddress``: The address to which Artemis will bind for RPC calls.
* ``webAddress``: The address the webserver should bind. Note that the port must be distinct from that of ``p2pAddress``
and ``rpcAddress`` if they are on the same machine.
+* ``notary.serviceLegalName``: The name of the notary service, required to setup distributed notaries with the network-bootstrapper.
Bootstrapping the network
~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/finance/src/integration-test/kotlin/net/corda/finance/flows/CashSelectionTest.kt b/finance/src/integration-test/kotlin/net/corda/finance/flows/CashSelectionTest.kt
index d813df59fa..8ae6164a56 100644
--- a/finance/src/integration-test/kotlin/net/corda/finance/flows/CashSelectionTest.kt
+++ b/finance/src/integration-test/kotlin/net/corda/finance/flows/CashSelectionTest.kt
@@ -1,6 +1,7 @@
package net.corda.finance.flows
-import net.corda.core.contracts.*
+import net.corda.core.contracts.TransactionState
+import net.corda.core.contracts.withoutIssuer
import net.corda.core.identity.Party
import net.corda.core.messaging.startFlow
import net.corda.core.transactions.TransactionBuilder
@@ -52,30 +53,57 @@ class CashSelectionTest : IntegrationTest() {
}
}
+ @Test
+ fun `cash selection sees states added in the same transaction`() {
+ driver(DriverParameters(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance"))) {
+ val node = startNode().getOrThrow() as InProcessImpl
+ val nodeIdentity = node.services.myInfo.singleIdentity()
+ val issuer = nodeIdentity.ref(1)
+ val coin = 1.DOLLARS.issuedBy(issuer)
+ val exitedAmount = 1.DOLLARS
+ val issuance = TransactionBuilder(null as Party?)
+ issuance.addOutputState(TransactionState(Cash.State(coin, nodeIdentity), Cash.PROGRAM_ID, defaultNotaryIdentity))
+ issuance.addCommand(Cash.Commands.Issue(), nodeIdentity.owningKey)
+
+ //insert ans select in the same transaction
+ val exitStates = node.database.transaction {
+
+ val transaction = node.services.signInitialTransaction(issuance, nodeIdentity.owningKey)
+ node.services.recordTransactions(transaction)
+
+ val builder = TransactionBuilder(notary = null)
+ AbstractCashSelection
+ .getInstance { node.services.jdbcSession().metaData }
+ .unconsumedCashStatesForSpending(node.services, exitedAmount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
+ }
+ val returnedCoinsNumber = 1
+ assertThat(exitStates.size).isEqualTo(returnedCoinsNumber)
+ }
+ }
+
@Test
fun `dont return extra coins if the selected amount has been reached`() {
driver(DriverParameters(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance"))) {
val node = startNode().getOrThrow() as InProcessImpl
val nodeIdentity = node.services.myInfo.singleIdentity()
- //issue $1 coin twice
val issuer = nodeIdentity.ref(1)
- repeat(2, {
- val coin = 1.DOLLARS.issuedBy(issuer)
- val issuance = TransactionBuilder(null as Party?)
- issuance.addOutputState(TransactionState(Cash.State(coin, nodeIdentity), Cash.PROGRAM_ID, defaultNotaryIdentity))
- issuance.addCommand(Cash.Commands.Issue(), nodeIdentity.owningKey)
- val transaction = node.services.signInitialTransaction(issuance, nodeIdentity.owningKey)
- node.database.transaction {
- node.services.recordTransactions(transaction)
- }
- })
-
- val exitedAmount = 1.DOLLARS
-
- val builder = TransactionBuilder(notary = null)
val exitStates = node.database.transaction {
+ //issue $1 coin twice
+ repeat(2, {
+ val coin = 1.DOLLARS.issuedBy(issuer)
+ val issuance = TransactionBuilder(null as Party?)
+ issuance.addOutputState(TransactionState(Cash.State(coin, nodeIdentity), Cash.PROGRAM_ID, defaultNotaryIdentity))
+ issuance.addCommand(Cash.Commands.Issue(), nodeIdentity.owningKey)
+
+ val transaction = node.services.signInitialTransaction(issuance, nodeIdentity.owningKey)
+
+ node.services.recordTransactions(transaction)
+ })
+
+ val exitedAmount = 1.DOLLARS
+ val builder = TransactionBuilder(notary = null)
AbstractCashSelection
.getInstance { node.services.jdbcSession().metaData }
.unconsumedCashStatesForSpending(node.services, exitedAmount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
@@ -105,12 +133,12 @@ class CashSelectionTest : IntegrationTest() {
val issuedAmount = coins.reduce { sum, element -> sum + element }.withoutIssuer()
- val availableBalance = node.rpc.getCashBalance(issuedAmount.token)
+ val availableBalance = node.rpc.getCashBalance(issuedAmount.token)
- assertThat(availableBalance).isEqualTo(issuedAmount)
+ assertThat(availableBalance).isEqualTo(issuedAmount)
val exitedAmount = 3.01.DOLLARS
- node.rpc.startFlow(::CashExitFlow, exitedAmount, OpaqueBytes.of(1)).returnValue.getOrThrow()
+ node.rpc.startFlow(::CashExitFlow, exitedAmount, OpaqueBytes.of(1)).returnValue.getOrThrow()
val availableBalanceAfterExit = node.rpc.getCashBalance(issuedAmount.token)
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/CordaPersistence.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/CordaPersistence.kt
index 969e89a721..5e1017a6be 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/CordaPersistence.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/CordaPersistence.kt
@@ -123,6 +123,7 @@ class CordaPersistence(
fun createSession(): Connection {
// We need to set the database for the current [Thread] or [Fiber] here as some tests share threads across databases.
_contextDatabase.set(this)
+ currentDBSession().flush()
return contextTransaction.connection
}
diff --git a/tools/explorer/capsule/build.gradle b/tools/explorer/capsule/build.gradle
index b2e6e37fe4..6d28eb9b98 100644
--- a/tools/explorer/capsule/build.gradle
+++ b/tools/explorer/capsule/build.gradle
@@ -50,11 +50,9 @@ task buildExplorerJAR(type: FatCapsule, dependsOn: project(':tools:explorer').co
caplets = ['ExplorerCaplet']
// JVM configuration:
- // - Constrain to small heap sizes to ease development on low end devices.
// - Switch to the G1 GC which is going to be the default in Java 9 and gives low pause times/string dedup.
//
- // If you change these flags, please also update Driver.kt
- jvmArgs = ['-Xmx512m', '-XX:+UseG1GC']
+ jvmArgs = ['-XX:+UseG1GC']
}
}
diff --git a/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java b/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java
index 7473c6ee22..f56c80cd54 100644
--- a/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java
+++ b/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java
@@ -20,9 +20,12 @@ import org.crsh.cli.*;
import org.crsh.command.*;
import org.crsh.text.*;
import org.crsh.text.ui.TableElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.*;
+import static java.util.stream.Collectors.joining;
import static net.corda.tools.shell.InteractiveShell.runFlowByNameFragment;
import static net.corda.tools.shell.InteractiveShell.runStateMachinesView;
@@ -34,12 +37,16 @@ import static net.corda.tools.shell.InteractiveShell.runStateMachinesView;
"flow constructors (the right one is picked automatically) are then specified using the same syntax as for the run command."
)
public class FlowShellCommand extends InteractiveShellCommand {
+
+ private static Logger logger = LoggerFactory.getLogger(FlowShellCommand.class);
+
@Command
@Usage("Start a (work)flow on the node. This is how you can change the ledger.")
public void start(
@Usage("The class name of the flow to run, or an unambiguous substring") @Argument String name,
@Usage("The data to pass as input") @Argument(unquote = false) List input
) {
+ logger.info("Executing command \"flow start {} {}\",", name, input.stream().collect(joining(" ")));
startFlow(name, input, out, ops(), ansiProgressRenderer(), objectMapper());
}
@@ -47,6 +54,7 @@ public class FlowShellCommand extends InteractiveShellCommand {
@Command
@Usage("watch information about state machines running on the node with result information")
public void watch(InvocationContext context) throws Exception {
+ logger.info("Executing command \"flow watch\".");
runStateMachinesView(out, ops());
}
@@ -67,6 +75,7 @@ public class FlowShellCommand extends InteractiveShellCommand {
@Command
@Usage("list flows that user can start")
public void list(InvocationContext context) throws Exception {
+ logger.info("Executing command \"flow list\".");
for (String name : ops().registeredFlows()) {
context.provide(name + System.lineSeparator());
}
diff --git a/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java b/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java
index 4addbdde41..2ea6b67ac3 100644
--- a/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java
+++ b/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java
@@ -20,6 +20,8 @@ import org.crsh.cli.Man;
import org.crsh.cli.Usage;
import org.crsh.command.InvocationContext;
import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -27,11 +29,15 @@ import java.util.Map;
import java.util.Set;
import static java.util.Comparator.comparing;
+import static java.util.stream.Collectors.joining;
// Note that this class cannot be converted to Kotlin because CRaSH does not understand InvocationContext