Merge remote-tracking branch 'open/master' into os-merge-3136e97

# Conflicts:
#	.idea/compiler.xml
#	node/src/main/kotlin/net/corda/node/serialization/kryo/CordaClassResolver.kt
#	node/src/main/kotlin/net/corda/node/serialization/kryo/CordaClosureSerializer.kt
#	node/src/main/kotlin/net/corda/node/serialization/kryo/DefaultKryoCustomizer.kt
#	node/src/main/kotlin/net/corda/node/serialization/kryo/Kryo.kt
#	node/src/main/kotlin/net/corda/node/serialization/kryo/KryoSerializationScheme.kt
#	node/src/main/kotlin/net/corda/node/serialization/kryo/SerializeAsTokenSerializer.kt
#	node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt
#	node/src/test/kotlin/net/corda/node/serialization/kryo/KryoStreamsTest.kt
#	node/src/test/kotlin/net/corda/node/serialization/kryo/KryoTests.kt
#	serialization/src/main/kotlin/net/corda/serialization/internal/SharedContexts.kt
This commit is contained in:
Shams Asari 2018-05-24 13:20:16 +01:00
commit c40e080dcc
67 changed files with 392 additions and 219 deletions

5
.idea/compiler.xml generated
View File

@ -56,6 +56,9 @@
<module name="corda-utils_integrationTest" target="1.8" /> <module name="corda-utils_integrationTest" target="1.8" />
<module name="corda-utils_main" target="1.8" /> <module name="corda-utils_main" target="1.8" />
<module name="corda-utils_test" target="1.8" /> <module name="corda-utils_test" target="1.8" />
<module name="corda-utils_integrationTest" target="1.8" />
<module name="corda-utils_main" target="1.8" />
<module name="corda-utils_test" target="1.8" />
<module name="corda-webserver_integrationTest" target="1.8" /> <module name="corda-webserver_integrationTest" target="1.8" />
<module name="corda-webserver_main" target="1.8" /> <module name="corda-webserver_main" target="1.8" />
<module name="corda-webserver_test" target="1.8" /> <module name="corda-webserver_test" target="1.8" />
@ -96,6 +99,8 @@
<module name="experimental-behave_main" target="1.8" /> <module name="experimental-behave_main" target="1.8" />
<module name="experimental-behave_smokeTest" target="1.8" /> <module name="experimental-behave_smokeTest" target="1.8" />
<module name="experimental-behave_test" target="1.8" /> <module name="experimental-behave_test" target="1.8" />
<module name="experimental-blobinspector_main" target="1.8" />
<module name="experimental-blobinspector_test" target="1.8" />
<module name="experimental-kryo-hook_main" target="1.8" /> <module name="experimental-kryo-hook_main" target="1.8" />
<module name="experimental-kryo-hook_test" target="1.8" /> <module name="experimental-kryo-hook_test" target="1.8" />
<module name="experimental_main" target="1.8" /> <module name="experimental_main" target="1.8" />

View File

@ -125,6 +125,7 @@ see changes to this list.
* Micheal Hinstridge (Thoughtworks) * Micheal Hinstridge (Thoughtworks)
* Michele Sollecito (R3) * Michele Sollecito (R3)
* Mike Hearn (R3) * Mike Hearn (R3)
* Mike Ward (R3)
* Mike Reichelt (US Bank) * Mike Reichelt (US Bank)
* Mustafa Ozturk (Natixis) * Mustafa Ozturk (Natixis)
* Nick Skinner (Northern Trust) * Nick Skinner (Northern Trust)
@ -161,6 +162,7 @@ see changes to this list.
* Sasmit Sahu * Sasmit Sahu
* Scott James * Scott James
* Shams Asari (R3) * Shams Asari (R3)
* Siddhartha Sengupta (Tradewind Markets)
* Simon Taylor (Barclays) * Simon Taylor (Barclays)
* Sofus Mortensen (Digital Asset Holdings) * Sofus Mortensen (Digital Asset Holdings)
* stevenroose * stevenroose

View File

