mirror of
https://github.com/corda/corda.git
synced 2025-03-14 00:06:45 +00:00
Merge pull request #876 from corda/os-merge-3136e97
O/S merge from 3136e97
This commit is contained in:
commit
77ef131c0f
4
.idea/compiler.xml
generated
4
.idea/compiler.xml
generated
@ -37,6 +37,8 @@
|
||||
<module name="capsule-crr-submission_test" target="1.8" />
|
||||
<module name="capsule-hsm-cert-generator_main" target="1.8" />
|
||||
<module name="capsule-hsm-cert-generator_test" target="1.8" />
|
||||
<module name="capsule-hsm-crl-generator_main" target="1.8" />
|
||||
<module name="capsule-hsm-crl-generator_test" target="1.8" />
|
||||
<module name="capsule-hsm_main" target="1.8" />
|
||||
<module name="capsule-hsm_test" target="1.8" />
|
||||
<module name="client_main" target="1.8" />
|
||||
@ -96,6 +98,8 @@
|
||||
<module name="experimental-behave_main" target="1.8" />
|
||||
<module name="experimental-behave_smokeTest" 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_test" target="1.8" />
|
||||
<module name="experimental_main" target="1.8" />
|
||||
|
@ -125,6 +125,7 @@ see changes to this list.
|
||||
* Micheal Hinstridge (Thoughtworks)
|
||||
* Michele Sollecito (R3)
|
||||
* Mike Hearn (R3)
|
||||
* Mike Ward (R3)
|
||||
* Mike Reichelt (US Bank)
|
||||
* Mustafa Ozturk (Natixis)
|
||||
* Nick Skinner (Northern Trust)
|
||||
@ -161,6 +162,7 @@ see changes to this list.
|
||||
* Sasmit Sahu
|
||||
* Scott James
|
||||
* Shams Asari (R3)
|
||||
* Siddhartha Sengupta (Tradewind Markets)
|
||||
* Simon Taylor (Barclays)
|
||||
* Sofus Mortensen (Digital Asset Holdings)
|
||||
* stevenroose
|
||||
|
@ -70,10 +70,6 @@ dependencies {
|
||||
compile "org.bouncycastle:bcpkix-jdk15on:${bouncycastle_version}"
|
||||
// Seems to be needed?
|
||||
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
|
||||
// Pulled in by whitelist
|
||||
compile ("com.esotericsoftware:kryo:4.0.0") {
|
||||
transitive = false
|
||||
}
|
||||
|
||||
// Log4J: logging framework (with SLF4J bindings)
|
||||
compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
|
||||
|
@ -7,11 +7,11 @@ import net.corda.core.serialization.SerializationCustomSerializer
|
||||
import net.corda.core.serialization.internal.SerializationEnvironment
|
||||
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
||||
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.amqp.AbstractAMQPSerializationScheme
|
||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||
import net.corda.serialization.internal.amqp.amqpMagic
|
||||
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
<Appenders>
|
||||
<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>
|
||||
|
||||
<!-- Required for printBasicInfo -->
|
||||
|
@ -13,9 +13,9 @@ package net.corda.core.utilities
|
||||
import com.esotericsoftware.kryo.KryoException
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
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.kryo.kryoMagic
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Rule
|
||||
|
Binary file not shown.
@ -8,6 +8,10 @@ Unreleased
|
||||
==========
|
||||
* Introduced a hierarchy of ``DatabaseMigrationException``s, allowing ``NodeStartup`` to gracefully inform users of problems related to database migrations before exiting with a non-zero code.
|
||||
|
||||
* ``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
|
||||
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:
|
||||
|
||||
* 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/>`_
|
||||
|
||||
* 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
|
||||
---------------------------
|
||||
|
||||
@ -32,44 +28,117 @@ Making the required changes
|
||||
2. Clone the fork to your local machine
|
||||
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
|
||||
-------------------
|
||||
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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
|
||||
-----------------
|
||||
|
||||
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>`_
|
||||
2. Include the change in the :doc:`changelog </changelog>` and :doc:`release notes </release-notes>` where applicable
|
||||
3. :doc:`Build the docs locally </building-the-docs>`
|
||||
4. Open the built .html files for the modified pages to ensure they render correctly
|
||||
1. Add comments and javadocs/kdocs. API functions must have javadoc/kdoc comments and sentences must be terminated
|
||||
with a full stop. We also start comments with capital letters, even for inline comments. Where Java APIs have
|
||||
synonyms (e.g. ``%d`` and ``%date``), we prefer the longer form for legibility reasons. You can configure your IDE
|
||||
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
|
||||
-----------------------------------
|
||||
|
||||
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:
|
||||
1. Create a pull request from your fork to the ``master`` branch of the Corda repo
|
||||
|
||||
* State that you have run the tests
|
||||
* 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>`_
|
||||
2. In the PR comments box, complete the pull-request checklist:
|
||||
|
||||
3. Request a review from a member of the Corda platform team via the `#design channel <http://slack.corda.net/>`_
|
||||
4. Wait for your PR to pass all four types of continuous integration tests (integration, API stability, build and unit)
|
||||
* [ ] Have you run the unit, integration and smoke tests as described here? https://docs.corda.net/head/testing.html
|
||||
* [ ] If you added/changed public APIs, did you write/update the JavaDocs?
|
||||
* [ ] 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
|
||||
locally, ask the reviewer for further details
|
||||
3. In the PR comments box, also add a clear description of the purpose for the PR
|
||||
|
||||
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
|
||||
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
|
||||
-----------------
|
||||
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
|
||||
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
|
||||
* 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
|
||||
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
|
||||
* 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.utilities.ByteSequence
|
||||
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.DescribedType
|
||||
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.amqp.AbstractAMQPSerializationScheme
|
||||
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.Paths
|
||||
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
||||
import java.time.Instant
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeoutException
|
||||
import kotlin.streams.toList
|
||||
import kotlin.collections.HashSet
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
import kotlin.streams.toList
|
||||
|
||||
/**
|
||||
* Class to bootstrap a local network of Corda nodes on the same filesystem.
|
||||
@ -348,22 +345,12 @@ class NetworkBootstrapper {
|
||||
private fun initialiseSerialization() {
|
||||
_contextSerializationEnv.set(SerializationEnvironmentImpl(
|
||||
SerializationFactoryImpl().apply {
|
||||
registerScheme(KryoParametersSerializationScheme)
|
||||
registerScheme(AMQPParametersSerializationScheme)
|
||||
},
|
||||
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()) {
|
||||
override fun rpcClientSerializerFactory(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.nodeapi.internal.config.SSLConfiguration
|
||||
import net.corda.nodeapi.internal.createDevKeyStores
|
||||
import net.corda.serialization.internal.AllWhitelist
|
||||
import net.corda.serialization.internal.SerializationContextImpl
|
||||
import net.corda.serialization.internal.SerializationFactoryImpl
|
||||
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.BOB_NAME
|
||||
import net.corda.testing.core.TestIdentity
|
||||
@ -362,13 +362,15 @@ class X509UtilitiesTest {
|
||||
@Test
|
||||
fun `serialize - deserialize X509CertPath`() {
|
||||
val factory = SerializationFactoryImpl().apply { registerScheme(AMQPServerSerializationScheme()) }
|
||||
val context = SerializationContextImpl(amqpMagic,
|
||||
val context = SerializationContextImpl(
|
||||
amqpMagic,
|
||||
javaClass.classLoader,
|
||||
AllWhitelist,
|
||||
emptyMap(),
|
||||
true,
|
||||
SerializationContext.UseCase.P2P,
|
||||
null)
|
||||
null
|
||||
)
|
||||
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE_NAME.x500Principal, rootCAKey)
|
||||
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"
|
||||
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"
|
||||
|
||||
// For caches rather than guava
|
||||
|
@ -10,12 +10,14 @@
|
||||
|
||||
package net.corda.node
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import joptsimple.OptionSet
|
||||
import joptsimple.util.EnumConverter
|
||||
import joptsimple.util.PathConverter
|
||||
import net.corda.core.internal.div
|
||||
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.NodeConfiguration
|
||||
import net.corda.node.services.config.parseAsNodeConfiguration
|
||||
@ -125,19 +127,22 @@ data class CmdLineOptions(val baseDirectory: Path,
|
||||
val bootstrapRaftCluster: Boolean,
|
||||
val unknownConfigKeysPolicy: UnknownConfigKeysPolicy,
|
||||
val devMode: Boolean) {
|
||||
fun loadConfig(): NodeConfiguration {
|
||||
val config = ConfigHelper.loadConfig(
|
||||
fun loadConfig(): Pair<Config, Try<NodeConfiguration>> {
|
||||
val rawConfig = ConfigHelper.loadConfig(
|
||||
baseDirectory,
|
||||
configFile,
|
||||
configOverrides = ConfigFactory.parseMap(mapOf("noLocalShell" to this.noLocalShell) +
|
||||
if (devMode) mapOf("devMode" to this.devMode) else emptyMap<String, Any>())
|
||||
).parseAsNodeConfiguration(unknownConfigKeysPolicy::handle)
|
||||
if (nodeRegistrationOption != null) {
|
||||
require(!config.devMode) { "registration cannot occur in devMode" }
|
||||
requireNotNull(config.compatibilityZoneURL) {
|
||||
"compatibilityZoneURL must be present in node configuration file in registration mode."
|
||||
)
|
||||
return rawConfig to Try.on {
|
||||
rawConfig.parseAsNodeConfiguration(unknownConfigKeysPolicy::handle).also {
|
||||
if (nodeRegistrationOption != null) {
|
||||
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)),
|
||||
networkMapClient,
|
||||
networkParameters.serialize().hash,
|
||||
services.myInfo.serialize().hash,
|
||||
configuration.baseDirectory,
|
||||
configuration.extraNetworkMapKeys)
|
||||
runOnStop += networkMapUpdater::close
|
||||
@ -862,7 +863,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
||||
private fun makeIdentityService(identityCert: X509Certificate): PersistentIdentityService {
|
||||
val trustRoot = configuration.loadTrustStore().getCertificate(X509Utilities.CORDA_ROOT_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
|
||||
|
@ -38,6 +38,7 @@ import net.corda.node.internal.cordapp.CordappLoader
|
||||
import net.corda.node.internal.security.RPCSecurityManagerImpl
|
||||
import net.corda.node.internal.security.RPCSecurityManagerWithAdditionalUser
|
||||
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.services.Permissions
|
||||
import net.corda.node.services.api.NodePropertiesStore
|
||||
|
@ -11,6 +11,8 @@
|
||||
package net.corda.node.internal
|
||||
|
||||
import com.jcabi.manifests.Manifests
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigRenderOptions
|
||||
import io.netty.channel.unix.Errors
|
||||
import net.corda.core.cordapp.Cordapp
|
||||
import net.corda.core.crypto.Crypto
|
||||
@ -19,6 +21,7 @@ import net.corda.core.internal.concurrent.thenMatch
|
||||
import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.randomOrNull
|
||||
import net.corda.core.utilities.Try
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.CmdLineOptions
|
||||
import net.corda.node.NodeArgsParser
|
||||
@ -92,7 +95,11 @@ open class NodeStartup(val args: Array<String>) {
|
||||
drawBanner(versionInfo)
|
||||
Node.printBasicNodeInfo(LOGS_CAN_BE_FOUND_IN_STRING, System.getProperty("log-path"))
|
||||
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 (conf0 is NodeConfigurationImpl) {
|
||||
println("Bootstrapping raft cluster (starting up as seed node).")
|
||||
@ -227,7 +234,7 @@ open class NodeStartup(val args: Array<String>) {
|
||||
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) {
|
||||
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.SerializationContext
|
||||
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.amqp.AbstractAMQPSerializationScheme
|
||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
|
||||
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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import com.esotericsoftware.kryo.*
|
||||
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.serialization.internal.AttachmentsClassLoader
|
||||
import net.corda.serialization.internal.MutableClassWhitelist
|
||||
import net.corda.serialization.internal.TransientClassWhiteList
|
||||
import net.corda.serialization.internal.amqp.hasAnnotationInHierarchy
|
||||
import java.io.PrintWriter
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import com.esotericsoftware.kryo.*
|
||||
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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import co.paralleluniverse.fibers.Fiber
|
||||
import co.paralleluniverse.io.serialization.kryo.KryoSerializer
|
||||
@ -22,10 +22,11 @@ import com.esotericsoftware.kryo.serializers.ClosureSerializer
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.ClassWhitelist
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.serialization.internal.*
|
||||
import net.corda.serialization.internal.SectionId
|
||||
import net.corda.serialization.internal.CordaSerializationEncoding.SNAPPY
|
||||
import java.security.PublicKey
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@ -140,3 +141,14 @@ abstract class AbstractKryoSerializationScheme : SerializationScheme {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val KRYO_CHECKPOINT_CONTEXT = SerializationContextImpl(
|
||||
kryoMagic,
|
||||
SerializationDefaults.javaClass.classLoader,
|
||||
QuasarWhitelist,
|
||||
emptyMap(),
|
||||
true,
|
||||
SerializationContext.UseCase.Checkpoint,
|
||||
SNAPPY,
|
||||
AlwaysAcceptEncodingWhitelist
|
||||
)
|
@ -13,8 +13,6 @@ package net.corda.node.serialization.kryo
|
||||
import com.esotericsoftware.kryo.pool.KryoPool
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.serialization.internal.CordaSerializationMagic
|
||||
import net.corda.serialization.internal.kryo.AbstractKryoSerializationScheme
|
||||
import net.corda.serialization.internal.kryo.kryoMagic
|
||||
|
||||
class KryoServerSerializationScheme : AbstractKryoSerializationScheme() {
|
||||
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 rpcServerKryoPool(context: SerializationContext): KryoPool = throw UnsupportedOperationException()
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
@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.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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
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.systemProperties
|
||||
import com.typesafe.config.ConfigParseOptions
|
||||
import com.typesafe.config.ConfigRenderOptions
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.div
|
||||
@ -64,8 +63,6 @@ object ConfigHelper {
|
||||
.withFallback(defaultConfig)
|
||||
.resolve()
|
||||
|
||||
log.info("Config:\n${finalConfig.root().render(ConfigRenderOptions.defaults())}")
|
||||
|
||||
val entrySet = finalConfig.entrySet().filter { entry -> entry.key.contains("\"") }
|
||||
for ((key) in entrySet) {
|
||||
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
|
||||
@ThreadSafe
|
||||
class InMemoryIdentityService(identities: Array<out PartyAndCertificate>,
|
||||
class InMemoryIdentityService(identities: List<out PartyAndCertificate> = emptyList(),
|
||||
override val trustRoot: X509Certificate) : SingletonSerializeAsToken(), IdentityService {
|
||||
companion object {
|
||||
private val log = contextLogger()
|
||||
|
@ -38,10 +38,17 @@ import javax.persistence.Entity
|
||||
import javax.persistence.Id
|
||||
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
|
||||
@ThreadSafe
|
||||
class PersistentIdentityService(override val trustRoot: X509Certificate,
|
||||
vararg caCertificates: X509Certificate) : SingletonSerializeAsToken(), IdentityServiceInternal {
|
||||
caCertificates: List<X509Certificate> = emptyList()) : SingletonSerializeAsToken(), IdentityServiceInternal {
|
||||
|
||||
companion object {
|
||||
private val log = contextLogger()
|
||||
|
@ -45,6 +45,7 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
|
||||
private val fileWatcher: NodeInfoWatcher,
|
||||
private val networkMapClient: NetworkMapClient?,
|
||||
private val currentParametersHash: SecureHash,
|
||||
private val ourNodeInfoHash: SecureHash?,
|
||||
private val baseDirectory: Path,
|
||||
private val extraNetworkMapKeys: List<UUID>
|
||||
) : AutoCloseable {
|
||||
@ -79,8 +80,10 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
|
||||
networkMapCache.addNode(it.nodeInfo)
|
||||
}
|
||||
is NodeInfoUpdate.Remove -> {
|
||||
val nodeInfo = networkMapCache.getNodeByHash(it.hash)
|
||||
nodeInfo?.let { networkMapCache.removeNode(it) }
|
||||
if (it.hash != ourNodeInfoHash) {
|
||||
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.
|
||||
(currentNodeHashes - allHashesFromNetworkMap - fileWatcher.processedNodeInfoHashes)
|
||||
.mapNotNull(networkMapCache::getNodeByHash)
|
||||
.forEach(networkMapCache::removeNode)
|
||||
.mapNotNull {
|
||||
if (it != ourNodeInfoHash) {
|
||||
networkMapCache.getNodeByHash(it)
|
||||
} else null
|
||||
}.forEach(networkMapCache::removeNode)
|
||||
|
||||
return cacheTimeout
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package net.corda.node.internal.serialization.testutils
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.serialization.internal.AllWhitelist
|
||||
import net.corda.serialization.internal.SerializationContextImpl
|
||||
import net.corda.serialization.internal.amqp.amqpMagic
|
||||
import net.corda.serialization.internal.AllWhitelist
|
||||
|
||||
val serializationProperties: MutableMap<Any, Any> = mutableMapOf()
|
||||
|
||||
@ -14,4 +14,5 @@ val serializationContext = SerializationContextImpl(
|
||||
properties = serializationProperties,
|
||||
objectReferencesEnabled = false,
|
||||
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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import net.corda.core.internal.declaredField
|
||||
import net.corda.serialization.internal.ByteBufferOutputStream
|
||||
@ -38,7 +38,7 @@ class KryoStreamsTest {
|
||||
fun `substitute output works`() {
|
||||
assertArrayEquals(byteArrayOf(100, -101), kryoOutput {
|
||||
write(100)
|
||||
substitute(::NegOutputStream)
|
||||
substitute(KryoStreamsTest::NegOutputStream)
|
||||
write(101)
|
||||
})
|
||||
}
|
||||
@ -47,7 +47,7 @@ class KryoStreamsTest {
|
||||
fun `substitute input works`() {
|
||||
kryoInput(byteArrayOf(100, 101).inputStream()) {
|
||||
assertEquals(100, read())
|
||||
substitute(::NegInputStream)
|
||||
substitute(KryoStreamsTest::NegInputStream)
|
||||
assertEquals(-101, read().toByte())
|
||||
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.
|
||||
*/
|
||||
|
||||
package net.corda.serialization.internal.kryo
|
||||
package net.corda.node.serialization.kryo
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
import com.esotericsoftware.kryo.KryoException
|
||||
@ -43,6 +43,7 @@ import org.slf4j.LoggerFactory
|
||||
import java.io.InputStream
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.test.*
|
||||
|
||||
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`() {
|
||||
val noReferencesContext = context.withoutReferences()
|
||||
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)
|
||||
originalList += obj
|
||||
deserialisedList += obj
|
||||
@ -116,8 +117,14 @@ class KryoTests(private val compression: CordaSerializationEncoding?) {
|
||||
val instant = Instant.ofEpochMilli(123)
|
||||
val instantCopy = Instant.ofEpochMilli(123)
|
||||
assertThat(instant).isNotSameAs(instantCopy)
|
||||
val listWithCopies = arrayListOf(instant, instantCopy)
|
||||
val listWithSameInstances = arrayListOf(instant, instant)
|
||||
val listWithCopies = ArrayList<Instant>().apply {
|
||||
this += instant
|
||||
this += instantCopy
|
||||
}
|
||||
val listWithSameInstances = ArrayList<Instant>().apply {
|
||||
this += instant
|
||||
this += instant
|
||||
}
|
||||
assertThat(listWithSameInstances.serialize(factory, noReferencesContext)).isEqualTo(listWithCopies.serialize(factory, noReferencesContext))
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class InMemoryIdentityServiceTests {
|
||||
val BOB get() = bob.party
|
||||
val BOB_IDENTITY get() = bob.identity
|
||||
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
|
||||
|
@ -15,6 +15,7 @@ import com.google.common.jimfs.Jimfs
|
||||
import com.nhaarman.mockito_kotlin.*
|
||||
import net.corda.cordform.CordformNode.NODE_INFO_DIRECTORY
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.sign
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
@ -71,7 +72,6 @@ class NetworkMapUpdaterTest {
|
||||
server = NetworkMapServer(cacheExpiryMs.millis, PortAllocation.Incremental(10000).nextHostAndPort())
|
||||
val hostAndPort = server.start()
|
||||
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
|
||||
@ -81,8 +81,13 @@ class NetworkMapUpdaterTest {
|
||||
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
|
||||
fun `process add node updates from network map, with additional node infos from dir`() {
|
||||
setUpdater()
|
||||
val (nodeInfo1, signedNodeInfo1) = createNodeInfoAndSigned("Info 1")
|
||||
val (nodeInfo2, signedNodeInfo2) = createNodeInfoAndSigned("Info 2")
|
||||
val (nodeInfo3, signedNodeInfo3) = createNodeInfoAndSigned("Info 3")
|
||||
@ -118,6 +123,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@Test
|
||||
fun `process remove node updates from network map, with additional node infos from dir`() {
|
||||
setUpdater()
|
||||
val (nodeInfo1, signedNodeInfo1) = createNodeInfoAndSigned("Info 1")
|
||||
val (nodeInfo2, signedNodeInfo2) = createNodeInfoAndSigned("Info 2")
|
||||
val (nodeInfo3, signedNodeInfo3) = createNodeInfoAndSigned("Info 3")
|
||||
@ -158,6 +164,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@Test
|
||||
fun `receive node infos from directory, without a network map`() {
|
||||
setUpdater()
|
||||
val fileNodeInfoAndSigned = createNodeInfoAndSigned("Info from file")
|
||||
|
||||
// Not subscribed yet.
|
||||
@ -176,6 +183,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@Test
|
||||
fun `emit new parameters update info on parameters update from network map`() {
|
||||
setUpdater()
|
||||
val paramsFeed = updater.trackParametersUpdate()
|
||||
val snapshot = paramsFeed.snapshot
|
||||
val updates = paramsFeed.updates.bufferUntilSubscribed()
|
||||
@ -198,6 +206,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@Test
|
||||
fun `ack network parameters update`() {
|
||||
setUpdater()
|
||||
val newParameters = testNetworkParameters(epoch = 314)
|
||||
server.scheduleParametersUpdate(newParameters, "Test update", Instant.MIN)
|
||||
updater.subscribeToNetworkMap()
|
||||
@ -214,6 +223,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@Test
|
||||
fun `fetch nodes from private network`() {
|
||||
setUpdater(extraNetworkMapKeys = listOf(privateNetUUID))
|
||||
server.addNodesToPrivateNetwork(privateNetUUID, listOf(ALICE_NAME))
|
||||
Assertions.assertThatThrownBy { networkMapClient.getNetworkMap(privateNetUUID).payload.nodeInfoHashes }
|
||||
.isInstanceOf(IOException::class.java)
|
||||
@ -230,6 +240,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@Test
|
||||
fun `remove node from filesystem deletes it from network map cache`() {
|
||||
setUpdater()
|
||||
val fileNodeInfoAndSigned1 = createNodeInfoAndSigned("Info from file 1")
|
||||
val fileNodeInfoAndSigned2 = createNodeInfoAndSigned("Info from file 2")
|
||||
updater.subscribeToNetworkMap()
|
||||
@ -252,6 +263,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@Test
|
||||
fun `remove node info file, but node in network map server`() {
|
||||
setUpdater()
|
||||
val nodeInfoBuilder = TestNodeInfoBuilder()
|
||||
val (_, key) = nodeInfoBuilder.addLegalIdentity(CordaX500Name("Info", "London", "GB"))
|
||||
val (serverNodeInfo, serverSignedNodeInfo) = nodeInfoBuilder.buildWithSigned(1, 1)
|
||||
@ -280,6 +292,23 @@ class NetworkMapUpdaterTest {
|
||||
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 {
|
||||
return mock {
|
||||
val data = ConcurrentHashMap<Party, NodeInfo>()
|
||||
|
@ -12,9 +12,6 @@ dependencies {
|
||||
|
||||
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"
|
||||
|
||||
// For AMQP serialisation.
|
||||
|
@ -15,7 +15,7 @@ internal val serializeOutputStreamPool = LazyPool(
|
||||
shouldReturnToPool = { it.size() < 256 * 1024 }, // Discard if it grew too large
|
||||
newInstance = { ByteBufferOutputStream(64 * 1024) })
|
||||
|
||||
internal fun <T> byteArrayOutput(task: (ByteBufferOutputStream) -> T): ByteArray {
|
||||
fun <T> byteArrayOutput(task: (ByteBufferOutputStream) -> T): ByteArray {
|
||||
return serializeOutputStreamPool.run { underlying ->
|
||||
task(underlying)
|
||||
underlying.toByteArray() // Must happen after close, to allow ZIP footer to be written for example.
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.corda.serialization.internal
|
||||
|
||||
import net.corda.core.serialization.ClassWhitelist
|
||||
import java.util.*
|
||||
|
||||
interface MutableClassWhitelist : ClassWhitelist {
|
||||
fun add(entry: Class<*>)
|
||||
@ -9,3 +10,41 @@ interface MutableClassWhitelist : ClassWhitelist {
|
||||
object AllWhitelist : ClassWhitelist {
|
||||
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.SerializationDefaults
|
||||
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.
|
||||
@ -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,
|
||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
||||
emptyMap(),
|
||||
true,
|
||||
SerializationContext.UseCase.RPCClient,
|
||||
null)
|
||||
null
|
||||
)
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
package net.corda.serialization.internal
|
||||
|
||||
import com.esotericsoftware.kryo.KryoException
|
||||
import net.corda.core.serialization.SerializationWhitelist
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import org.apache.activemq.artemis.api.core.SimpleString
|
||||
@ -40,7 +39,6 @@ object DefaultWhitelist : SerializationWhitelist {
|
||||
mapOf(Unit to Unit).javaClass, // SingletonMap
|
||||
NetworkHostAndPort::class.java,
|
||||
SimpleString::class.java,
|
||||
KryoException::class.java, // TODO: Will be removed when we migrate away from Kryo
|
||||
StringBuffer::class.java,
|
||||
Unit::class.java,
|
||||
java.io.ByteArrayInputStream::class.java,
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
package net.corda.serialization.internal
|
||||
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.serialization.SerializationEncoding
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
@ -64,5 +63,4 @@ enum class CordaSerializationEncoding : SerializationEncoding, OrdinalWriter {
|
||||
abstract fun wrap(stream: InputStream): InputStream
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal val encodingNotPermittedFormat = "Encoding not permitted: %s"
|
||||
const 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.utilities.ByteSequence
|
||||
import net.corda.serialization.internal.amqp.amqpMagic
|
||||
import net.corda.serialization.internal.kryo.kryoMagic
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.NotSerializableException
|
||||
import java.util.*
|
||||
@ -108,7 +107,7 @@ open class SerializationFactoryImpl(
|
||||
constructor() : this(ConcurrentHashMap())
|
||||
|
||||
companion object {
|
||||
val magicSize = sequenceOf(kryoMagic, amqpMagic).map { it.size }.distinct().single()
|
||||
val magicSize = amqpMagic.size
|
||||
}
|
||||
|
||||
private val creator: List<StackTraceElement> = Exception().stackTrace.asList()
|
||||
@ -124,7 +123,7 @@ open class SerializationFactoryImpl(
|
||||
return schemes.computeIfAbsent(lookupKey) {
|
||||
registeredSchemes.filter { it.canDeserializeVersion(magic, target) }.forEach { return@computeIfAbsent it } // XXX: Not single?
|
||||
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.")
|
||||
} to magic
|
||||
}
|
||||
@ -154,15 +153,12 @@ open class SerializationFactoryImpl(
|
||||
registeredSchemes += scheme
|
||||
}
|
||||
|
||||
val alreadyRegisteredSchemes: Collection<SerializationScheme> get() = Collections.unmodifiableCollection(registeredSchemes)
|
||||
|
||||
override fun toString(): String {
|
||||
return "${this.javaClass.name} registeredSchemes=$registeredSchemes ${creator.joinToString("\n")}"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is SerializationFactoryImpl &&
|
||||
other.registeredSchemes == this.registeredSchemes
|
||||
return other is SerializationFactoryImpl && other.registeredSchemes == this.registeredSchemes
|
||||
}
|
||||
|
||||
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.SerializationDefaults
|
||||
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.
|
||||
@ -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,
|
||||
AllButBlacklisted,
|
||||
emptyMap(),
|
||||
true,
|
||||
SerializationContext.UseCase.Storage,
|
||||
null,
|
||||
AlwaysAcceptEncodingWhitelist)
|
||||
AlwaysAcceptEncodingWhitelist
|
||||
)
|
||||
|
||||
val AMQP_RPC_SERVER_CONTEXT = SerializationContextImpl(amqpMagic,
|
||||
val AMQP_RPC_SERVER_CONTEXT = SerializationContextImpl(
|
||||
amqpMagic,
|
||||
SerializationDefaults.javaClass.classLoader,
|
||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
||||
emptyMap(),
|
||||
true,
|
||||
SerializationContext.UseCase.RPCServer,
|
||||
null)
|
||||
null
|
||||
)
|
||||
|
@ -15,35 +15,18 @@ package net.corda.serialization.internal
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.serialization.internal.CordaSerializationEncoding.SNAPPY
|
||||
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 shared by the server and client.
|
||||
*
|
||||
* 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,
|
||||
val AMQP_P2P_CONTEXT = SerializationContextImpl(
|
||||
amqpMagic,
|
||||
SerializationDefaults.javaClass.classLoader,
|
||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
||||
emptyMap(),
|
||||
true,
|
||||
SerializationContext.UseCase.P2P,
|
||||
null)
|
||||
null
|
||||
)
|
||||
|
||||
internal object AlwaysAcceptEncodingWhitelist : EncodingWhitelist {
|
||||
object AlwaysAcceptEncodingWhitelist : EncodingWhitelist {
|
||||
override fun acceptEncoding(encoding: SerializationEncoding) = true
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,10 @@ import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationFactory
|
||||
import java.util.*
|
||||
|
||||
internal fun checkUseCase(allowedUseCases: EnumSet<SerializationContext.UseCase>) {
|
||||
fun checkUseCase(allowedUseCases: EnumSet<SerializationContext.UseCase>) {
|
||||
val currentContext: SerializationContext = SerializationFactory.currentFactory?.currentContext
|
||||
?: throw IllegalStateException("Current context is not set")
|
||||
if (!allowedUseCases.contains(currentContext.useCase)) {
|
||||
throw IllegalStateException("UseCase '${currentContext.useCase}' is not within '$allowedUseCases'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,7 @@ import net.corda.core.internal.objectOrNewInstance
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.serialization.internal.CordaSerializationMagic
|
||||
import net.corda.serialization.internal.DefaultWhitelist
|
||||
import net.corda.serialization.internal.MutableClassWhitelist
|
||||
import net.corda.serialization.internal.SerializationScheme
|
||||
import net.corda.serialization.internal.*
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
@ -124,14 +124,33 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
|
||||
}
|
||||
|
||||
internal fun Class<*>.checkSupportedMapType() {
|
||||
checkHashMap()
|
||||
checkWeakHashMap()
|
||||
checkDictionary()
|
||||
}
|
||||
|
||||
private fun Class<*>.checkHashMap() {
|
||||
if (HashMap::class.java.isAssignableFrom(this) && !LinkedHashMap::class.java.isAssignableFrom(this)) {
|
||||
throw IllegalArgumentException(
|
||||
"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: "
|
||||
+ "use java.util.LinkedHashMap instead.")
|
||||
} else if (Dictionary::class.java.isAssignableFrom(this)) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Class<*>.checkDictionary() {
|
||||
if (Dictionary::class.java.isAssignableFrom(this)) {
|
||||
throw IllegalArgumentException(
|
||||
"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.SerializerFactory
|
@ -10,18 +10,18 @@
|
||||
|
||||
package net.corda.serialization.internal;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import net.corda.core.serialization.SerializationContext;
|
||||
import net.corda.core.serialization.SerializationFactory;
|
||||
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.serialization.internal.kryo.CordaClosureSerializer;
|
||||
import net.corda.serialization.internal.kryo.KryoSerializationSchemeKt;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -36,7 +36,15 @@ public final class LambdaCheckpointSerializationTest {
|
||||
@Before
|
||||
public void setup() {
|
||||
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
|
||||
|
@ -24,9 +24,9 @@ import net.corda.core.node.services.AttachmentStorage
|
||||
import net.corda.core.serialization.ClassWhitelist
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.serialization.internal.kryo.CordaClassResolver
|
||||
import net.corda.serialization.internal.kryo.CordaKryo
|
||||
import net.corda.serialization.internal.kryo.kryoMagic
|
||||
import net.corda.node.serialization.kryo.CordaClassResolver
|
||||
import net.corda.node.serialization.kryo.CordaKryo
|
||||
import net.corda.node.serialization.kryo.kryoMagic
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.testing.services.MockAttachmentStorage
|
||||
import org.junit.Rule
|
||||
|
@ -13,11 +13,11 @@ package net.corda.serialization.internal
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
import com.esotericsoftware.kryo.util.DefaultClassResolver
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.node.serialization.kryo.kryoMagic
|
||||
import net.corda.node.services.statemachine.DataSessionMessage
|
||||
import net.corda.serialization.internal.amqp.DeserializationInput
|
||||
import net.corda.serialization.internal.amqp.Envelope
|
||||
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.kryoSpecific
|
||||
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.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.node.serialization.kryo.kryoMagic
|
||||
import net.corda.node.services.statemachine.DataSessionMessage
|
||||
import net.corda.serialization.internal.kryo.kryoMagic
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.internal.amqpSpecific
|
||||
import net.corda.testing.internal.kryoSpecific
|
||||
|
@ -15,10 +15,10 @@ import com.esotericsoftware.kryo.KryoException
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.serialization.internal.kryo.CordaClassResolver
|
||||
import net.corda.serialization.internal.kryo.CordaKryo
|
||||
import net.corda.serialization.internal.kryo.DefaultKryoCustomizer
|
||||
import net.corda.serialization.internal.kryo.kryoMagic
|
||||
import net.corda.node.serialization.kryo.CordaClassResolver
|
||||
import net.corda.node.serialization.kryo.CordaKryo
|
||||
import net.corda.node.serialization.kryo.DefaultKryoCustomizer
|
||||
import net.corda.node.serialization.kryo.kryoMagic
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
|
@ -14,8 +14,8 @@ import com.esotericsoftware.kryo.Kryo
|
||||
import com.esotericsoftware.kryo.util.DefaultClassResolver
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.node.serialization.kryo.kryoMagic
|
||||
import net.corda.node.services.statemachine.DataSessionMessage
|
||||
import net.corda.serialization.internal.kryo.kryoMagic
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.internal.kryoSpecific
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
|
@ -3,8 +3,8 @@ package net.corda.serialization.internal.amqp
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.serialization.internal.*
|
||||
import net.corda.serialization.internal.kryo.BuiltInExceptionsWhitelist
|
||||
import net.corda.serialization.internal.kryo.GlobalTransientClassWhiteList
|
||||
import net.corda.serialization.internal.BuiltInExceptionsWhitelist
|
||||
import net.corda.serialization.internal.GlobalTransientClassWhiteList
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -59,7 +59,7 @@ import java.util.*
|
||||
/**
|
||||
* 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
|
||||
|
@ -15,11 +15,11 @@
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<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>
|
||||
<!-- Required for printBasicInfo -->
|
||||
<Console name="Console-Appender-Println" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%msg%n" />
|
||||
<PatternLayout pattern="%msg%n"/>
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
@ -32,8 +32,8 @@
|
||||
<Logger name="BasicInfo" additivity="false">
|
||||
<AppenderRef ref="Console-Appender-Println"/>
|
||||
</Logger>
|
||||
<Logger name="org.hibernate.SQL" level="info" additivity="false">
|
||||
<AppenderRef ref="Console-Appender"/>
|
||||
<Logger name="org.hibernate.SQL" level="info" additivity="false">
|
||||
<AppenderRef ref="Console-Appender"/>
|
||||
</Logger>
|
||||
<Logger name="org.jolokia" additivity="true" level="warn">
|
||||
<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.serialization.internal.*
|
||||
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.serialization.internal.*
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<Appenders>
|
||||
<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>
|
||||
</Appenders>
|
||||
|
||||
|
@ -46,7 +46,7 @@ class InteractiveShellTest {
|
||||
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")
|
||||
private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory())
|
||||
|
||||
|
@ -12,9 +12,10 @@
|
||||
|
||||
package com.r3.enclaves.txverify
|
||||
|
||||
import com.esotericsoftware.minlog.Log
|
||||
import net.corda.core.contracts.Attachment
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import java.io.File
|
||||
@ -82,7 +83,6 @@ private fun deserialise(reqBytes: ByteArray): LedgerTransaction {
|
||||
|
||||
// Note: This is only here for debugging purposes
|
||||
fun main(args: Array<String>) {
|
||||
Log.TRACE()
|
||||
Class.forName("com.r3.enclaves.txverify.EnclaveletSerializationScheme")
|
||||
val reqBytes = File(args[0]).readBytes()
|
||||
verifyInEnclave(reqBytes)
|
||||
|
@ -21,8 +21,6 @@ import net.corda.serialization.internal.SerializationFactoryImpl
|
||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||
import net.corda.serialization.internal.amqp.amqpMagic
|
||||
import net.corda.serialization.internal.kryo.AbstractKryoSerializationScheme
|
||||
import net.corda.serialization.internal.kryo.kryoMagic
|
||||
|
||||
@Suppress("UNUSED")
|
||||
private class EnclaveletSerializationScheme {
|
||||
@ -33,7 +31,6 @@ private class EnclaveletSerializationScheme {
|
||||
init {
|
||||
nodeSerializationEnv = SerializationEnvironmentImpl(
|
||||
SerializationFactoryImpl(HashMap()).apply {
|
||||
registerScheme(KryoVerifierSerializationScheme)
|
||||
registerScheme(AMQPVerifierSerializationScheme)
|
||||
},
|
||||
/**
|
||||
@ -50,15 +47,6 @@ private class EnclaveletSerializationScheme {
|
||||
}
|
||||
}
|
||||
|
||||
private object KryoVerifierSerializationScheme : 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 AMQPVerifierSerializationScheme : AbstractAMQPSerializationScheme(emptySet(), HashMap()) {
|
||||
override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean {
|
||||
return magic == amqpMagic && target == SerializationContext.UseCase.P2P
|
||||
|
Loading…
x
Reference in New Issue
Block a user