Merge remote-tracking branch 'open/master' into os-merge-244167d

# Conflicts:
#	docs/source/example-code/src/main/kotlin/net/corda/docs/FlowCookbook.kt
#	docs/source/example-code/src/main/kotlin/net/corda/docs/LaunchSpaceshipFlow.kt
#	docs/source/example-code/src/main/kotlin/net/corda/docs/tutorial/tearoffs/TutorialTearOffs.kt
#	docs/source/running-a-node.rst
#	experimental/behave/build.gradle
#	experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/helpers/Substeps.kt
#	experimental/kryo-hook/build.gradle
#	experimental/quasar-hook/build.gradle
#	node/src/integration-test/kotlin/net/corda/node/AuthDBTests.kt
#	node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt
#	node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java
#	node/src/test/kotlin/net/corda/node/internal/NodeTest.kt
#	node/src/test/kotlin/net/corda/node/services/messaging/ArtemisMessagingTest.kt
#	node/src/test/kotlin/net/corda/node/services/persistence/HibernateConfigurationTest.kt
#	samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt
#	samples/irs-demo/src/integration-test/kotlin/net/corda/test/spring/SpringDriver.kt
#	testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/NodeBasedTest.kt
This commit is contained in:
Shams Asari 2018-07-04 18:38:34 +01:00
commit 20a589d66d
100 changed files with 713 additions and 582 deletions

2
.idea/compiler.xml generated
View File

@ -170,6 +170,8 @@
<module name="mock_test" target="1.8" />
<module name="network-bootstrapper_main" target="1.8" />
<module name="network-bootstrapper_test" target="1.8" />
<module name="network-verifier_main" target="1.8" />
<module name="network-verifier_test" target="1.8" />
<module name="network-visualiser_main" target="1.8" />
<module name="network-visualiser_test" target="1.8" />
<module name="node-api_main" target="1.8" />

View File

@ -188,6 +188,7 @@ allprojects {
jvmTarget = "1.8"
javaParameters = true // Useful for reflection.
freeCompilerArgs = ['-Xjvm-default=compatibility']
allWarningsAsErrors = true
}
}

View File