@ -7,11 +7,11 @@ import net.corda.core.serialization.SerializationCustomSerializer
import net.corda.core.serialization.internal.SerializationEnvironment import net.corda.core.serialization.internal.SerializationEnvironment
import net.corda.core.serialization.internal.SerializationEnvironmentImpl import net.corda.core.serialization.internal.SerializationEnvironmentImpl
import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.serialization.internal.nodeSerializationEnv
import net.corda.nodeapi.internal.serialization.amqp.custom.RxNotificationSerializer
import net.corda.serialization.internal.* import net.corda.serialization.internal.*
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
/** /**

View File

@ -23,7 +23,7 @@
<Appenders> <Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT"> <Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout pattern="%highlight{%level{length=1} %date{HH:mm:ssZ} [%t] %c{2}.%method - %msg %X%n}{INFO=white,WARN=red,FATAL=bright red}" /> <PatternLayout pattern="%highlight{%level{length=1} %date{HH:mm:ssZ} [%t] %c{2}.%method - %msg %equals{%X}{{}}{}%n}{INFO=white,WARN=red,FATAL=bright red}" />
</Console> </Console>
<!-- Required for printBasicInfo --> <!-- Required for printBasicInfo -->

View File

@ -13,9 +13,9 @@ package net.corda.core.utilities
import com.esotericsoftware.kryo.KryoException import com.esotericsoftware.kryo.KryoException
import net.corda.core.crypto.random63BitValue import net.corda.core.crypto.random63BitValue
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.serialization.internal.KRYO_CHECKPOINT_CONTEXT import net.corda.node.serialization.kryo.KRYO_CHECKPOINT_CONTEXT
import net.corda.node.serialization.kryo.kryoMagic
import net.corda.serialization.internal.SerializationContextImpl import net.corda.serialization.internal.SerializationContextImpl
import net.corda.serialization.internal.kryo.kryoMagic
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule import org.junit.Rule

View File

@ -7,6 +7,10 @@ release, see :doc:`upgrade-notes`.
Unreleased Unreleased
========== ==========
* ``NodeStartup`` will now only print node's configuration if ``devMode`` is ``true``, avoiding the risk of printing passwords in a production setup.
* SLF4J's MDC will now only be printed to the console if not empty. No more log lines ending with "{}".
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be * ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be
public and was already internal for Kotlin code. public and was already internal for Kotlin code.

View File

@ -11,20 +11,16 @@ Identifying an area to contribute
--------------------------------- ---------------------------------
There are several ways to identify an area where you can contribute to Corda: There are several ways to identify an area where you can contribute to Corda:
* Browse issues labelled as ``good first issue`` in the
`Corda GitHub Issues <https://github.com/corda/corda/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22>`_
* Any issue with a ``good first issue`` label is considered ideal for open-source contributions
* If there is a feature you would like to add and there isn't a corresponding issue labelled as ``good first issue``,
that doesn't mean your contribution isn't welcome. Please reach out on the ``#design`` channel to clarify (see
below)
* Ask in the ``#design`` channel of the `Corda Slack <http://slack.corda.net/>`_ * Ask in the ``#design`` channel of the `Corda Slack <http://slack.corda.net/>`_
* Browse the `Corda GitHub issues <https://github.com/corda/corda/issues>`_
* It's always worth checking in the ``#design`` channel whether a given issue is a good target for your
contribution. Someone else may already be working on it, or it may be blocked by an on-going piece of work
* Browse issues labelled as ``HelpWanted`` on the
`Corda JIRA board <https://r3-cev.atlassian.net/issues/?jql=labels%20%3D%20HelpWanted>`_
* Any issue with a ``HelpWanted`` label is considered ideal for open-source contributions
* If there is a feature you would like to add and there isn't a corresponding issue labelled as ``HelpWanted``, that
doesn't mean your contribution isn't welcome. Please reach out on the ``#design`` channel to clarify
Making the required changes Making the required changes
--------------------------- ---------------------------
@ -32,44 +28,117 @@ Making the required changes
2. Clone the fork to your local machine 2. Clone the fork to your local machine
3. Make the changes, in accordance with the :doc:`code style guide </codestyle>` 3. Make the changes, in accordance with the :doc:`code style guide </codestyle>`
Things to check
^^^^^^^^^^^^^^^
Is your error handling up to scratch?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Errors should not leak to the UI. When writing tools intended for end users, like the node or command line tools,
remember to add ``try``/``catch`` blocks. Throw meaningful errors. For example, instead of throwing an
``OutOfMemoryError``, use the error message to indicate that a file is missing, a network socket was unreachable, etc.
Tools should not dump stack traces to the end user.
Look for API breaks
~~~~~~~~~~~~~~~~~~~
We have an automated checker tool that runs as part of our continuous integration pipeline and helps a lot, but it
can't catch semantic changes where the behavior of an API changes in ways that might violate app developer expectations.
Suppress inevitable compiler warnings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compiler warnings should have a ``@Suppress`` annotation on them if they're expected and can't be avoided.
Remove deprecated functionality
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When deprecating functionality, make sure you remove the deprecated uses in the codebase.
Avoid making formatting changes as you work
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In Kotlin 1.2.20, new style guide rules were implemented. The new Kotlin style guide is significantly more detailed
than before and IntelliJ knows how to implement those rules. Re-formatting the codebase creates a lot of diffs that
make merging more complicated.
Things to consider when writing CLI apps
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Set exit codes using ``exitProcess``. Zero means success. Other numbers mean errors. Setting a unique error code
(starting from 1) for each thing that can conceivably break makes your tool shell-scripting friendly
* Do a bit of work to figure out reasonable defaults. Nobody likes having to set a dozen flags before the tool will
cooperate
* Your ``--help`` text or other docs should ideally include examples. Writing examples is also a good way to find out
that your program requires a dozen flags to do anything
* Flags should have sensible defaults
* Dont print logging output to the console unless the user requested it via a ``verbose`` flag (conventionally
shortened to ``-v``) or a ``log-to-console`` flag. Logs should be either suppressed or saved to a text file during
normal usage, except for errors, which are always OK to print
Testing the changes Testing the changes
------------------- -------------------
Adding tests
^^^^^^^^^^^^
Unit tests and integration tests for external API changes must cover Java and Kotlin. For internal API changes these
tests can be scaled back to kotlin only.
Running the tests Running the tests
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
Your changes must pass the tests described :doc:`here </testing>`. Your changes must pass the tests described :doc:`here </testing>`.
Manual testing
^^^^^^^^^^^^^^
Before sending that code for review, spend time poking and prodding the tool and thinking, “Would the experience of
using this feature make my mum proud of me?”. Automated tests are not a substitute for dogfooding.
Building against the master branch Building against the master branch
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can test your changes against CorDapps defined in other repos by following the instructions :doc:`here </building-against-master>`. You can test your changes against CorDapps defined in other repos by following the instructions
:doc:`here </building-against-master>`.
Updating the docs Updating the docs
----------------- -----------------
Any changes to Corda's public API must be documented as follows: Any changes to Corda's public API must be documented as follows:
1. Update the relevant `.rst file(s) <https://github.com/corda/corda/tree/master/docs/source>`_ 1. Add comments and javadocs/kdocs. API functions must have javadoc/kdoc comments and sentences must be terminated
2. Include the change in the :doc:`changelog </changelog>` and :doc:`release notes </release-notes>` where applicable with a full stop. We also start comments with capital letters, even for inline comments. Where Java APIs have
3. :doc:`Build the docs locally </building-the-docs>` synonyms (e.g. ``%d`` and ``%date``), we prefer the longer form for legibility reasons. You can configure your IDE
4. Open the built .html files for the modified pages to ensure they render correctly to highlight these in bright yellow
2. Update the relevant `.rst file(s) <https://github.com/corda/corda/tree/master/docs/source>`_
3. Include the change in the :doc:`changelog </changelog>` if the change is external and therefore visible to CorDapp
developers and/or node operators
4. :doc:`Build the docs locally </building-the-docs>`
5. Check the built .html files (under ``docs/build/html``) for the modified pages to ensure they render correctly
6. If relevant, add a sample. Samples are one of the key ways in which users learn about what the platform can do.
If you add a new API or feature and don't update the samples, your work will be much less impactful
Merging the changes back into Corda Merging the changes back into Corda
----------------------------------- -----------------------------------
1. Create a pull request from your fork to the master branch of the Corda repo 1. Create a pull request from your fork to the ``master`` branch of the Corda repo
2. Complete the pull-request checklist in the comments box:
* State that you have run the tests 2. In the PR comments box, complete the pull-request checklist:
* State that you have included JavaDocs for any new public APIs
* State that you have included the change in the :doc:`changelog </changelog>` and
:doc:`release notes </release-notes>` where applicable
* State that you are in agreement with the terms of
`CONTRIBUTING.md <https://github.com/corda/corda/blob/master/CONTRIBUTING.md>`_
3. Request a review from a member of the Corda platform team via the `#design channel <http://slack.corda.net/>`_ * [ ] Have you run the unit, integration and smoke tests as described here? https://docs.corda.net/head/testing.html
4. Wait for your PR to pass all four types of continuous integration tests (integration, API stability, build and unit) * [ ] If you added/changed public APIs, did you write/update the JavaDocs?
* [ ] If the changes are of interest to application developers, have you added them to the changelog, and potentially
release notes?
* [ ] If you are contributing for the first time, please read the agreement in CONTRIBUTING.md now and add to this
Pull Request that you agree to it.
* Currently, external contributors cannot see the output of these tests. If your PR fails a test that passed 3. In the PR comments box, also add a clear description of the purpose for the PR
locally, ask the reviewer for further details
5. Once a reviewer has approved the PR and the tests have passed, squash-and-merge the PR as a single commit 4. Request a review from a member of the Corda platform team via the `#design channel <http://slack.corda.net/>`_
5. The reviewer will either:
* Accept and merge your PR
* Request that you make further changes. Do this by committing and pushing the changes onto the branch you are PRing
into Corda. The PR will be updated automatically

View File

@ -66,6 +66,34 @@ created the "denial of state" transaction, allowing the attack to be resolved of
In the case of the validating model, the use of anonymous, freshly-generated public keys instead of legal identities to In the case of the validating model, the use of anonymous, freshly-generated public keys instead of legal identities to
identify parties in a transaction limit the information the notary cluster sees. identify parties in a transaction limit the information the notary cluster sees.
Data visibility
^^^^^^^^^^^^^^^
Below is a summary of what specific transaction components have to be revealed to each type of notary:
+-----------------------------------+---------------+-----------------------+
| Transaction components | Validating | Non-validating |
+===================================+===============+=======================+
| Input states | Fully visible | References only [1]_ |
+-----------------------------------+---------------+-----------------------+
| Output states | Fully visible | Hidden |
+-----------------------------------+---------------+-----------------------+
| Commands (with signer identities) | Fully visible | Hidden |
+-----------------------------------+---------------+-----------------------+
| Attachments | Fully visible | Hidden |
+-----------------------------------+---------------+-----------------------+
| Time window | Fully visible | Fully visible |
+-----------------------------------+---------------+-----------------------+
| Notary identity | Fully visible | Fully visible |
+-----------------------------------+---------------+-----------------------+
| Signatures | Fully visible | Hidden |
+-----------------------------------+---------------+-----------------------+
Both types of notaries record the calling party's identity: the public key and the X.500 Distinguished Name.
.. [1] A state reference is composed of the issuing transaction's id and the state's position in the outputs. It does not
reveal what kind of state it is or its contents.
Multiple notaries Multiple notaries
----------------- -----------------
Each Corda network can have multiple notary clusters, each potentially running a different consensus algorithm. This Each Corda network can have multiple notary clusters, each potentially running a different consensus algorithm. This

View File

@ -6,7 +6,7 @@ Default in-memory database
By default, nodes store their data in an H2 database. You can connect directly to a running node's database to see its By default, nodes store their data in an H2 database. You can connect directly to a running node's database to see its
stored states, transactions and attachments as follows: stored states, transactions and attachments as follows:
* Download the `h2 platform-independent zip <http://www.h2database.com/html/download.html>`_, unzip the zip, and * Download the **last stable** `h2 platform-independent zip <http://www.h2database.com/html/download.html>`_, unzip the zip, and
navigate in a terminal window to the unzipped folder navigate in a terminal window to the unzipped folder
* Change directories to the bin folder: ``cd h2/bin`` * Change directories to the bin folder: ``cd h2/bin``

View File

@ -7,7 +7,7 @@ Attachments are ZIP/JAR files referenced from transaction by hash, but not inclu
itself. These files are automatically requested from the node sending the transaction when needed and cached itself. These files are automatically requested from the node sending the transaction when needed and cached
locally so they are not re-requested if encountered again. Attachments typically contain: locally so they are not re-requested if encountered again. Attachments typically contain:
* Contract executable code * Contract code
* Metadata about a transaction, such as PDF version of an invoice being settled * Metadata about a transaction, such as PDF version of an invoice being settled
* Shared information to be permanently recorded on the ledger * Shared information to be permanently recorded on the ledger

View File

@ -5,7 +5,11 @@ import net.corda.core.serialization.EncodingWhitelist
import net.corda.core.serialization.SerializationEncoding import net.corda.core.serialization.SerializationEncoding
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.serialization.internal.SerializationFactoryImpl import net.corda.serialization.internal.SerializationFactoryImpl
import net.corda.serialization.internal.amqp.* import net.corda.serialization.internal.amqp.CompositeType
import net.corda.serialization.internal.amqp.DeserializationInput
import net.corda.serialization.internal.amqp.RestrictedType
import net.corda.serialization.internal.amqp.TypeNotation
import net.corda.serialization.internal.amqp.amqpMagic
import org.apache.qpid.proton.amqp.Binary import org.apache.qpid.proton.amqp.Binary
import org.apache.qpid.proton.amqp.DescribedType import org.apache.qpid.proton.amqp.DescribedType
import org.apache.qpid.proton.amqp.Symbol import org.apache.qpid.proton.amqp.Symbol

View File

@ -37,19 +37,16 @@ import net.corda.serialization.internal.CordaSerializationMagic
import net.corda.serialization.internal.SerializationFactoryImpl import net.corda.serialization.internal.SerializationFactoryImpl
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.kryo.AbstractKryoSerializationScheme
import net.corda.serialization.internal.kryo.kryoMagic
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardCopyOption.REPLACE_EXISTING import java.nio.file.StandardCopyOption.REPLACE_EXISTING
import java.time.Instant import java.time.Instant
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.TimeoutException import java.util.concurrent.TimeoutException
import kotlin.streams.toList
import kotlin.collections.HashSet
import kotlin.collections.component1 import kotlin.collections.component1
import kotlin.collections.component2 import kotlin.collections.component2
import kotlin.collections.set import kotlin.collections.set
import kotlin.streams.toList
/** /**
* Class to bootstrap a local network of Corda nodes on the same filesystem. * Class to bootstrap a local network of Corda nodes on the same filesystem.
@ -348,22 +345,12 @@ class NetworkBootstrapper {
private fun initialiseSerialization() { private fun initialiseSerialization() {
_contextSerializationEnv.set(SerializationEnvironmentImpl( _contextSerializationEnv.set(SerializationEnvironmentImpl(
SerializationFactoryImpl().apply { SerializationFactoryImpl().apply {
registerScheme(KryoParametersSerializationScheme)
registerScheme(AMQPParametersSerializationScheme) registerScheme(AMQPParametersSerializationScheme)
}, },
AMQP_P2P_CONTEXT) AMQP_P2P_CONTEXT)
) )
} }
private object KryoParametersSerializationScheme : AbstractKryoSerializationScheme() {
override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean {
return magic == kryoMagic && target == SerializationContext.UseCase.P2P
}
override fun rpcClientKryoPool(context: SerializationContext) = throw UnsupportedOperationException()
override fun rpcServerKryoPool(context: SerializationContext) = throw UnsupportedOperationException()
}
private object AMQPParametersSerializationScheme : AbstractAMQPSerializationScheme(emptyList()) { private object AMQPParametersSerializationScheme : AbstractAMQPSerializationScheme(emptyList()) {
override fun rpcClientSerializerFactory(context: SerializationContext) = throw UnsupportedOperationException() override fun rpcClientSerializerFactory(context: SerializationContext) = throw UnsupportedOperationException()
override fun rpcServerSerializerFactory(context: SerializationContext) = throw UnsupportedOperationException() override fun rpcServerSerializerFactory(context: SerializationContext) = throw UnsupportedOperationException()

View File

@ -21,10 +21,10 @@ import net.corda.core.serialization.serialize
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.config.SSLConfiguration
import net.corda.nodeapi.internal.createDevKeyStores import net.corda.nodeapi.internal.createDevKeyStores
import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.SerializationContextImpl import net.corda.serialization.internal.SerializationContextImpl
import net.corda.serialization.internal.SerializationFactoryImpl import net.corda.serialization.internal.SerializationFactoryImpl
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.AllWhitelist
import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.TestIdentity import net.corda.testing.core.TestIdentity
@ -362,13 +362,15 @@ class X509UtilitiesTest {
@Test @Test
fun `serialize - deserialize X509CertPath`() { fun `serialize - deserialize X509CertPath`() {
val factory = SerializationFactoryImpl().apply { registerScheme(AMQPServerSerializationScheme()) } val factory = SerializationFactoryImpl().apply { registerScheme(AMQPServerSerializationScheme()) }
val context = SerializationContextImpl(amqpMagic, val context = SerializationContextImpl(
amqpMagic,
javaClass.classLoader, javaClass.classLoader,
AllWhitelist, AllWhitelist,
emptyMap(), emptyMap(),
true, true,
SerializationContext.UseCase.P2P, SerializationContext.UseCase.P2P,
null) null
)
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE_NAME.x500Principal, rootCAKey) val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE_NAME.x500Principal, rootCAKey)
val certificate = X509Utilities.createCertificate(CertificateType.TLS, rootCACert, rootCAKey, BOB_NAME.x500Principal, BOB.publicKey) val certificate = X509Utilities.createCertificate(CertificateType.TLS, rootCACert, rootCAKey, BOB_NAME.x500Principal, BOB.publicKey)

View File

@ -84,6 +84,10 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
// Kryo: object graph serialization.
compile "com.esotericsoftware:kryo:4.0.0"
compile "de.javakaffee:kryo-serializers:0.41"
compile "com.google.guava:guava:$guava_version" compile "com.google.guava:guava:$guava_version"
// For caches rather than guava // For caches rather than guava

View File

@ -10,12 +10,14 @@
package net.corda.node package net.corda.node
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import joptsimple.OptionSet import joptsimple.OptionSet
import joptsimple.util.EnumConverter import joptsimple.util.EnumConverter
import joptsimple.util.PathConverter import joptsimple.util.PathConverter
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.exists import net.corda.core.internal.exists
import net.corda.core.utilities.Try
import net.corda.node.services.config.ConfigHelper import net.corda.node.services.config.ConfigHelper
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.parseAsNodeConfiguration import net.corda.node.services.config.parseAsNodeConfiguration
@ -125,19 +127,22 @@ data class CmdLineOptions(val baseDirectory: Path,
val bootstrapRaftCluster: Boolean, val bootstrapRaftCluster: Boolean,
val unknownConfigKeysPolicy: UnknownConfigKeysPolicy, val unknownConfigKeysPolicy: UnknownConfigKeysPolicy,
val devMode: Boolean) { val devMode: Boolean) {
fun loadConfig(): NodeConfiguration { fun loadConfig(): Pair<Config, Try<NodeConfiguration>> {
val config = ConfigHelper.loadConfig( val rawConfig = ConfigHelper.loadConfig(
baseDirectory, baseDirectory,
configFile, configFile,
configOverrides = ConfigFactory.parseMap(mapOf("noLocalShell" to this.noLocalShell) + configOverrides = ConfigFactory.parseMap(mapOf("noLocalShell" to this.noLocalShell) +
if (devMode) mapOf("devMode" to this.devMode) else emptyMap<String, Any>()) if (devMode) mapOf("devMode" to this.devMode) else emptyMap<String, Any>())
).parseAsNodeConfiguration(unknownConfigKeysPolicy::handle) )
if (nodeRegistrationOption != null) { return rawConfig to Try.on {
require(!config.devMode) { "registration cannot occur in devMode" } rawConfig.parseAsNodeConfiguration(unknownConfigKeysPolicy::handle).also {
requireNotNull(config.compatibilityZoneURL) { if (nodeRegistrationOption != null) {
"compatibilityZoneURL must be present in node configuration file in registration mode." require(!it.devMode) { "registration cannot occur in devMode" }
requireNotNull(it.compatibilityZoneURL) {
"compatibilityZoneURL must be present in node configuration file in registration mode."
}
}
} }
} }
return config
} }
} }

View File

@ -382,6 +382,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
NodeInfoWatcher(configuration.baseDirectory, getRxIoScheduler(), Duration.ofMillis(configuration.additionalNodeInfoPollingFrequencyMsec)), NodeInfoWatcher(configuration.baseDirectory, getRxIoScheduler(), Duration.ofMillis(configuration.additionalNodeInfoPollingFrequencyMsec)),
networkMapClient, networkMapClient,
networkParameters.serialize().hash, networkParameters.serialize().hash,
services.myInfo.serialize().hash,
configuration.baseDirectory, configuration.baseDirectory,
configuration.extraNetworkMapKeys) configuration.extraNetworkMapKeys)
runOnStop += networkMapUpdater::close runOnStop += networkMapUpdater::close
@ -862,7 +863,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
private fun makeIdentityService(identityCert: X509Certificate): PersistentIdentityService { private fun makeIdentityService(identityCert: X509Certificate): PersistentIdentityService {
val trustRoot = configuration.loadTrustStore().getCertificate(X509Utilities.CORDA_ROOT_CA) val trustRoot = configuration.loadTrustStore().getCertificate(X509Utilities.CORDA_ROOT_CA)
val nodeCa = configuration.loadNodeKeyStore().getCertificate(X509Utilities.CORDA_CLIENT_CA) val nodeCa = configuration.loadNodeKeyStore().getCertificate(X509Utilities.CORDA_CLIENT_CA)
return PersistentIdentityService(trustRoot, identityCert, nodeCa) return PersistentIdentityService(trustRoot, listOf(identityCert, nodeCa))
} }
protected abstract fun makeTransactionVerifierService(): TransactionVerifierService protected abstract fun makeTransactionVerifierService(): TransactionVerifierService

View File

@ -38,6 +38,7 @@ import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.security.RPCSecurityManagerImpl import net.corda.node.internal.security.RPCSecurityManagerImpl
import net.corda.node.internal.security.RPCSecurityManagerWithAdditionalUser import net.corda.node.internal.security.RPCSecurityManagerWithAdditionalUser
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
import net.corda.node.serialization.kryo.KRYO_CHECKPOINT_CONTEXT
import net.corda.node.serialization.kryo.KryoServerSerializationScheme import net.corda.node.serialization.kryo.KryoServerSerializationScheme
import net.corda.node.services.Permissions import net.corda.node.services.Permissions
import net.corda.node.services.api.NodePropertiesStore import net.corda.node.services.api.NodePropertiesStore

View File

@ -11,6 +11,8 @@
package net.corda.node.internal package net.corda.node.internal
import com.jcabi.manifests.Manifests import com.jcabi.manifests.Manifests
import com.typesafe.config.Config
import com.typesafe.config.ConfigRenderOptions
import io.netty.channel.unix.Errors import io.netty.channel.unix.Errors
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.cordapp.Cordapp import net.corda.core.cordapp.Cordapp
@ -19,6 +21,7 @@ import net.corda.core.internal.concurrent.thenMatch
import net.corda.core.internal.createDirectories import net.corda.core.internal.createDirectories
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.randomOrNull import net.corda.core.internal.randomOrNull
import net.corda.core.utilities.Try
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.node.CmdLineOptions import net.corda.node.CmdLineOptions
import net.corda.node.NodeArgsParser import net.corda.node.NodeArgsParser
@ -91,7 +94,11 @@ open class NodeStartup(val args: Array<String>) {
drawBanner(versionInfo) drawBanner(versionInfo)
Node.printBasicNodeInfo(LOGS_CAN_BE_FOUND_IN_STRING, System.getProperty("log-path")) Node.printBasicNodeInfo(LOGS_CAN_BE_FOUND_IN_STRING, System.getProperty("log-path"))
val conf = try { val conf = try {
val conf0 = loadConfigFile(cmdlineOptions) val (rawConfig, conf0Result) = loadConfigFile(cmdlineOptions)
if (cmdlineOptions.devMode) {
println("Config:\n${rawConfig.root().render(ConfigRenderOptions.defaults())}")
}
val conf0 = conf0Result.getOrThrow()
if (cmdlineOptions.bootstrapRaftCluster) { if (cmdlineOptions.bootstrapRaftCluster) {
if (conf0 is NodeConfigurationImpl) { if (conf0 is NodeConfigurationImpl) {
println("Bootstrapping raft cluster (starting up as seed node).") println("Bootstrapping raft cluster (starting up as seed node).")
@ -223,7 +230,7 @@ open class NodeStartup(val args: Array<String>) {
NodeRegistrationHelper(conf, HTTPNetworkRegistrationService(compatibilityZoneURL), nodeRegistrationConfig).buildKeystore() NodeRegistrationHelper(conf, HTTPNetworkRegistrationService(compatibilityZoneURL), nodeRegistrationConfig).buildKeystore()
} }
protected open fun loadConfigFile(cmdlineOptions: CmdLineOptions): NodeConfiguration = cmdlineOptions.loadConfig() protected open fun loadConfigFile(cmdlineOptions: CmdLineOptions): Pair<Config, Try<NodeConfiguration>> = cmdlineOptions.loadConfig()
protected open fun banJavaSerialisation(conf: NodeConfiguration) { protected open fun banJavaSerialisation(conf: NodeConfiguration) {
val isOracleDbDriver = conf.dataSourceProperties.getProperty("dataSource.url", "").startsWith("jdbc:oracle:") val isOracleDbDriver = conf.dataSourceProperties.getProperty("dataSource.url", "").startsWith("jdbc:oracle:")

View File

@ -4,10 +4,10 @@ import net.corda.core.cordapp.Cordapp
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationCustomSerializer import net.corda.core.serialization.SerializationCustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.custom.RxNotificationSerializer
import net.corda.serialization.internal.CordaSerializationMagic import net.corda.serialization.internal.CordaSerializationMagic
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
/** /**

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.* import com.esotericsoftware.kryo.*
import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Input
@ -23,6 +23,7 @@ import net.corda.core.serialization.SerializationContext
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.serialization.internal.AttachmentsClassLoader import net.corda.serialization.internal.AttachmentsClassLoader
import net.corda.serialization.internal.MutableClassWhitelist import net.corda.serialization.internal.MutableClassWhitelist
import net.corda.serialization.internal.TransientClassWhiteList
import net.corda.serialization.internal.amqp.hasAnnotationInHierarchy import net.corda.serialization.internal.amqp.hasAnnotationInHierarchy
import java.io.PrintWriter import java.io.PrintWriter
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
@ -156,43 +157,6 @@ class CordaClassResolver(serializationContext: SerializationContext) : DefaultCl
} }
} }
class BuiltInExceptionsWhitelist : ClassWhitelist {
companion object {
private val packageName = "^(?:java|kotlin)(?:[.]|$)".toRegex()
}
override fun hasListed(type: Class<*>) = Throwable::class.java.isAssignableFrom(type) && packageName.containsMatchIn(type.`package`.name)
}
sealed class AbstractMutableClassWhitelist(private val whitelist: MutableSet<String>, private val delegate: ClassWhitelist) : MutableClassWhitelist {
override fun hasListed(type: Class<*>): Boolean {
/**
* There are certain delegates like [net.corda.serialization.internal.AllButBlacklisted]
* which may throw when asked whether the type is listed.
* In such situations - it may be a good idea to ask [delegate] first before making a check against own [whitelist].
*/
return delegate.hasListed(type) || (type.name in whitelist)
}
override fun add(entry: Class<*>) {
whitelist += entry.name
}
}
// TODO: Need some concept of from which class loader
class GlobalTransientClassWhiteList(delegate: ClassWhitelist) : AbstractMutableClassWhitelist(whitelist, delegate) {
companion object {
private val whitelist: MutableSet<String> = Collections.synchronizedSet(mutableSetOf())
}
}
/**
* A whitelist that can be customised via the [net.corda.core.serialization.SerializationWhitelist],
* since it implements [MutableClassWhitelist].
*/
class TransientClassWhiteList(delegate: ClassWhitelist) : AbstractMutableClassWhitelist(Collections.synchronizedSet(mutableSetOf()), delegate)
/** /**
* This class is not currently used, but can be installed to log a large number of missing entries from the whitelist * This class is not currently used, but can be installed to log a large number of missing entries from the whitelist
* and was used to track down the initial set. * and was used to track down the initial set.

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.Serializer import com.esotericsoftware.kryo.Serializer

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.* import com.esotericsoftware.kryo.*
import com.esotericsoftware.kryo.factories.ReflectionSerializerFactory import com.esotericsoftware.kryo.factories.ReflectionSerializerFactory

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import co.paralleluniverse.fibers.Fiber import co.paralleluniverse.fibers.Fiber
import co.paralleluniverse.io.serialization.kryo.KryoSerializer import co.paralleluniverse.io.serialization.kryo.KryoSerializer
@ -22,10 +22,10 @@ import com.esotericsoftware.kryo.serializers.ClosureSerializer
import net.corda.core.internal.uncheckedCast import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.serialization.internal.* import net.corda.serialization.internal.*
import net.corda.serialization.internal.SectionId
import java.security.PublicKey import java.security.PublicKey
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@ -140,3 +140,14 @@ abstract class AbstractKryoSerializationScheme : SerializationScheme {
} }
} }
} }
val KRYO_CHECKPOINT_CONTEXT = SerializationContextImpl(
kryoMagic,
SerializationDefaults.javaClass.classLoader,
QuasarWhitelist,
emptyMap(),
true,
SerializationContext.UseCase.Checkpoint,
null,
AlwaysAcceptEncodingWhitelist
)

View File

@ -13,8 +13,6 @@ package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.pool.KryoPool import com.esotericsoftware.kryo.pool.KryoPool
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.serialization.internal.CordaSerializationMagic import net.corda.serialization.internal.CordaSerializationMagic
import net.corda.serialization.internal.kryo.AbstractKryoSerializationScheme
import net.corda.serialization.internal.kryo.kryoMagic
class KryoServerSerializationScheme : AbstractKryoSerializationScheme() { class KryoServerSerializationScheme : AbstractKryoSerializationScheme() {
override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean { override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean {
@ -22,7 +20,5 @@ class KryoServerSerializationScheme : AbstractKryoSerializationScheme() {
} }
override fun rpcClientKryoPool(context: SerializationContext): KryoPool = throw UnsupportedOperationException() override fun rpcClientKryoPool(context: SerializationContext): KryoPool = throw UnsupportedOperationException()
override fun rpcServerKryoPool(context: SerializationContext): KryoPool = throw UnsupportedOperationException() override fun rpcServerKryoPool(context: SerializationContext): KryoPool = throw UnsupportedOperationException()
} }

View File

@ -10,7 +10,7 @@
@file:JvmName("KryoStreams") @file:JvmName("KryoStreams")
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.KryoException import com.esotericsoftware.kryo.KryoException

View File

@ -15,7 +15,6 @@ import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigFactory.systemEnvironment import com.typesafe.config.ConfigFactory.systemEnvironment
import com.typesafe.config.ConfigFactory.systemProperties import com.typesafe.config.ConfigFactory.systemProperties
import com.typesafe.config.ConfigParseOptions import com.typesafe.config.ConfigParseOptions
import com.typesafe.config.ConfigRenderOptions
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.createDirectories import net.corda.core.internal.createDirectories
import net.corda.core.internal.div import net.corda.core.internal.div
@ -64,8 +63,6 @@ object ConfigHelper {
.withFallback(defaultConfig) .withFallback(defaultConfig)
.resolve() .resolve()
log.info("Config:\n${finalConfig.root().render(ConfigRenderOptions.defaults())}")
val entrySet = finalConfig.entrySet().filter { entry -> entry.key.contains("\"") } val entrySet = finalConfig.entrySet().filter { entry -> entry.key.contains("\"") }
for ((key) in entrySet) { for ((key) in entrySet) {
log.error("Config files should not contain \" in property names. Please fix: $key") log.error("Config files should not contain \" in property names. Please fix: $key")

View File

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

View File

@ -38,10 +38,17 @@ import javax.persistence.Entity
import javax.persistence.Id import javax.persistence.Id
import javax.persistence.Lob import javax.persistence.Lob
/**
* An identity service that stores parties and their identities to a key value tables in the database. The entries are
* cached for efficient lookup.
*
* @param trustRoot certificate from the zone operator for identity on the network.
* @param caCertificates list of additional certificates.
*/
// TODO There is duplicated logic between this and InMemoryIdentityService // TODO There is duplicated logic between this and InMemoryIdentityService
@ThreadSafe @ThreadSafe
class PersistentIdentityService(override val trustRoot: X509Certificate, class PersistentIdentityService(override val trustRoot: X509Certificate,
vararg caCertificates: X509Certificate) : SingletonSerializeAsToken(), IdentityServiceInternal { caCertificates: List<X509Certificate> = emptyList()) : SingletonSerializeAsToken(), IdentityServiceInternal {
companion object { companion object {
private val log = contextLogger() private val log = contextLogger()

View File

@ -45,6 +45,7 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
private val fileWatcher: NodeInfoWatcher, private val fileWatcher: NodeInfoWatcher,
private val networkMapClient: NetworkMapClient?, private val networkMapClient: NetworkMapClient?,
private val currentParametersHash: SecureHash, private val currentParametersHash: SecureHash,
private val ourNodeInfoHash: SecureHash?,
private val baseDirectory: Path, private val baseDirectory: Path,
private val extraNetworkMapKeys: List<UUID> private val extraNetworkMapKeys: List<UUID>
) : AutoCloseable { ) : AutoCloseable {
@ -79,8 +80,10 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
networkMapCache.addNode(it.nodeInfo) networkMapCache.addNode(it.nodeInfo)
} }
is NodeInfoUpdate.Remove -> { is NodeInfoUpdate.Remove -> {
val nodeInfo = networkMapCache.getNodeByHash(it.hash) if (it.hash != ourNodeInfoHash) {
nodeInfo?.let { networkMapCache.removeNode(it) } val nodeInfo = networkMapCache.getNodeByHash(it.hash)
nodeInfo?.let { networkMapCache.removeNode(it) }
}
} }
} }
} }
@ -137,8 +140,11 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
// Remove node info from network map. // Remove node info from network map.
(currentNodeHashes - allHashesFromNetworkMap - fileWatcher.processedNodeInfoHashes) (currentNodeHashes - allHashesFromNetworkMap - fileWatcher.processedNodeInfoHashes)
.mapNotNull(networkMapCache::getNodeByHash) .mapNotNull {
.forEach(networkMapCache::removeNode) if (it != ourNodeInfoHash) {
networkMapCache.getNodeByHash(it)
} else null
}.forEach(networkMapCache::removeNode)
return cacheTimeout return cacheTimeout
} }

