mirror of
https://github.com/corda/corda.git
synced 2025-03-22 12:05:59 +00:00
Removing warnings
This commit is contained in:
parent
20a589d66d
commit
0c8c914882
7
.idea/compiler.xml
generated
7
.idea/compiler.xml
generated
@ -54,6 +54,12 @@
|
||||
<module name="contracts-states_test" target="1.8" />
|
||||
<module name="corda-core_integrationTest" target="1.8" />
|
||||
<module name="corda-core_smokeTest" target="1.8" />
|
||||
<module name="corda-enterprise-testing_main" target="1.8" />
|
||||
<module name="corda-enterprise-testing_test" target="1.8" />
|
||||
<module name="corda-enterprise-tools_main" target="1.8" />
|
||||
<module name="corda-enterprise-tools_test" target="1.8" />
|
||||
<module name="corda-enterprise_main" target="1.8" />
|
||||
<module name="corda-enterprise_test" target="1.8" />
|
||||
<module name="corda-finance_integrationTest" target="1.8" />
|
||||
<module name="corda-project-testing_main" target="1.8" />
|
||||
<module name="corda-project-testing_test" target="1.8" />
|
||||
@ -93,6 +99,7 @@
|
||||
<module name="demobench_main" target="1.8" />
|
||||
<module name="demobench_test" target="1.8" />
|
||||
<module name="dist_binFiles" target="1.8" />
|
||||
<module name="dist_installerFiles" target="1.8" />
|
||||
<module name="dist_licenseFiles" target="1.8" />
|
||||
<module name="dist_main" target="1.8" />
|
||||
<module name="dist_readmeFiles" target="1.8" />
|
||||
|
@ -7,12 +7,10 @@ import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.NotaryInfo
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.node.services.config.CertChainPolicyConfig
|
||||
import net.corda.node.services.config.EnterpriseConfiguration
|
||||
import net.corda.node.services.config.MutualExclusionConfiguration
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
@ -102,7 +100,7 @@ class BridgeSmokeTest {
|
||||
bridgeJar.copyToDirectory(testDir)
|
||||
}
|
||||
|
||||
fun createNetworkParams(baseDirectory: Path) {
|
||||
private fun createNetworkParams(baseDirectory: Path) {
|
||||
val dummyNotaryParty = TestIdentity(DUMMY_NOTARY_NAME)
|
||||
val notaryInfo = NotaryInfo(dummyNotaryParty.party, false)
|
||||
val copier = NetworkParametersCopier(NetworkParameters(
|
||||
@ -112,18 +110,18 @@ class BridgeSmokeTest {
|
||||
maxMessageSize = 10485760,
|
||||
maxTransactionSize = 40000,
|
||||
epoch = 1,
|
||||
whitelistedContractImplementations = emptyMap<String, List<AttachmentId>>()
|
||||
whitelistedContractImplementations = emptyMap()
|
||||
), overwriteFile = true)
|
||||
copier.install(baseDirectory)
|
||||
}
|
||||
|
||||
fun SSLConfiguration.createBridgeKeyStores(legalName: CordaX500Name,
|
||||
rootCert: X509Certificate = DEV_ROOT_CA.certificate,
|
||||
intermediateCa: CertificateAndKeyPair = DEV_INTERMEDIATE_CA) {
|
||||
private fun SSLConfiguration.createBridgeKeyStores(legalName: CordaX500Name,
|
||||
rootCert: X509Certificate = DEV_ROOT_CA.certificate,
|
||||
intermediateCa: CertificateAndKeyPair = DEV_INTERMEDIATE_CA) {
|
||||
|
||||
certificatesDirectory.createDirectories()
|
||||
if (!trustStoreFile.exists()) {
|
||||
loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/${DEV_CA_TRUST_STORE_FILE}"), DEV_CA_TRUST_STORE_PASS).save(trustStoreFile, trustStorePassword)
|
||||
loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/$DEV_CA_TRUST_STORE_FILE"), DEV_CA_TRUST_STORE_PASS).save(trustStoreFile, trustStorePassword)
|
||||
}
|
||||
|
||||
val (nodeCaCert, nodeCaKeyPair) = createDevNodeCa(intermediateCa, legalName)
|
||||
@ -189,13 +187,13 @@ class BridgeSmokeTest {
|
||||
}
|
||||
}
|
||||
|
||||
fun serverListening(host: String, port: Int): Boolean {
|
||||
private fun serverListening(host: String, port: Int): Boolean {
|
||||
var s: Socket? = null
|
||||
try {
|
||||
return try {
|
||||
s = Socket(host, port)
|
||||
return true
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
return false
|
||||
false
|
||||
} finally {
|
||||
try {
|
||||
s?.close()
|
||||
@ -212,7 +210,6 @@ class BridgeSmokeTest {
|
||||
doReturn("cordacadevpass").whenever(it).keyStorePassword
|
||||
doReturn(NetworkHostAndPort("localhost", 11005)).whenever(it).p2pAddress
|
||||
doReturn(null).whenever(it).jmxMonitoringHttpPort
|
||||
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
|
||||
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000), externalBridge = true)).whenever(it).enterpriseConfiguration
|
||||
}
|
||||
val artemisServer = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", 11005), MAX_MESSAGE_SIZE)
|
||||
|
@ -17,7 +17,6 @@ import net.corda.bridge.createBridgeKeyStores
|
||||
import net.corda.bridge.createNetworkParams
|
||||
import net.corda.bridge.services.artemis.BridgeArtemisConnectionServiceImpl
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.services.config.CertChainPolicyConfig
|
||||
import net.corda.node.services.config.EnterpriseConfiguration
|
||||
import net.corda.node.services.config.MutualExclusionConfiguration
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
@ -102,7 +101,6 @@ class ArtemisConnectionTest {
|
||||
doReturn("cordacadevpass").whenever(it).keyStorePassword
|
||||
doReturn(NetworkHostAndPort("localhost", 11005)).whenever(it).p2pAddress
|
||||
doReturn(null).whenever(it).jmxMonitoringHttpPort
|
||||
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
|
||||
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000), externalBridge = true)).whenever(it).enterpriseConfiguration
|
||||
}
|
||||
val artemisServer = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", 11005), MAX_MESSAGE_SIZE)
|
||||
|
@ -57,14 +57,16 @@ class StateMachineDataModel {
|
||||
private val progressTracking by observable(NodeMonitorModel::progressTracking)
|
||||
private val progressEvents = progressTracking.recordAsAssociation(ProgressTrackingEvent::stateMachineId)
|
||||
|
||||
val counter = Counter()
|
||||
private val counter = Counter()
|
||||
|
||||
private val stateMachineIndexMap = HashMap<StateMachineRunId, Int>()
|
||||
private val stateMachineStatus = stateMachineUpdates.fold(FXCollections.observableArrayList<SimpleObjectProperty<StateMachineStatus>>()) { list, update ->
|
||||
when (update) {
|
||||
is StateMachineUpdate.Added -> {
|
||||
counter.addSmm()
|
||||
val flowInitiator= update.stateMachineInfo.initiator
|
||||
// TODO Use invocationContext instead
|
||||
@Suppress("DEPRECATION")
|
||||
val flowInitiator = update.stateMachineInfo.initiator
|
||||
val added: SimpleObjectProperty<StateMachineStatus> =
|
||||
SimpleObjectProperty(StateMachineStatus.Added(update.id, update.stateMachineInfo.flowLogicClassName, flowInitiator))
|
||||
list.add(added)
|
||||
@ -83,7 +85,7 @@ class StateMachineDataModel {
|
||||
private val stateMachineDataList = stateMachineStatus.map {
|
||||
val smStatus = it.value as StateMachineStatus.Added
|
||||
val id = smStatus.id
|
||||
val progress = SimpleObjectProperty(progressEvents.get(id))
|
||||
val progress = SimpleObjectProperty(progressEvents[id])
|
||||
StateMachineData(id, smStatus.stateMachineName, smStatus.flowInitiator,
|
||||
Pair(it, EasyBind.map(progress) { ProgressStatus(it?.message) }))
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ data class StateMachineInfo @JvmOverloads constructor(
|
||||
* An object representing information about the initiator of the flow. Note that this field is
|
||||
* superceded by the [invocationContext] property, which has more detail.
|
||||
*/
|
||||
@Deprecated("There is more info available using 'context'") val initiator: FlowInitiator,
|
||||
@Deprecated("There is more info available using 'invocationContext'") val initiator: FlowInitiator,
|
||||
/** A [DataFeed] of the current progress step as a human readable string, and updates to that string. */
|
||||
val progressTrackerStepAndUpdates: DataFeed<String, String>?,
|
||||
/** An [InvocationContext] describing why and by whom the flow was started. */
|
||||
|
@ -136,7 +136,7 @@ class IntegrationTestingTutorial : IntegrationTest() {
|
||||
// move to Bob
|
||||
parallel(
|
||||
(1..numberOfStates).map { i ->
|
||||
expect(match = { it.moved() == i * 100 }) { update: Vault.Update<Cash.State> ->
|
||||
expect(match = { it.moved() == i * 100 }) { _: Vault.Update<Cash.State> ->
|
||||
}
|
||||
}
|
||||
),
|
||||
@ -154,7 +154,7 @@ class IntegrationTestingTutorial : IntegrationTest() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Vault.Update<Cash.State>.moved(): Int {
|
||||
private fun Vault.Update<Cash.State>.moved(): Int {
|
||||
val consumedSum = consumed.sumBy { it.state.data.amount.quantity.toInt() }
|
||||
val producedSum = produced.sumBy { it.state.data.amount.quantity.toInt() }
|
||||
return consumedSum - producedSum
|
||||
|
@ -40,6 +40,7 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
@ -134,7 +135,7 @@ public class FlowCookbookJava {
|
||||
// We retrieve a notary from the network map.
|
||||
// DOCSTART 01
|
||||
CordaX500Name notaryName = new CordaX500Name("Notary Service", "London", "GB");
|
||||
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(notaryName);
|
||||
Party specificNotary = Objects.requireNonNull(getServiceHub().getNetworkMapCache().getNotary(notaryName));
|
||||
// Alternatively, we can pick an arbitrary notary from the notary
|
||||
// list. However, it is always preferable to specify the notary
|
||||
// explicitly, as the notary list might change when new notaries are
|
||||
@ -378,7 +379,7 @@ public class FlowCookbookJava {
|
||||
// Or we can add the output state as a ``TransactionState``, which already specifies
|
||||
// the output's contract and notary.
|
||||
// DOCSTART 51
|
||||
TransactionState txState = new TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
|
||||
TransactionState txState = new TransactionState<>(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
|
||||
// DOCEND 51
|
||||
|
||||
// Commands can be added as ``Command``s.
|
||||
@ -662,7 +663,7 @@ public class FlowCookbookJava {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkTransaction(SignedTransaction stx) {
|
||||
protected void checkTransaction(@NotNull SignedTransaction stx) {
|
||||
requireThat(require -> {
|
||||
// Any additional checking we see fit...
|
||||
DummyState outputState = (DummyState) stx.getTx().getOutputs().get(0).getData();
|
||||
|
@ -13,6 +13,7 @@ package net.corda.docs.java.tutorial.contract;
|
||||
import net.corda.core.contracts.*;
|
||||
import net.corda.core.transactions.LedgerTransaction;
|
||||
import net.corda.core.transactions.LedgerTransaction.InOutGroup;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Currency;
|
||||
@ -22,6 +23,7 @@ import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
|
||||
import static net.corda.core.contracts.ContractsDSL.requireThat;
|
||||
import static net.corda.finance.utils.StateSumming.sumCashBy;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class CommercialPaper implements Contract {
|
||||
// DOCSTART 1
|
||||
public static final String IOU_CONTRACT_ID = "com.example.contract.IOUContract";
|
||||
@ -29,7 +31,7 @@ public class CommercialPaper implements Contract {
|
||||
|
||||
// DOCSTART 3
|
||||
@Override
|
||||
public void verify(LedgerTransaction tx) {
|
||||
public void verify(@NotNull LedgerTransaction tx) {
|
||||
List<InOutGroup<State, State>> groups = tx.groupStates(State.class, State::withoutOwner);
|
||||
CommandWithParties<Commands> cmd = requireSingleCommand(tx.getCommands(), Commands.class);
|
||||
// DOCEND 3
|
||||
@ -37,7 +39,7 @@ public class CommercialPaper implements Contract {
|
||||
// DOCSTART 4
|
||||
TimeWindow timeWindow = tx.getTimeWindow();
|
||||
|
||||
for (InOutGroup group : groups) {
|
||||
for (InOutGroup<State, State> group : groups) {
|
||||
List<State> inputs = group.getInputs();
|
||||
List<State> outputs = group.getOutputs();
|
||||
|
||||
@ -57,6 +59,7 @@ public class CommercialPaper implements Contract {
|
||||
Amount<Issued<Currency>> received = sumCashBy(tx.getOutputStates(), input.getOwner());
|
||||
if (timeWindow == null) throw new IllegalArgumentException("Redemptions must be timestamped");
|
||||
Instant time = timeWindow.getFromTime();
|
||||
if (time == null) throw new IllegalArgumentException("Redemptions must have a from time");
|
||||
requireThat(require -> {
|
||||
require.using("the paper must have matured", time.isAfter(input.getMaturityDate()));
|
||||
require.using("the received amount equals the face value", received == input.getFaceValue());
|
||||
@ -68,6 +71,7 @@ public class CommercialPaper implements Contract {
|
||||
State output = outputs.get(0);
|
||||
if (timeWindow == null) throw new IllegalArgumentException("Issuances must have a time-window");
|
||||
Instant time = timeWindow.getUntilTime();
|
||||
if (time == null) throw new IllegalArgumentException("Issuances must have an until time");
|
||||
requireThat(require -> {
|
||||
// Don't allow people to issue commercial paper under other entities identities.
|
||||
require.using("output states are issued by a command signer", cmd.getSigners().contains(output.getIssuance().getParty().getOwningKey()));
|
||||
|
@ -11,19 +11,19 @@
|
||||
package net.corda.behave.network
|
||||
|
||||
import net.corda.behave.database.DatabaseType
|
||||
import net.corda.behave.file.*
|
||||
import net.corda.behave.monitoring.PatternWatch
|
||||
import net.corda.behave.file.LogSource
|
||||
import net.corda.behave.file.currentDirectory
|
||||
import net.corda.behave.file.stagingRoot
|
||||
import net.corda.behave.file.tmpDirectory
|
||||
import net.corda.behave.node.Distribution
|
||||
import net.corda.behave.node.Node
|
||||
import net.corda.behave.node.configuration.NotaryType
|
||||
import net.corda.behave.process.Command
|
||||
import net.corda.behave.process.JarCommand
|
||||
import net.corda.core.CordaException
|
||||
import net.corda.core.CordaRuntimeException
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.minutes
|
||||
import net.corda.core.utilities.seconds
|
||||
import java.io.Closeable
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
@ -147,116 +147,8 @@ class Network private constructor(
|
||||
* using Local signing and "Auto Approval" mode
|
||||
*/
|
||||
private fun bootstrapDoorman() {
|
||||
|
||||
// TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution)
|
||||
signalFailure("Bootstrapping a Corda Enterprise network using the Doorman is no longer supported; exiting ...")
|
||||
return
|
||||
|
||||
// WARNING!! Need to use the correct bootstrapper
|
||||
// only if using OS nodes (need to choose the latest version)
|
||||
val r3node = nodes.values
|
||||
.find { it.config.distribution.type == Distribution.Type.CORDA_ENTERPRISE } ?: throw CordaRuntimeException("Missing R3 distribution node")
|
||||
val distribution = r3node.config.distribution
|
||||
|
||||
// Copy over reference configuration files used in bootstrapping
|
||||
val source = doormanConfigDirectory
|
||||
val doormanTargetDirectory = targetDirectory / "doorman"
|
||||
source.toFile().copyRecursively(doormanTargetDirectory.toFile(), true)
|
||||
|
||||
// Use master version of Bootstrapper
|
||||
val doormanJar = Distribution.R3_MASTER.doormanJar
|
||||
log.info("DoormanJar URL: $doormanJar\n")
|
||||
|
||||
// 1. Create key stores for local signer
|
||||
|
||||
// java -jar doorman-<version>.jar --mode ROOT_KEYGEN
|
||||
log.info("Doorman target directory: $doormanTargetDirectory")
|
||||
runCommand(JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf", "--mode", "ROOT_KEYGEN", "--trust-store-password", "password"),
|
||||
doormanTargetDirectory, timeout))
|
||||
|
||||
// java -jar doorman-<version>.jar --mode CA_KEYGEN
|
||||
runCommand(JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf", "--mode", "CA_KEYGEN"),
|
||||
doormanTargetDirectory, timeout))
|
||||
|
||||
// 2. Start the doorman service for notary registration
|
||||
doormanNMS = JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf"),
|
||||
doormanTargetDirectory, timeout)
|
||||
|
||||
val doormanCommand = runCommand(doormanNMS, noWait = true)
|
||||
log.info("Waiting for DoormanNMS to be alive")
|
||||
|
||||
PatternWatch(doormanCommand.output, "Network management web services started on").await(30.seconds)
|
||||
log.info("DoormanNMS up and running")
|
||||
|
||||
// Notary Nodes
|
||||
val notaryNodes = nodes.values.filter { it.config.notary.notaryType != NotaryType.NONE }
|
||||
notaryNodes.forEach { notaryNode ->
|
||||
val notaryTargetDirectory = targetDirectory / notaryNode.config.name
|
||||
log.info("Notary target directory: $notaryTargetDirectory")
|
||||
|
||||
// 3. Create notary node and register with the doorman
|
||||
runCommand(JarCommand(distribution.cordaJar,
|
||||
arrayOf("--initial-registration",
|
||||
"--base-directory", "$notaryTargetDirectory",
|
||||
"--network-root-truststore", "../doorman/certificates/distribute-nodes/network-root-truststore.jks",
|
||||
"--network-root-truststore-password", "password"),
|
||||
notaryTargetDirectory, timeout))
|
||||
|
||||
// 4. Generate node info files for notary nodes
|
||||
runCommand(JarCommand(distribution.cordaJar,
|
||||
arrayOf("--just-generate-node-info",
|
||||
"--base-directory", "$notaryTargetDirectory"),
|
||||
notaryTargetDirectory, timeout))
|
||||
|
||||
// cp (or ln -s) nodeInfo* notary-node-info
|
||||
val nodeInfoFile = notaryTargetDirectory.toFile().listFiles { _, filename -> filename.matches("nodeInfo-.+".toRegex()) }.firstOrNull() ?: throw CordaRuntimeException("Missing notary nodeInfo file")
|
||||
|
||||
Files.copy(nodeInfoFile.toPath(), (notaryTargetDirectory / "notary-node-info"), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
// exit Doorman process
|
||||
doormanCommand.interrupt()
|
||||
doormanCommand.waitFor()
|
||||
|
||||
// 5. Add notary identities to the network parameters
|
||||
|
||||
// 6. Load initial network parameters file for network map service
|
||||
val networkParamsConfig = if (notaryNodes.isEmpty()) "network-parameters-without-notary.conf" else "network-parameters.conf"
|
||||
val updateNetworkParams = JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanTargetDirectory/node.conf", "--set-network-parameters", "$doormanTargetDirectory/$networkParamsConfig"),
|
||||
doormanTargetDirectory, timeout)
|
||||
runCommand(updateNetworkParams)
|
||||
|
||||
// 7. Start a fully configured Doorman / NMS
|
||||
doormanNMS = JarCommand(doormanJar,
|
||||
arrayOf("--config-file", "$doormanConfigDirectory/node.conf"),
|
||||
doormanTargetDirectory, timeout)
|
||||
|
||||
val doormanNMSCommand = runCommand(doormanNMS, noWait = true)
|
||||
log.info("Waiting for DoormanNMS to be alive")
|
||||
|
||||
PatternWatch(doormanNMSCommand.output, "Network management web services started on").await(30.seconds)
|
||||
log.info("DoormanNMS up and running")
|
||||
|
||||
// 8. Register other participant nodes
|
||||
val partyNodes = nodes.values.filter { it.config.notary.notaryType == NotaryType.NONE }
|
||||
partyNodes.forEach { partyNode ->
|
||||
val partyTargetDirectory = targetDirectory / partyNode.config.name
|
||||
log.info("Party target directory: $partyTargetDirectory")
|
||||
|
||||
// 3. Create notary node and register with the doorman
|
||||
runCommand(JarCommand(distribution.cordaJar,
|
||||
arrayOf("--initial-registration",
|
||||
"--network-root-truststore", "../doorman/certificates/distribute-nodes/network-root-truststore.jks",
|
||||
"--network-root-truststore-password", "password",
|
||||
"--base-directory", "$partyTargetDirectory"),
|
||||
partyTargetDirectory, timeout))
|
||||
}
|
||||
|
||||
isDoormanNMSRunning = true
|
||||
}
|
||||
|
||||
private fun runCommand(command: Command, noWait: Boolean = false): Command {
|
||||
@ -446,7 +338,7 @@ class Network private constructor(
|
||||
val rpcProxyPortNo = node.config.nodeInterface.rpcProxy
|
||||
val pid = Files.lines(tmpDirectory / "rpcProxy-pid-$rpcProxyPortNo").findFirst().get()
|
||||
// TODO: consider generic implementation to support non *nix platforms
|
||||
Command(listOf("kill", "-9", "$pid")).run()
|
||||
Command(listOf("kill", "-9", pid)).run()
|
||||
(tmpDirectory / "rpcProxy-pid-$rpcProxyPortNo").deleteIfExists()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
|
@ -14,7 +14,6 @@ import net.corda.behave.database.DatabaseConnection
|
||||
import net.corda.behave.database.DatabaseType
|
||||
import net.corda.behave.file.LogSource
|
||||
import net.corda.behave.file.currentDirectory
|
||||
import net.corda.behave.file.stagingRoot
|
||||
import net.corda.behave.monitoring.PatternWatch
|
||||
import net.corda.behave.node.configuration.*
|
||||
import net.corda.behave.process.JarCommand
|
||||
@ -31,8 +30,8 @@ import net.corda.core.internal.div
|
||||
import net.corda.core.internal.exists
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.minutes
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.minutes
|
||||
import net.corda.core.utilities.seconds
|
||||
import org.apache.commons.io.FileUtils
|
||||
import java.net.InetAddress
|
||||
@ -45,7 +44,7 @@ import java.util.concurrent.CountDownLatch
|
||||
*/
|
||||
class Node(
|
||||
val config: Configuration,
|
||||
val rootDirectory: Path = currentDirectory,
|
||||
private val rootDirectory: Path = currentDirectory,
|
||||
private val settings: ServiceSettings = ServiceSettings(),
|
||||
val rpcProxy: Boolean = false,
|
||||
val networkType: Distribution.Type
|
||||
@ -77,18 +76,6 @@ class Node(
|
||||
|
||||
private var haveDependenciesStopped = false
|
||||
|
||||
fun describe(): String {
|
||||
val network = config.nodeInterface
|
||||
val database = config.database
|
||||
return """
|
||||
|Node Information: ${config.name}
|
||||
| - P2P: ${network.host}:${network.p2pPort}
|
||||
| - RPC: ${network.host}:${network.rpcPort}
|
||||
| - SSH: ${network.host}:${network.sshPort}
|
||||
| - DB: ${network.host}:${database.port} (${database.type})
|
||||
|""".trimMargin()
|
||||
}
|
||||
|
||||
fun configure() {
|
||||
if (isConfigured) { return }
|
||||
isConfigured = true
|
||||
@ -164,10 +151,6 @@ class Node(
|
||||
}
|
||||
}
|
||||
|
||||
val nodeInfoGenerationOutput: LogSource by lazy {
|
||||
LogSource(logDirectory, "node-info-gen.log")
|
||||
}
|
||||
|
||||
val logOutput: LogSource by lazy {
|
||||
val hostname = InetAddress.getLocalHost().hostName
|
||||
LogSource(logDirectory, "node-$hostname.*.log")
|
||||
@ -387,10 +370,11 @@ class Node(
|
||||
val name = name ?: error("Node name not set")
|
||||
val directory = directory ?: error("Runtime directory not set")
|
||||
// TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution)
|
||||
val compatibilityZoneURL = null
|
||||
if (networkType == Distribution.Type.CORDA_ENTERPRISE && System.getProperty("USE_NETWORK_SERVICES") != null)
|
||||
"http://localhost:1300" // TODO: add additional USE_NETWORK_SERVICES_URL to specify location of existing operational environment to use.
|
||||
else null
|
||||
val compatibilityZoneURL = if (networkType == Distribution.Type.CORDA_ENTERPRISE && System.getProperty("USE_NETWORK_SERVICES") != null) {
|
||||
"http://localhost:1300" // TODO: add additional USE_NETWORK_SERVICES_URL to specify location of existing operational environment to use.
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return Node(
|
||||
Configuration(
|
||||
name,
|
||||
|
@ -72,7 +72,7 @@ class ScenarioState {
|
||||
|
||||
inline fun <T> withNetwork(action: ScenarioState.() -> T): T {
|
||||
ensureNetworkIsRunning()
|
||||
return action()
|
||||
return this.action()
|
||||
}
|
||||
|
||||
inline fun <T> withClient(nodeName: String, crossinline action: (CordaRPCOps) -> T): T {
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
package net.corda.behave.scenarios.helpers
|
||||
|
||||
import net.corda.behave.logging.getLogger
|
||||
import net.corda.behave.scenarios.ScenarioState
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import org.slf4j.Logger
|
||||
@ -32,12 +31,12 @@ abstract class Substeps(protected val state: ScenarioState) {
|
||||
}
|
||||
|
||||
protected fun <T> withClientProxy(nodeName: String, action: ScenarioState.(CordaRPCOps) -> T): T {
|
||||
return state.withClientProxy(nodeName, {
|
||||
return@withClientProxy try {
|
||||
return state.withClientProxy(nodeName) {
|
||||
try {
|
||||
action(state, it)
|
||||
} catch (ex: Exception) {
|
||||
state.error<T>(ex.message ?: "Failed to execute HTTP call")
|
||||
state.error(ex.message ?: "Failed to execute HTTP call")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ repositories {
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'idea'
|
||||
|
||||
description 'A javaagent to allow hooking into Kryo'
|
||||
|
@ -114,7 +114,6 @@ object FiberMonitor {
|
||||
thread {
|
||||
while (true) {
|
||||
Thread.sleep(1000)
|
||||
this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ package net.corda.flowhook
|
||||
|
||||
import java.lang.instrument.Instrumentation
|
||||
|
||||
@Suppress("UNUSED")
|
||||
@Suppress("UNUSED", "UNUSED_PARAMETER")
|
||||
class FlowHookAgent {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@ -22,4 +22,3 @@ class FlowHookAgent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import org.apache.activemq.artemis.core.io.buffer.TimedBuffer
|
||||
import java.sql.Connection
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@Suppress("UNUSED")
|
||||
@Suppress("UNUSED", "UNUSED_PARAMETER")
|
||||
object FlowHookContainer {
|
||||
|
||||
@JvmStatic
|
||||
|
@ -34,7 +34,6 @@ repositories {
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'net.corda.plugins.cordapp'
|
||||
|
||||
|
@ -11,13 +11,11 @@ import java.util.concurrent.Callable
|
||||
|
||||
// Responsible for executing test scenario for a single node executing `LinearStateBatchNotariseFlow` and verifying the results
|
||||
class LinearStateScenarioRunner(options: OptionSet) : AbstractScenarioRunner(options), Callable<Boolean> {
|
||||
|
||||
companion object {
|
||||
private val logger = contextLogger()
|
||||
}
|
||||
|
||||
override fun call(): Boolean {
|
||||
|
||||
scenarioInitialized()
|
||||
|
||||
try {
|
||||
@ -42,6 +40,7 @@ class LinearStateScenarioRunner(options: OptionSet) : AbstractScenarioRunner(opt
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun verifyResultsAndStatesTally(results: MutableList<LinearStateBatchNotariseFlow.Result>, states: Vault.Page<LinearStateBatchNotariseContract.State>): Boolean {
|
||||
// Unfortunately, there is absolutely nothing in `LinearStateBatchNotariseFlow.Result` which can link it to the original transaction
|
||||
return true
|
||||
|
@ -27,8 +27,8 @@ class CashSelectionOracleImpl : AbstractCashSelection(maxRetries = 16, retrySlee
|
||||
private val log = contextLogger()
|
||||
}
|
||||
|
||||
override fun isCompatible(metaData: DatabaseMetaData): Boolean {
|
||||
return metaData.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true)
|
||||
override fun isCompatible(metadata: DatabaseMetaData): Boolean {
|
||||
return metadata.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true)
|
||||
}
|
||||
|
||||
override fun toString() = "${this::class.qualifiedName} for '$JDBC_DRIVER_NAME'"
|
||||
|
@ -16,7 +16,6 @@ import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.toBase58String
|
||||
import java.sql.Connection
|
||||
import java.sql.DatabaseMetaData
|
||||
import java.sql.ResultSet
|
||||
@ -32,8 +31,8 @@ class CashSelectionSQLServerImpl : AbstractCashSelection(maxRetries = 16, retryS
|
||||
private val log = contextLogger()
|
||||
}
|
||||
|
||||
override fun isCompatible(metaData: DatabaseMetaData): Boolean {
|
||||
return metaData.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true)
|
||||
override fun isCompatible(metadata: DatabaseMetaData): Boolean {
|
||||
return metadata.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true)
|
||||
}
|
||||
|
||||
override fun toString() = "${this::class.qualifiedName} for '$JDBC_DRIVER_NAME'"
|
||||
|
@ -8,7 +8,6 @@ import java.nio.file.Paths
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
if (args.isEmpty()) {
|
||||
println("Usage: launcher <main-class-name> [args]")
|
||||
exitProcess(0)
|
||||
@ -54,15 +53,14 @@ fun main(args: Array<String>) {
|
||||
@Suppress("unchecked")
|
||||
private fun fixBaseDirArg(args: Array<String>, nodeBaseDirFromArgs: Path): Array<String> {
|
||||
val baseDirIdx = args.indexOf("--base-directory")
|
||||
if (baseDirIdx != -1){
|
||||
args[baseDirIdx+1] = nodeBaseDirFromArgs.toString()
|
||||
return args
|
||||
return if (baseDirIdx != -1) {
|
||||
// Replace the arg that follows, i.e. --base-directory X
|
||||
// TODO This will not work for --base-directory=X
|
||||
args[baseDirIdx + 1] = nodeBaseDirFromArgs.toString()
|
||||
args
|
||||
} else {
|
||||
args + listOf("--base-directory", nodeBaseDirFromArgs.toString())
|
||||
}
|
||||
|
||||
val argsWithBaseDir = args.copyOf(args.size + 2)
|
||||
argsWithBaseDir[argsWithBaseDir.lastIndex - 1] = "--base-directory"
|
||||
argsWithBaseDir[argsWithBaseDir.lastIndex] = nodeBaseDirFromArgs.toString()
|
||||
return argsWithBaseDir as Array<String>
|
||||
}
|
||||
|
||||
private fun setupClassLoader(nodeBaseDir: Path): ClassLoader {
|
||||
|
@ -257,7 +257,7 @@ class MySQLNotaryServiceTests : IntegrationTest() {
|
||||
}
|
||||
|
||||
private fun createNotaryNode(): InternalMockNetwork.MockNode {
|
||||
val dataStoreProperties = makeTestDataSourceProperties(configSupplier = { _, _ -> ConfigFactory.empty() }, fallBackConfigSupplier = ::inMemoryH2DataSourceConfig).apply {
|
||||
val dataStoreProperties = makeInternalTestDataSourceProperties(configSupplier = { ConfigFactory.empty() }).apply {
|
||||
setProperty("autoCommit", "false")
|
||||
}
|
||||
return mockNet.createUnstartedNode(
|
||||
|
@ -16,6 +16,7 @@ import net.corda.node.utilities.AffinityExecutor
|
||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
|
||||
import org.hibernate.Session
|
||||
import org.hibernate.query.NativeQuery
|
||||
import java.io.Serializable
|
||||
import java.sql.SQLTransientConnectionException
|
||||
import java.time.Duration
|
||||
@ -132,7 +133,7 @@ class RunOnceService(private val database: CordaPersistence, private val machine
|
||||
|
||||
private fun insertMutualExclusion(session: Session) {
|
||||
val query = session.createNativeQuery("INSERT INTO $TABLE VALUES ('X', :machineName, :pid, CURRENT_TIMESTAMP, :version)", MutualExclusion::class.java)
|
||||
query.unwrap(org.hibernate.SQLQuery::class.java).addSynchronizedEntityClass(MutualExclusion::class.java)
|
||||
query.unwrap(NativeQuery::class.java).addSynchronizedEntityClass(MutualExclusion::class.java)
|
||||
query.setParameter("pid", pid)
|
||||
query.setParameter("machineName", machineName)
|
||||
query.setParameter("version", 0)
|
||||
|
@ -70,7 +70,7 @@ class MultiThreadedStateMachineManager(
|
||||
val checkpointStorage: CheckpointStorage,
|
||||
val executor: ExecutorService,
|
||||
val database: CordaPersistence,
|
||||
val secureRandom: SecureRandom,
|
||||
private val secureRandom: SecureRandom,
|
||||
private val unfinishedFibers: ReusableLatch = ReusableLatch(),
|
||||
private val classloader: ClassLoader = MultiThreadedStateMachineManager::class.java.classLoader
|
||||
) : StateMachineManager, StateMachineManagerInternal {
|
||||
@ -158,7 +158,7 @@ class MultiThreadedStateMachineManager(
|
||||
}
|
||||
serviceHub.networkMapCache.nodeReady.then {
|
||||
resumeRestoredFlows(fibers)
|
||||
flowMessaging.start { receivedMessage, deduplicationHandler ->
|
||||
flowMessaging.start { _, deduplicationHandler ->
|
||||
lifeCycle.requireState(State.STARTED, StateMachineStoppedException("Flow cannot be started. State machine is stopped.")) {
|
||||
deliverExternalEvent(deduplicationHandler.externalCause)
|
||||
}
|
||||
@ -306,10 +306,10 @@ class MultiThreadedStateMachineManager(
|
||||
}
|
||||
|
||||
private fun checkQuasarJavaAgentPresence() {
|
||||
check(SuspendableHelper.isJavaAgentActive(), {
|
||||
check(SuspendableHelper.isJavaAgentActive()) {
|
||||
"""Missing the '-javaagent' JVM argument. Make sure you run the tests with the Quasar java agent attached to your JVM.
|
||||
#See https://docs.corda.net/troubleshooting.html - 'Fiber classes not instrumented' for more details.""".trimMargin("#")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun decrementLiveFibers() {
|
||||
@ -324,8 +324,7 @@ class MultiThreadedStateMachineManager(
|
||||
return checkpointStorage.getAllCheckpoints().map { (id, serializedCheckpoint) ->
|
||||
// If a flow is added before start() then don't attempt to restore it
|
||||
if (concurrentBox.content.flows.containsKey(id)) return@map null
|
||||
val checkpoint = deserializeCheckpoint(serializedCheckpoint)
|
||||
if (checkpoint == null) return@map null
|
||||
val checkpoint = deserializeCheckpoint(serializedCheckpoint) ?: return@map null
|
||||
createFlowFromCheckpoint(
|
||||
id = id,
|
||||
checkpoint = checkpoint,
|
||||
@ -440,7 +439,7 @@ class MultiThreadedStateMachineManager(
|
||||
val flowId = sessionToFlow[recipientId]
|
||||
if (flowId == null) {
|
||||
deduplicationHandler.afterDatabaseTransaction()
|
||||
if (sessionMessage.payload is EndSessionMessage) {
|
||||
if (sessionMessage.payload === EndSessionMessage) {
|
||||
logger.debug {
|
||||
"Got ${EndSessionMessage::class.java.simpleName} for " +
|
||||
"unknown session $recipientId, discarding..."
|
||||
@ -537,12 +536,6 @@ class MultiThreadedStateMachineManager(
|
||||
isStartIdempotent: Boolean
|
||||
): CordaFuture<FlowStateMachine<A>> {
|
||||
val flowId = StateMachineRunId.createRandom()
|
||||
val deduplicationSeed = when (flowStart) {
|
||||
FlowStart.Explicit -> flowId.uuid.toString()
|
||||
is FlowStart.Initiated ->
|
||||
"${flowStart.initiatingMessage.initiatorSessionId.toLong}-" +
|
||||
"${flowStart.initiatingMessage.initiationEntropy}"
|
||||
}
|
||||
|
||||
// Before we construct the state machine state by freezing the FlowLogic we need to make sure that lazy properties
|
||||
// have access to the fiber (and thereby the service hub)
|
||||
@ -553,7 +546,7 @@ class MultiThreadedStateMachineManager(
|
||||
val frozenFlowLogic = (flowLogic as FlowLogic<*>).serialize(context = checkpointSerializationContext!!)
|
||||
|
||||
val flowCorDappVersion = FlowStateMachineImpl.createSubFlowVersion(serviceHub.cordappProvider.getCordappForFlow(flowLogic), serviceHub.myInfo.platformVersion)
|
||||
val initialCheckpoint = Checkpoint.create(invocationContext, flowStart, flowLogic.javaClass, frozenFlowLogic, ourIdentity, deduplicationSeed, flowCorDappVersion).getOrThrow()
|
||||
val initialCheckpoint = Checkpoint.create(invocationContext, flowStart, flowLogic.javaClass, frozenFlowLogic, ourIdentity, flowCorDappVersion).getOrThrow()
|
||||
val startedFuture = openFuture<Unit>()
|
||||
val initialState = StateMachineState(
|
||||
checkpoint = initialCheckpoint,
|
||||
@ -721,7 +714,7 @@ class MultiThreadedStateMachineManager(
|
||||
private fun addAndStartFlow(id: StateMachineRunId, flow: Flow) {
|
||||
val checkpoint = flow.fiber.snapshot().checkpoint
|
||||
for (sessionId in getFlowSessionIds(checkpoint)) {
|
||||
sessionToFlow.put(sessionId, id)
|
||||
sessionToFlow[sessionId] = id
|
||||
}
|
||||
concurrentBox.concurrent {
|
||||
val oldFlow = flows.put(id, flow)
|
||||
|
@ -246,7 +246,6 @@ class RunOnceServiceTest {
|
||||
assertEquals('X', result.id)
|
||||
assertEquals("machine1", result.machineName)
|
||||
assertEquals("123", result.pid)
|
||||
assertTrue(result.timestamp is LocalDateTime)
|
||||
return result
|
||||
}
|
||||
|
||||
@ -256,7 +255,6 @@ class RunOnceServiceTest {
|
||||
assertEquals('X', result.id)
|
||||
assertEquals("machine2", result.machineName)
|
||||
assertEquals("789", result.pid)
|
||||
assertTrue(result.timestamp is LocalDateTime)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import net.corda.testing.node.MockServices
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.lang.reflect.Method
|
||||
import java.math.BigInteger
|
||||
import java.net.URL
|
||||
import javax.persistence.*
|
||||
@ -32,7 +33,6 @@ import java.net.URLClassLoader
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
class SchemaMigrationTest {
|
||||
|
||||
@Test
|
||||
@ -82,7 +82,7 @@ class SchemaMigrationTest {
|
||||
|
||||
// check that the file was picked up
|
||||
val nrOfChangesOnDiscoveredFile = db.dataSource.connection.use {
|
||||
it.createStatement().executeQuery("select count(*) from DATABASECHANGELOG where filename ='migration/${fileName}'").use { rs ->
|
||||
it.createStatement().executeQuery("select count(*) from DATABASECHANGELOG where filename ='migration/$fileName'").use { rs ->
|
||||
rs.next()
|
||||
rs.getInt(1)
|
||||
}
|
||||
@ -102,9 +102,11 @@ class SchemaMigrationTest {
|
||||
}
|
||||
|
||||
//hacky way to add a folder to the classpath
|
||||
fun addToClassPath(file: Path) = URLClassLoader::class.java.getDeclaredMethod("addURL", URL::class.java).apply {
|
||||
isAccessible = true
|
||||
invoke(ClassLoader.getSystemClassLoader(), file.toFile().toURL())
|
||||
private fun addToClassPath(file: Path): Method {
|
||||
return URLClassLoader::class.java.getDeclaredMethod("addURL", URL::class.java).apply {
|
||||
isAccessible = true
|
||||
invoke(ClassLoader.getSystemClassLoader(), file.toUri().toURL())
|
||||
}
|
||||
}
|
||||
|
||||
object DummyTestSchema
|
||||
@ -116,9 +118,9 @@ class SchemaMigrationTest {
|
||||
|
||||
@ElementCollection
|
||||
@Column(name = "participants")
|
||||
@CollectionTable(name = "dummy_test_states_parts", joinColumns = arrayOf(
|
||||
@CollectionTable(name = "dummy_test_states_parts", joinColumns = [
|
||||
JoinColumn(name = "output_index", referencedColumnName = "output_index"),
|
||||
JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")))
|
||||
JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")])
|
||||
override var participants: MutableSet<AbstractParty>? = null,
|
||||
|
||||
@Transient
|
||||
|
@ -40,7 +40,6 @@ class LinearStateBatchNotariseContract : Contract {
|
||||
}
|
||||
|
||||
override fun verify(tx: LedgerTransaction) {
|
||||
val command = tx.commands.requireSingleCommand<Commands>()
|
||||
val timeWindow: TimeWindow? = tx.timeWindow
|
||||
tx.commands.requireSingleCommand<Commands>()
|
||||
}
|
||||
}
|
||||
|
@ -230,27 +230,6 @@ abstract class OnLedgerAsset<T : Any, C : CommandData, S : FungibleAsset<T>> : C
|
||||
return Pair(gathered, gatheredAmount)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an transaction exiting fungible assets from the ledger.
|
||||
*
|
||||
* @param tx transaction builder to add states and commands to.
|
||||
* @param amountIssued the amount to be exited, represented as a quantity of issued currency.
|
||||
* @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is
|
||||
* the responsibility of the caller to check that they do not attempt to exit funds held by others.
|
||||
* @return the public keys which must sign the transaction for it to be valid.
|
||||
*/
|
||||
@Throws(InsufficientBalanceException::class)
|
||||
@JvmStatic
|
||||
@Deprecated("Replaced with generateExit() which takes in a party to pay change to")
|
||||
fun <S : FungibleAsset<T>, T: Any> generateExit(tx: TransactionBuilder, amountIssued: Amount<Issued<T>>,
|
||||
assetStates: List<StateAndRef<S>>,
|
||||
deriveState: (TransactionState<S>, Amount<Issued<T>>, AbstractParty) -> TransactionState<S>,
|
||||
generateMoveCommand: () -> CommandData,
|
||||
generateExitCommand: (Amount<Issued<T>>) -> CommandData): Set<PublicKey> {
|
||||
val owner = assetStates.map { it.state.data.owner }.toSet().firstOrNull() ?: throw InsufficientBalanceException(amountIssued)
|
||||
return generateExit(tx, amountIssued, assetStates, owner, deriveState, generateMoveCommand, generateExitCommand)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an transaction exiting fungible assets from the ledger.
|
||||
*
|
||||
@ -323,31 +302,6 @@ abstract class OnLedgerAsset<T : Any, C : CommandData, S : FungibleAsset<T>> : C
|
||||
|
||||
abstract fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): Collection<CommandWithParties<C>>
|
||||
|
||||
/**
|
||||
* Generate an transaction exiting assets from the ledger.
|
||||
*
|
||||
* @param tx transaction builder to add states and commands to.
|
||||
* @param amountIssued the amount to be exited, represented as a quantity of issued currency.
|
||||
* @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is
|
||||
* the responsibility of the caller to check that they do not exit funds held by others.
|
||||
* @param payChangeTo party to pay any change to; this is normally a confidential identity of the calling
|
||||
* party.
|
||||
* @return the public keys which must sign the transaction for it to be valid.
|
||||
*/
|
||||
@Throws(InsufficientBalanceException::class)
|
||||
@Deprecated("Replaced with generateExit() which takes in a party to pay change to")
|
||||
fun generateExit(tx: TransactionBuilder, amountIssued: Amount<Issued<T>>,
|
||||
assetStates: List<StateAndRef<S>>): Set<PublicKey> {
|
||||
return generateExit(
|
||||
tx,
|
||||
amountIssued,
|
||||
assetStates,
|
||||
deriveState = { state, amount, owner -> deriveState(state, amount, owner) },
|
||||
generateMoveCommand = { -> generateMoveCommand() },
|
||||
generateExitCommand = { amount -> generateExitCommand(amount) }
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an transaction exiting assets from the ledger.
|
||||
*
|
||||
@ -367,8 +321,8 @@ abstract class OnLedgerAsset<T : Any, C : CommandData, S : FungibleAsset<T>> : C
|
||||
assetStates,
|
||||
payChangeTo,
|
||||
deriveState = { state, amount, owner -> deriveState(state, amount, owner) },
|
||||
generateMoveCommand = { -> generateMoveCommand() },
|
||||
generateExitCommand = { amount -> generateExitCommand(amount) }
|
||||
generateMoveCommand = { generateMoveCommand() },
|
||||
generateExitCommand = { generateExitCommand(it) }
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -14,22 +14,18 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.contracts.TransactionState
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.StatesNotAvailableException
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.utilities.*
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import java.sql.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
/**
|
||||
* Pluggable interface to allow for different cash selection provider implementations
|
||||
@ -41,17 +37,17 @@ import kotlin.concurrent.withLock
|
||||
abstract class AbstractCashSelection(private val maxRetries: Int = 8, private val retrySleep: Int = 100,
|
||||
private val retryCap: Int = 2000) {
|
||||
companion object {
|
||||
val instance = AtomicReference<AbstractCashSelection>()
|
||||
private val instance = AtomicReference<AbstractCashSelection>()
|
||||
|
||||
fun getInstance(metadata: () -> java.sql.DatabaseMetaData): AbstractCashSelection {
|
||||
return instance.get() ?: {
|
||||
val _metadata = metadata()
|
||||
val metadataResult = metadata()
|
||||
val cashSelectionAlgos = ServiceLoader.load(AbstractCashSelection::class.java).toList()
|
||||
val cashSelectionAlgo = cashSelectionAlgos.firstOrNull { it.isCompatible(_metadata) }
|
||||
val cashSelectionAlgo = cashSelectionAlgos.firstOrNull { it.isCompatible(metadataResult) }
|
||||
cashSelectionAlgo?.let {
|
||||
instance.set(cashSelectionAlgo)
|
||||
cashSelectionAlgo
|
||||
} ?: throw ClassNotFoundException("\nUnable to load compatible cash selection algorithm implementation for JDBC driver ($_metadata)." +
|
||||
} ?: throw ClassNotFoundException("\nUnable to load compatible cash selection algorithm implementation for JDBC driver ($metadataResult)." +
|
||||
"\nPlease specify an implementation in META-INF/services/${AbstractCashSelection::class.java}")
|
||||
}.invoke()
|
||||
}
|
||||
@ -84,7 +80,7 @@ abstract class AbstractCashSelection(private val maxRetries: Int = 8, private va
|
||||
abstract fun executeQuery(connection: Connection, amount: Amount<Currency>, lockId: UUID, notary: Party?,
|
||||
onlyFromIssuerParties: Set<AbstractParty>, withIssuerRefs: Set<OpaqueBytes>, withResultSet: (ResultSet) -> Boolean): Boolean
|
||||
|
||||
override abstract fun toString(): String
|
||||
abstract override fun toString(): String
|
||||
|
||||
/**
|
||||
* Query to gather Cash states that are available and retry if they are temporarily unavailable.
|
||||
@ -149,7 +145,7 @@ abstract class AbstractCashSelection(private val maxRetries: Int = 8, private va
|
||||
|
||||
if (stateRefs.isNotEmpty()) {
|
||||
// TODO: future implementation to retrieve contract states from a Vault BLOB store
|
||||
stateAndRefs.addAll(services.loadStates(stateRefs) as Collection<StateAndRef<Cash.State>>)
|
||||
stateAndRefs.addAll(uncheckedCast(services.loadStates(stateRefs)))
|
||||
}
|
||||
|
||||
val success = stateAndRefs.isNotEmpty() && totalPennies >= amount.quantity
|
||||
|
@ -13,6 +13,9 @@ package com.r3.corda.enterprise.perftestcordapp.flows
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.cash.selection.AbstractCashSelection
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.issuedBy
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.InsufficientBalanceException
|
||||
@ -60,10 +63,13 @@ class CashExitFlow(private val amount: Amount<Currency>,
|
||||
.getInstance { serviceHub.jdbcSession().metaData }
|
||||
.unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
|
||||
val signers = try {
|
||||
val changeOwner = exitStates.map { it.state.data.owner }.toSet().firstOrNull() ?: throw InsufficientBalanceException(amount)
|
||||
Cash().generateExit(
|
||||
builder,
|
||||
amount.issuedBy(issuer),
|
||||
exitStates)
|
||||
exitStates,
|
||||
changeOwner
|
||||
)
|
||||
} catch (e: InsufficientBalanceException) {
|
||||
throw CashException("Exiting more cash than exists", e)
|
||||
}
|
||||
|
@ -14,6 +14,10 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
|
||||
import net.corda.confidential.SwapIdentitiesFlow
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.flows.FlowException
|
||||
@ -23,6 +27,7 @@ import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
@ -54,7 +59,7 @@ class CashIssueAndDoublePayment(val amount: Amount<Currency>,
|
||||
= txState.copy(data = txState.data.copy(amount = amt, owner = owner))
|
||||
|
||||
val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary))
|
||||
val cashStateAndRef = serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single() as StateAndRef<Cash.State>
|
||||
val cashStateAndRef: StateAndRef<Cash.State> = uncheckedCast(serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single())
|
||||
|
||||
progressTracker.currentStep = GENERATING_ID
|
||||
val txIdentities = if (anonymous) {
|
||||
@ -86,7 +91,7 @@ class CashIssueAndDoublePayment(val amount: Amount<Currency>,
|
||||
progressTracker.currentStep = FINALISING_TX
|
||||
val notarised1 = finaliseTx(tx1, setOf(recipient), "Unable to notarise spend first time")
|
||||
try {
|
||||
val notarised2 = finaliseTx(tx2, setOf(recipient), "Unable to notarise spend second time")
|
||||
finaliseTx(tx2, setOf(recipient), "Unable to notarise spend second time")
|
||||
} catch (expected: CashException) {
|
||||
val cause = expected.cause
|
||||
if (cause is NotaryException) {
|
||||
|
@ -14,12 +14,17 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
|
||||
import net.corda.confidential.SwapIdentitiesFlow
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
@ -51,7 +56,7 @@ class CashIssueAndDuplicatePayment(val amount: Amount<Currency>,
|
||||
= txState.copy(data = txState.data.copy(amount = amt, owner = owner))
|
||||
|
||||
val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary))
|
||||
val cashStateAndRef = serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single() as StateAndRef<Cash.State>
|
||||
val cashStateAndRef: StateAndRef<Cash.State> = uncheckedCast(serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single())
|
||||
|
||||
progressTracker.currentStep = GENERATING_ID
|
||||
val txIdentities = if (anonymous) {
|
||||
@ -74,7 +79,7 @@ class CashIssueAndDuplicatePayment(val amount: Amount<Currency>,
|
||||
val tx = serviceHub.signInitialTransaction(spendTx, keysForSigning)
|
||||
|
||||
progressTracker.currentStep = FINALISING_TX
|
||||
val notarised1 = finaliseTx(tx, setOf(recipient), "Unable to notarise spend first time")
|
||||
finaliseTx(tx, setOf(recipient), "Unable to notarise spend first time")
|
||||
val notarised2 = finaliseTx(tx, setOf(recipient), "Unable to notarise spend second time")
|
||||
|
||||
return Result(notarised2.id, recipient)
|
||||
|
@ -14,12 +14,17 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
|
||||
import net.corda.confidential.SwapIdentitiesFlow
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
@ -51,7 +56,7 @@ class CashIssueAndPaymentNoSelection(val amount: Amount<Currency>,
|
||||
|
||||
progressTracker.currentStep = GENERATING_TX
|
||||
val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary))
|
||||
val cashStateAndRef = serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single() as StateAndRef<Cash.State>
|
||||
val cashStateAndRef: StateAndRef<Cash.State> = uncheckedCast(serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single())
|
||||
|
||||
progressTracker.currentStep = GENERATING_ID
|
||||
val txIdentities = if (anonymous) {
|
||||
|
@ -12,6 +12,9 @@ package com.r3.corda.enterprise.perftestcordapp.flows
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.issuedBy
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
|
@ -12,6 +12,10 @@ package com.r3.corda.enterprise.perftestcordapp.flows
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
|
||||
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
|
||||
import net.corda.confidential.SwapIdentitiesFlow
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.InsufficientBalanceException
|
||||
|
@ -104,8 +104,7 @@ class LinearStateBatchNotariseFlow(private val notary: Party,
|
||||
}
|
||||
builder.addCommand(LinearStateBatchNotariseContract.Commands.Evolve(), us.owningKey)
|
||||
builder.setTimeWindow(TimeWindow.fromOnly(serviceHub.clock.instant()))
|
||||
val tx = serviceHub.signInitialTransaction(builder, us.owningKey)
|
||||
return tx
|
||||
return serviceHub.signInitialTransaction(builder, us.owningKey)
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
@ -117,17 +116,16 @@ class LinearStateBatchNotariseFlow(private val notary: Party,
|
||||
@Suspendable
|
||||
private fun assembleInitialTx(us: Party): SignedTransaction {
|
||||
val builder = TransactionBuilder(notary)
|
||||
(0 until n).forEach { outputIndex ->
|
||||
(0 until n).forEach {
|
||||
builder.addOutputState(TransactionState(LinearStateBatchNotariseContract.State(UniqueIdentifier(), us, serviceHub.clock.instant()), LinearStateBatchNotariseContract.CP_PROGRAM_ID, notary))
|
||||
}
|
||||
builder.addCommand(LinearStateBatchNotariseContract.Commands.Create(), us.owningKey)
|
||||
builder.setTimeWindow(TimeWindow.fromOnly(serviceHub.clock.instant()))
|
||||
val tx = serviceHub.signInitialTransaction(builder, us.owningKey)
|
||||
return tx
|
||||
return serviceHub.signInitialTransaction(builder, us.owningKey)
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
protected fun finaliseTx(tx: SignedTransaction, message: String): SignedTransaction {
|
||||
private fun finaliseTx(tx: SignedTransaction, message: String): SignedTransaction {
|
||||
try {
|
||||
return subFlow(FinalityFlow(tx))
|
||||
} catch (e: NotaryException) {
|
||||
|
@ -11,9 +11,6 @@
|
||||
package net.corda.testing.node
|
||||
|
||||
import com.google.common.collect.MutableClassToInstanceMap
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.typesafe.config.ConfigParseOptions
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.cordapp.CordappProvider
|
||||
@ -34,9 +31,6 @@ import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.internal.ServicesForResolutionImpl
|
||||
import net.corda.node.internal.configureDatabase
|
||||
import net.corda.node.internal.cordapp.CordappLoader
|
||||
import net.corda.node.services.api.SchemaService
|
||||
import net.corda.node.services.api.VaultServiceInternal
|
||||
import net.corda.node.services.api.WritableTransactionStorage
|
||||
import net.corda.node.services.api.*
|
||||
import net.corda.node.services.identity.InMemoryIdentityService
|
||||
import net.corda.node.services.schema.HibernateObserver
|
||||
@ -89,7 +83,7 @@ open class MockServices private constructor(
|
||||
*/
|
||||
@JvmStatic
|
||||
fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().toString()): Properties {
|
||||
return makeTestDataSourceProperties(nodeName, null, ::databaseProviderDataSourceConfig, ::inMemoryH2DataSourceConfig)
|
||||
return makeInternalTestDataSourceProperties(nodeName)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +103,7 @@ open class MockServices private constructor(
|
||||
networkParameters: NetworkParameters = testNetworkParameters(),
|
||||
vararg moreKeys: KeyPair): Pair<CordaPersistence, MockServices> {
|
||||
val cordappLoader = CordappLoader.createWithTestPackages(cordappPackages)
|
||||
val dataSourceProps = makeTestDataSourceProperties(initialIdentity.name.organisation, SecureHash.randomSHA256().toString())
|
||||
val dataSourceProps = makeInternalTestDataSourceProperties(initialIdentity.name.organisation, SecureHash.randomSHA256().toString())
|
||||
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas)
|
||||
val database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(initialIdentity.name.organisation), identityService::wellKnownPartyFromX500Name, identityService::wellKnownPartyFromAnonymous, schemaService)
|
||||
val mockService = database.transaction {
|
||||
|
@ -383,7 +383,7 @@ open class InternalMockNetwork(private val cordappPackages: List<String>,
|
||||
val config = mockNodeConfiguration().also {
|
||||
doReturn(baseDirectory(id).createDirectories()).whenever(it).baseDirectory
|
||||
doReturn(parameters.legalName ?: CordaX500Name("Mock Company $id", "London", "GB")).whenever(it).myLegalName
|
||||
doReturn(makeTestDataSourceProperties("node_$id","net_$networkId")).whenever(it).dataSourceProperties
|
||||
doReturn(makeInternalTestDataSourceProperties("node_$id", "net_$networkId")).whenever(it).dataSourceProperties
|
||||
doReturn(makeTestDatabaseProperties("node_$id")).whenever(it).database
|
||||
doReturn(emptyList<SecureHash>()).whenever(it).extraNetworkMapKeys
|
||||
parameters.configOverrides(it)
|
||||
|
@ -146,16 +146,16 @@ internal interface InternalMockMessagingService : MessagingService {
|
||||
* @param nodeName Reflects the "instance" of the in-memory database or database username/schema.
|
||||
* Defaults to a random string. Passed to [configSupplier] and [fallBackConfigSupplier] methods.
|
||||
* @param nodeNameExtension Provides additional name extension for [configSupplier] and [fallBackConfigSupplier].
|
||||
* @param configSupplier Returns [Config] with dataSourceProperties, invoked with [nodeName] and [nodeNameExtension] parameters.
|
||||
* @param configSupplier Returns [Config] with dataSourceProperties, invoked with [nodeName].
|
||||
* Defaults to configuration created when 'databaseProvider' system property is set.
|
||||
* @param fallBackConfigSupplier Returns [Config] with dataSourceProperties, invoked with [nodeName] and [nodeNameExtension] parameters.
|
||||
* Defaults to configuration of in-memory H2 instance.
|
||||
*/
|
||||
fun makeTestDataSourceProperties(nodeName: String? = SecureHash.randomSHA256().toString(),
|
||||
nodeNameExtension: String? = null,
|
||||
configSupplier: (String?, String?) -> Config = ::databaseProviderDataSourceConfig,
|
||||
fallBackConfigSupplier: (String?, String?) -> Config = ::inMemoryH2DataSourceConfig): Properties {
|
||||
val config = configSupplier(nodeName, nodeNameExtension)
|
||||
fun makeInternalTestDataSourceProperties(nodeName: String? = SecureHash.randomSHA256().toString(),
|
||||
nodeNameExtension: String? = null,
|
||||
configSupplier: (String?) -> Config = ::databaseProviderDataSourceConfig,
|
||||
fallBackConfigSupplier: (String?, String?) -> Config = ::inMemoryH2DataSourceConfig): Properties {
|
||||
val config = configSupplier(nodeName)
|
||||
.withFallback(fallBackConfigSupplier(nodeName, nodeNameExtension))
|
||||
.resolve()
|
||||
|
||||
@ -175,8 +175,8 @@ fun makeTestDataSourceProperties(nodeName: String? = SecureHash.randomSHA256().t
|
||||
* @param configSupplier Returns [Config] with databaseProperties, invoked with [nodeName] parameter.
|
||||
*/
|
||||
fun makeTestDatabaseProperties(nodeName: String? = null,
|
||||
configSupplier: (String?, String?) -> Config = ::databaseProviderDataSourceConfig): DatabaseConfig {
|
||||
val config = configSupplier(nodeName, null)
|
||||
configSupplier: (String?) -> Config = ::databaseProviderDataSourceConfig): DatabaseConfig {
|
||||
val config = configSupplier(nodeName)
|
||||
val transactionIsolationLevel = if (config.hasPath(DatabaseConstants.TRANSACTION_ISOLATION_LEVEL))
|
||||
TransactionIsolationLevel.valueOf(config.getString(DatabaseConstants.TRANSACTION_ISOLATION_LEVEL))
|
||||
else TransactionIsolationLevel.READ_COMMITTED
|
||||
@ -188,11 +188,9 @@ fun makeTestDatabaseProperties(nodeName: String? = null,
|
||||
* Reads database and dataSource configuration from a file denoted by 'databaseProvider' system property,
|
||||
* overwritten by system properties and defaults to H2 in memory db.
|
||||
* @param nodeName Reflects the "instance" of the database username/schema, the value will be used to replace ${custom.nodeOrganizationName} placeholder
|
||||
* @param notUsed Not uses, required for API backward compatibility.
|
||||
* if the placeholder is present in config.
|
||||
*/
|
||||
fun databaseProviderDataSourceConfig(nodeName: String? = null, notUsed: String? = null): Config {
|
||||
|
||||
fun databaseProviderDataSourceConfig(nodeName: String? = null): Config {
|
||||
val parseOptions = ConfigParseOptions.defaults()
|
||||
|
||||
val keys = listOf(DatabaseConstants.DATA_SOURCE_URL, DatabaseConstants.DATA_SOURCE_CLASSNAME,
|
||||
@ -218,11 +216,11 @@ fun databaseProviderDataSourceConfig(nodeName: String? = null, notUsed: String?
|
||||
|
||||
/**
|
||||
* Creates data source configuration for in memory H2 as it would be specified in reference.conf 'datasource' snippet.
|
||||
* @param nodeName Reflects the "instance" of the database username/schema
|
||||
* @param providedNodeName Reflects the "instance" of the database username/schema
|
||||
* @param postfix Additional postix added to database "instance" name to add uniqueness when running integration tests.
|
||||
*/
|
||||
fun inMemoryH2DataSourceConfig(nodeName: String? = null, postfix: String? = null) : Config {
|
||||
val nodeName = nodeName ?: SecureHash.randomSHA256().toString()
|
||||
fun inMemoryH2DataSourceConfig(providedNodeName: String? = null, postfix: String? = null) : Config {
|
||||
val nodeName = providedNodeName ?: SecureHash.randomSHA256().toString()
|
||||
val h2InstanceName = if (postfix != null) nodeName + "_" + postfix else nodeName
|
||||
|
||||
return ConfigFactory.parseMap(mapOf(
|
||||
|
@ -12,6 +12,7 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.concurrent.doneFuture
|
||||
import net.corda.core.internal.openHttpConnection
|
||||
import net.corda.core.internal.responseAs
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
@ -29,7 +30,6 @@ import java.time.Instant
|
||||
import javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM
|
||||
|
||||
class CordaRPCProxyClient(private val targetHostAndPort: NetworkHostAndPort) : CordaRPCOps {
|
||||
|
||||
companion object {
|
||||
val log = contextLogger()
|
||||
}
|
||||
@ -47,7 +47,7 @@ class CordaRPCProxyClient(private val targetHostAndPort: NetworkHostAndPort) : C
|
||||
log.info("Corda RPC Proxy client calling: $flowName with values: $argList")
|
||||
val response = doPost<Any>(targetHostAndPort, "start-flow", argList.serialize().bytes)
|
||||
val result = doneFuture(response)
|
||||
return FlowHandleImpl(StateMachineRunId.createRandom(), result) as FlowHandle<T>
|
||||
return uncheckedCast(FlowHandleImpl(StateMachineRunId.createRandom(), result))
|
||||
}
|
||||
|
||||
override fun nodeInfo(): NodeInfo {
|
||||
|
@ -25,6 +25,7 @@ import javax.ws.rs.core.MediaType
|
||||
import javax.ws.rs.core.Response
|
||||
import javax.ws.rs.core.Response.status
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Path(RPC_PROXY_PATH)
|
||||
class RPCProxyWebService(targetHostAndPort: NetworkHostAndPort) {
|
||||
|
||||
@ -108,7 +109,7 @@ class RPCProxyWebService(targetHostAndPort: NetworkHostAndPort) {
|
||||
fun vaultQuery(input: InputStream): Response {
|
||||
log.info("vaultQuery")
|
||||
val contractStateType = input.readBytes().deserialize<String>()
|
||||
val clazz = Class.forName(contractStateType) as Class<ContractState>
|
||||
val clazz = Class.forName(contractStateType).asSubclass(ContractState::class.java)
|
||||
return use {
|
||||
log.info("Calling vaultQuery with: $clazz")
|
||||
it.vaultQuery(clazz)
|
||||
@ -125,7 +126,7 @@ class RPCProxyWebService(targetHostAndPort: NetworkHostAndPort) {
|
||||
for (i in argsList.indices) {
|
||||
log.info("$i: ${argsList[i]}")
|
||||
}
|
||||
val flowClass = Class.forName(argsList[0] as String) as Class<FlowLogic<*>>
|
||||
val flowClass = Class.forName(argsList[0] as String).asSubclass(FlowLogic::class.java)
|
||||
val flowArgs = argsList.drop(1).toTypedArray()
|
||||
log.info("Calling flow: $flowClass with arguments: ${flowArgs.asList()}")
|
||||
rpcClient.startFlowDynamic(flowClass, *flowArgs).returnValue.getOrThrow()
|
||||
|
@ -176,7 +176,7 @@ private fun handleCommand(options: OptionSet, baseDirectory: Path, configFile: P
|
||||
options.has(DRY_RUN) -> {
|
||||
val writer = getMigrationOutput(baseDirectory, options)
|
||||
migrationLogger.info("Exporting the current db migrations ...")
|
||||
runMigrationCommand { migration, dataSource ->
|
||||
runMigrationCommand { migration, _ ->
|
||||
migration.generateMigrationScript(writer)
|
||||
}
|
||||
}
|
||||
@ -240,7 +240,7 @@ private fun runWithDataSource(config: Configuration, baseDirectory: Path, classL
|
||||
val jarDirs = config.jarDirs.map { Paths.get(it) }
|
||||
for (jarDir in jarDirs) {
|
||||
if (!jarDir.exists()) {
|
||||
errorAndExit("Could not find the configured JDBC driver directory: '${jarDir}'.")
|
||||
errorAndExit("Could not find the configured JDBC driver directory: '$jarDir'.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,7 +252,7 @@ private fun runWithDataSource(config: Configuration, baseDirectory: Path, classL
|
||||
errorAndExit("""Failed to create datasource.
|
||||
|Please check that the correct JDBC driver is installed in one of the following folders:
|
||||
|${(driversFolder + jarDirs).joinToString("\n\t - ", "\t - ")}
|
||||
|Caused By ${e}""".trimMargin(), e)
|
||||
|Caused By $e""".trimMargin(), e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ class TransactionViewer : CordaView("Transactions") {
|
||||
}
|
||||
override fun computeValue(): SecureHash {
|
||||
return if (hashList.isEmpty()) SecureHash.zeroHash
|
||||
else hashList.fold(hashList[0], { one, another -> one.hashConcat(another) })
|
||||
else hashList.fold(hashList[0], SecureHash::hashConcat)
|
||||
}
|
||||
}
|
||||
graphicProperty().bind(hashBinding.map { identicon(it, 30.0) })
|
||||
@ -325,7 +325,7 @@ class TransactionViewer : CordaView("Transactions") {
|
||||
}
|
||||
}
|
||||
is IOUState -> {
|
||||
fun Pane.partyLabel(party: Party) = label(party.nameOrNull().let { PartyNameFormatter.short.format(it) } ?: "Anonymous") {
|
||||
fun Pane.partyLabel(party: Party) = label(party.nameOrNull().let { PartyNameFormatter.short.format(it) }) {
|
||||
tooltip(party.owningKey.toBase58String())
|
||||
}
|
||||
row {
|
||||
@ -363,8 +363,7 @@ private fun calculateTotalEquiv(myIdentity: Party?,
|
||||
outputs: List<ContractState>): AmountDiff<Currency> {
|
||||
val (reportingCurrency, exchange) = reportingCurrencyExchange
|
||||
fun List<ContractState>.sum(): Long {
|
||||
val cashSum: Long = map { it as? Cash.State }
|
||||
.filterNotNull()
|
||||
val cashSum: Long = mapNotNull { it as? Cash.State }
|
||||
.filter { it.owner.owningKey.toKnownParty().value == myIdentity }
|
||||
.map { exchange(it.amount.withoutIssuer()).quantity }
|
||||
.sum()
|
||||
|
@ -16,7 +16,7 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.internal.LazyPool
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import org.apache.jmeter.config.Argument
|
||||
import org.apache.jmeter.config.Arguments
|
||||
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient
|
||||
@ -27,7 +27,7 @@ import java.util.*
|
||||
/**
|
||||
* Do most of the work for firing flow start requests via RPC at a Corda node.
|
||||
*/
|
||||
abstract class BaseFlowSampler() : AbstractJavaSamplerClient() {
|
||||
abstract class BaseFlowSampler : AbstractJavaSamplerClient() {
|
||||
companion object {
|
||||
private data class RPCParams(val address: NetworkHostAndPort, val user: String, val password: String)
|
||||
private data class RPCClient(val rpcClient: CordaRPCClient, val rpcConnection: CordaRPCConnection, val ops: CordaRPCOps)
|
||||
@ -40,7 +40,7 @@ abstract class BaseFlowSampler() : AbstractJavaSamplerClient() {
|
||||
|
||||
val allArgs = setOf(label, host, port, username, password)
|
||||
|
||||
val log = loggerFor<BaseFlowSampler>()
|
||||
val log = contextLogger()
|
||||
|
||||
private val rpcClientPools = Collections.synchronizedMap(mutableMapOf<RPCParams, LazyPool<RPCClient>>())
|
||||
}
|
||||
@ -48,7 +48,7 @@ abstract class BaseFlowSampler() : AbstractJavaSamplerClient() {
|
||||
private var rpcParams: RPCParams? = null
|
||||
private var rpcPool: LazyPool<RPCClient>? = null
|
||||
|
||||
var labelValue: String? = null
|
||||
private var labelValue: String? = null
|
||||
|
||||
override fun getDefaultParameters(): Arguments {
|
||||
// Add copies of all args, since they seem to be mutable.
|
||||
@ -70,7 +70,7 @@ abstract class BaseFlowSampler() : AbstractJavaSamplerClient() {
|
||||
labelValue = null
|
||||
}
|
||||
rpcPool = rpcClientPools.computeIfAbsent(rpcParams) {
|
||||
LazyPool<RPCClient> {
|
||||
LazyPool {
|
||||
val rpcClient = CordaRPCClient(it.address)
|
||||
val rpcConnection = rpcClient.start(it.user, it.password)
|
||||
val rpcProxy = rpcConnection.proxy
|
||||
@ -98,14 +98,14 @@ abstract class BaseFlowSampler() : AbstractJavaSamplerClient() {
|
||||
try {
|
||||
val flowResult = handle.returnValue.get()
|
||||
result.sampleEnd()
|
||||
return result.apply {
|
||||
result.apply {
|
||||
isSuccessful = true
|
||||
additionalFlowResponseProcessing(context, this, flowResult)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
result.sampleEnd()
|
||||
e.printStackTrace()
|
||||
return result.apply {
|
||||
result.apply {
|
||||
isSuccessful = false
|
||||
additionalFlowResponseProcessing(context, this, e)
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.notarytest.service.JDBCLoadTestFlow
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.time.Instant
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/** The number of test flows to run on each notary node */
|
||||
@ -43,7 +40,7 @@ fun main(args: Array<String>) {
|
||||
CordaRPCClient(it).start(notaryDemoUser.username, notaryDemoUser.password).use {
|
||||
println(it.proxy.nodeInfo())
|
||||
val totalTime = Stopwatch.createStarted()
|
||||
val durations = run(it.proxy, 1)
|
||||
run(it.proxy, 1)
|
||||
totalTime.stop()
|
||||
|
||||
val totalTx = TEST_RUNS * TRANSACTION_COUNT
|
||||
@ -65,13 +62,3 @@ private fun run(rpc: CordaRPCOps, inputStateCount: Int? = null): List<Long> {
|
||||
flowDuration
|
||||
}
|
||||
}
|
||||
|
||||
private fun printCSV(node: NetworkHostAndPort, durations: List<Long>, testRuns: Int, batchSize: Int) {
|
||||
val pw = PrintWriter(File("notarytest-${Instant.now()}-${node.host}${node.port}-${testRuns}x$batchSize.csv"))
|
||||
val sb = StringBuilder()
|
||||
sb.append("$testRuns, $batchSize")
|
||||
sb.append('\n')
|
||||
sb.append(durations.joinToString())
|
||||
pw.write(sb.toString())
|
||||
pw.close()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user