@ -39,7 +39,6 @@ task metadata(type: ProGuardTask) {
keepattributes '*'
dontoptimize
printseeds
verbose
dontwarn 'com.sun.jna.**'
@ -47,6 +46,7 @@ task metadata(type: ProGuardTask) {
dontwarn 'org.jetbrains.kotlin.com.intellij.**'
dontwarn 'org.jetbrains.kotlin.com.google.j2objc.annotations.**'
dontwarn 'org.jetbrains.kotlin.com.google.errorprone.annotations.**'
dontnote
keep 'class org.jetbrains.kotlin.load.java.JvmAnnotationNames { *; }'
keep 'class org.jetbrains.kotlin.metadata.** { *; }', includedescriptorclasses: true
@ -68,6 +68,7 @@ task validate(type: ProGuardTask) {
verbose
dontwarn 'org.jetbrains.kotlin.com.google.errorprone.annotations.**'
dontnote
keep 'class *'
}
@ -77,5 +78,4 @@ artifacts {
}
defaultTasks "metadata"
assemble.dependsOn metadata
metadata.finalizedBy validate

View File

@ -401,6 +401,11 @@ class JacksonSupportTest(@Suppress("unused") private val name: String, factory:
testToStringSerialisation(UUID.randomUUID())
}
@Test
fun Instant() {
testToStringSerialisation(Instant.now())
}
@Test
fun `Date is treated as Instant`() {
val date = Date()

View File

@ -13,7 +13,6 @@ package net.corda.client.jfx
import net.corda.client.jfx.model.NodeMonitorModel
import net.corda.client.jfx.model.ProgressTrackingEvent
import net.corda.core.context.InvocationOrigin
import net.corda.core.contracts.Amount
import net.corda.core.contracts.ContractState
import net.corda.core.crypto.isFulfilledBy
import net.corda.core.crypto.keys
@ -32,12 +31,9 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import net.corda.finance.DOLLARS
import net.corda.finance.USD
import net.corda.finance.flows.CashExitFlow
import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.flows.CashPaymentFlow
import net.corda.node.services.Permissions.Companion.invokeRpc
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.node.services.Permissions.Companion.all
import net.corda.testing.core.*
import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.driver
@ -75,18 +71,7 @@ class NodeMonitorModelTest : IntegrationTest() {
private fun setup(runTest: () -> Unit) {
driver(DriverParameters(extraCordappPackagesToScan = listOf("net.corda.finance"))) {
val cashUser = User("user1", "test", permissions = setOf(
startFlow<CashIssueFlow>(),
startFlow<CashPaymentFlow>(),
startFlow<CashExitFlow>(),
invokeRpc(CordaRPCOps::notaryIdentities),
invokeRpc("vaultTrackBy"),
invokeRpc("vaultQueryBy"),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed),
invokeRpc(CordaRPCOps::stateMachineRecordedTransactionMappingFeed),
invokeRpc(CordaRPCOps::stateMachinesFeed),
invokeRpc(CordaRPCOps::networkMapFeed))
)
val cashUser = User("user1", "test", permissions = setOf(all()))
val aliceNodeHandle = startNode(providedName = ALICE_NAME, rpcUsers = listOf(cashUser)).getOrThrow()
aliceNode = aliceNodeHandle.nodeInfo
newNode = { nodeName -> startNode(providedName = nodeName).getOrThrow().nodeInfo }
@ -135,11 +120,7 @@ class NodeMonitorModelTest : IntegrationTest() {
@Test
fun `cash issue works end to end`() = setup {
rpc.startFlow(::CashIssueFlow,
Amount(100, USD),
OpaqueBytes(ByteArray(1, { 1 })),
notaryParty
)
rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notaryParty)
vaultUpdates.expectEvents(isStrict = false) {
sequence(

View File

@ -111,12 +111,12 @@ class NodeMonitorModel : AutoCloseable {
* TODO provide an unsubscribe mechanism
*/
fun register(nodeHostAndPort: NetworkHostAndPort, username: String, password: String) {
// `retryableStateMachineUpdatesSubject` will change it's upstream subscriber in case of RPC connection failure, this `Observable` should
// never produce an error.
// `stateMachineUpdatesSubject` will stay firmly subscribed to `retryableStateMachineUpdatesSubject`
retryableStateMachineUpdatesSubject.subscribe(stateMachineUpdatesSubject)
@Suppress("DEPRECATION")
// Proxy may change during re-connect, ensure that subject wiring accurately reacts to this activity.
proxyObservable.addListener { _, _, wrapper ->
if (wrapper != null) {

View File

@ -58,7 +58,7 @@ data class PartiallyResolvedTransaction(
return PartiallyResolvedTransaction(
transaction = transaction,
inputs = transaction.inputs.map { stateRef ->
val tx = inputTransactions.get(stateRef)
val tx = inputTransactions[stateRef]
if (tx == null) {
InputResolution.Unresolved(stateRef)
} else {
@ -74,7 +74,7 @@ data class PartiallyResolvedTransaction(
val outputCount = transaction.coreTransaction.inputs.size
val stateRefs = (0 until outputCount).map { StateRef(transaction.id, it) }
stateRefs.map { stateRef ->
val tx = inputTransactions.get(stateRef)
val tx = inputTransactions[stateRef]
if (tx == null) {
OutputResolution.Unresolved(stateRef)
} else {
@ -94,6 +94,7 @@ class TransactionDataModel {
private val collectedTransactions = transactions.recordInSequence().distinctBy { it.id }
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
@Suppress("DEPRECATION")
val partiallyResolvedTransactions = collectedTransactions.map {
PartiallyResolvedTransaction.fromSignedTransaction(it,
it.inputs.map { stateRef ->

View File

@ -84,14 +84,12 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
@Before
fun setup() {
node = startNode(ALICE_NAME, rpcUsers = listOf(rpcUser))
client = CordaRPCClient(node.internals.configuration.rpcOptions.address!!)
client = CordaRPCClient(node.internals.configuration.rpcOptions.address)
}
@Test
fun `flows draining mode can be enabled and queried`() {
asALoggerUser { rpcOps ->
val newValue = true
rpcOps.setFlowsDrainingModeEnabled(true)
@ -104,7 +102,6 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
@Test
fun `flows draining mode can be disabled and queried`() {
asALoggerUser { rpcOps ->
rpcOps.setFlowsDrainingModeEnabled(true)
val newValue = false
@ -118,7 +115,6 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
@Test
fun `node starts with flows draining mode disabled`() {
asALoggerUser { rpcOps ->
val defaultStartingMode = rpcOps.isFlowsDrainingModeEnabled()
@ -127,14 +123,12 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
}
private fun login(username: String, password: String, externalTrace: Trace? = null, impersonatedActor: Actor? = null): CordaRPCConnection {
return client.start(username, password, externalTrace, impersonatedActor)
}
private fun asALoggerUser(action: (CordaRPCOps) -> Unit) {
login(rpcUser.username, rpcUser.password).use {
action(it.proxy)
}
}
}
}

View File

@ -90,6 +90,7 @@ task predeterminise(type: ProGuardTask) {
dontpreverify
dontobfuscate
dontoptimize
dontnote
printseeds
verbose
@ -133,6 +134,7 @@ task determinise(type: ProGuardTask) {
keepattributes '*'
keepdirectories
dontobfuscate
dontnote
printseeds
verbose
@ -178,7 +180,6 @@ task checkDeterminism(type: ProGuardTask, dependsOn: jdkTask) {
defaultTasks "determinise"
determinise.finalizedBy metafix
metafix.finalizedBy checkDeterminism
assemble.dependsOn checkDeterminism
def deterministicJar = metafix.outputs.files.singleFile
artifacts {

View File

@ -18,10 +18,10 @@ import java.util.*
* A unique identifier for a single state machine run, valid across node restarts. Note that a single run always
* has at least one flow, but that flow may also invoke sub-flows: they all share the same run id.
*/
@DeleteForDJVM
@CordaSerializable
data class StateMachineRunId(val uuid: UUID) {
companion object {
@DeleteForDJVM
fun createRandom(): StateMachineRunId = StateMachineRunId(UUID.randomUUID())
}

View File

@ -11,6 +11,7 @@
package net.corda.core.internal
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.DeleteForDJVM
import net.corda.core.DoNotImplement
import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.InvocationContext
@ -20,6 +21,7 @@ import net.corda.core.node.ServiceHub
import org.slf4j.Logger
/** This is an internal interface that is implemented by code in the node module. You should look at [FlowLogic]. */
@DeleteForDJVM
@DoNotImplement
interface FlowStateMachine<FLOWRETURN> {
@Suspendable

View File

@ -12,11 +12,15 @@ package net.corda.core.node.services
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.DoNotImplement
import net.corda.core.crypto.CompositeKey
import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SignableData
import net.corda.core.crypto.TransactionSignature
import net.corda.core.identity.PartyAndCertificate
import java.security.KeyPair
import java.security.PrivateKey
import java.security.PublicKey
import java.security.cert.X509Certificate
/**
* The KMS is responsible for storing and using private keys to sign things. An implementation of this may, for example,

View File

@ -140,7 +140,7 @@ object MappedSchemaValidator {
fieldsFromOtherMappedSchema(schema) + methodsFromOtherMappedSchema(schema)
/** Returns true if [javax.persistence] annotation expect [javax.persistence.Transient] is found. */
private inline fun hasJpaAnnotation(annotations: Array<Annotation>) =
private fun hasJpaAnnotation(annotations: Array<Annotation>) =
annotations.any { annotation -> annotation.toString().startsWith("@javax.persistence.") && annotation !is javax.persistence.Transient }
class SchemaCrossReferenceReport(private val schema: String, private val entity: String, private val referencedSchema: String,

View File

@ -58,7 +58,7 @@ class WireTransaction(componentGroups: List<ComponentGroup>, val privacySalt: Pr
@DeleteForDJVM
constructor(componentGroups: List<ComponentGroup>) : this(componentGroups, PrivacySalt())
@Deprecated("Required only in some unit-tests and for backwards compatibility purposes.", ReplaceWith("WireTransaction(val componentGroups: List<ComponentGroup>, override val privacySalt: PrivacySalt)"), DeprecationLevel.WARNING)
@Deprecated("Required only for backwards compatibility purposes.", ReplaceWith("WireTransaction(val componentGroups: List<ComponentGroup>, override val privacySalt: PrivacySalt)"), DeprecationLevel.WARNING)
@DeleteForDJVM
constructor(inputs: List<StateRef>,
attachments: List<SecureHash>,

View File

@ -41,7 +41,8 @@ class ContractsDSLTests {
}
@RunWith(Parameterized::class)
class RequireSingleCommandTests(private val testFunction: (Collection<CommandWithParties<CommandData>>) -> CommandWithParties<CommandData>, description: String) {
class RequireSingleCommandTests(private val testFunction: (Collection<CommandWithParties<CommandData>>) -> CommandWithParties<CommandData>,
@Suppress("UNUSED_PARAMETER") description: String) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{1}")
@ -74,7 +75,8 @@ class ContractsDSLTests {
}
@RunWith(Parameterized::class)
class SelectWithSingleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, PublicKey?, AbstractParty?) -> Iterable<CommandWithParties<CommandData>>, description: String) {
class SelectWithSingleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, PublicKey?, AbstractParty?) -> Iterable<CommandWithParties<CommandData>>,
@Suppress("UNUSED_PARAMETER") description: String) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{1}")
@ -122,7 +124,8 @@ class ContractsDSLTests {
}
@RunWith(Parameterized::class)
class SelectWithMultipleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, Collection<PublicKey>?, Collection<Party>?) -> Iterable<CommandWithParties<CommandData>>, description: String) {
class SelectWithMultipleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, Collection<PublicKey>?, Collection<Party>?) -> Iterable<CommandWithParties<CommandData>>,
@Suppress("UNUSED_PARAMETER") description: String) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{1}")

View File

@ -30,6 +30,7 @@ import net.corda.testing.dsl.LedgerDSL
import net.corda.testing.dsl.TestLedgerDSLInterpreter
import net.corda.testing.dsl.TestTransactionDSLInterpreter
import net.corda.testing.internal.TEST_TX_TIME
import net.corda.testing.internal.createWireTransaction
import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockServices
import net.corda.testing.node.ledger
@ -274,7 +275,7 @@ class PartialMerkleTreeTest {
timeWindow: TimeWindow? = null,
attachments: List<SecureHash> = emptyList()
): WireTransaction {
return WireTransaction(
return createWireTransaction(
inputs = testTx.inputs,
attachments = attachments,
outputs = testTx.outputs,

View File

@ -67,7 +67,7 @@ class AttachmentTests {
bobNode.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
// Insert an attachment into node zero's store directly.
val id = aliceNode.database.transaction {
aliceNode.attachments.importAttachment(fakeAttachment().inputStream())
aliceNode.attachments.importAttachment(fakeAttachment().inputStream(), "test", null)
}
// Get node one to run a flow to fetch it and insert it.
@ -120,7 +120,7 @@ class AttachmentTests {
val attachment = fakeAttachment()
// Insert an attachment into node zero's store directly.
val id = aliceNode.database.transaction {
aliceNode.attachments.importAttachment(attachment.inputStream())
aliceNode.attachments.importAttachment(attachment.inputStream(), "test", null)
}
// Corrupt its store.

View File

@ -156,7 +156,7 @@ class ResolveTransactionsFlowTest {
}
// TODO: this operation should not require an explicit transaction
val id = megaCorpNode.transaction {
megaCorpNode.services.attachments.importAttachment(makeJar())
megaCorpNode.services.attachments.importAttachment(makeJar(), "test", null)
}
val stx2 = makeTransactions(withAttachment = id).second
val p = TestFlow(stx2, megaCorp)
@ -211,6 +211,7 @@ class ResolveTransactionsFlowTest {
}
}
@Suppress("unused")
@InitiatedBy(TestFlow::class)
private class TestResponseFlow(val otherSideSession: FlowSession) : FlowLogic<Void?>() {
@Suspendable

View File

@ -21,10 +21,10 @@ import rx.Observable
import java.util.*
class TopologicalSortTest {
class DummyTransaction(
class DummyTransaction constructor(
override val id: SecureHash,
override val inputs: List<StateRef>,
val numberOfOutputs: Int,
@Suppress("CanBeParameter") private val numberOfOutputs: Int,
override val notary: Party
) : CoreTransaction() {
override val outputs: List<TransactionState<ContractState>> = (1..numberOfOutputs).map {
@ -78,7 +78,7 @@ class TopologicalSortTest {
}
// Swap two random items
transactions.combine(Generator.intRange(0, N - 1), Generator.intRange(0, N - 2)) { txs, i, j ->
transactions.combine(Generator.intRange(0, N - 1), Generator.intRange(0, N - 2)) { txs, i, _ ->
val k = 0 // if (i == j) i + 1 else j
val tmp = txs[i]
txs[i] = txs[k]
@ -94,7 +94,7 @@ class TopologicalSortTest {
}
}
fun checkTopologicallyOrdered(txs: List<SignedTransaction>) {
private fun checkTopologicallyOrdered(txs: List<SignedTransaction>) {
val outputs = HashSet<StateRef>()
for (tx in txs) {
if (!outputs.containsAll(tx.inputs)) {

View File

@ -18,6 +18,7 @@ import net.corda.core.crypto.CompositeKey
import net.corda.core.identity.Party
import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.*
import net.corda.testing.internal.createWireTransaction
import net.corda.testing.internal.rigorousMock
import org.junit.Rule
import org.junit.Test
@ -63,7 +64,7 @@ class TransactionTests {
val cpub = ck.public
val c1 = CompositeKey.Builder().addKeys(apub, bpub).build(2)
val compKey = CompositeKey.Builder().addKeys(c1, cpub).build(1)
val wtx = WireTransaction(
val wtx = createWireTransaction(
inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)),
attachments = emptyList(),
outputs = emptyList(),
@ -89,7 +90,7 @@ class TransactionTests {
@Test
fun `signed transaction missing signatures`() {
val wtx = WireTransaction(
val wtx = createWireTransaction(
inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)),
attachments = emptyList(),
outputs = emptyList(),
@ -129,8 +130,8 @@ class TransactionTests {
}, DummyContract.PROGRAM_ID))
val id = SecureHash.randomSHA256()
val timeWindow: TimeWindow? = null
val privacySalt: PrivacySalt = PrivacySalt()
val transaction: LedgerTransaction = LedgerTransaction(
val privacySalt = PrivacySalt()
val transaction = LedgerTransaction(
inputs,
outputs,
commands,
@ -147,7 +148,7 @@ class TransactionTests {
@Test
fun `transaction cannot have duplicate inputs`() {
val stateRef = StateRef(SecureHash.randomSHA256(), 0)
fun buildTransaction() = WireTransaction(
fun buildTransaction() = createWireTransaction(
inputs = listOf(stateRef, stateRef),
attachments = emptyList(),
outputs = emptyList(),
@ -170,7 +171,7 @@ class TransactionTests {
val attachments = emptyList<Attachment>()
val id = SecureHash.randomSHA256()
val timeWindow: TimeWindow? = null
val privacySalt: PrivacySalt = PrivacySalt()
val privacySalt = PrivacySalt()
fun buildTransaction() = LedgerTransaction(
inputs,
outputs,
@ -188,7 +189,7 @@ class TransactionTests {
@Test
fun `transactions with identical contents must have different ids`() {
val outputState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DummyContract.PROGRAM_ID, DUMMY_NOTARY)
fun buildTransaction() = WireTransaction(
fun buildTransaction() = createWireTransaction(
inputs = emptyList(),
attachments = emptyList(),
outputs = listOf(outputState),

View File

@ -50,6 +50,7 @@ enum class PrintOrVisualise {
Visualise
}
@Suppress("DEPRECATION")
fun main(args: Array<String>) {
require(args.isNotEmpty()) { "Usage: <binary> [Print|Visualise]" }
val printOrVisualise = PrintOrVisualise.valueOf(args[0])
@ -109,6 +110,7 @@ fun main(args: Array<String>) {
}
}
// END 5
Unit
}
}

View File

@ -8,7 +8,7 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
@file:Suppress("UNUSED_VARIABLE", "unused")
@file:Suppress("UNUSED_VARIABLE", "unused", "DEPRECATION")
package net.corda.docs

View File

@ -8,6 +8,8 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
@file:Suppress("UNUSED_VARIABLE")
package net.corda.docs.tutorial.tearoffs
import net.corda.core.contracts.Command
@ -52,4 +54,4 @@ fun main(args: Array<String>) {
} catch (e: FilteredTransactionVerificationException) {
throw MerkleTreeException("Rate Fix Oracle: Couldn't verify partial Merkle tree.")
}
}
}

View File

@ -43,6 +43,27 @@ Optionally run the node's webserver as well by opening a terminal window in the
.. warning:: The node webserver is for testing purposes only and will be removed soon.
Command-line options
~~~~~~~~~~~~~~~~~~~~
The node can optionally be started with the following command-line options:
* ``--base-directory``: The node working directory where all the files are kept (default: ``.``)
* ``--bootstrap-raft-cluster``: Bootstraps Raft cluster. The node forms a single node cluster (ignoring otherwise configured peer
addresses), acting as a seed for other nodes to join the cluster
* ``--config-file``: The path to the config file (default: ``node.conf``)
* ``--help``
* ``--initial-registration``: Start initial node registration with Corda network to obtain certificate from the permissioning
server
* ``--just-generate-node-info``: Perform the node start-up task necessary to generate its nodeInfo, save it to disk, then
quit
* ``--log-to-console``: If set, prints logging to the console as well as to a file
* ``--logging-level <[ERROR,WARN,INFO, DEBUG,TRACE]>``: Enable logging at this level and higher (default: INFO)
* ``--network-root-truststore``: Network root trust store obtained from network operator
* ``--network-root-truststore-password``: Network root trust store password obtained from network operator
* ``--no-local-shell``: Do not start the embedded shell locally
* ``--sshd``: Enables SSHD server for node administration
* ``--version``: Print the version and exit
Enabling remote debugging
~~~~~~~~~~~~~~~~~~~~~~~~~
To enable remote debugging of the node, run the following from the terminal window:
@ -61,8 +82,11 @@ This command line will start the node with JMX metrics accessible via HTTP on po
See :ref:`Monitoring your node <jolokia_ref>` for further details.
Starting all nodes at once from the command line (native)
---------------------------------------------------------
Starting all nodes at once from the command line
------------------------------------------------
Native
~~~~~~
If you created your nodes using ``deployNodes``, a ``runnodes`` shell script (or batch file on Windows) will have been
generated to allow you to quickly start up all nodes and their webservers. ``runnodes`` should only be used for testing
purposes.
@ -79,8 +103,8 @@ If you receive an ``OutOfMemoryError`` exception when interacting with the nodes
Java heap memory available to them, which you can do when running them individually. See
:ref:`starting-an-individual-corda-node`.
Starting all nodes at once from the command line (docker-compose)
-----------------------------------------------------------------
docker-compose
~~~~~~~~~~~~~~
If you created your nodes using ``Dockerform``, the ``docker-compose.yml`` file and corresponding ``Dockerfile`` for
nodes has been created and configured appropriately. Navigate to ``build/nodes`` directory and run ``docker-compose up``
command. This will startup nodes inside new, internal network.

View File

@ -411,32 +411,38 @@ For more information on the client RPC interface and how to build an RPC client
Running nodes across machines
-----------------------------
The nodes can be split across different machines and configured to communicate across the network.
The nodes can be configured to communicate as a network even when distributed across several machines:
After deploying the nodes, navigate to the build folder (``kotlin-source/build/nodes``) and for each node that needs to
be moved to another machine open its config file and change the Artemis messaging address to the IP address of the machine
where the node will run (e.g. ``p2pAddress="10.18.0.166:10007"``).
* Deploy the nodes as usual:
These changes require new node-info files to be distributed amongst the nodes. Use the network bootstrapper tool
(see :doc:`network-bootstrapper` for more information on this and how to built it) to update the files and have
them distributed locally.
* Unix/Mac OSX: ``./gradlew deployNodes``
* Windows: ``gradlew.bat deployNodes``
``java -jar network-bootstrapper.jar kotlin-source/build/nodes``
* Navigate to the build folder (``kotlin-source/build/nodes``)
* For each node, open its ``node.conf`` file and change ``localhost`` in its ``p2pAddress`` to the IP address of the machine
where the node will be run (e.g. ``p2pAddress="10.18.0.166:10007"``)
* These changes require new node-info files to be distributed amongst the nodes. Use the network bootstrapper tool
(see :doc:`network-bootstrapper`) to update the files and have them distributed locally:
Once that's done move the node folders to their designated machines (e.g. using a USB key). It is important that none of the
nodes - including the notary - end up on more than one machine. Each computer should also have a copy of ``runnodes``
and ``runnodes.bat``.
``java -jar network-bootstrapper.jar kotlin-source/build/nodes``
For example, you may end up with the following layout:
* Move the node folders to their individual machines (e.g. using a USB key). It is important that none of the
nodes - including the notary - end up on more than one machine. Each computer should also have a copy of ``runnodes``
and ``runnodes.bat``.
* Machine 1: ``Notary``, ``PartyA``, ``runnodes``, ``runnodes.bat``
* Machine 2: ``PartyB``, ``PartyC``, ``runnodes``, ``runnodes.bat``
For example, you may end up with the following layout:
After starting each node, the nodes will be able to see one another and agree IOUs among themselves.
* Machine 1: ``Notary``, ``PartyA``, ``runnodes``, ``runnodes.bat``
* Machine 2: ``PartyB``, ``PartyC``, ``runnodes``, ``runnodes.bat``
.. note:: If you are using H2 and wish to use the same ``h2port`` value for all the nodes, then only assign them that
value after the nodes have been moved to their machines. The initial bootstrapping process requires access to the nodes'
databases and if they share the same H2 port then the process will fail.
* After starting each node, the nodes will be able to see one another and agree IOUs among themselves
.. warning:: The bootstrapper must be run **after** the ``node.conf`` files have been modified, but **before** the nodes
are distributed across machines. Otherwise, the nodes will not be able to communicate.
.. note:: If you are using H2 and wish to use the same ``h2port`` value for two or more nodes, you must only assign them that
value after the nodes have been moved to their individual machines. The initial bootstrapping process requires access to the
nodes' databases and if two nodes share the same H2 port, the process will fail.
Testing and debugging
---------------------

View File

@ -1,41 +1,23 @@
buildscript {
ext.kotlin_version = '1.2.40'
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.3'
classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
}
}
plugins {
id "org.jetbrains.kotlin.jvm"
id 'com.github.johnrengelman.shadow' version '2.0.3'
id 'java'
id 'application'
}
repositories {
mavenCentral()
}
apply plugin: 'kotlin'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
compile group: 'info.picocli', name: 'picocli', version: '3.0.1'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
compile "info.picocli:picocli:3.0.1"
testCompile "junit:junit:$junit_version"
}
mainClassName = "net.corda.avalanche.MainKt"
shadowJar {
baseName = "avalanche"

View File

@ -8,37 +8,18 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
buildscript {
ext.commonsio_version = '2.6'
ext.commonslogging_version = '1.2'
ext.cucumber_version = '1.2.5'
ext.crash_version = 'cce5a00f114343c1145c1d7756e1dd6df3ea984e'
ext.docker_client_version = '8.11.0'
repositories {
maven {
jcenter()
url 'https://jitpack.io'
}
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
ext {
commonsio_version = '2.6'
cucumber_version = '1.2.5'
crash_version = 'cce5a00f114343c1145c1d7756e1dd6df3ea984e'
docker_client_version = '8.11.0'
}
group 'net.corda.behave'
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'net.corda.plugins.publish-utils'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
sourceSets {
behave {
kotlin {
@ -89,6 +70,7 @@ dependencies {
compile "org.slf4j:log4j-over-slf4j:$slf4j_version"
compile "org.slf4j:jul-to-slf4j:$slf4j_version"
compile "org.slf4j:jcl-over-slf4j:$slf4j_version"
compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
compile "org.apache.logging.log4j:log4j-core:$log4j_version"
@ -96,10 +78,9 @@ dependencies {
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
// FastClasspathScanner: classpath scanning
compile 'io.github.lukehutch:fast-classpath-scanner:2.12.3'
compile "io.github.lukehutch:fast-classpath-scanner:$fast_classpath_scanner_version"
compile "commons-io:commons-io:$commonsio_version"
compile "commons-logging:commons-logging:$commonslogging_version"
compile "com.spotify:docker-client:$docker_client_version"
compile "io.reactivex:rxjava:$rxjava_version"
@ -122,14 +103,6 @@ dependencies {
behaveCompile "info.cukes:cucumber-picocontainer:$cucumber_version"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
test {
testLogging.showStandardStreams = true
}

View File

@ -13,22 +13,22 @@ 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
import org.slf4j.LoggerFactory
abstract class Substeps(protected val state: ScenarioState) {
protected val log: Logger = LoggerFactory.getLogger(javaClass)
protected val log = getLogger<Substeps>()
protected fun withNetwork(action: ScenarioState.() -> Unit) =
state.withNetwork(action)
protected fun withNetwork(action: ScenarioState.() -> Unit) = state.withNetwork(action)
protected fun <T> withClient(nodeName: String, action: ScenarioState.(CordaRPCOps) -> T): T {
return state.withClient(nodeName, {
return@withClient try {
return state.withClient(nodeName) {
try {
action(state, it)
} catch (ex: Exception) {
state.error<T>(ex.message ?: "Failed to execute RPC call")
state.error(ex.message ?: "Failed to execute RPC call")
}
})
}
}
protected fun <T> withClientProxy(nodeName: String, action: ScenarioState.(CordaRPCOps) -> T): T {
@ -40,4 +40,4 @@ abstract class Substeps(protected val state: ScenarioState) {
}
})
}
}
}

View File

@ -15,7 +15,6 @@ import org.junit.Test
import rx.observers.TestSubscriber
class CommandTests {
@Test
fun `successful command returns zero`() {
val exitCode = Command(listOf("ls", "/")).run()

View File

@ -34,7 +34,7 @@ dependencies {
compile project(':finance')
// ObjectWeb Asm: a library for synthesising and working with JVM bytecode.
compile "org.ow2.asm:asm:5.0.4"
compile "org.ow2.asm:asm:$asm_version"
compile "com.google.guava:guava:$guava_version"

View File

@ -8,33 +8,11 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
buildscript {
// For sharing constants between builds
Properties constants = new Properties()
file("$projectDir/../../constants.properties").withInputStream { constants.load(it) }
ext.kotlin_version = constants.getProperty("kotlinVersion")
ext.javaassist_version = "3.12.1.GA"
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
ext {
javaassist_version = "3.12.1.GA"
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'idea'
description 'A javaagent to allow hooking into Kryo'

View File

@ -8,33 +8,11 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
buildscript {
// For sharing constants between builds
Properties constants = new Properties()
file("$projectDir/../../constants.properties").withInputStream { constants.load(it) }
ext.kotlin_version = constants.getProperty("kotlinVersion")
ext.javaassist_version = "3.12.1.GA"
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
ext {
javaassist_version = "3.12.1.GA"
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'idea'
description 'A javaagent to allow hooking into the instrumentation by Quasar'

View File

@ -12,12 +12,12 @@ package net.corda.finance.contracts.universal
import net.corda.core.crypto.toStringShort
import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import java.math.BigDecimal
import java.security.PublicKey
import java.time.Instant
private class PrettyPrint(arr : Arrangement) {
val parties = involvedParties(arr)
private val sb = StringBuilder()
@ -26,21 +26,21 @@ private class PrettyPrint(arr : Arrangement) {
private var atStart = true
private fun print(msg: String) {
if (atStart)
repeat(indentLevel, { sb.append(' ') })
repeat(indentLevel) { sb.append(' ') }
sb.append(msg)
atStart = false
}
private fun println(message: Any?) {
if (atStart)
repeat(indentLevel, { sb.append(' ') })
repeat(indentLevel) { sb.append(' ') }
sb.appendln(message)
atStart = true
}
private fun print(msg: Any?) {
if (atStart)
repeat(indentLevel, { sb.append(' ') })
repeat(indentLevel) { sb.append(' ') }
sb.append(msg)
atStart = false
}
@ -55,8 +55,7 @@ private class PrettyPrint(arr : Arrangement) {
val partyMap = mutableMapOf<PublicKey, String>()
val usedPartyNames = mutableSetOf<String>()
fun createPartyName(party : Party) : String
{
fun createPartyName(party : Party): String {
val parts = party.name.organisation.toLowerCase().split(' ')
var camelName = parts.drop(1).fold(parts.first()) {
@ -79,38 +78,38 @@ private class PrettyPrint(arr : Arrangement) {
}
}
fun prettyPrint(per: Perceivable<Boolean>, x: Boolean? = null) {
fun prettyPrintBoolean(per: Perceivable<Boolean>) {
when (per) {
is Const -> print("\"${per.value}\"")
is PerceivableOr -> {
prettyPrint(per.left)
prettyPrintBoolean(per.left)
print(" or ")
prettyPrint(per.right)
prettyPrintBoolean(per.right)
}
is PerceivableAnd -> {
prettyPrint(per.left)
prettyPrintBoolean(per.left)
print(" and ")
prettyPrint(per.right)
prettyPrintBoolean(per.right)
}
is TimePerceivable -> {
when (per.cmp) {
Comparison.GT, Comparison.GTE -> {
print("after(")
prettyPrint(per.instant)
prettyPrintInstant(per.instant)
print(")")
}
Comparison.LT, Comparison.LTE -> {
print("before(")
prettyPrint(per.instant)
prettyPrintInstant(per.instant)
print(")")
}
}
}
is PerceivableComparison<*> -> {
when (per.type) {
BigDecimal::class.java -> prettyPrint(per.left as Perceivable<BigDecimal>)
Instant::class.java -> prettyPrint(per.left as Perceivable<Instant>)
Boolean::class.java -> prettyPrint(per.left as Perceivable<Boolean>)
BigDecimal::class.java -> prettyPrintBigDecimal(uncheckedCast(per.left))
Instant::class.java -> prettyPrintInstant(uncheckedCast(per.left))
Boolean::class.java -> prettyPrintBoolean(uncheckedCast(per.left))
}
when (per.cmp) {
Comparison.GT -> print(" > ")
@ -119,9 +118,9 @@ private class PrettyPrint(arr : Arrangement) {
Comparison.LTE -> print(" <= ")
}
when (per.type) {
BigDecimal::class.java -> prettyPrint(per.right as Perceivable<BigDecimal>)
Instant::class.java -> prettyPrint(per.right as Perceivable<Instant>)
Boolean::class.java -> prettyPrint(per.right as Perceivable<Boolean>)
BigDecimal::class.java -> prettyPrintBigDecimal(uncheckedCast(per.right))
Instant::class.java -> prettyPrintInstant(uncheckedCast(per.right))
Boolean::class.java -> prettyPrintBoolean(uncheckedCast(per.right))
}
}
is TerminalEvent -> print("TerminalEvent(${partyMap[per.reference.owningKey]}, \"${per.source}\")")
@ -130,7 +129,7 @@ private class PrettyPrint(arr : Arrangement) {
}
}
fun prettyPrint(per: Perceivable<Instant>, x: Instant? = null) {
fun prettyPrintInstant(per: Perceivable<Instant>) {
when (per) {
is Const -> print("\"${per.value}\"")
is StartDate -> print("startDate")
@ -139,34 +138,33 @@ private class PrettyPrint(arr : Arrangement) {
}
}
fun prettyPrint(per: Perceivable<BigDecimal>, x: BigDecimal? = null) {
fun prettyPrintBigDecimal(per: Perceivable<BigDecimal>) {
when (per) {
is PerceivableOperation<BigDecimal> -> {
prettyPrint(per.left)
prettyPrintBigDecimal(per.left)
when (per.op) {
Operation.PLUS -> print(" + ")
Operation.MINUS -> print(" - ")
Operation.DIV -> print(" / ")
Operation.TIMES -> print(" * ")
else -> print(per.op)
}
prettyPrint(per.right)
prettyPrintBigDecimal(per.right)
}
is UnaryPlus -> {
print("(")
prettyPrint(per.arg)
prettyPrintBigDecimal(per.arg)
print(".).plus()")
}
is Const -> print(per.value)
is Interest -> {
print("Interest(")
prettyPrint(per.amount)
prettyPrintBigDecimal(per.amount)
print(", \"${per.dayCountConvention}\", ")
prettyPrint(per.amount)
prettyPrintBigDecimal(per.amount)
print(", ")
prettyPrint(per.start)
prettyPrintInstant(per.start)
print(", ")
prettyPrint(per.end)
prettyPrintInstant(per.end)
print(")")
}
is CurrencyCross -> print("${per.foreign}/${per.domestic}")
@ -175,7 +173,6 @@ private class PrettyPrint(arr : Arrangement) {
}
fun prettyPrint(arr: Arrangement) {
when (arr) {
is Zero -> println("zero")
is RollOut -> {
@ -193,7 +190,7 @@ private class PrettyPrint(arr : Arrangement) {
is Continuation -> println("next()")
is Obligation -> {
print("${partyMap[arr.from.owningKey]}.gives( ${partyMap[arr.to.owningKey]}, ")
prettyPrint(arr.amount)
prettyPrintBigDecimal(arr.amount)
println(", ${arr.currency})")
}
is Actions -> {
@ -201,7 +198,7 @@ private class PrettyPrint(arr : Arrangement) {
indent {
for ((name, condition, arrangement) in arr.actions) {
print("\"$name\".givenThat(")
prettyPrint(condition)
prettyPrintBoolean(condition)
println(") {")
indent {
prettyPrint(arrangement)

View File

@ -46,46 +46,45 @@ class UniversalContract : Contract {
class Split(val ratio: BigDecimal) : Commands
}
fun eval(@Suppress("UNUSED_PARAMETER") tx: LedgerTransaction, expr: Perceivable<Instant>): Instant? = when (expr) {
fun evalInstant(expr: Perceivable<Instant>): Instant? = when (expr) {
is Const -> expr.value
is StartDate -> null
is EndDate -> null
else -> throw Error("Unable to evaluate")
}
fun eval(tx: LedgerTransaction, expr: Perceivable<Boolean>): Boolean = when (expr) {
is PerceivableAnd -> eval(tx, expr.left) && eval(tx, expr.right)
is PerceivableOr -> eval(tx, expr.left) || eval(tx, expr.right)
fun evalBoolean(tx: LedgerTransaction, expr: Perceivable<Boolean>): Boolean = when (expr) {
is PerceivableAnd -> evalBoolean(tx, expr.left) && evalBoolean(tx, expr.right)
is PerceivableOr -> evalBoolean(tx, expr.left) || evalBoolean(tx, expr.right)
is Const<Boolean> -> expr.value
is TimePerceivable -> when (expr.cmp) {
Comparison.LTE -> tx.timeWindow!!.fromTime!! <= eval(tx, expr.instant)
Comparison.GTE -> tx.timeWindow!!.untilTime!! >= eval(tx, expr.instant)
Comparison.LTE -> tx.timeWindow!!.fromTime!! <= evalInstant(expr.instant)
Comparison.GTE -> tx.timeWindow!!.untilTime!! >= evalInstant(expr.instant)
else -> throw NotImplementedError("eval special")
}
is ActorPerceivable -> tx.commands.single().signers.contains(expr.actor.owningKey)
else -> throw NotImplementedError("eval - Boolean - " + expr.javaClass.name)
}
fun eval(tx: LedgerTransaction, expr: Perceivable<BigDecimal>): BigDecimal =
fun evalBigDecimal(tx: LedgerTransaction, expr: Perceivable<BigDecimal>): BigDecimal =
when (expr) {
is Const<BigDecimal> -> expr.value
is UnaryPlus -> {
val x = eval(tx, expr.arg)
val x = evalBigDecimal(tx, expr.arg)
if (x > BigDecimal.ZERO)
x
else
BigDecimal.ZERO
}
is PerceivableOperation -> {
val l = eval(tx, expr.left)
val r = eval(tx, expr.right)
val l = evalBigDecimal(tx, expr.left)
val r = evalBigDecimal(tx, expr.right)
when (expr.op) {
Operation.DIV -> l / r
Operation.MINUS -> l - r
Operation.PLUS -> l + r
Operation.TIMES -> l * r
else -> throw NotImplementedError("eval - amount - operation " + expr.op)
}
}
is Fixing -> {
@ -93,8 +92,8 @@ class UniversalContract : Contract {
0.0.bd
}
is Interest -> {
val a = eval(tx, expr.amount)
val i = eval(tx, expr.interest)
val a = evalBigDecimal(tx, expr.amount)
val i = evalBigDecimal(tx, expr.interest)
//TODO
@ -105,7 +104,7 @@ class UniversalContract : Contract {
fun validateImmediateTransfers(tx: LedgerTransaction, arrangement: Arrangement): Arrangement = when (arrangement) {
is Obligation -> {
val amount = eval(tx, arrangement.amount)
val amount = evalBigDecimal(tx, arrangement.amount)
requireThat { "transferred quantity is non-negative" using (amount >= BigDecimal.ZERO) }
Obligation(const(amount), arrangement.currency, arrangement.from, arrangement.to)
}
@ -220,7 +219,7 @@ class UniversalContract : Contract {
"action must have a time-window" using (tx.timeWindow != null)
// "action must be authorized" by (cmd.signers.any { action.actors.any { party -> party.owningKey == it } })
// todo perhaps merge these two requirements?
"condition must be met" using (eval(tx, action.condition))
"condition must be met" using evalBoolean(tx, action.condition)
}
// verify that any resulting transfers can be resolved
@ -297,7 +296,7 @@ class UniversalContract : Contract {
perceivable.dayCountConvention, replaceFixing(tx, perceivable.interest, fixings, unusedFixings),
perceivable.start, perceivable.end))
is Fixing -> {
val dt = eval(tx, perceivable.date)
val dt = evalInstant(perceivable.date)
if (dt != null && fixings.containsKey(FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor))) {
unusedFixings.remove(FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor))
uncheckedCast(Const(fixings[FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor)]!!))

View File

@ -24,13 +24,12 @@ class IRS {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
val notional = 50.M
val currency = EUR
val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
private val testTxTime1: Instant = Instant.parse("2017-09-02T12:00:00.00Z")
private val notional = 50.M
private val currency = EUR
private val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
/*
@ -43,7 +42,7 @@ class IRS {
*/
val contractInitial = arrange {
private val contractInitial = arrange {
rollOut("2016-09-01".ld, "2018-09-01".ld, Frequency.Quarterly) {
actions {
(acmeCorp or highStreetBank) may {
@ -62,7 +61,8 @@ class IRS {
}
}
}
val contractAfterFixingFirst = arrange {
private val contractAfterFixingFirst = arrange {
actions {
(acmeCorp or highStreetBank) may {
val floating = interest(notional, "act/365", 1.0.bd, "2016-09-01", "2016-12-01")
@ -93,15 +93,15 @@ class IRS {
rollOut("2016-12-01".ld, "2018-09-01".ld, Frequency.Quarterly) {
actions {
(acmeCorp or highStreetBank) may {
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
val nextFloating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
val nextFixed = interest(notional, "act/365", 0.5.bd, start, end)
"pay floating" anytime {
highStreetBank.owes(acmeCorp, floating - fixed, currency)
highStreetBank.owes(acmeCorp, nextFloating - nextFixed, currency)
next()
}
"pay fixed" anytime {
highStreetBank.owes(acmeCorp, fixed - floating, currency)
highStreetBank.owes(acmeCorp, nextFixed - nextFloating, currency)
next()
}
}
@ -112,7 +112,7 @@ class IRS {
}
}
val contractAfterExecutionFirst = arrange {
private val contractAfterExecutionFirst = arrange {
rollOut("2016-12-01".ld, "2018-09-01".ld, Frequency.Quarterly) {
actions {
(acmeCorp or highStreetBank) may {
@ -132,19 +132,20 @@ class IRS {
}
}
val paymentFirst = arrange { highStreetBank.owes(acmeCorp, 250.K, EUR) }
private val paymentFirst = arrange { highStreetBank.owes(acmeCorp, 250.K, EUR) }
val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY), contractInitial)
private val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY), contractInitial)
val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterFixingFirst)
val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterExecutionFirst)
private val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterFixingFirst)
private val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterExecutionFirst)
private val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY), paymentFirst)
val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY), paymentFirst)
@Test
fun issue() {
transaction {
output(UNIVERSAL_PROGRAM_ID, stateInitial)
timeWindow(TEST_TX_TIME_1)
timeWindow(testTxTime1)
tweak {
command(acmeCorp.owningKey, UniversalContract.Commands.Issue())
@ -160,7 +161,7 @@ class IRS {
transaction {
input(UNIVERSAL_PROGRAM_ID, stateInitial)
output(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst)
timeWindow(TEST_TX_TIME_1)
timeWindow(testTxTime1)
tweak {
command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name"))
@ -200,7 +201,7 @@ class IRS {
input(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst)
output(UNIVERSAL_PROGRAM_ID, stateAfterExecutionFirst)
output(UNIVERSAL_PROGRAM_ID, statePaymentFirst)
timeWindow(TEST_TX_TIME_1)
timeWindow(testTxTime1)
tweak {
command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name"))

View File

@ -35,6 +35,8 @@ import java.util.*
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.jvmErasure
@ -42,6 +44,17 @@ import kotlin.reflect.jvm.jvmErasure
@Target(AnnotationTarget.PROPERTY)
annotation class OldConfig(val value: String)
/**
* This annotation can be used to provide ConfigParser for the class,
* the [parseAs] method will use the provided parser instead of data class constructs to parse the object.
*/
@Target(AnnotationTarget.CLASS)
annotation class CustomConfigParser(val parser: KClass<out ConfigParser<*>>)
interface ConfigParser<T> {
fun parse(config: Config): T
}
const val CUSTOM_NODE_PROPERTIES_ROOT = "custom"
// TODO Move other config parsing to use parseAs and remove this
@ -50,7 +63,10 @@ operator fun <T : Any> Config.getValue(receiver: Any, metadata: KProperty<*>): T
}
fun <T : Any> Config.parseAs(clazz: KClass<T>, onUnknownKeys: ((Set<String>, logger: Logger) -> Unit) = UnknownConfigKeysPolicy.FAIL::handle, nestedPath: String? = null): T {
require(clazz.isData) { "Only Kotlin data classes can be parsed. Offending: ${clazz.qualifiedName}" }
// Use custom parser if provided, instead of treating the object as data class.
clazz.findAnnotation<CustomConfigParser>()?.let { return uncheckedCast(it.parser.createInstance().parse(this)) }
require(clazz.isData) { "Only Kotlin data classes or class annotated with CustomConfigParser can be parsed. Offending: ${clazz.qualifiedName}" }
val constructor = clazz.primaryConstructor!!
val parameters = constructor.parameters
val parameterNames = parameters.flatMap { param ->

View File

@ -237,6 +237,36 @@ class ConfigParsingTest {
}
}
@Test
fun `parse with provided parser`() {
val type1Config = mapOf("type" to "1", "value" to "type 1 value")
val type2Config = mapOf("type" to "2", "value" to "type 2 value")
val configuration = config("values" to listOf(type1Config, type2Config))
val objects = configuration.parseAs<TestObjects>()
assertThat(objects.values).containsExactly(TestObject.Type1("type 1 value"), TestObject.Type2("type 2 value"))
}
class TestParser : ConfigParser<TestObject> {
override fun parse(config: Config): TestObject {
val type = config.getInt("type")
return when (type) {
1 -> config.parseAs<TestObject.Type1>(onUnknownKeys = UnknownConfigKeysPolicy.IGNORE::handle)
2 -> config.parseAs<TestObject.Type2>(onUnknownKeys = UnknownConfigKeysPolicy.IGNORE::handle)
else -> throw IllegalArgumentException("Unsupported Object type : '$type'")
}
}
}
data class TestObjects(val values: List<TestObject>)
@CustomConfigParser(TestParser::class)
sealed class TestObject {
data class Type1(val value: String) : TestObject()
data class Type2(val value: String) : TestObject()
}
private inline fun <reified S : SingleData<V>, reified L : ListData<V>, V : Any> testPropertyType(
value1: V,
value2: V,
@ -320,6 +350,7 @@ class ConfigParsingTest {
require(positive > 0) { "$positive is not positive" }
}
}
data class OldData(
@OldConfig("oldValue")
val newValue: String)

View File

@ -63,6 +63,7 @@ class AuthDBTests : NodeBasedTest() {
private lateinit var client: CordaRPCClient
private lateinit var db: UsersDB
@Suppress("MemberVisibilityCanBePrivate")
@Parameterized.Parameter
lateinit var passwordEncryption: PasswordEncryption
@ -110,7 +111,7 @@ class AuthDBTests : NodeBasedTest() {
)
node = startNode(ALICE_NAME, rpcUsers = emptyList(), configOverrides = securityConfig)
client = CordaRPCClient(node.internals.configuration.rpcOptions.address!!)
client = CordaRPCClient(node.internals.configuration.rpcOptions.address)
}
@Test
@ -243,9 +244,8 @@ private data class RoleAndPermissions(val role: String, val permissions: List<St
/*
* Manage in-memory DB mocking a users database with the schema expected by Node's security manager
*/
private class UsersDB : AutoCloseable {
val jdbcUrl: String
private class UsersDB(name: String, users: List<UserAndRoles> = emptyList(), roleAndPermissions: List<RoleAndPermissions> = emptyList()) : AutoCloseable {
val jdbcUrl = "jdbc:h2:mem:$name;DB_CLOSE_DELAY=-1"
companion object {
const val DB_CREATE_SCHEMA = """
@ -295,11 +295,7 @@ private class UsersDB : AutoCloseable {
}
}
constructor(name: String,
users: List<UserAndRoles> = emptyList(),
roleAndPermissions: List<RoleAndPermissions> = emptyList()) {
jdbcUrl = "jdbc:h2:mem:$name;DB_CLOSE_DELAY=-1"
init {
dataSource = DataSourceFactory.createDataSource(Properties().apply {
put("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource")
put("dataSource.url", jdbcUrl)
@ -307,11 +303,9 @@ private class UsersDB : AutoCloseable {
session {
it.execute(DB_CREATE_SCHEMA)
}
require(users.map { it.username }.toSet().size == users.size) {
"Duplicate username in input"
}
users.forEach { insert(it) }
roleAndPermissions.forEach { insert(it) }
}

View File

@ -32,7 +32,6 @@ import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.internal.IntegrationTest
import net.corda.testing.internal.IntegrationTestSchemas
import net.corda.testing.node.NotarySpec
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.node.internal.SharedCompatibilityZoneParams
import net.corda.testing.node.internal.internalDriver
import net.corda.testing.node.internal.network.NetworkMapServer
@ -64,7 +63,6 @@ class NodeRegistrationTest : IntegrationTest() {
private val notaryName = CordaX500Name("NotaryService", "Zurich", "CH")
private val aliceName = CordaX500Name("Alice", "London", "GB")
private val genevieveName = CordaX500Name("Genevieve", "London", "GB")
private val log = contextLogger()
}
@Rule
@ -82,7 +80,7 @@ class NodeRegistrationTest : IntegrationTest() {
pollInterval = 1.seconds,
hostAndPort = portAllocation.nextHostAndPort(),
myHostNameValue = "localhost",
additionalServices = registrationHandler)
additionalServices = *arrayOf(registrationHandler))
serverHostAndPort = server.start()
}

View File

@ -78,7 +78,7 @@ class MQSecurityAsNodeTest : P2PMQSecurityTest() {
@Test
fun `login to a non ssl port as a node user`() {
val attacker = clientTo(alice.internals.configuration.rpcOptions.address!!, sslConfiguration = null)
val attacker = clientTo(alice.internals.configuration.rpcOptions.address, sslConfiguration = null)
assertThatExceptionOfType(ActiveMQSecurityException::class.java).isThrownBy {
attacker.start(NODE_P2P_USER, NODE_P2P_USER, enableSSL = false)
}
@ -86,7 +86,7 @@ class MQSecurityAsNodeTest : P2PMQSecurityTest() {
@Test
fun `login to a non ssl port as a peer user`() {
val attacker = clientTo(alice.internals.configuration.rpcOptions.address!!, sslConfiguration = null)
val attacker = clientTo(alice.internals.configuration.rpcOptions.address, sslConfiguration = null)
assertThatExceptionOfType(ActiveMQSecurityException::class.java).isThrownBy {
attacker.start(PEER_USER, PEER_USER, enableSSL = false) // Login as a peer
}

View File

@ -18,7 +18,7 @@ import org.junit.Test
*/
class MQSecurityAsRPCTest : RPCMQSecurityTest() {
override fun createAttacker(): SimpleMQClient {
return clientTo(alice.internals.configuration.rpcOptions.address!!)
return clientTo(alice.internals.configuration.rpcOptions.address)
}
@Test

View File

@ -41,6 +41,7 @@ import net.corda.testing.node.internal.NodeBasedTest
import net.corda.testing.node.internal.startFlow
import org.apache.activemq.artemis.api.core.ActiveMQNonExistentQueueException
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
import org.apache.activemq.artemis.api.core.RoutingType
import org.apache.activemq.artemis.api.core.SimpleString
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.ClassRule
@ -125,9 +126,9 @@ abstract class MQSecurityTest : NodeBasedTest() {
}
fun loginToRPCAndGetClientQueue(): String {
loginToRPC(alice.internals.configuration.rpcOptions.address!!, rpcUser)
loginToRPC(alice.internals.configuration.rpcOptions.address, rpcUser)
val clientQueueQuery = SimpleString("${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.${rpcUser.username}.*")
val client = clientTo(alice.internals.configuration.rpcOptions.address!!)
val client = clientTo(alice.internals.configuration.rpcOptions.address)
client.start(rpcUser.username, rpcUser.password, false)
return client.session.addressQuery(clientQueueQuery).queueNames.single().toString()
}
@ -140,7 +141,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
fun assertTempQueueCreationAttackFails(queue: String) {
assertAttackFails(queue, "CREATE_NON_DURABLE_QUEUE") {
attacker.session.createTemporaryQueue(queue, queue)
attacker.session.createTemporaryQueue(queue, RoutingType.MULTICAST, queue)
}
// Double-check
assertThatExceptionOfType(ActiveMQNonExistentQueueException::class.java).isThrownBy {
@ -157,7 +158,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
fun assertNonTempQueueCreationAttackFails(queue: String, durable: Boolean) {
val permission = if (durable) "CREATE_DURABLE_QUEUE" else "CREATE_NON_DURABLE_QUEUE"
assertAttackFails(queue, permission) {
attacker.session.createQueue(queue, queue, durable)
attacker.session.createQueue(queue, RoutingType.MULTICAST, queue, durable)
}
// Double-check
assertThatExceptionOfType(ActiveMQNonExistentQueueException::class.java).isThrownBy {

View File

@ -14,11 +14,10 @@ import com.typesafe.config.Config
import com.typesafe.config.ConfigException
import net.corda.core.context.AuthServiceId
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.div
import net.corda.core.internal.TimedFlow
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.seconds
import net.corda.node.internal.artemis.CertificateChainCheckPolicy
import net.corda.node.services.config.rpc.NodeRpcOptions
import net.corda.nodeapi.BrokerRpcSslOptions
import net.corda.nodeapi.internal.config.NodeSSLConfiguration
@ -51,6 +50,7 @@ interface NodeConfiguration : NodeSSLConfiguration {
val devModeOptions: DevModeOptions?
val compatibilityZoneURL: URL?
val networkServices: NetworkServicesConfig?
@Suppress("DEPRECATION")
val certificateChainCheckPolicies: List<CertChainPolicyConfig>
val verifierType: VerifierType
val flowTimeout: FlowTimeoutConfiguration
@ -237,6 +237,7 @@ data class NodeConfigurationImpl(
override val messagingServerExternal: Boolean = (messagingServerAddress != null),
override val enterpriseConfiguration: EnterpriseConfiguration,
override val notary: NotaryConfig?,
@Suppress("DEPRECATION")
@Deprecated("Do not configure")
override val certificateChainCheckPolicies: List<CertChainPolicyConfig> = emptyList(),
override val devMode: Boolean = false,
@ -413,6 +414,7 @@ data class NodeConfigurationImpl(
}
// Check for usage of deprecated config
@Suppress("DEPRECATION")
if(certificateChainCheckPolicies.isNotEmpty()) {
logger.warn("""You are configuring certificateChainCheckPolicies. This is a setting that is not used, and will be removed in a future version.
|Please contact the R3 team on the public slack to discuss your use case.
@ -467,18 +469,7 @@ enum class CertChainPolicyType {
}
@Deprecated("Do not use")
data class CertChainPolicyConfig(val role: String, private val policy: CertChainPolicyType, private val trustedAliases: Set<String>) {
val certificateChainCheckPolicy: CertificateChainCheckPolicy
get() {
return when (policy) {
CertChainPolicyType.Any -> CertificateChainCheckPolicy.Any
CertChainPolicyType.RootMustMatch -> CertificateChainCheckPolicy.RootMustMatch
CertChainPolicyType.LeafMustMatch -> CertificateChainCheckPolicy.LeafMustMatch
CertChainPolicyType.MustContainOneOf -> CertificateChainCheckPolicy.MustContainOneOf(trustedAliases)
CertChainPolicyType.UsernameMustMatch -> CertificateChainCheckPolicy.UsernameMustMatchCommonName
}
}
}
data class CertChainPolicyConfig(val role: String, private val policy: CertChainPolicyType, private val trustedAliases: Set<String>)
// Supported types of authentication/authorization data providers
enum class AuthDataSourceType {
@ -515,8 +506,6 @@ data class SecurityConfiguration(val authService: SecurityConfiguration.AuthServ
}
}
fun copyWithAdditionalUser(user: User) = AuthService(dataSource.copyWithAdditionalUser(user), id, options)
// Optional components: cache
data class Options(val cache: Options.Cache?) {
@ -544,12 +533,6 @@ data class SecurityConfiguration(val authService: SecurityConfiguration.AuthServ
AuthDataSourceType.DB -> require(users == null && connection != null)
}
}
fun copyWithAdditionalUser(user: User): DataSource {
val extendedList = this.users?.toMutableList() ?: mutableListOf()
extendedList.add(user)
return DataSource(this.type, this.passwordEncryption, this.connection, listOf(*extendedList.toTypedArray()))
}
}
companion object {

View File

@ -34,7 +34,7 @@ import javax.annotation.concurrent.ThreadSafe
*/
// TODO There is duplicated logic between this and PersistentIdentityService
@ThreadSafe
class InMemoryIdentityService(identities: List<out PartyAndCertificate> = emptyList(),
class InMemoryIdentityService(identities: List<PartyAndCertificate> = emptyList(),
override val trustRoot: X509Certificate) : SingletonSerializeAsToken(), IdentityService {
companion object {
private val log = contextLogger()

View File

@ -63,7 +63,7 @@ class E2ETestKeyManagementService(val identityService: IdentityService,
}
override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate {
return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey), revocationEnabled)
return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey))
}
private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey))

View File

@ -40,8 +40,7 @@ import java.time.Duration
fun freshCertificate(identityService: IdentityService,
subjectPublicKey: PublicKey,
issuer: PartyAndCertificate,
issuerSigner: ContentSigner,
revocationEnabled: Boolean = false): PartyAndCertificate {
issuerSigner: ContentSigner): PartyAndCertificate {
val issuerRole = CertRole.extract(issuer.certificate)
require(issuerRole == CertRole.LEGAL_IDENTITY) { "Confidential identities can only be issued from well known identities, provided issuer ${issuer.name} has role $issuerRole" }
val issuerCert = issuer.certificate

View File

@ -98,8 +98,9 @@ class PersistentKeyManagementService(val identityService: IdentityService,
return keyPair.public
}
override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate =
freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey), revocationEnabled)
override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate {
return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey))
}
private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey))

View File

@ -66,10 +66,10 @@ import kotlin.streams.toList
@ThreadSafe
class SingleThreadedStateMachineManager(
val serviceHub: ServiceHubInternal,
val checkpointStorage: CheckpointStorage,
private 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 = SingleThreadedStateMachineManager::class.java.classLoader
) : StateMachineManager, StateMachineManagerInternal {
@ -145,7 +145,7 @@ class SingleThreadedStateMachineManager(
}
serviceHub.networkMapCache.nodeReady.then {
resumeRestoredFlows(fibers)
flowMessaging.start { receivedMessage, deduplicationHandler ->
flowMessaging.start { _, deduplicationHandler ->
executor.execute {
deliverExternalEvent(deduplicationHandler.externalCause)
}
@ -296,10 +296,10 @@ class SingleThreadedStateMachineManager(
}
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() {
@ -314,8 +314,7 @@ class SingleThreadedStateMachineManager(
return checkpointStorage.getAllCheckpoints().map { (id, serializedCheckpoint) ->
// If a flow is added before start() then don't attempt to restore it
mutex.locked { if (flows.containsKey(id)) return@map null }
val checkpoint = deserializeCheckpoint(serializedCheckpoint)
if (checkpoint == null) return@map null
val checkpoint = deserializeCheckpoint(serializedCheckpoint) ?: return@map null
logger.debug { "Restored $checkpoint" }
createFlowFromCheckpoint(
id = id,
@ -534,12 +533,6 @@ class SingleThreadedStateMachineManager(
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)
@ -551,7 +544,7 @@ class SingleThreadedStateMachineManager(
val flowCorDappVersion = 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,

View File

@ -2,6 +2,7 @@ package net.corda.node.services.statemachine
import net.corda.core.flows.StateMachineRunId
import net.corda.core.internal.ThreadBox
import net.corda.core.internal.TimedFlow
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.messaging.DataFeed
import net.corda.core.utilities.contextLogger
@ -100,12 +101,6 @@ class StaffedFlowHospital {
private data class ConsultationReport(val error: Throwable, val diagnosis: Diagnosis, val by: List<Staff>)
/**
* The flow running in [flowFiber] has cleaned, possibly as a result of a flow hospital resume.
*/
// It's okay for flows to be cleaned... we fix them now!
fun flowCleaned(flowFiber: FlowFiber) = Unit
/**
* The flow has been removed from the state machine.
*/

View File

@ -79,7 +79,6 @@ data class Checkpoint(
flowLogicClass: Class<FlowLogic<*>>,
frozenFlowLogic: SerializedBytes<FlowLogic<*>>,
ourIdentity: Party,
deduplicationSeed: String,
subFlowVersion: SubFlowVersion
): Try<Checkpoint> {
return SubFlow.create(flowLogicClass, subFlowVersion).map { topLevelSubFlow ->

View File

@ -55,9 +55,7 @@ class HospitalisingInterceptor(
when (nextState.checkpoint.errorState) {
is ErrorState.Clean -> {
if (hospitalisedFlows.remove(fiber.id) != null) {
flowHospital.flowCleaned(fiber)
}
hospitalisedFlows.remove(fiber.id)
}
is ErrorState.Errored -> {
val exceptionsToHandle = nextState.checkpoint.errorState.errors.map { it.exception }

View File

@ -86,7 +86,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
Transactional.Committed(value)
} else {
// Some database transactions, including us, writing, with readers seeing whatever is in the database and writers seeing the (in memory) value.
Transactional.InFlight(this, key, { loadValue(key) }).apply { alsoWrite(value) }
Transactional.InFlight(this, key, _readerValueLoader = { loadValue(key) }).apply { alsoWrite(value) }
}
}
@ -156,13 +156,13 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
}
// Helpers to know if transaction(s) are currently writing the given key.
protected fun weAreWriting(key: K): Boolean = pendingKeys.get(key)?.contains(contextTransaction) ?: false
protected fun anyoneWriting(key: K): Boolean = pendingKeys.get(key)?.isNotEmpty() ?: false
protected fun weAreWriting(key: K): Boolean = pendingKeys[key]?.contains(contextTransaction) ?: false
protected fun anyoneWriting(key: K): Boolean = pendingKeys[key]?.isNotEmpty() ?: false
// Indicate this database transaction is a writer of this key.
private fun addPendingKey(key: K, databaseTransaction: DatabaseTransaction): Boolean {
var added = true
pendingKeys.compute(key) { k, oldSet ->
pendingKeys.compute(key) { _, oldSet ->
if (oldSet == null) {
val newSet = HashSet<DatabaseTransaction>(0)
newSet += databaseTransaction
@ -177,7 +177,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
// Remove this database transaction as a writer of this key, because the transaction committed or rolled back.
private fun removePendingKey(key: K, databaseTransaction: DatabaseTransaction) {
pendingKeys.compute(key) { k, oldSet ->
pendingKeys.compute(key) { _, oldSet ->
if (oldSet == null) {
oldSet
} else {
@ -209,7 +209,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
}
// No one can see it.
class Missing<T>() : Transactional<T>() {
class Missing<T> : Transactional<T>() {
override val value: T
get() = throw NoSuchElementException("Not present")
override val isPresent: Boolean
@ -238,7 +238,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
fun alsoWrite(_value: T) {
// Make the lazy loader the writers see actually just return the value that has been set.
writerValueLoader.set({ _value })
writerValueLoader.set { _value }
// We make all these vals so that the lambdas do not need a reference to this, and so the onCommit only has a weak ref to the value.
// We want this so that the cache could evict the value (due to memory constraints etc) without the onCommit callback
// retaining what could be a large memory footprint object.
@ -252,10 +252,9 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
// and then stop saying the transaction is writing the key.
tx.onCommit {
if (strongComitted.compareAndSet(false, true)) {
val dereferencedKey = strongKey
val dereferencedValue = weakValue.get()
if (dereferencedValue != null) {
strongMap.cache.put(dereferencedKey, Committed(dereferencedValue))
strongMap.cache.put(strongKey, Committed(dereferencedValue))
}
}
strongMap.removePendingKey(strongKey, tx)
@ -272,7 +271,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
private fun loadAsWriter(): T {
val _value = writerValueLoader.get()()
if (writerValueLoader.get() == _writerValueLoader) {
writerValueLoader.set({ _value })
writerValueLoader.set { _value }
}
return _value
}
@ -282,7 +281,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
private fun loadAsReader(): T? {
val _value = readerValueLoader.get()()
if (readerValueLoader.get() == _readerValueLoader) {
readerValueLoader.set({ _value })
readerValueLoader.set { _value }
}
return _value
}
@ -320,7 +319,7 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
toPersistentEntity,
persistentEntityClass) {
//TODO determine cacheBound based on entity class later or with node config allowing tuning, or using some heuristic based on heap size
override val cache = NonInvalidatingCache<K, Transactional<V>>(
override val cache = NonInvalidatingCache(
bound = cacheBound,
loadFunction = { key: K ->
// This gets called if a value is read and the cache has no Transactional for this key yet.
@ -331,10 +330,10 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
// If someone is writing (but not us)
// For those not writing, the value cannot be seen.
// For those writing, they need to re-load the value from the database (which their database transaction CAN see).
Transactional.InFlight<K, V>(this, key, { null }, { loadValue(key)!! })
Transactional.InFlight(this, key, { null }, { loadValue(key)!! })
} else {
// If no one is writing, then the value does not exist.
Transactional.Missing<V>()
Transactional.Missing()
}
} else {
// A value was found
@ -342,10 +341,10 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
// If we are writing, it might not be globally visible, and was evicted from the cache.
// For those not writing, they need to check the database again.
// For those writing, they can see the value found.
Transactional.InFlight<K, V>(this, key, { loadValue(key) }, { value })
Transactional.InFlight(this, key, { loadValue(key) }, { value })
} else {
// If no one is writing, then make it globally visible.
Transactional.Committed<V>(value)
Transactional.Committed(value)
}
}
})
@ -364,26 +363,22 @@ class WeightBasedAppendOnlyPersistentMap<K, V, E, out EK>(
fromPersistentEntity,
toPersistentEntity,
persistentEntityClass) {
override val cache = NonInvalidatingWeightBasedCache<K, Transactional<V>>(
override val cache = NonInvalidatingWeightBasedCache(
maxWeight = maxWeight,
weigher = object : Weigher<K, Transactional<V>> {
override fun weigh(key: K, value: Transactional<V>): Int {
return weighingFunc(key, value)
}
},
weigher = Weigher { key, value -> weighingFunc(key, value) },
loadFunction = { key: K ->
val value: V? = loadValue(key)
if (value == null) {
if (anyoneWriting(key)) {
Transactional.InFlight<K, V>(this, key, { null }, { loadValue(key)!! })
Transactional.InFlight(this, key, { null }, { loadValue(key)!! })
} else {
Transactional.Missing<V>()
Transactional.Missing()
}
} else {
if (weAreWriting(key)) {
Transactional.InFlight<K, V>(this, key, { loadValue(key) }, { value })
Transactional.InFlight(this, key, { loadValue(key) }, { value })
} else {
Transactional.Committed<V>(value)
Transactional.Committed(value)
}
}
})

View File

@ -46,9 +46,6 @@ import org.junit.Rule;
import org.junit.Test;
import rx.Observable;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CertificateException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -80,7 +77,7 @@ public class VaultQueryJavaTests {
private CordaPersistence database;
@Before
public void setUp() throws CertificateException, InvalidAlgorithmParameterException {
public void setUp() {
List<String> cordappPackages = asList(
"net.corda.testing.internal.vault",
"net.corda.finance.contracts.asset",
@ -101,14 +98,10 @@ public class VaultQueryJavaTests {
}
@After
public void cleanUp() throws IOException {
public void cleanUp() {
database.close();
}
/**
* Sample Vault Query API tests
*/
/**
* Static queryBy() tests
*/
@ -119,6 +112,7 @@ public class VaultQueryJavaTests {
FieldInfo currency = getField("currency", SampleCashSchemaV2.PersistentCashState.class);
CriteriaExpression.AggregateFunctionExpression<Object, Boolean> expression = sum(quantity, singletonList(currency), Sort.Direction.ASC);
@SuppressWarnings("unchecked")
VaultCustomQueryCriteria<SampleCashSchemaV2.PersistentCashState> criteria = new VaultCustomQueryCriteria(expression, Vault.StateStatus.UNCONSUMED, null);
database.transaction(tx -> vaultService.queryBy(FungibleAsset.class, criteria));
@ -131,13 +125,14 @@ public class VaultQueryJavaTests {
FieldInfo stateRef = getField("stateRef", SampleCashSchemaV2.PersistentCashState.class);
CriteriaExpression.AggregateFunctionExpression<Object, Boolean> expression = sum(quantity, asList(currency, stateRef), Sort.Direction.ASC);
@SuppressWarnings("unchecked")
VaultCustomQueryCriteria<SampleCashSchemaV2.PersistentCashState> criteria = new VaultCustomQueryCriteria(expression, Vault.StateStatus.UNCONSUMED, null);
database.transaction(tx -> vaultService.queryBy(FungibleAsset.class, criteria));
}
@Test
public void unconsumedLinearStates() throws VaultQueryException {
public void unconsumedLinearStates() {
database.transaction(tx -> {
vaultFiller.fillWithSomeTestLinearStates(3);
return tx;
@ -209,7 +204,7 @@ public class VaultQueryJavaTests {
}
@Test
public void consumedDealStatesPagedSorted() throws VaultQueryException {
public void consumedDealStatesPagedSorted() {
List<String> dealIds = asList("123", "456", "789");
@SuppressWarnings("unchecked")
Triple<StateAndRef<LinearState>, UniqueIdentifier, Vault<DealState>> ids =
@ -320,7 +315,6 @@ public class VaultQueryJavaTests {
DataFeed<Vault.Page<ContractState>, Vault.Update<ContractState>> results = vaultService.trackBy(ContractState.class, criteria);
Vault.Page<ContractState> snapshot = results.getSnapshot();
Observable<Vault.Update<ContractState>> updates = results.getUpdates();
// DOCEND VaultJavaQueryExample4
assertThat(snapshot.getStates()).hasSize(3);
@ -374,7 +368,6 @@ public class VaultQueryJavaTests {
@SuppressWarnings("unchecked")
public void aggregateFunctionsWithoutGroupClause() {
database.transaction(tx -> {
Amount<Currency> dollars100 = new Amount<>(100, Currency.getInstance("USD"));
Amount<Currency> dollars200 = new Amount<>(200, Currency.getInstance("USD"));
Amount<Currency> dollars300 = new Amount<>(300, Currency.getInstance("USD"));
@ -420,7 +413,6 @@ public class VaultQueryJavaTests {
@SuppressWarnings("unchecked")
public void aggregateFunctionsWithSingleGroupClause() {
database.transaction(tx -> {
Amount<Currency> dollars100 = new Amount<>(100, Currency.getInstance("USD"));
Amount<Currency> dollars200 = new Amount<>(200, Currency.getInstance("USD"));
Amount<Currency> dollars300 = new Amount<>(300, Currency.getInstance("USD"));

View File

@ -34,7 +34,6 @@ import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.unwrap
import net.corda.finance.DOLLARS
import net.corda.finance.GBP
import net.corda.finance.USD
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.flows.CashPaymentFlow
@ -167,6 +166,7 @@ class CordaRPCOpsImplTest {
@Test
fun `issue and move`() {
@Suppress("DEPRECATION")
withPermissions(invokeRpc(CordaRPCOps::stateMachinesFeed),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed),
invokeRpc("vaultTrackBy"),
@ -178,11 +178,7 @@ class CordaRPCOpsImplTest {
vaultTrackCash = rpc.vaultTrackBy<Cash.State>().updates
}
val result = rpc.startFlow(::CashIssueFlow,
100.DOLLARS,
OpaqueBytes(ByteArray(1, { 1 })),
notary
)
val result = rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notary)
mockNet.runNetwork()
@ -257,7 +253,7 @@ class CordaRPCOpsImplTest {
fun `cash command by user not permissioned for cash`() {
withoutAnyPermissions {
assertThatExceptionOfType(PermissionException::class.java).isThrownBy {
rpc.startFlow(::CashIssueFlow, Amount(100, USD), OpaqueBytes(ByteArray(1, { 1 })), notary)
rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notary)
}
}
}

View File

@ -70,7 +70,7 @@ class NodeTest {
fun `generateAndSaveNodeInfo works`() {
val configuration = createConfig(ALICE_NAME)
val info = VersionInfo(789, "3.0", "SNAPSHOT", "R3")
configureDatabase(configuration.dataSourceProperties, configuration.database, { null }, { null }).use { database ->
configureDatabase(configuration.dataSourceProperties, configuration.database, { null }, { null }).use {
val node = Node(configuration, info, initialiseSerialization = false)
assertEquals(node.generateNodeInfo(), node.generateNodeInfo()) // Node info doesn't change (including the serial)
}

View File

@ -19,7 +19,6 @@ import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.Test
import rx.Notification
import rx.Observable
import rx.Subscription
import rx.subjects.UnicastSubject
import java.time.Instant
import java.util.*
@ -38,7 +37,7 @@ class RoundTripObservableSerializerTests {
.maximumSize(100)
.build()
subMap.put(id, ObservableSubscription(mock<Subscription>()))
subMap.put(id, ObservableSubscription(mock()))
return subMap
}
@ -48,7 +47,7 @@ class RoundTripObservableSerializerTests {
})
private fun createRpcObservableMap(): Cache<Trace.InvocationId, UnicastSubject<Notification<*>>> {
val onObservableRemove = RemovalListener<Trace.InvocationId, UnicastSubject<Notification<*>>> { key, value, cause ->
val onObservableRemove = RemovalListener<Trace.InvocationId, UnicastSubject<Notification<*>>> { key, _, _ ->
val observableId = key!!
observablesToReap.locked { observables.add(observableId) }
@ -85,7 +84,7 @@ class RoundTripObservableSerializerTests {
// What we're actually going to serialize then deserialize
val obs = Observable.create<Int>({ 12 })
val obs = Observable.create<Int> { Math.random() }
val serverSerializationContext = RpcServerObservableSerializer.createContext(
serializationContext, serverObservableContext)
@ -95,6 +94,6 @@ class RoundTripObservableSerializerTests {
val blob = SerializationOutput(serverSerializer).serialize(obs, serverSerializationContext)
val obs2 = DeserializationInput(clientSerializer).deserialize(blob, clientSerializationContext)
DeserializationInput(clientSerializer).deserialize(blob, clientSerializationContext)
}
}
}

View File

@ -8,13 +8,12 @@ import net.corda.node.internal.serialization.testutils.TestObservableContext
import net.corda.node.internal.serialization.testutils.serializationContext
import net.corda.node.serialization.amqp.RpcServerObservableSerializer
import net.corda.node.services.messaging.ObservableSubscription
import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.SerializationOutput
import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.AllWhitelist
import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.Test
import rx.Observable
import rx.Subscription
import java.time.Instant
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit
@ -28,7 +27,7 @@ class RpcServerObservableSerializerTests {
.maximumSize(100)
.build()
subMap.put(Trace.InvocationId("test1", Instant.now()), ObservableSubscription(mock<Subscription>()))
subMap.put(Trace.InvocationId("test1", Instant.now()), ObservableSubscription(mock()))
return subMap
}
@ -72,7 +71,7 @@ class RpcServerObservableSerializerTests {
register(RpcServerObservableSerializer())
}
val obs = Observable.create<Int>({ 12 })
val obs = Observable.create<Int> { Math.random() }
val newContext = RpcServerObservableSerializer.createContext(serializationContext, observable)
try {

View File

@ -10,22 +10,8 @@
package net.corda.node.services.events
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.argForWhich
import com.nhaarman.mockito_kotlin.doAnswer
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.eq
import com.nhaarman.mockito_kotlin.same
import com.nhaarman.mockito_kotlin.timeout
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.verifyNoMoreInteractions
import com.nhaarman.mockito_kotlin.whenever
import junit.framework.Assert.fail
import net.corda.core.contracts.SchedulableState
import net.corda.core.contracts.ScheduledActivity
import net.corda.core.contracts.ScheduledStateRef
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionState
import com.nhaarman.mockito_kotlin.*
import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowLogicRef
@ -46,11 +32,7 @@ import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.spectator
import net.corda.testing.node.MockServices
import net.corda.testing.node.TestClock
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.*
import org.junit.rules.TestWatcher
import org.junit.runner.Description
import org.slf4j.Logger
@ -61,6 +43,7 @@ import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals
import kotlin.test.fail
open class NodeSchedulerServiceTestBase {
protected class Event(time: Instant) {
@ -97,7 +80,7 @@ open class NodeSchedulerServiceTestBase {
doLookup(transactionStates).whenever(it).loadState(any())
}
protected val traces = Collections.synchronizedList(mutableListOf<ScheduledStateRef>())
private val traces = Collections.synchronizedList(mutableListOf<ScheduledStateRef>())
@Before
fun resetTraces() {
@ -108,7 +91,7 @@ open class NodeSchedulerServiceTestBase {
doReturn(false).whenever(it).isTraceEnabled
doAnswer {
traces += it.getArgument<ScheduledStateRef>(1)
}.whenever(it).trace(eq(NodeSchedulerService.schedulingAsNextFormat), any<Object>())
}.whenever(it).trace(eq(NodeSchedulerService.schedulingAsNextFormat), any<Any>())
}
protected fun assertWaitingFor(ssr: ScheduledStateRef) {
@ -283,7 +266,7 @@ class NodeSchedulerServiceTest : NodeSchedulerServiceTestBase() {
class NodeSchedulerPersistenceTest : NodeSchedulerServiceTestBase() {
private val databaseConfig: DatabaseConfig = DatabaseConfig()
fun createScheduler(db: CordaPersistence): NodeSchedulerService {
private fun createScheduler(db: CordaPersistence): NodeSchedulerService {
return NodeSchedulerService(
testClock,
db,
@ -295,7 +278,7 @@ class NodeSchedulerPersistenceTest : NodeSchedulerServiceTestBase() {
log = log).apply { start() }
}
fun transactionStateMock(logicRef: FlowLogicRef, time: Instant): TransactionState<*> {
private fun transactionStateMock(logicRef: FlowLogicRef, time: Instant): TransactionState<*> {
return rigorousMock<TransactionState<SchedulableState>>().also {
doReturn(rigorousMock<SchedulableState>().also {
doReturn(ScheduledActivity(logicRef, time)).whenever(it).nextScheduledActivity(any(), any())

View File

@ -81,7 +81,6 @@ class ArtemisMessagingTest {
doReturn("cordacadevpass").whenever(it).keyStorePassword
doReturn(NetworkHostAndPort("0.0.0.0", serverPort)).whenever(it).p2pAddress
doReturn(null).whenever(it).jmxMonitoringHttpPort
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration
doReturn(FlowTimeoutConfiguration(5.seconds, 3, backoffBase = 1.0)).whenever(it).flowTimeout
}

View File

@ -200,7 +200,7 @@ class DBCheckpointStorageTests {
override fun call() {}
}
val frozenLogic = logic.serialize(context = SerializationDefaults.CHECKPOINT_CONTEXT)
val checkpoint = Checkpoint.create(InvocationContext.shell(), FlowStart.Explicit, logic.javaClass, frozenLogic, ALICE, "", SubFlowVersion.CoreFlow(version)).getOrThrow()
val checkpoint = Checkpoint.create(InvocationContext.shell(), FlowStart.Explicit, logic.javaClass, frozenLogic, ALICE, SubFlowVersion.CoreFlow(version)).getOrThrow()
return id to checkpoint.serialize(context = SerializationDefaults.CHECKPOINT_CONTEXT)
}

View File

@ -17,18 +17,14 @@ import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.TransactionSignature
import net.corda.core.toFuture
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.WireTransaction
import net.corda.node.internal.configureDatabase
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.transactions.PersistentUniquenessProvider
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.TestIdentity
import net.corda.testing.core.dummyCommand
import net.corda.testing.core.*
import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.createWireTransaction
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
@ -176,7 +172,7 @@ class DBTransactionStorageTests {
}
private fun newTransaction(): SignedTransaction {
val wtx = WireTransaction(
val wtx = createWireTransaction(
inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)),
attachments = emptyList(),
outputs = emptyList(),
@ -184,6 +180,9 @@ class DBTransactionStorageTests {
notary = DUMMY_NOTARY,
timeWindow = null
)
return SignedTransaction(wtx, listOf(TransactionSignature(ByteArray(1), ALICE_PUBKEY, SignatureMetadata(1, Crypto.findSignatureScheme(ALICE_PUBKEY).schemeNumberID))))
return SignedTransaction(
wtx,
listOf(TransactionSignature(ByteArray(1), ALICE_PUBKEY, SignatureMetadata(1, Crypto.findSignatureScheme(ALICE_PUBKEY).schemeNumberID)))
)
}
}

View File

@ -14,7 +14,6 @@ import com.nhaarman.mockito_kotlin.*
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.crypto.generateKeyPair
import net.corda.core.identity.AbstractParty
@ -39,13 +38,13 @@ import net.corda.finance.schemas.SampleCashSchemaV3
import net.corda.finance.schemas.CashSchemaV1
import net.corda.finance.utils.sumCash
import net.corda.node.internal.configureDatabase
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.node.services.api.WritableTransactionStorage
import net.corda.node.services.schema.ContractStateAndRef
import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.vault.VaultSchemaV1
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.node.services.api.WritableTransactionStorage
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.services.vault.VaultSchemaV1
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.nodeapi.internal.persistence.HibernateConfiguration
@ -85,18 +84,18 @@ class HibernateConfigurationTest {
val testSerialization = SerializationEnvironmentRule()
lateinit var services: MockServices
private lateinit var vaultFiller: VaultFiller
lateinit var bankServices: MockServices
lateinit var issuerServices: MockServices
lateinit var notaryServices: MockServices
private lateinit var bankServices: MockServices
private lateinit var issuerServices: MockServices
private lateinit var notaryServices: MockServices
lateinit var database: CordaPersistence
val vault: VaultService get() = services.vaultService
// Hibernate configuration objects
lateinit var hibernateConfig: HibernateConfiguration
lateinit var hibernatePersister: HibernateObserver
lateinit var sessionFactory: SessionFactory
lateinit var entityManager: EntityManager
lateinit var criteriaBuilder: CriteriaBuilder
private lateinit var hibernatePersister: HibernateObserver
private lateinit var sessionFactory: SessionFactory
private lateinit var entityManager: EntityManager
private lateinit var criteriaBuilder: CriteriaBuilder
// Identities used
private lateinit var identity: Party
@ -104,7 +103,7 @@ class HibernateConfigurationTest {
private lateinit var notary: Party
// test States
lateinit var cashStates: List<StateAndRef<Cash.State>>
private lateinit var cashStates: List<StateAndRef<Cash.State>>
@Before
fun setUp() {
@ -701,7 +700,7 @@ class HibernateConfigurationTest {
val queryResults = entityManager.createQuery(criteriaQuery).resultList
queryResults.forEach {
val cashState = (services.loadState(toStateRef(it.stateRef!!)) as TransactionState<Cash.State>).data
val cashState = services.loadState(toStateRef(it.stateRef!!)).data as Cash.State
println("${it.stateRef} with owner: ${cashState.owner.owningKey.toBase58String()}")
}
@ -785,7 +784,7 @@ class HibernateConfigurationTest {
// execute query
val queryResults = entityManager.createQuery(criteriaQuery).resultList
queryResults.forEach {
val cashState = (services.loadState(toStateRef(it.stateRef!!)) as TransactionState<Cash.State>).data
val cashState = services.loadState(toStateRef(it.stateRef!!)).data as Cash.State
println("${it.stateRef} with owner ${cashState.owner.owningKey.toBase58String()} and participants ${cashState.participants.map { it.owningKey.toBase58String() }}")
}
@ -924,6 +923,6 @@ class HibernateConfigurationTest {
}
private fun toStateRef(pStateRef: PersistentStateRef): StateRef {
return StateRef(SecureHash.parse(pStateRef.txId!!), pStateRef.index!!)
return StateRef(SecureHash.parse(pStateRef.txId), pStateRef.index)
}
}
}

View File

@ -15,11 +15,7 @@ import com.google.common.jimfs.Configuration
import com.google.common.jimfs.Jimfs
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.internal.read
import net.corda.core.internal.readAll
import net.corda.core.internal.readFully
import net.corda.core.internal.write
import net.corda.core.internal.writeLines
import net.corda.core.internal.*
import net.corda.core.node.services.vault.AttachmentQueryCriteria
import net.corda.core.node.services.vault.AttachmentSort
import net.corda.core.node.services.vault.Builder
@ -69,7 +65,7 @@ class NodeAttachmentStorageTest {
fun `insert and retrieve`() {
val (testJar, expectedHash) = makeTestJar()
val id = testJar.read { storage.importAttachment(it) }
val id = testJar.read { storage.importAttachment(it, "test", null) }
assertEquals(expectedHash, id)
assertNull(storage.openAttachment(SecureHash.randomSHA256()))
@ -94,7 +90,7 @@ class NodeAttachmentStorageTest {
val (testJar, expectedHash) = makeTestJar()
val (jarB, hashB) = makeTestJar(listOf(Pair("file", "content")))
val id = testJar.read { storage.importAttachment(it) }
val id = testJar.read { storage.importAttachment(it, "test", null) }
assertEquals(expectedHash, id)
@ -109,7 +105,7 @@ class NodeAttachmentStorageTest {
stream.close()
val idB = jarB.read { storage.importAttachment(it) }
val idB = jarB.read { storage.importAttachment(it, "test", null) }
assertEquals(hashB, idB)
storage.openAttachment(id)!!.openAsJAR().use {
@ -129,6 +125,7 @@ class NodeAttachmentStorageTest {
val (jarB, hashB) = makeTestJar(listOf(Pair("file", "content")))
val (jarC, hashC) = makeTestJar(listOf(Pair("magic_file", "magic_content_puff")))
@Suppress("DEPRECATION")
jarA.read { storage.importAttachment(it) }
jarB.read { storage.importAttachment(it, "uploaderB", "fileB.zip") }
jarC.read { storage.importAttachment(it, "uploaderC", "fileC.zip") }
@ -196,11 +193,11 @@ class NodeAttachmentStorageTest {
fun `duplicates not allowed`() {
val (testJar, _) = makeTestJar()
testJar.read {
storage.importAttachment(it)
storage.importAttachment(it, "test", null)
}
assertFailsWith<FileAlreadyExistsException> {
testJar.read {
storage.importAttachment(it)
storage.importAttachment(it, "test", null)
}
}
}
@ -209,7 +206,7 @@ class NodeAttachmentStorageTest {
fun `corrupt entry throws exception`() {
val (testJar, _) = makeTestJar()
val id = database.transaction {
val id = testJar.read { storage.importAttachment(it) }
val id = testJar.read { storage.importAttachment(it, "test", null) }
// Corrupt the file in the store.
val bytes = testJar.readAll()
@ -237,7 +234,7 @@ class NodeAttachmentStorageTest {
path.writeLines(listOf("Hey", "there!"))
path.read {
assertFailsWith<IllegalArgumentException>("either empty or not a JAR") {
storage.importAttachment(it)
storage.importAttachment(it, "test", null)
}
}
}

View File

@ -15,6 +15,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.internal.InputStreamAndHash
import net.corda.core.node.services.AttachmentId
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.testing.common.internal.testNetworkParameters
@ -31,6 +32,7 @@ import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.InputStream
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@ -67,10 +69,10 @@ class MaxTransactionSizeTests {
val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 2)
val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 3)
val flow = aliceNode.transaction {
val hash1 = aliceNode.services.attachments.importAttachment(bigFile1.inputStream)
val hash2 = aliceNode.services.attachments.importAttachment(bigFile2.inputStream)
val hash3 = aliceNode.services.attachments.importAttachment(bigFile3.inputStream)
val hash4 = aliceNode.services.attachments.importAttachment(bigFile4.inputStream)
val hash1 = aliceNode.importAttachment(bigFile1.inputStream)
val hash2 = aliceNode.importAttachment(bigFile2.inputStream)
val hash3 = aliceNode.importAttachment(bigFile3.inputStream)
val hash4 = aliceNode.importAttachment(bigFile4.inputStream)
assertEquals(hash1, bigFile1.sha256)
SendLargeTransactionFlow(notary, bob, hash1, hash2, hash3, hash4)
}
@ -90,10 +92,10 @@ class MaxTransactionSizeTests {
val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 2)
val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 3)
val flow = aliceNode.transaction {
val hash1 = aliceNode.services.attachments.importAttachment(bigFile1.inputStream)
val hash2 = aliceNode.services.attachments.importAttachment(bigFile2.inputStream)
val hash3 = aliceNode.services.attachments.importAttachment(bigFile3.inputStream)
val hash4 = aliceNode.services.attachments.importAttachment(bigFile4.inputStream)
val hash1 = aliceNode.importAttachment(bigFile1.inputStream)
val hash2 = aliceNode.importAttachment(bigFile2.inputStream)
val hash3 = aliceNode.importAttachment(bigFile3.inputStream)
val hash4 = aliceNode.importAttachment(bigFile4.inputStream)
assertEquals(hash1, bigFile1.sha256)
SendLargeTransactionFlow(notary, bob, hash1, hash2, hash3, hash4, verify = false)
}
@ -104,6 +106,10 @@ class MaxTransactionSizeTests {
}
}
private fun StartedMockNode.importAttachment(inputStream: InputStream): AttachmentId {
return services.attachments.importAttachment(inputStream, "test", null)
}
@StartableByRPC
@InitiatingFlow
class SendLargeTransactionFlow(private val notary: Party,

View File

@ -51,7 +51,6 @@ import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.ExternalResource
import java.time.Duration
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.temporal.ChronoUnit
@ -113,7 +112,7 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
override val bob = TestIdentity(BOB_NAME, 80)
override val cashNotary = TestIdentity(CordaX500Name("Cash Notary Service", "Zurich", "CH"), 21)
override val charlie = TestIdentity(CHARLIE_NAME, 90)
override val dummyCashIssuer = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10)
final override val dummyCashIssuer = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10)
override val DUMMY_CASH_ISSUER = dummyCashIssuer.ref(1)
override val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20)
override val DUMMY_OBLIGATION_ISSUER = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10).party
@ -143,7 +142,7 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
cordappPackages,
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity),
megaCorp,
moreKeys = DUMMY_NOTARY_KEY)
moreKeys = *arrayOf(DUMMY_NOTARY_KEY))
database = databaseAndServices.first
services = databaseAndServices.second
vaultFiller = VaultFiller(services, dummyNotary)
@ -161,7 +160,7 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
}
}
class VaultQueryRollbackRule(val vaultQueryParties: VaultQueryParties) : ExternalResource() {
class VaultQueryRollbackRule(private val vaultQueryParties: VaultQueryParties) : ExternalResource() {
lateinit var transaction: DatabaseTransaction

View File

@ -75,7 +75,7 @@ class VaultWithCashTest {
private val servicesKey = generateKeyPair()
lateinit var services: MockServices
private lateinit var vaultFiller: VaultFiller
lateinit var issuerServices: MockServices
private lateinit var issuerServices: MockServices
val vaultService: VaultService get() = services.vaultService
lateinit var database: CordaPersistence
private lateinit var notaryServices: MockServices
@ -88,7 +88,7 @@ class VaultWithCashTest {
cordappPackages,
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity),
TestIdentity(MEGA_CORP.name, servicesKey),
moreKeys = dummyNotary.keyPair)
moreKeys = *arrayOf(dummyNotary.keyPair))
database = databaseAndServices.first
services = databaseAndServices.second
vaultFiller = VaultFiller(services, dummyNotary)
@ -141,7 +141,7 @@ class VaultWithCashTest {
database.transaction {
// A tx that spends our money.
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, BOB)
Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val spendPTX = services.signInitialTransaction(spendTXBuilder, freshKey)
notaryServices.addSignature(spendPTX)
}
@ -189,7 +189,7 @@ class VaultWithCashTest {
val first = backgroundExecutor.fork {
database.transaction {
val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn1Builder, 60.DOLLARS, BOB)
Cash.generateSpend(services, txn1Builder, 60.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
val txn1 = services.addSignature(ptxn1, freshKey)
println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}")
@ -220,7 +220,7 @@ class VaultWithCashTest {
val second = backgroundExecutor.fork {
database.transaction {
val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn2Builder, 80.DOLLARS, BOB)
Cash.generateSpend(services, txn2Builder, 80.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
val txn2 = services.addSignature(ptxn2, freshKey)
println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}")
@ -344,7 +344,7 @@ class VaultWithCashTest {
database.transaction {
// A tx that spends our money.
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, BOB)
Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val spendPTX = notaryServices.signInitialTransaction(spendTXBuilder)
val spendTX = services.addSignature(spendPTX, freshKey)
services.recordTransactions(spendTX)

View File

@ -23,7 +23,6 @@ import rx.Observable
import rx.subjects.PublishSubject
import java.io.Closeable
import java.util.*
import kotlin.test.fail
class ObservablesTests {
private fun isInDatabaseTransaction() = contextTransactionOrNull != null
@ -68,7 +67,7 @@ class ObservablesTests {
assertThat(secondEvent.get()).isEqualTo(0 to false)
}
class TestException : Exception("Synthetic exception for tests") {}
class TestException : Exception("Synthetic exception for tests")
@Test
fun `bufferUntilDatabaseCommit swallows if transaction rolled back`() {
@ -93,7 +92,6 @@ class ObservablesTests {
assertThat(secondEvent.isDone).isFalse()
throw TestException()
}
fail("Should not have successfully completed transaction")
} catch (e: TestException) {
}
assertThat(secondEvent.isDone).isFalse()
@ -125,7 +123,6 @@ class ObservablesTests {
assertThat(secondEvent.isDone).isFalse()
throw TestException()
}
fail("Should not have successfully completed transaction")
} catch (e: TestException) {
}
assertThat(secondEvent.isDone).isTrue()

View File

@ -11,10 +11,8 @@
package net.corda.attachmentdemo
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.getOrThrow
import net.corda.node.services.Permissions.Companion.invokeRpc
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.node.services.Permissions.Companion.all
import net.corda.testing.core.DUMMY_BANK_A_NAME
import net.corda.testing.core.DUMMY_BANK_B_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME
@ -42,14 +40,7 @@ class AttachmentDemoTest : IntegrationTest() {
fun `attachment demo using a 10MB zip file`() {
val numOfExpectedBytes = 10_000_000
driver(DriverParameters(isDebug = true, portAllocation = PortAllocation.Incremental(20000), startNodesInProcess = true)) {
val demoUser = listOf(User("demo", "demo", setOf(
startFlow<AttachmentDemoFlow>(),
invokeRpc(CordaRPCOps::attachmentExists),
invokeRpc(CordaRPCOps::uploadAttachment),
invokeRpc(CordaRPCOps::openAttachment),
invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed)
)))
val demoUser = listOf(User("demo", "demo", setOf(all())))
val (nodeA, nodeB) = listOf(
startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = demoUser, maximumHeapSize = "1g"),
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = demoUser, maximumHeapSize = "1g")

View File

@ -96,14 +96,12 @@ fun sender(rpc: CordaRPCOps, numOfClearBytes: Int = 1024) { // default size 1K.
}
private fun sender(rpc: CordaRPCOps, inputStream: InputStream, hash: SecureHash.SHA256, executor: ScheduledExecutorService) {
// Get the identity key of the other side (the recipient).
val notaryFuture: CordaFuture<Party> = poll(executor, DUMMY_NOTARY_NAME.toString()) { rpc.wellKnownPartyFromX500Name(DUMMY_NOTARY_NAME) }
val otherSideFuture: CordaFuture<Party> = poll(executor, DUMMY_BANK_B_NAME.toString()) { rpc.wellKnownPartyFromX500Name(DUMMY_BANK_B_NAME) }
// Make sure we have the file in storage
if (!rpc.attachmentExists(hash)) {
inputStream.use {
val avail = inputStream.available()
val id = rpc.uploadAttachment(it)
require(hash == id) { "Id was '$id' instead of '$hash'" }
}
@ -143,6 +141,7 @@ class AttachmentDemoFlow(private val otherSide: Party,
}
}
@Suppress("DEPRECATION")
// DOCSTART 1
fun recipient(rpc: CordaRPCOps, webPort: Int) {
println("Waiting to receive transaction ...")

View File

@ -68,9 +68,7 @@ repositories {
maven {
url 'https://dl.bintray.com/palantir/releases' // docker-compose-rule is published on bintray
}
repositories {
maven { url 'https://jitpack.io' }
}
maven { url 'https://jitpack.io' }
}
dependencies {

View File

@ -8,6 +8,8 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
@file:Suppress("DEPRECATION")
package net.corda.test.spring
import net.corda.core.concurrent.CordaFuture

View File

@ -0,0 +1,49 @@
apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
dependencies {
cordaCompile project(":core")
cordaCompile project(":node-api")
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
testCompile project(":test-utils")
testCompile "junit:junit:$junit_version"
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
ext.rpcUsers = [['username': "default", 'password': "default", 'permissions': [ 'ALL' ]]]
directory "./build/nodes"
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : false]
p2pPort 10002
rpcSettings {
port 10003
adminPort 10004
}
h2Port 20004
}
node {
name "O=Bank A,L=London,C=GB"
p2pPort 10005
cordapps = []
rpcUsers = ext.rpcUsers
rpcSettings {
port 10007
adminPort 10008
}
}
node {
name "O=Bank B,L=New York,C=US"
p2pPort 10009
cordapps = []
rpcUsers = ext.rpcUsers
rpcSettings {
port 10011
adminPort 10012
}
}
}

View File

@ -0,0 +1,81 @@
package net.corda.verification
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.CommandData
import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractState
import net.corda.core.flows.*
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.unwrap
@StartableByRPC
@InitiatingFlow
class TestCommsFlowInitiator(val x500Name: CordaX500Name? = null) : FlowLogic<List<String>>() {
object SENDING : ProgressTracker.Step("SENDING")
object RECIEVED_ALL : ProgressTracker.Step("RECIEVED_ALL")
object FINALIZING : ProgressTracker.Step("FINALIZING")
override val progressTracker: ProgressTracker = ProgressTracker(SENDING, RECIEVED_ALL, FINALIZING)
@Suspendable
override fun call(): List<String> {
progressTracker.currentStep = SENDING
val responses = serviceHub.networkMapCache.allNodes.map {
it.legalIdentities.first()
}.filterNot {
it in serviceHub.myInfo.legalIdentities
}.filterNot {
it in serviceHub.networkMapCache.notaryIdentities
}.filter(::matchesX500)
.map {
val initiateFlow = initiateFlow(it)
initiateFlow.receive<String>().unwrap { it }
}.toList().also {
progressTracker.currentStep = RECIEVED_ALL
}
val tx = TransactionBuilder(notary = serviceHub.networkMapCache.notaryIdentities.first())
tx.addOutputState(CommsTestState(responses, serviceHub.myInfo.legalIdentities.first()), CommsTestContract::class.qualifiedName!!)
tx.addCommand(CommsTestCommand, serviceHub.myInfo.legalIdentities.first().owningKey)
val signedTx = serviceHub.signInitialTransaction(tx)
subFlow(FinalityFlow(signedTx))
return responses
}
fun matchesX500(it: Party): Boolean {
return x500Name?.equals(it.name) ?: true
}
}
@InitiatedBy(TestCommsFlowInitiator::class)
class TestCommsFlowResponder(val otherSideSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
otherSideSession.send("Hello from: " + serviceHub.myInfo.legalIdentities.first().name.toString())
}
}
@CordaSerializable
data class CommsTestState(val responses: List<String>, val issuer: AbstractParty) : ContractState {
override val participants: List<AbstractParty>
get() = listOf(issuer)
}
@CordaSerializable
object CommsTestCommand : CommandData
class CommsTestContract : Contract {
override fun verify(tx: LedgerTransaction) {
}
}

View File

@ -0,0 +1,65 @@
package net.corda.verification
import net.corda.core.contracts.CommandData
import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractState
import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.AbstractParty
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
@StartableByRPC
class TestNotaryFlow : FlowLogic<String>() {
object ISSUING : ProgressTracker.Step("ISSUING")
object ISSUED : ProgressTracker.Step("ISSUED")
object DESTROYING : ProgressTracker.Step("DESTROYING")
object FINALIZED : ProgressTracker.Step("FINALIZED")
override val progressTracker: ProgressTracker = ProgressTracker(ISSUING, ISSUED, DESTROYING, FINALIZED)
override fun call(): String {
val issueBuilder = TransactionBuilder()
val notary = serviceHub.networkMapCache.notaryIdentities.first()
issueBuilder.notary = notary;
val myIdentity = serviceHub.myInfo.legalIdentities.first()
issueBuilder.addOutputState(NotaryTestState(notary.name.toString(), myIdentity), NotaryTestContract::class.qualifiedName!!)
issueBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey)
val signedTx = serviceHub.signInitialTransaction(issueBuilder)
val issueResult = subFlow(FinalityFlow(signedTx))
progressTracker.currentStep = ISSUED
val destroyBuilder = TransactionBuilder()
destroyBuilder.notary = notary;
destroyBuilder.addInputState(issueResult.tx.outRefsOfType<NotaryTestState>().first())
destroyBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey)
val signedDestroyT = serviceHub.signInitialTransaction(destroyBuilder)
val result = subFlow(FinalityFlow(signedDestroyT))
progressTracker.currentStep = DESTROYING
progressTracker.currentStep = FINALIZED
return "notarised: " + result.notary.toString() + "::" + result.tx.id
}
}
@CordaSerializable
data class NotaryTestState(val id: String, val issuer: AbstractParty) : ContractState {
override val participants: List<AbstractParty>
get() = listOf(issuer)
}
@CordaSerializable
object NotaryTestCommand : CommandData
class NotaryTestContract : Contract {
override fun verify(tx: LedgerTransaction) {
}
}

View File

@ -0,0 +1,34 @@
package net.corda.configsample
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.DUMMY_BANK_A_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.core.TestIdentity
import net.corda.verification.TestCommsFlowInitiator
import org.junit.Assert
import org.junit.Test
class TestCommsFlowInitiatorTest {
val ALICE = TestIdentity(ALICE_NAME, 70)
val NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 12)
val DUMMY_BANK_A = TestIdentity(DUMMY_BANK_A_NAME, 3)
@Test
fun `should allow all node infos through if no x500 is passed`() {
val testCommsFlowInitiator = TestCommsFlowInitiator()
Assert.assertTrue(testCommsFlowInitiator.matchesX500(ALICE.party))
Assert.assertTrue(testCommsFlowInitiator.matchesX500(NOTARY.party))
Assert.assertTrue(testCommsFlowInitiator.matchesX500(DUMMY_BANK_A.party))
}
@Test
fun `should allow only specified x500 if no x500 is passed`() {
val testCommsFlowInitiator = TestCommsFlowInitiator(ALICE_NAME)
Assert.assertTrue(testCommsFlowInitiator.matchesX500(ALICE.party))
Assert.assertFalse(testCommsFlowInitiator.matchesX500(NOTARY.party))
Assert.assertFalse(testCommsFlowInitiator.matchesX500(DUMMY_BANK_A.party))
}
}

View File

@ -83,6 +83,7 @@ task predeterminise(type: ProGuardTask, dependsOn: project(':core-deterministic'
dontpreverify
dontobfuscate
dontoptimize
dontnote
printseeds
verbose
@ -123,6 +124,7 @@ task determinise(type: ProGuardTask) {
keepattributes '*'
keepdirectories
dontobfuscate
dontnote
printseeds
verbose
@ -161,7 +163,6 @@ task checkDeterminism(type: ProGuardTask, dependsOn: jdkTask) {
defaultTasks "determinise"
determinise.finalizedBy metafix
metafix.finalizedBy checkDeterminism
assemble.dependsOn checkDeterminism
def deterministicJar = metafix.outputs.files.singleFile
artifacts {

View File

@ -18,6 +18,7 @@ import java.nio.ByteBuffer
@KeepForDJVM
class OrdinalBits(private val ordinal: Int) {
@KeepForDJVM
interface OrdinalWriter {
val bits: OrdinalBits
@JvmDefault val encodedSize get() = 1

View File

@ -10,6 +10,7 @@
package net.corda.serialization.internal.amqp
import net.corda.core.KeepForDJVM
import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.SerializationContext
import net.corda.serialization.internal.amqp.SerializerFactory.Companion.nameForType
@ -68,6 +69,7 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
* subclass in the schema, so that we can distinguish between subclasses.
*/
// TODO: should this be a custom serializer at all, or should it just be a plain AMQPSerializer?
@KeepForDJVM
class SubClass<T : Any>(private val clazz: Class<*>, private val superClassSerializer: CustomSerializer<T>) : CustomSerializer<T>() {
// TODO: should this be empty or contain the schema of the super?
override val schemaForDocumentation = Schema(emptyList())

View File

@ -80,6 +80,7 @@ enum class TransformTypes(val build: (Annotation) -> Transform) : DescribedType
* @param constants The list of enum constants on the type the transforms are being applied to
*/
override fun validate(list: List<Transform>, constants: Map<String, Int>) {
@KeepForDJVM
data class Node(val transform: RenameSchemaTransform, var next: Node?, var prev: Node?, var visitedBy: Node? = null) {
fun visit(visitedBy: Node) {
this.visitedBy = visitedBy

View File

@ -164,6 +164,7 @@ class EnumDefaultSchemaTransform(val old: String, val new: String) : Transform()
* @property from the name of the property or constant prior to being changed, i.e. what it was
* @property to the new name of the property or constant after the change has been made, i.e. what it is now
*/
@KeepForDJVM
class RenameSchemaTransform(val from: String, val to: String) : Transform() {
companion object : DescribedTypeConstructor<RenameSchemaTransform> {
/**

View File

@ -23,7 +23,7 @@ public class JavaGenericsTest {
private final Integer v;
private Inner(Integer v) { this.v = v; }
public Integer getV() { return v; }
Integer getV() { return v; }
}
private static class A<T> {
@ -35,7 +35,7 @@ public class JavaGenericsTest {
@Test
public void basicGeneric() throws NotSerializableException {
A a1 = new A(1);
A a1 = new A<>(1);
SerializerFactory factory = testDefaultFactory();
@ -76,7 +76,7 @@ public class JavaGenericsTest {
@Test
public void forceWildcard() throws NotSerializableException {
SerializedBytes<?> bytes = forceWildcardSerialize(new A(new Inner(29)));
SerializedBytes<?> bytes = forceWildcardSerialize(new A<>(new Inner(29)));
Inner i = (Inner)forceWildcardDeserialize(bytes).getT();
assertEquals(29, i.getV());
}
@ -85,7 +85,7 @@ public class JavaGenericsTest {
public void forceWildcardSharedFactory() throws NotSerializableException {
SerializerFactory factory = testDefaultFactory();
SerializedBytes<?> bytes = forceWildcardSerializeFactory(new A(new Inner(29)), factory);
SerializedBytes<?> bytes = forceWildcardSerializeFactory(new A<>(new Inner(29)), factory);
Inner i = (Inner)forceWildcardDeserializeFactory(bytes, factory).getT();
assertEquals(29, i.getV());

View File

@ -17,6 +17,7 @@ import java.io.NotSerializableException;
import java.lang.reflect.Field;
import java.util.Map;
import static net.corda.core.internal.InternalUtils.uncheckedCast;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.junit.Assert.*;
@ -40,6 +41,7 @@ public class JavaPrivatePropertyTests {
B(Boolean b) { this.b = b; }
@SuppressWarnings("unused")
public Boolean isB() {
return this.b;
}
@ -48,6 +50,7 @@ public class JavaPrivatePropertyTests {
static class B2 {
private Boolean b;
@SuppressWarnings("unused")
public Boolean isB() {
return this.b;
}
@ -60,6 +63,7 @@ public class JavaPrivatePropertyTests {
static class B3 {
private Boolean b;
@SuppressWarnings("unused")
// break the BEAN format explicitly (i.e. it's not isB)
public Boolean isb() {
return this.b;
@ -77,6 +81,7 @@ public class JavaPrivatePropertyTests {
return this.a;
}
@SuppressWarnings("unused")
public Boolean isA() {
return this.a > 0;
}
@ -155,7 +160,7 @@ public class JavaPrivatePropertyTests {
Field f = SerializerFactory.class.getDeclaredField("serializersByDescriptor");
f.setAccessible(true);
Map<?, AMQPSerializer<?>> serializersByDescriptor = (Map<?, AMQPSerializer<?>>) f.get(factory);
Map<?, AMQPSerializer<?>> serializersByDescriptor = uncheckedCast(f.get(factory));
assertEquals(1, serializersByDescriptor.size());
ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]);
@ -182,7 +187,7 @@ public class JavaPrivatePropertyTests {
//
Field f = SerializerFactory.class.getDeclaredField("serializersByDescriptor");
f.setAccessible(true);
Map<?, AMQPSerializer<?>> serializersByDescriptor = (Map<?, AMQPSerializer<?>>) f.get(factory);
Map<?, AMQPSerializer<?>> serializersByDescriptor = uncheckedCast(f.get(factory));
assertEquals(1, serializersByDescriptor.size());
ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]);

View File

@ -27,7 +27,6 @@ import org.junit.Test
import kotlin.test.assertEquals
class ContractAttachmentSerializerTest {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
@ -61,7 +60,7 @@ class ContractAttachmentSerializerTest {
fun `write contract attachment and read it back using token context`() {
val attachment = GeneratedAttachment("test".toByteArray())
mockServices.attachments.importAttachment(attachment.open())
mockServices.attachments.importAttachment(attachment.open(), "test", null)
val contractAttachment = ContractAttachment(attachment, DummyContract.PROGRAM_ID)
val serialized = contractAttachment.serialize(factory, contextWithToken)
@ -78,7 +77,7 @@ class ContractAttachmentSerializerTest {
val largeAttachmentSize = 1024 * 1024
val attachment = GeneratedAttachment(ByteArray(largeAttachmentSize))
mockServices.attachments.importAttachment(attachment.open())
mockServices.attachments.importAttachment(attachment.open(), "test", null)
val contractAttachment = ContractAttachment(attachment, DummyContract.PROGRAM_ID)
val serialized = contractAttachment.serialize(factory, contextWithToken)

View File

@ -12,10 +12,9 @@ package net.corda.serialization.internal.amqp
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput
import net.corda.serialization.internal.amqp.testutils.deserialize
import net.corda.serialization.internal.amqp.testutils.serialize
import net.corda.serialization.internal.amqp.testutils.testDefaultFactory
import net.corda.serialization.internal.amqp.testutils.testName
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Ignore
import org.junit.Test
import java.io.NotSerializableException
@ -38,7 +37,7 @@ class ErrorMessagesTests {
val testname = "${javaClass.name}\$${testName()}"
Assertions.assertThatThrownBy {
assertThatThrownBy {
TestSerializationOutput(VERBOSE, sf).serialize(C(1))
}.isInstanceOf(NotSerializableException::class.java).hasMessage(errMsg("a", testname))
}
@ -53,7 +52,7 @@ class ErrorMessagesTests {
val testname = "${javaClass.name}\$${testName()}"
Assertions.assertThatThrownBy {
assertThatThrownBy {
TestSerializationOutput(VERBOSE, sf).serialize(C(1, 2))
}.isInstanceOf(NotSerializableException::class.java).hasMessage(errMsg("b", testname))
}
@ -65,28 +64,27 @@ class ErrorMessagesTests {
// despite b being private, the getter we've added is public and thus allows for the serialisation
// of the object
data class C(val a: Int, private val b: Int) {
public fun getB() = b
@Suppress("unused")
fun getB() = b
}
val sf = testDefaultFactory()
val testname = "${javaClass.name}\$${testName()}"
val bytes = TestSerializationOutput(VERBOSE, sf).serialize(C(1, 2))
val c = DeserializationInput(sf).deserialize(bytes)
DeserializationInput(sf).deserialize(bytes)
}
// Java allows this to be set at the class level yet Kotlin doesn't for some reason
@Ignore("Current behaviour allows for the serialization of objects with private members, this will be disallowed at some point in the future")
@Test
fun protectedProperty() {
data class C(protected val a: Int)
open class C(@Suppress("unused") protected val a: Int)
val sf = testDefaultFactory()
val testname = "${javaClass.name}\$${testName()}"
Assertions.assertThatThrownBy {
assertThatThrownBy {
TestSerializationOutput(VERBOSE, sf).serialize(C(1))
}.isInstanceOf(NotSerializableException::class.java).hasMessage(errMsg("a", testname))
}

View File

@ -287,7 +287,7 @@ class GenericsTests {
private fun fingerprintingDiffersStrip(state: Any) {
class cl : ClassLoader()
val m = ClassLoader::class.java.getDeclaredMethod("findLoadedClass", *arrayOf<Class<*>>(String::class.java))
val m = ClassLoader::class.java.getDeclaredMethod("findLoadedClass", String::class.java)
m.isAccessible = true
val factory1 = testDefaultFactory()
@ -305,16 +305,16 @@ class GenericsTests {
// now deserialise those objects
val factory3 = testDefaultFactory()
factory3.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
val des1 = DeserializationInput(factory3).deserializeAndReturnEnvelope(ser1.obj)
DeserializationInput(factory3).deserializeAndReturnEnvelope(ser1.obj)
val factory4 = SerializerFactory(AllWhitelist, cl())
factory4.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
val des2 = DeserializationInput(factory4).deserializeAndReturnEnvelope(ser2.obj)
DeserializationInput(factory4).deserializeAndReturnEnvelope(ser2.obj)
}
@Test
fun fingerprintingDiffers() {
val state = TransactionState<TestContractState> (
val state = TransactionState(
TestContractState(listOf(miniCorp.party)),
"wibble", miniCorp.party,
encumbrance = null,
@ -327,7 +327,7 @@ class GenericsTests {
@Test
fun fingerprintingDiffersList() {
val state = TransactionState<TestContractState> (
val state = TransactionState(
TestContractState(listOf(miniCorp.party)),
"wibble", miniCorp.party,
encumbrance = null,

View File

@ -107,7 +107,7 @@ class PrivatePropertyTests {
@ConstructorForDeserialization
constructor() : this(0, 0)
fun setA(a: Int, b: Int) { this.a = a }
fun setA(a: Int, @Suppress("UNUSED_PARAMETER") b: Int) { this.a = a }
fun getA() = a
}

View File

@ -4,7 +4,8 @@ import net.corda.core.serialization.ConstructorForDeserialization
import net.corda.serialization.internal.amqp.testutils.deserialize
import net.corda.serialization.internal.amqp.testutils.serialize
import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryNoEvolution
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Test
class RoundTripTests {
@ -16,20 +17,15 @@ class RoundTripTests {
val bytes = SerializationOutput(factory).serialize(C(mutableListOf("a", "b", "c")))
val newC = DeserializationInput(factory).deserialize(bytes)
Assertions.assertThatThrownBy {
assertThatThrownBy {
newC.l.add("d")
}.isInstanceOf(UnsupportedOperationException::class.java)
}
@Test
fun mutableStillMutable() {
class C {
val l: MutableList<String>
@Suppress("Unused")
constructor (l: MutableList<String>) {
this.l = l.toMutableList()
}
class C(l: MutableList<String>) {
val l: MutableList<String> = l.toMutableList()
}
val factory = testDefaultFactoryNoEvolution()
@ -37,6 +33,7 @@ class RoundTripTests {
val newC = DeserializationInput(factory).deserialize(bytes)
newC.l.add("d")
assertThat(newC.l).containsExactly("a", "b", "c", "d")
}
@Test
@ -52,6 +49,7 @@ class RoundTripTests {
val newC = DeserializationInput(factory).deserialize(bytes)
newC.l.add("d")
assertThat(newC.l).containsExactly("a", "b", "c", "d")
}
@Test
@ -61,6 +59,6 @@ class RoundTripTests {
val factory = testDefaultFactoryNoEvolution()
val bytes = SerializationOutput(factory).serialize(C(listOf("a", "b", "c")))
val newC = DeserializationInput(factory).deserialize(bytes)
val newC2 = newC.copy(l = (newC.l + "d"))
newC.copy(l = (newC.l + "d"))
}
}
}

View File

@ -898,6 +898,7 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
class GenericSubclass(param: OtherGeneric<String>) : GenericSuperclass<String>(param) {
override fun equals(other: Any?): Boolean = other is GenericSubclass // This is a bit lame but we just want to check it doesn't throw exceptions
override fun hashCode(): Int = javaClass.hashCode()
}
@Test
@ -976,8 +977,10 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
assertSame(objCopy.a, objCopy.b)
}
data class Spike private constructor(val a: String) {
class Spike private constructor(val a: String) {
constructor() : this("a")
override fun equals(other: Any?): Boolean = other is Spike && other.a == this.a
override fun hashCode(): Int = a.hashCode()
}
@Test
@ -1038,7 +1041,7 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
serdes(obj, factory, factory2)
}
data class ByteArrays(val a: ByteArray, val b: ByteArray)
class ByteArrays(val a: ByteArray, val b: ByteArray)
@Test
fun `test byte arrays not reference counted`() {
@ -1172,7 +1175,7 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
}
//
// Example stacktrace that this test is tryint to reproduce
// Example stacktrace that this test is trying to reproduce
//
// java.lang.IllegalArgumentException:
// net.corda.core.contracts.TransactionState ->
@ -1189,10 +1192,6 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
//
@Test
fun reproduceWrongNumberOfArguments() {
val field = SerializerFactory::class.java.getDeclaredField("serializersByType").apply {
this.isAccessible = true
}
data class C(val a: Amount<Currency>)
val factory = testDefaultFactoryNoEvolution()
@ -1347,7 +1346,7 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
val bytes = SerializationOutput(testDefaultFactory()).serialize(i)
try {
val i2 = DeserializationInput(testDefaultFactory()).deserialize(bytes)
DeserializationInput(testDefaultFactory()).deserialize(bytes)
} catch (e: NotSerializableException) {
throw Error("Deserializing serialized \$C should not throw")
}

View File

@ -45,7 +45,7 @@ class SerializationPropertyOrdering {
val u = User(l,l)
val output = TestSerializationOutput(VERBOSE, sf).serializeAndReturnSchema(u)
val input = DeserializationInput(sf).deserialize(output.obj)
DeserializationInput(sf).deserialize(output.obj)
}
@Test

View File

@ -79,6 +79,7 @@ include 'samples:notary-demo'
include 'samples:bank-of-corda-demo'
include 'samples:business-network-demo'
include 'samples:cordapp-configuration'
include 'samples:network-verifier'
include 'serialization'
include 'serialization-deterministic'
include 'cordform-common'

View File

@ -45,7 +45,7 @@ class MockKeyManagementService(val identityService: IdentityService,
override fun filterMyKeys(candidateKeys: Iterable<PublicKey>): Iterable<PublicKey> = candidateKeys.filter { it in this.keys }
override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate {
return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey), revocationEnabled)
return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey))
}
private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey))

View File

@ -79,10 +79,10 @@ abstract class NodeBasedTest(private val cordappPackages: List<String> = emptyLi
// Wait until ports are released
val portNotBoundChecks = startedNodes.flatMap {
listOf(
it.internals.configuration.p2pAddress.let { addressMustNotBeBoundFuture(shutdownExecutor, it) },
it.internals.configuration.rpcOptions.address?.let { addressMustNotBeBoundFuture(shutdownExecutor, it) }
addressMustNotBeBoundFuture(shutdownExecutor, it.internals.configuration.p2pAddress),
addressMustNotBeBoundFuture(shutdownExecutor, it.internals.configuration.rpcOptions.address)
)
}.filterNotNull()
}
startedNodes.clear()
portNotBoundChecks.transpose().getOrThrow()
} finally {

View File

@ -10,12 +10,15 @@
package net.corda.testing.internal
import net.corda.core.contracts.*
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.Crypto.generateKeyPair
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.NodeInfo
import net.corda.core.transactions.WireTransaction
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.loggerFor
import net.corda.node.services.config.configureDevKeyAndTrustStores
@ -149,3 +152,15 @@ fun createNodeSslConfig(path: Path, name: CordaX500Name = CordaX500Name("MegaCor
return sslConfig
}
/** This is the same as the deprecated [WireTransaction] c'tor but avoids the deprecation warning. */
fun createWireTransaction(inputs: List<StateRef>,
attachments: List<SecureHash>,
outputs: List<TransactionState<*>>,
commands: List<Command<*>>,
notary: Party?,
timeWindow: TimeWindow?,
privacySalt: PrivacySalt = PrivacySalt()): WireTransaction {
val componentGroups = WireTransaction.createComponentGroups(inputs, outputs, commands, attachments, notary, timeWindow)
return WireTransaction(componentGroups, privacySalt)
}

View File

@ -196,6 +196,7 @@ class NodeTerminalView : Fragment() {
invoke = ::pollCashBalances
)
@Suppress("DEPRECATION")
private fun initialise(config: NodeConfigWrapper, ops: CordaRPCOps) {
try {
val (txInit, txNext) = ops.internalVerifiedTransactionsFeed()

View File

@ -11,19 +11,10 @@ buildscript {
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
}
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'java'

View File

@ -13,7 +13,6 @@ import java.io.File
class CommandLineInterface {
fun run(parsedArgs: CliParser) {
val baseDir = parsedArgs.baseDirectory
val cacheDir = File(baseDir, Constants.BOOTSTRAPPER_DIR_NAME)
@ -37,7 +36,7 @@ class CommandLineInterface {
.build().getOrThrow()
persistContext(contextFile, objectMapper, context)
} else {
val context = setupContextFromExisting(contextFile, objectMapper, networkName)
val context = setupContextFromExisting(contextFile, objectMapper)
val (_, instantiator, _) = Backend.fromContext(context, cacheDir)
val nodeAdder = NodeAdder(context, NodeInstantiator(instantiator, context))
parsedArgs.nodesToAdd.map {
@ -48,7 +47,7 @@ class CommandLineInterface {
}
private fun setupContextFromExisting(contextFile: File, objectMapper: ObjectMapper, networkName: String): Context {
private fun setupContextFromExisting(contextFile: File, objectMapper: ObjectMapper): Context {
return contextFile.let {
if (it.exists()) {
it.inputStream().use {

View File

@ -23,7 +23,7 @@ class Context(val networkName: String, val backendType: Backend.BackendType, bac
var extraParams = ConcurrentHashMap<String, String>(backendOptions)
private fun registerNode(name: String, nodeInstanceRequest: NodeInstanceRequest) {
nodes.computeIfAbsent(name, { _ -> ConcurrentHashSet() }).add(nodeInstanceRequest.toPersistable())
nodes.computeIfAbsent(name) { ConcurrentHashSet() }.add(nodeInstanceRequest.toPersistable())
}
fun registerNode(request: NodeInstanceRequest) {
@ -53,7 +53,7 @@ class Context(val networkName: String, val backendType: Backend.BackendType, bac
nodeInstanceRequest.actualX500,
nodeInstanceRequest.localImageId,
nodeInstanceRequest.remoteImageName,
nodeInstanceRequest.nodeConfig.rpcOptions.address!!.port,
nodeInstanceRequest.nodeConfig.rpcOptions.address.port,
nodeInstanceRequest.expectedFqName,
"",
""
@ -62,8 +62,7 @@ class Context(val networkName: String, val backendType: Backend.BackendType, bac
}
}
fun NodeInstanceRequest.toPersistable(): PersistableNodeInstance {
private fun NodeInstanceRequest.toPersistable(): PersistableNodeInstance {
return fromInstanceRequest(this)
}
}

View File

@ -2,12 +2,11 @@ package net.corda.bootstrapper.nodes
import com.typesafe.config.ConfigFactory
import net.corda.bootstrapper.Constants
import org.slf4j.LoggerFactory
import net.corda.core.utilities.contextLogger
import java.io.File
class NodeFinder(private val scratchDir: File) {
fun findNodes(): List<FoundNode> {
return scratchDir.walkBottomUp().filter { it.name == "node.conf" && !it.absolutePath.contains(Constants.BOOTSTRAPPER_DIR_NAME) }.map {
try {
@ -17,7 +16,7 @@ class NodeFinder(private val scratchDir: File) {
}
}.filterNotNull()
.filter { !it.first.hasPath("notary") }
.map { (nodeConfig, nodeConfigFile) ->
.map { (_, nodeConfigFile) ->
LOG.info("We've found a node with name: ${nodeConfigFile.parentFile.name}")
FoundNode(nodeConfigFile, nodeConfigFile.parentFile)
}.toList()
@ -25,7 +24,7 @@ class NodeFinder(private val scratchDir: File) {
}
companion object {
val LOG = LoggerFactory.getLogger(NodeFinder::class.java)
val LOG = contextLogger()
}
}

View File

@ -39,40 +39,37 @@ class NodeInstantiator(val instantiator: Instantiator,
}
fun instantiateNodeInstance(request: Context.PersistableNodeInstance): CompletableFuture<InstanceInfo> {
return instantiateNodeInstance(request.remoteImageName, request.rpcPort!!, request.instanceName, request.fqdn, request.instanceX500).thenApplyAsync {
return instantiateNodeInstance(request.remoteImageName, request.instanceName, request.fqdn, request.instanceX500).thenApplyAsync {
InstanceInfo(request.groupName, request.instanceName, request.fqdn, it.first, it.second)
}
}
fun instantiateNodeInstance(request: NodeInstanceRequest): CompletableFuture<NodeInstance> {
return instantiateNodeInstance(request.remoteImageName, request.nodeConfig.rpcOptions.address!!.port, request.nodeInstanceName, request.expectedFqName, request.actualX500)
return instantiateNodeInstance(request.remoteImageName, request.nodeInstanceName, request.expectedFqName, request.actualX500)
.thenApplyAsync { (reachableName, portMapping) ->
request.toNodeInstance(reachableName, portMapping)
}
}
fun instantiateNotaryInstance(request: NodeInstanceRequest): CompletableFuture<NodeInstance> {
return instantiateNotaryInstance(request.remoteImageName, request.nodeConfig.rpcOptions.address!!.port, request.nodeInstanceName, request.expectedFqName)
return instantiateNotaryInstance(request.remoteImageName, request.nodeInstanceName, request.expectedFqName)
.thenApplyAsync { (reachableName, portMapping) ->
request.toNodeInstance(reachableName, portMapping)
}
}
private fun instantiateNotaryInstance(remoteImageName: String,
rpcPort: Int,
nodeInstanceName: String,
expectedFqName: String): CompletableFuture<Pair<String, Map<Int, Int>>> {
return instantiator.instantiateContainer(
remoteImageName,
listOf(Constants.NODE_P2P_PORT, Constants.NODE_RPC_PORT, Constants.NODE_SSHD_PORT),
nodeInstanceName,
mapOf("OUR_NAME" to expectedFqName,
"OUR_PORT" to Constants.NODE_P2P_PORT.toString())
mapOf("OUR_NAME" to expectedFqName, "OUR_PORT" to Constants.NODE_P2P_PORT.toString())
)
}
private fun instantiateNodeInstance(remoteImageName: String,
rpcPort: Int,
nodeInstanceName: String,
expectedFqName: String,
actualX500: String): CompletableFuture<Pair<String, Map<Int, Int>>> {

View File

@ -7,13 +7,12 @@ import net.corda.serialization.internal.AMQP_P2P_CONTEXT
import net.corda.serialization.internal.AMQP_STORAGE_CONTEXT
import net.corda.serialization.internal.SerializationFactoryImpl
class SerializationEngine {
companion object {
fun init() {
synchronized(this) {
if (nodeSerializationEnv == null) {
val classloader = this.javaClass.classLoader
val classloader = this::class.java.classLoader
nodeSerializationEnv = SerializationEnvironmentImpl(
SerializationFactoryImpl().apply {
registerScheme(AMQPServerSerializationScheme(emptyList()))
@ -27,4 +26,4 @@ class SerializationEngine {
}
}
}
}
}