View File

@ -1,9 +1,9 @@
package net.corda.node.internal.serialization.testutils package net.corda.node.internal.serialization.testutils
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.SerializationContextImpl import net.corda.serialization.internal.SerializationContextImpl
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.AllWhitelist
val serializationProperties: MutableMap<Any, Any> = mutableMapOf() val serializationProperties: MutableMap<Any, Any> = mutableMapOf()
@ -14,4 +14,5 @@ val serializationContext = SerializationContextImpl(
properties = serializationProperties, properties = serializationProperties,
objectReferencesEnabled = false, objectReferencesEnabled = false,
useCase = SerializationContext.UseCase.Testing, useCase = SerializationContext.UseCase.Testing,
encoding = null) encoding = null
)

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import net.corda.core.internal.declaredField import net.corda.core.internal.declaredField
import net.corda.serialization.internal.ByteBufferOutputStream import net.corda.serialization.internal.ByteBufferOutputStream
@ -38,7 +38,7 @@ class KryoStreamsTest {
fun `substitute output works`() { fun `substitute output works`() {
assertArrayEquals(byteArrayOf(100, -101), kryoOutput { assertArrayEquals(byteArrayOf(100, -101), kryoOutput {
write(100) write(100)
substitute(::NegOutputStream) substitute(KryoStreamsTest::NegOutputStream)
write(101) write(101)
}) })
} }
@ -47,7 +47,7 @@ class KryoStreamsTest {
fun `substitute input works`() { fun `substitute input works`() {
kryoInput(byteArrayOf(100, 101).inputStream()) { kryoInput(byteArrayOf(100, 101).inputStream()) {
assertEquals(100, read()) assertEquals(100, read())
substitute(::NegInputStream) substitute(KryoStreamsTest::NegInputStream)
assertEquals(-101, read().toByte()) assertEquals(-101, read().toByte())
assertEquals(-1, read()) assertEquals(-1, read())
} }

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. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
package net.corda.serialization.internal.kryo package net.corda.node.serialization.kryo
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.KryoException import com.esotericsoftware.kryo.KryoException
@ -43,6 +43,7 @@ import org.slf4j.LoggerFactory
import java.io.InputStream import java.io.InputStream
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
import kotlin.collections.ArrayList
import kotlin.test.* import kotlin.test.*
class TestScheme : AbstractKryoSerializationScheme() { class TestScheme : AbstractKryoSerializationScheme() {
@ -103,7 +104,7 @@ class KryoTests(private val compression: CordaSerializationEncoding?) {
fun `serialised form is stable when the same object instance is added to the deserialised object graph`() { fun `serialised form is stable when the same object instance is added to the deserialised object graph`() {
val noReferencesContext = context.withoutReferences() val noReferencesContext = context.withoutReferences()
val obj : ByteSequence = Ints.toByteArray(0x01234567).sequence() val obj : ByteSequence = Ints.toByteArray(0x01234567).sequence()
val originalList : ArrayList<ByteSequence> = arrayListOf(obj) val originalList : ArrayList<ByteSequence> = ArrayList<ByteSequence>().apply { this += obj }
val deserialisedList = originalList.serialize(factory, noReferencesContext).deserialize(factory, noReferencesContext) val deserialisedList = originalList.serialize(factory, noReferencesContext).deserialize(factory, noReferencesContext)
originalList += obj originalList += obj
deserialisedList += obj deserialisedList += obj
@ -116,8 +117,14 @@ class KryoTests(private val compression: CordaSerializationEncoding?) {
val instant = Instant.ofEpochMilli(123) val instant = Instant.ofEpochMilli(123)
val instantCopy = Instant.ofEpochMilli(123) val instantCopy = Instant.ofEpochMilli(123)
assertThat(instant).isNotSameAs(instantCopy) assertThat(instant).isNotSameAs(instantCopy)
val listWithCopies = arrayListOf(instant, instantCopy) val listWithCopies = ArrayList<Instant>().apply {
val listWithSameInstances = arrayListOf(instant, instant) this += instant
this += instantCopy
}
val listWithSameInstances = ArrayList<Instant>().apply {
this += instant
this += instant
}
assertThat(listWithSameInstances.serialize(factory, noReferencesContext)).isEqualTo(listWithCopies.serialize(factory, noReferencesContext)) assertThat(listWithSameInstances.serialize(factory, noReferencesContext)).isEqualTo(listWithCopies.serialize(factory, noReferencesContext))
} }

View File

@ -42,7 +42,7 @@ class InMemoryIdentityServiceTests {
val BOB get() = bob.party val BOB get() = bob.party
val BOB_IDENTITY get() = bob.identity val BOB_IDENTITY get() = bob.identity
val BOB_PUBKEY get() = bob.publicKey val BOB_PUBKEY get() = bob.publicKey
fun createService(vararg identities: PartyAndCertificate) = InMemoryIdentityService(identities, DEV_ROOT_CA.certificate) fun createService(vararg identities: PartyAndCertificate) = InMemoryIdentityService(identities.toList(), DEV_ROOT_CA.certificate)
} }
@Rule @Rule

View File

@ -15,6 +15,7 @@ import com.google.common.jimfs.Jimfs
import com.nhaarman.mockito_kotlin.* import com.nhaarman.mockito_kotlin.*
import net.corda.cordform.CordformNode.NODE_INFO_DIRECTORY import net.corda.cordform.CordformNode.NODE_INFO_DIRECTORY
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sign import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party import net.corda.core.identity.Party
@ -71,7 +72,6 @@ class NetworkMapUpdaterTest {
server = NetworkMapServer(cacheExpiryMs.millis, PortAllocation.Incremental(10000).nextHostAndPort()) server = NetworkMapServer(cacheExpiryMs.millis, PortAllocation.Incremental(10000).nextHostAndPort())
val hostAndPort = server.start() val hostAndPort = server.start()
networkMapClient = NetworkMapClient(URL("http://${hostAndPort.host}:${hostAndPort.port}"), DEV_ROOT_CA.certificate) networkMapClient = NetworkMapClient(URL("http://${hostAndPort.host}:${hostAndPort.port}"), DEV_ROOT_CA.certificate)
updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient, server.networkParameters.serialize().hash, baseDir, listOf(privateNetUUID))
} }
@After @After
@ -81,8 +81,13 @@ class NetworkMapUpdaterTest {
server.close() server.close()
} }
private fun setUpdater(ourNodeHash: SecureHash? = null, extraNetworkMapKeys: List<UUID> = emptyList()) {
updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient, server.networkParameters.serialize().hash, ourNodeHash, baseDir, extraNetworkMapKeys)
}
@Test @Test
fun `process add node updates from network map, with additional node infos from dir`() { fun `process add node updates from network map, with additional node infos from dir`() {
setUpdater()
val (nodeInfo1, signedNodeInfo1) = createNodeInfoAndSigned("Info 1") val (nodeInfo1, signedNodeInfo1) = createNodeInfoAndSigned("Info 1")
val (nodeInfo2, signedNodeInfo2) = createNodeInfoAndSigned("Info 2") val (nodeInfo2, signedNodeInfo2) = createNodeInfoAndSigned("Info 2")
val (nodeInfo3, signedNodeInfo3) = createNodeInfoAndSigned("Info 3") val (nodeInfo3, signedNodeInfo3) = createNodeInfoAndSigned("Info 3")
@ -118,6 +123,7 @@ class NetworkMapUpdaterTest {
@Test @Test
fun `process remove node updates from network map, with additional node infos from dir`() { fun `process remove node updates from network map, with additional node infos from dir`() {
setUpdater()
val (nodeInfo1, signedNodeInfo1) = createNodeInfoAndSigned("Info 1") val (nodeInfo1, signedNodeInfo1) = createNodeInfoAndSigned("Info 1")
val (nodeInfo2, signedNodeInfo2) = createNodeInfoAndSigned("Info 2") val (nodeInfo2, signedNodeInfo2) = createNodeInfoAndSigned("Info 2")
val (nodeInfo3, signedNodeInfo3) = createNodeInfoAndSigned("Info 3") val (nodeInfo3, signedNodeInfo3) = createNodeInfoAndSigned("Info 3")
@ -158,6 +164,7 @@ class NetworkMapUpdaterTest {
@Test @Test
fun `receive node infos from directory, without a network map`() { fun `receive node infos from directory, without a network map`() {
setUpdater()
val fileNodeInfoAndSigned = createNodeInfoAndSigned("Info from file") val fileNodeInfoAndSigned = createNodeInfoAndSigned("Info from file")
// Not subscribed yet. // Not subscribed yet.
@ -176,6 +183,7 @@ class NetworkMapUpdaterTest {
@Test @Test
fun `emit new parameters update info on parameters update from network map`() { fun `emit new parameters update info on parameters update from network map`() {
setUpdater()
val paramsFeed = updater.trackParametersUpdate() val paramsFeed = updater.trackParametersUpdate()
val snapshot = paramsFeed.snapshot val snapshot = paramsFeed.snapshot
val updates = paramsFeed.updates.bufferUntilSubscribed() val updates = paramsFeed.updates.bufferUntilSubscribed()
@ -198,6 +206,7 @@ class NetworkMapUpdaterTest {
@Test @Test
fun `ack network parameters update`() { fun `ack network parameters update`() {
setUpdater()
val newParameters = testNetworkParameters(epoch = 314) val newParameters = testNetworkParameters(epoch = 314)
server.scheduleParametersUpdate(newParameters, "Test update", Instant.MIN) server.scheduleParametersUpdate(newParameters, "Test update", Instant.MIN)
updater.subscribeToNetworkMap() updater.subscribeToNetworkMap()
@ -214,6 +223,7 @@ class NetworkMapUpdaterTest {
@Test @Test
fun `fetch nodes from private network`() { fun `fetch nodes from private network`() {
setUpdater(extraNetworkMapKeys = listOf(privateNetUUID))
server.addNodesToPrivateNetwork(privateNetUUID, listOf(ALICE_NAME)) server.addNodesToPrivateNetwork(privateNetUUID, listOf(ALICE_NAME))
Assertions.assertThatThrownBy { networkMapClient.getNetworkMap(privateNetUUID).payload.nodeInfoHashes } Assertions.assertThatThrownBy { networkMapClient.getNetworkMap(privateNetUUID).payload.nodeInfoHashes }
.isInstanceOf(IOException::class.java) .isInstanceOf(IOException::class.java)
@ -230,6 +240,7 @@ class NetworkMapUpdaterTest {
@Test @Test
fun `remove node from filesystem deletes it from network map cache`() { fun `remove node from filesystem deletes it from network map cache`() {
setUpdater()
val fileNodeInfoAndSigned1 = createNodeInfoAndSigned("Info from file 1") val fileNodeInfoAndSigned1 = createNodeInfoAndSigned("Info from file 1")
val fileNodeInfoAndSigned2 = createNodeInfoAndSigned("Info from file 2") val fileNodeInfoAndSigned2 = createNodeInfoAndSigned("Info from file 2")
updater.subscribeToNetworkMap() updater.subscribeToNetworkMap()
@ -252,6 +263,7 @@ class NetworkMapUpdaterTest {
@Test @Test
fun `remove node info file, but node in network map server`() { fun `remove node info file, but node in network map server`() {
setUpdater()
val nodeInfoBuilder = TestNodeInfoBuilder() val nodeInfoBuilder = TestNodeInfoBuilder()
val (_, key) = nodeInfoBuilder.addLegalIdentity(CordaX500Name("Info", "London", "GB")) val (_, key) = nodeInfoBuilder.addLegalIdentity(CordaX500Name("Info", "London", "GB"))
val (serverNodeInfo, serverSignedNodeInfo) = nodeInfoBuilder.buildWithSigned(1, 1) val (serverNodeInfo, serverSignedNodeInfo) = nodeInfoBuilder.buildWithSigned(1, 1)
@ -280,6 +292,23 @@ class NetworkMapUpdaterTest {
assertThat(networkMapCache.allNodeHashes).containsOnly(serverSignedNodeInfo.raw.hash) assertThat(networkMapCache.allNodeHashes).containsOnly(serverSignedNodeInfo.raw.hash)
} }
// Test fix for ENT-1882
// This scenario can happen when signing of network map server is performed much longer after the node joined the network.
// Network map will advertise hashes without that node.
@Test
fun `not remove own node info when it is not in network map yet`() {
val (myInfo, signedMyInfo) = createNodeInfoAndSigned("My node info")
val (_, signedOtherInfo) = createNodeInfoAndSigned("Other info")
setUpdater(ourNodeHash = signedMyInfo.raw.hash)
networkMapCache.addNode(myInfo) // Simulate behaviour on node startup when our node info is added to cache
networkMapClient.publish(signedOtherInfo)
updater.subscribeToNetworkMap()
Thread.sleep(2L * cacheExpiryMs)
verify(networkMapCache, never()).removeNode(myInfo)
assertThat(server.networkMapHashes()).containsOnly(signedOtherInfo.raw.hash)
assertThat(networkMapCache.allNodeHashes).containsExactlyInAnyOrder(signedMyInfo.raw.hash, signedOtherInfo.raw.hash)
}
private fun createMockNetworkMapCache(): NetworkMapCacheInternal { private fun createMockNetworkMapCache(): NetworkMapCacheInternal {
return mock { return mock {
val data = ConcurrentHashMap<Party, NodeInfo>() val data = ConcurrentHashMap<Party, NodeInfo>()

View File

@ -12,9 +12,6 @@ dependencies {
compile "org.apache.activemq:artemis-commons:${artemis_version}" compile "org.apache.activemq:artemis-commons:${artemis_version}"
// Kryo: object graph serialization.
compile "com.esotericsoftware:kryo:4.0.0"
compile "de.javakaffee:kryo-serializers:0.41"
compile "org.ow2.asm:asm:$asm_version" compile "org.ow2.asm:asm:$asm_version"
// For AMQP serialisation. // For AMQP serialisation.

View File

@ -15,7 +15,7 @@ internal val serializeOutputStreamPool = LazyPool(
shouldReturnToPool = { it.size() < 256 * 1024 }, // Discard if it grew too large shouldReturnToPool = { it.size() < 256 * 1024 }, // Discard if it grew too large
newInstance = { ByteBufferOutputStream(64 * 1024) }) newInstance = { ByteBufferOutputStream(64 * 1024) })
internal fun <T> byteArrayOutput(task: (ByteBufferOutputStream) -> T): ByteArray { fun <T> byteArrayOutput(task: (ByteBufferOutputStream) -> T): ByteArray {
return serializeOutputStreamPool.run { underlying -> return serializeOutputStreamPool.run { underlying ->
task(underlying) task(underlying)
underlying.toByteArray() // Must happen after close, to allow ZIP footer to be written for example. underlying.toByteArray() // Must happen after close, to allow ZIP footer to be written for example.

View File

@ -1,6 +1,7 @@
package net.corda.serialization.internal package net.corda.serialization.internal
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import java.util.*
interface MutableClassWhitelist : ClassWhitelist { interface MutableClassWhitelist : ClassWhitelist {
fun add(entry: Class<*>) fun add(entry: Class<*>)
@ -9,3 +10,41 @@ interface MutableClassWhitelist : ClassWhitelist {
object AllWhitelist : ClassWhitelist { object AllWhitelist : ClassWhitelist {
override fun hasListed(type: Class<*>): Boolean = true override fun hasListed(type: Class<*>): Boolean = true
} }
class BuiltInExceptionsWhitelist : ClassWhitelist {
companion object {
private val packageName = "^(?:java|kotlin)(?:[.]|$)".toRegex()
}
override fun hasListed(type: Class<*>): Boolean {
return Throwable::class.java.isAssignableFrom(type) && packageName.containsMatchIn(type.`package`.name)
}
}
sealed class AbstractMutableClassWhitelist(private val whitelist: MutableSet<String>, private val delegate: ClassWhitelist) : MutableClassWhitelist {
override fun hasListed(type: Class<*>): Boolean {
/**
* There are certain delegates like [net.corda.serialization.internal.AllButBlacklisted]
* which may throw when asked whether the type is listed.
* In such situations - it may be a good idea to ask [delegate] first before making a check against own [whitelist].
*/
return delegate.hasListed(type) || (type.name in whitelist)
}
override fun add(entry: Class<*>) {
whitelist += entry.name
}
}
/**
* A whitelist that can be customised via the [net.corda.core.serialization.SerializationWhitelist],
* since it implements [MutableClassWhitelist].
*/
class TransientClassWhiteList(delegate: ClassWhitelist) : AbstractMutableClassWhitelist(Collections.synchronizedSet(mutableSetOf()), delegate)
// TODO: Need some concept of from which class loader
class GlobalTransientClassWhiteList(delegate: ClassWhitelist) : AbstractMutableClassWhitelist(whitelist, delegate) {
companion object {
private val whitelist: MutableSet<String> = Collections.synchronizedSet(mutableSetOf())
}
}

View File

@ -15,9 +15,6 @@ package net.corda.serialization.internal
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationDefaults import net.corda.core.serialization.SerializationDefaults
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.kryo.BuiltInExceptionsWhitelist
import net.corda.serialization.internal.kryo.GlobalTransientClassWhiteList
import net.corda.serialization.internal.kryo.kryoMagic
/* /*
* Serialisation contexts for the client. * Serialisation contexts for the client.
@ -26,10 +23,12 @@ import net.corda.serialization.internal.kryo.kryoMagic
*/ */
val AMQP_RPC_CLIENT_CONTEXT = SerializationContextImpl(amqpMagic, val AMQP_RPC_CLIENT_CONTEXT = SerializationContextImpl(
amqpMagic,
SerializationDefaults.javaClass.classLoader, SerializationDefaults.javaClass.classLoader,
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()), GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
emptyMap(), emptyMap(),
true, true,
SerializationContext.UseCase.RPCClient, SerializationContext.UseCase.RPCClient,
null) null
)

View File

@ -10,7 +10,6 @@
package net.corda.serialization.internal package net.corda.serialization.internal
import com.esotericsoftware.kryo.KryoException
import net.corda.core.serialization.SerializationWhitelist import net.corda.core.serialization.SerializationWhitelist
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
@ -40,7 +39,6 @@ object DefaultWhitelist : SerializationWhitelist {
mapOf(Unit to Unit).javaClass, // SingletonMap mapOf(Unit to Unit).javaClass, // SingletonMap
NetworkHostAndPort::class.java, NetworkHostAndPort::class.java,
SimpleString::class.java, SimpleString::class.java,
KryoException::class.java, // TODO: Will be removed when we migrate away from Kryo
StringBuffer::class.java, StringBuffer::class.java,
Unit::class.java, Unit::class.java,
java.io.ByteArrayInputStream::class.java, java.io.ByteArrayInputStream::class.java,

View File

@ -10,7 +10,6 @@
package net.corda.serialization.internal package net.corda.serialization.internal
import net.corda.core.internal.VisibleForTesting
import net.corda.core.serialization.SerializationEncoding import net.corda.core.serialization.SerializationEncoding
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
@ -64,5 +63,4 @@ enum class CordaSerializationEncoding : SerializationEncoding, OrdinalWriter {
abstract fun wrap(stream: InputStream): InputStream abstract fun wrap(stream: InputStream): InputStream
} }
@VisibleForTesting const val encodingNotPermittedFormat = "Encoding not permitted: %s"
internal val encodingNotPermittedFormat = "Encoding not permitted: %s"

View File

@ -18,7 +18,6 @@ import net.corda.core.internal.copyBytes
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.kryo.kryoMagic
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.NotSerializableException import java.io.NotSerializableException
import java.util.* import java.util.*
@ -108,7 +107,7 @@ open class SerializationFactoryImpl(
constructor() : this(ConcurrentHashMap()) constructor() : this(ConcurrentHashMap())
companion object { companion object {
val magicSize = sequenceOf(kryoMagic, amqpMagic).map { it.size }.distinct().single() val magicSize = amqpMagic.size
} }
private val creator: List<StackTraceElement> = Exception().stackTrace.asList() private val creator: List<StackTraceElement> = Exception().stackTrace.asList()
@ -124,7 +123,7 @@ open class SerializationFactoryImpl(
return schemes.computeIfAbsent(lookupKey) { return schemes.computeIfAbsent(lookupKey) {
registeredSchemes.filter { it.canDeserializeVersion(magic, target) }.forEach { return@computeIfAbsent it } // XXX: Not single? registeredSchemes.filter { it.canDeserializeVersion(magic, target) }.forEach { return@computeIfAbsent it } // XXX: Not single?
logger.warn("Cannot find serialization scheme for: [$lookupKey, " + logger.warn("Cannot find serialization scheme for: [$lookupKey, " +
"${if (magic == amqpMagic) "AMQP" else if (magic == kryoMagic) "Kryo" else "UNKNOWN MAGIC"}] registeredSchemes are: $registeredSchemes") "${if (magic == amqpMagic) "AMQP" else "UNKNOWN MAGIC"}] registeredSchemes are: $registeredSchemes")
throw UnsupportedOperationException("Serialization scheme $lookupKey not supported.") throw UnsupportedOperationException("Serialization scheme $lookupKey not supported.")
} to magic } to magic
} }
@ -154,15 +153,12 @@ open class SerializationFactoryImpl(
registeredSchemes += scheme registeredSchemes += scheme
} }
val alreadyRegisteredSchemes: Collection<SerializationScheme> get() = Collections.unmodifiableCollection(registeredSchemes)
override fun toString(): String { override fun toString(): String {
return "${this.javaClass.name} registeredSchemes=$registeredSchemes ${creator.joinToString("\n")}" return "${this.javaClass.name} registeredSchemes=$registeredSchemes ${creator.joinToString("\n")}"
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
return other is SerializationFactoryImpl && return other is SerializationFactoryImpl && other.registeredSchemes == this.registeredSchemes
other.registeredSchemes == this.registeredSchemes
} }
override fun hashCode(): Int = registeredSchemes.hashCode() override fun hashCode(): Int = registeredSchemes.hashCode()

View File

@ -15,9 +15,6 @@ package net.corda.serialization.internal
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationDefaults import net.corda.core.serialization.SerializationDefaults
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.kryo.BuiltInExceptionsWhitelist
import net.corda.serialization.internal.kryo.GlobalTransientClassWhiteList
import net.corda.serialization.internal.kryo.kryoMagic
/* /*
* Serialisation contexts for the server. * Serialisation contexts for the server.
@ -30,19 +27,23 @@ import net.corda.serialization.internal.kryo.kryoMagic
*/ */
val AMQP_STORAGE_CONTEXT = SerializationContextImpl(amqpMagic, val AMQP_STORAGE_CONTEXT = SerializationContextImpl(
amqpMagic,
SerializationDefaults.javaClass.classLoader, SerializationDefaults.javaClass.classLoader,
AllButBlacklisted, AllButBlacklisted,
emptyMap(), emptyMap(),
true, true,
SerializationContext.UseCase.Storage, SerializationContext.UseCase.Storage,
null, null,
AlwaysAcceptEncodingWhitelist) AlwaysAcceptEncodingWhitelist
)
val AMQP_RPC_SERVER_CONTEXT = SerializationContextImpl(amqpMagic, val AMQP_RPC_SERVER_CONTEXT = SerializationContextImpl(
amqpMagic,
SerializationDefaults.javaClass.classLoader, SerializationDefaults.javaClass.classLoader,
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()), GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
emptyMap(), emptyMap(),
true, true,
SerializationContext.UseCase.RPCServer, SerializationContext.UseCase.RPCServer,
null) null
)

View File

@ -15,35 +15,18 @@ package net.corda.serialization.internal
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.serialization.internal.CordaSerializationEncoding.SNAPPY import net.corda.serialization.internal.CordaSerializationEncoding.SNAPPY
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.kryo.BuiltInExceptionsWhitelist
import net.corda.serialization.internal.kryo.GlobalTransientClassWhiteList
import net.corda.serialization.internal.kryo.kryoMagic
/* val AMQP_P2P_CONTEXT = SerializationContextImpl(
* Serialisation contexts shared by the server and client. amqpMagic,
*
* NOTE: The [KRYO_STORAGE_CONTEXT] and [AMQP_STORAGE_CONTEXT]
* CANNOT always be instantiated outside of the server and so
* MUST be kept separate from these ones!
*/
val KRYO_CHECKPOINT_CONTEXT = SerializationContextImpl(kryoMagic,
SerializationDefaults.javaClass.classLoader,
QuasarWhitelist,
emptyMap(),
true,
SerializationContext.UseCase.Checkpoint,
SNAPPY,
AlwaysAcceptEncodingWhitelist)
val AMQP_P2P_CONTEXT = SerializationContextImpl(amqpMagic,
SerializationDefaults.javaClass.classLoader, SerializationDefaults.javaClass.classLoader,
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()), GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
emptyMap(), emptyMap(),
true, true,
SerializationContext.UseCase.P2P, SerializationContext.UseCase.P2P,
null) null
)
internal object AlwaysAcceptEncodingWhitelist : EncodingWhitelist { object AlwaysAcceptEncodingWhitelist : EncodingWhitelist {
override fun acceptEncoding(encoding: SerializationEncoding) = true override fun acceptEncoding(encoding: SerializationEncoding) = true
} }

View File

@ -14,7 +14,7 @@ import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationFactory import net.corda.core.serialization.SerializationFactory
import java.util.* import java.util.*
internal fun checkUseCase(allowedUseCases: EnumSet<SerializationContext.UseCase>) { fun checkUseCase(allowedUseCases: EnumSet<SerializationContext.UseCase>) {
val currentContext: SerializationContext = SerializationFactory.currentFactory?.currentContext val currentContext: SerializationContext = SerializationFactory.currentFactory?.currentContext
?: throw IllegalStateException("Current context is not set") ?: throw IllegalStateException("Current context is not set")
if (!allowedUseCases.contains(currentContext.useCase)) { if (!allowedUseCases.contains(currentContext.useCase)) {

View File

@ -18,10 +18,7 @@ import net.corda.core.internal.objectOrNewInstance
import net.corda.core.internal.uncheckedCast import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.serialization.internal.CordaSerializationMagic import net.corda.serialization.internal.*
import net.corda.serialization.internal.DefaultWhitelist
import net.corda.serialization.internal.MutableClassWhitelist
import net.corda.serialization.internal.SerializationScheme
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap

View File

@ -124,14 +124,33 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
} }
internal fun Class<*>.checkSupportedMapType() { internal fun Class<*>.checkSupportedMapType() {
checkHashMap()
checkWeakHashMap()
checkDictionary()
}
private fun Class<*>.checkHashMap() {
if (HashMap::class.java.isAssignableFrom(this) && !LinkedHashMap::class.java.isAssignableFrom(this)) { if (HashMap::class.java.isAssignableFrom(this) && !LinkedHashMap::class.java.isAssignableFrom(this)) {
throw IllegalArgumentException( throw IllegalArgumentException(
"Map type $this is unstable under iteration. Suggested fix: use java.util.LinkedHashMap instead.") "Map type $this is unstable under iteration. Suggested fix: use java.util.LinkedHashMap instead.")
} else if (WeakHashMap::class.java.isAssignableFrom(this)) { }
}
/**
* The [WeakHashMap] class does not exist within the DJVM, and so we need
* to isolate this reference.
*/
private fun Class<*>.checkWeakHashMap() {
if (WeakHashMap::class.java.isAssignableFrom(this)) {
throw IllegalArgumentException("Weak references with map types not supported. Suggested fix: " throw IllegalArgumentException("Weak references with map types not supported. Suggested fix: "
+ "use java.util.LinkedHashMap instead.") + "use java.util.LinkedHashMap instead.")
} else if (Dictionary::class.java.isAssignableFrom(this)) { }
}
private fun Class<*>.checkDictionary() {
if (Dictionary::class.java.isAssignableFrom(this)) {
throw IllegalArgumentException( throw IllegalArgumentException(
"Unable to serialise deprecated type $this. Suggested fix: prefer java.util.map implementations") "Unable to serialise deprecated type $this. Suggested fix: prefer java.util.map implementations")
} }
} }

View File

@ -1,4 +1,4 @@
package net.corda.nodeapi.internal.serialization.amqp.custom package net.corda.serialization.internal.amqp.custom
import net.corda.serialization.internal.amqp.CustomSerializer import net.corda.serialization.internal.amqp.CustomSerializer
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory

View File

@ -10,18 +10,18 @@
package net.corda.serialization.internal; package net.corda.serialization.internal;
import com.google.common.collect.Maps;
import net.corda.core.serialization.SerializationContext; import net.corda.core.serialization.SerializationContext;
import net.corda.core.serialization.SerializationFactory; import net.corda.core.serialization.SerializationFactory;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import net.corda.node.serialization.kryo.CordaClosureSerializer;
import net.corda.node.serialization.kryo.KryoSerializationSchemeKt;
import net.corda.testing.core.SerializationEnvironmentRule; import net.corda.testing.core.SerializationEnvironmentRule;
import net.corda.serialization.internal.kryo.CordaClosureSerializer;
import net.corda.serialization.internal.kryo.KryoSerializationSchemeKt;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -36,7 +36,15 @@ public final class LambdaCheckpointSerializationTest {
@Before @Before
public void setup() { public void setup() {
factory = testSerialization.getSerializationFactory(); factory = testSerialization.getSerializationFactory();
context = new SerializationContextImpl(KryoSerializationSchemeKt.getKryoMagic(), this.getClass().getClassLoader(), AllWhitelist.INSTANCE, Maps.newHashMap(), true, SerializationContext.UseCase.Checkpoint, null); context = new SerializationContextImpl(
KryoSerializationSchemeKt.getKryoMagic(),
getClass().getClassLoader(),
AllWhitelist.INSTANCE,
Collections.emptyMap(),
true,
SerializationContext.UseCase.Checkpoint,
null
);
} }
@Test @Test

View File

@ -24,9 +24,9 @@ import net.corda.core.node.services.AttachmentStorage
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.serialization.internal.kryo.CordaClassResolver import net.corda.node.serialization.kryo.CordaClassResolver
import net.corda.serialization.internal.kryo.CordaKryo import net.corda.node.serialization.kryo.CordaKryo
import net.corda.serialization.internal.kryo.kryoMagic import net.corda.node.serialization.kryo.kryoMagic
import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.rigorousMock
import net.corda.testing.services.MockAttachmentStorage import net.corda.testing.services.MockAttachmentStorage
import org.junit.Rule import org.junit.Rule

View File

@ -13,11 +13,11 @@ package net.corda.serialization.internal
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.util.DefaultClassResolver import com.esotericsoftware.kryo.util.DefaultClassResolver
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.node.serialization.kryo.kryoMagic
import net.corda.node.services.statemachine.DataSessionMessage import net.corda.node.services.statemachine.DataSessionMessage
import net.corda.serialization.internal.amqp.DeserializationInput import net.corda.serialization.internal.amqp.DeserializationInput
import net.corda.serialization.internal.amqp.Envelope import net.corda.serialization.internal.amqp.Envelope
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.kryo.kryoMagic
import net.corda.testing.internal.amqpSpecific import net.corda.testing.internal.amqpSpecific
import net.corda.testing.internal.kryoSpecific import net.corda.testing.internal.kryoSpecific
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule

View File

@ -16,8 +16,8 @@ import net.corda.core.identity.CordaX500Name
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.node.serialization.kryo.kryoMagic
import net.corda.node.services.statemachine.DataSessionMessage import net.corda.node.services.statemachine.DataSessionMessage
import net.corda.serialization.internal.kryo.kryoMagic
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.internal.amqpSpecific import net.corda.testing.internal.amqpSpecific
import net.corda.testing.internal.kryoSpecific import net.corda.testing.internal.kryoSpecific

View File

@ -15,10 +15,10 @@ import com.esotericsoftware.kryo.KryoException
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.serialization.internal.kryo.CordaClassResolver import net.corda.node.serialization.kryo.CordaClassResolver
import net.corda.serialization.internal.kryo.CordaKryo import net.corda.node.serialization.kryo.CordaKryo
import net.corda.serialization.internal.kryo.DefaultKryoCustomizer import net.corda.node.serialization.kryo.DefaultKryoCustomizer
import net.corda.serialization.internal.kryo.kryoMagic import net.corda.node.serialization.kryo.kryoMagic
import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.rigorousMock
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat

View File

@ -14,8 +14,8 @@ import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.util.DefaultClassResolver import com.esotericsoftware.kryo.util.DefaultClassResolver
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.node.serialization.kryo.kryoMagic
import net.corda.node.services.statemachine.DataSessionMessage import net.corda.node.services.statemachine.DataSessionMessage
import net.corda.serialization.internal.kryo.kryoMagic
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.internal.kryoSpecific import net.corda.testing.internal.kryoSpecific
import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertArrayEquals

View File

@ -3,8 +3,8 @@ package net.corda.serialization.internal.amqp
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.serialization.internal.* import net.corda.serialization.internal.*
import net.corda.serialization.internal.kryo.BuiltInExceptionsWhitelist import net.corda.serialization.internal.BuiltInExceptionsWhitelist
import net.corda.serialization.internal.kryo.GlobalTransientClassWhiteList import net.corda.serialization.internal.GlobalTransientClassWhiteList
import org.junit.Test import org.junit.Test
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -59,7 +59,7 @@ import java.util.*
/** /**
* Returns a simple [InMemoryIdentityService] containing the supplied [identities]. * Returns a simple [InMemoryIdentityService] containing the supplied [identities].
*/ */
fun makeTestIdentityService(vararg identities: PartyAndCertificate) = InMemoryIdentityService(identities, DEV_ROOT_CA.certificate) fun makeTestIdentityService(vararg identities: PartyAndCertificate) = InMemoryIdentityService(identities.toList(), DEV_ROOT_CA.certificate)
/** /**
* An implementation of [ServiceHub] that is designed for in-memory unit tests of contract validation logic. It has * An implementation of [ServiceHub] that is designed for in-memory unit tests of contract validation logic. It has

View File

@ -15,11 +15,11 @@
</Properties> </Properties>
<Appenders> <Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT"> <Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout pattern="[%-5level] %date{HH:mm:ss,SSS} [%t] (%F:%L) %c{2}.%method - %msg %X%n" /> <PatternLayout pattern="[%-5level] %date{HH:mm:ss,SSS} [%t] (%F:%L) %c{2}.%method - %msg %equals{%X}{{}}{}%n"/>
</Console> </Console>
<!-- Required for printBasicInfo --> <!-- Required for printBasicInfo -->
<Console name="Console-Appender-Println" target="SYSTEM_OUT"> <Console name="Console-Appender-Println" target="SYSTEM_OUT">
<PatternLayout pattern="%msg%n" /> <PatternLayout pattern="%msg%n"/>
</Console> </Console>
</Appenders> </Appenders>
<Loggers> <Loggers>
@ -32,8 +32,8 @@
<Logger name="BasicInfo" additivity="false"> <Logger name="BasicInfo" additivity="false">
<AppenderRef ref="Console-Appender-Println"/> <AppenderRef ref="Console-Appender-Println"/>
</Logger> </Logger>
<Logger name="org.hibernate.SQL" level="info" additivity="false"> <Logger name="org.hibernate.SQL" level="info" additivity="false">
<AppenderRef ref="Console-Appender"/> <AppenderRef ref="Console-Appender"/>
</Logger> </Logger>
<Logger name="org.jolokia" additivity="true" level="warn"> <Logger name="org.jolokia" additivity="true" level="warn">
<AppenderRef ref="Console-Appender-Println"/> <AppenderRef ref="Console-Appender-Println"/>

View File

@ -16,6 +16,7 @@ import net.corda.client.rpc.internal.serialization.amqp.AMQPClientSerializationS
import net.corda.core.DoNotImplement import net.corda.core.DoNotImplement
import net.corda.core.serialization.internal.* import net.corda.core.serialization.internal.*
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
import net.corda.node.serialization.kryo.KRYO_CHECKPOINT_CONTEXT
import net.corda.node.serialization.kryo.KryoServerSerializationScheme import net.corda.node.serialization.kryo.KryoServerSerializationScheme
import net.corda.serialization.internal.* import net.corda.serialization.internal.*
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule

View File

@ -18,7 +18,7 @@
<Appenders> <Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT"> <Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout pattern="[%-5level] %date{HH:mm:ss,SSS} [%t] (%F:%L) %c{2}.%method - %msg %X%n" /> <PatternLayout pattern="[%-5level] %date{HH:mm:ss,SSS} [%t] (%F:%L) %c{2}.%method - %msg %equals{%X}{{}}{}%n" />
</Console> </Console>
</Appenders> </Appenders>

View File

@ -46,7 +46,7 @@ class InteractiveShellTest {
override fun call() = a override fun call() = a
} }
private val ids = InMemoryIdentityService(arrayOf(megaCorp.identity), DEV_ROOT_CA.certificate) private val ids = InMemoryIdentityService(listOf(megaCorp.identity), DEV_ROOT_CA.certificate)
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory()) private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory())