mirror of
https://github.com/corda/corda.git
synced 2025-05-06 02:28:28 +00:00
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:
commit
c40e080dcc
5
.idea/compiler.xml
generated
5
.idea/compiler.xml
generated
@ -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" />
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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 -->
|
||||||
|
@ -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
|
||||||
|
Binary file not shown.
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
* Don’t 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
|
||||||
|
@ -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
|
||||||
|
@ -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``
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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:")
|
||||||
|
@ -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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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.
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||||
|
)
|
@ -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()
|
||||||
|
|
||||||
}
|
}
|
@ -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
|
@ -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
|
@ -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")
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
|
@ -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())
|
||||||
}
|
}
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
@ -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>()
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
|
@ -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,
|
||||||
|
@ -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"
|
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)) {
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"/>
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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())
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user