Resolved merge conflicts.

This commit is contained in:
szymonsztuka 2018-05-30 16:36:06 +01:00
commit 37cadbce69
10 changed files with 94 additions and 35 deletions

View File

@ -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.

View File

@ -130,7 +130,9 @@ 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:
* Complete the pull-request checklist:
* [ ] 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?
@ -139,7 +141,9 @@ Merging the changes back into Corda
* [ ] 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.
3. In the PR comments box, also add a clear description of the purpose for the PR
* 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 <http://slack.corda.net/>`_

View File

@ -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

View File

@ -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
~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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,14 +53,44 @@ 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)
val exitStates = node.database.transaction {
//issue $1 coin twice
repeat(2, {
val coin = 1.DOLLARS.issuedBy(issuer)
val issuance = TransactionBuilder(null as Party?)
@ -67,15 +98,12 @@ class CashSelectionTest : IntegrationTest() {
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 {
AbstractCashSelection
.getInstance { node.services.jdbcSession().metaData }
.unconsumedCashStatesForSpending(node.services, exitedAmount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))

View File

@ -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
}

View File

@ -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']
}
}

View File

@ -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<String> 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<TableElement> 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<String> context) throws Exception {
logger.info("Executing command \"flow list\".");
for (String name : ops().registeredFlows()) {
context.provide(name + System.lineSeparator());
}

View File

@ -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<Map<?, ?>> which
// is the closest you can get in Kotlin to raw types.
public class RunShellCommand extends InteractiveShellCommand {
private static Logger logger = LoggerFactory.getLogger(RunShellCommand.class);
@Command
@Man(
"Runs a method from the CordaRPCOps interface, which is the same interface exposed to RPC clients.\n\n" +
@ -40,10 +46,8 @@ public class RunShellCommand extends InteractiveShellCommand {
"consulting the developer guide at https://docs.corda.net/api/kotlin/corda/net.corda.core.messaging/-corda-r-p-c-ops/index.html"
)
@Usage("runs a method from the CordaRPCOps interface on the node.")
public Object main(
InvocationContext<Map> context,
@Usage("The command to run") @Argument(unquote = false) List<String> command
) {
public Object main(InvocationContext<Map> context, @Usage("The command to run") @Argument(unquote = false) List<String> command) {
logger.info("Executing command \"run {}\",", command.stream().collect(joining(" ")));
StringToMethodCallParser<CordaRPCOps> parser = new StringToMethodCallParser<>(CordaRPCOps.class, objectMapper());
if (command == null) {

View File

@ -15,14 +15,23 @@ package net.corda.tools.shell;
import net.corda.tools.shell.utlities.ANSIProgressRenderer;
import net.corda.tools.shell.utlities.CRaSHANSIProgressRenderer;
import org.crsh.cli.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import static java.util.stream.Collectors.joining;
public class StartShellCommand extends InteractiveShellCommand {
private static Logger logger = LoggerFactory.getLogger(StartShellCommand.class);
@Command
@Man("An alias for 'flow start'. Example: \"start Yo target: Some other company\"")
public void main(@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<String> input) {
logger.info("Executing command \"start {} {}\",", name, input.stream().collect(joining(" ")));
ANSIProgressRenderer ansiProgressRenderer = ansiProgressRenderer();
FlowShellCommand.startFlow(name, input, out, ops(), ansiProgressRenderer != null ? ansiProgressRenderer : new CRaSHANSIProgressRenderer(out), objectMapper());
}