mirror of
https://github.com/corda/corda.git
synced 2025-05-02 08:43:15 +00:00
Small API fixes against M16 (#1737)
* Move CompositeSignaturesWithKeys into net.corda.core.crypto package. (cherry picked from commit 8f29562) * Rename and move CordaPluginRegistry to reflect its real purpose now. Simplify serialization code a bit. (cherry picked from commit e2ecd3a) * Docs: docsite improvements * Remove discussion of webserver from 'writing a cordapp' page. * Fixup some flow docs. * Add a couple more package descriptions. (cherry picked from commit 2aedc43) * Review comments (cherry picked from commit ba1d007) * Review comments - always apply default whitelist and no longer load it via ServiceLoader (cherry picked from commit 7d4d7bb) * Added wording about renaming services resource file
This commit is contained in:
parent
393323e082
commit
30a829adbf
@ -1,8 +1,8 @@
|
|||||||
package net.corda.core.cordapp
|
package net.corda.core.cordapp
|
||||||
|
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ import java.net.URL
|
|||||||
* @property rpcFlows List of RPC initiable flows classes
|
* @property rpcFlows List of RPC initiable flows classes
|
||||||
* @property schedulableFlows List of flows startable by the scheduler
|
* @property schedulableFlows List of flows startable by the scheduler
|
||||||
* @property servies List of RPC services
|
* @property servies List of RPC services
|
||||||
* @property plugins List of Corda plugin registries
|
* @property serializationWhitelists List of Corda plugin registries
|
||||||
* @property customSchemas List of custom schemas
|
* @property customSchemas List of custom schemas
|
||||||
* @property jarPath The path to the JAR for this CorDapp
|
* @property jarPath The path to the JAR for this CorDapp
|
||||||
*/
|
*/
|
||||||
@ -30,7 +30,7 @@ interface Cordapp {
|
|||||||
val rpcFlows: List<Class<out FlowLogic<*>>>
|
val rpcFlows: List<Class<out FlowLogic<*>>>
|
||||||
val schedulableFlows: List<Class<out FlowLogic<*>>>
|
val schedulableFlows: List<Class<out FlowLogic<*>>>
|
||||||
val services: List<Class<out SerializeAsToken>>
|
val services: List<Class<out SerializeAsToken>>
|
||||||
val plugins: List<CordaPluginRegistry>
|
val serializationWhitelists: List<SerializationWhitelist>
|
||||||
val customSchemas: Set<MappedSchema>
|
val customSchemas: Set<MappedSchema>
|
||||||
val jarPath: URL
|
val jarPath: URL
|
||||||
val cordappClasses: List<String>
|
val cordappClasses: List<String>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.crypto.composite.CompositeSignaturesWithKeys
|
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.security.*
|
import java.security.*
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto.composite
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.crypto.TransactionSignature
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
/**
|
/**
|
@ -2,8 +2,8 @@ package net.corda.core.internal.cordapp
|
|||||||
|
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
@ -14,7 +14,7 @@ data class CordappImpl(
|
|||||||
override val rpcFlows: List<Class<out FlowLogic<*>>>,
|
override val rpcFlows: List<Class<out FlowLogic<*>>>,
|
||||||
override val schedulableFlows: List<Class<out FlowLogic<*>>>,
|
override val schedulableFlows: List<Class<out FlowLogic<*>>>,
|
||||||
override val services: List<Class<out SerializeAsToken>>,
|
override val services: List<Class<out SerializeAsToken>>,
|
||||||
override val plugins: List<CordaPluginRegistry>,
|
override val serializationWhitelists: List<SerializationWhitelist>,
|
||||||
override val customSchemas: Set<MappedSchema>,
|
override val customSchemas: Set<MappedSchema>,
|
||||||
override val jarPath: URL) : Cordapp {
|
override val jarPath: URL) : Cordapp {
|
||||||
override val name: String = File(jarPath.toURI()).name.removeSuffix(".jar")
|
override val name: String = File(jarPath.toURI()).name.removeSuffix(".jar")
|
||||||
@ -24,5 +24,5 @@ data class CordappImpl(
|
|||||||
*
|
*
|
||||||
* TODO: Also add [SchedulableFlow] as a Cordapp class
|
* TODO: Also add [SchedulableFlow] as a Cordapp class
|
||||||
*/
|
*/
|
||||||
override val cordappClasses = ((rpcFlows + initiatedFlows + services + plugins.map { javaClass }).map { it.name } + contractClassNames)
|
override val cordappClasses = ((rpcFlows + initiatedFlows + services + serializationWhitelists.map { javaClass }).map { it.name } + contractClassNames)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
package net.corda.core.node
|
|
||||||
|
|
||||||
import net.corda.core.serialization.SerializationCustomization
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implement this interface on a class advertised in a META-INF/services/net.corda.core.node.CordaPluginRegistry file
|
|
||||||
* to extend a Corda node with additional application services.
|
|
||||||
*/
|
|
||||||
abstract class CordaPluginRegistry {
|
|
||||||
/**
|
|
||||||
* Optionally whitelist types for use in object serialization, as we lock down the types that can be serialized.
|
|
||||||
*
|
|
||||||
* For example, if you add a new [net.corda.core.contracts.ContractState] it needs to be whitelisted. You can do that
|
|
||||||
* either by adding the [net.corda.core.serialization.CordaSerializable] annotation or via this method.
|
|
||||||
**
|
|
||||||
* @return true if you register types, otherwise you will be filtered out of the list of plugins considered in future.
|
|
||||||
*/
|
|
||||||
open fun customizeSerialization(custom: SerializationCustomization): Boolean = false
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package net.corda.core.serialization
|
|
||||||
|
|
||||||
interface SerializationCustomization {
|
|
||||||
fun addToWhitelist(vararg types: Class<*>)
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
|||||||
|
package net.corda.core.serialization
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a subclass of this via the [java.util.ServiceLoader] mechanism to be able to whitelist types for
|
||||||
|
* serialisation that you cannot otherwise annotate. The name of the class must appear in a text file on the
|
||||||
|
* classpath under the path META-INF/services/net.corda.core.serialization.SerializationWhitelist
|
||||||
|
*/
|
||||||
|
interface SerializationWhitelist {
|
||||||
|
/**
|
||||||
|
* Optionally whitelist types for use in object serialization, as we lock down the types that can be serialized.
|
||||||
|
*
|
||||||
|
* For example, if you add a new [net.corda.core.contracts.ContractState] it needs to be whitelisted. You can do that
|
||||||
|
* either by adding the [net.corda.core.serialization.CordaSerializable] annotation or via this method.
|
||||||
|
*/
|
||||||
|
val whitelist: List<Class<*>>
|
||||||
|
}
|
@ -1,13 +1,12 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.crypto.CompositeKey.NodeAndWeight
|
import net.corda.core.crypto.CompositeKey.NodeAndWeight
|
||||||
import net.corda.core.crypto.composite.CompositeSignaturesWithKeys
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.cert
|
||||||
import net.corda.core.internal.declaredField
|
import net.corda.core.internal.declaredField
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.internal.cert
|
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import net.corda.testing.TestDependencyInjectionBase
|
import net.corda.testing.TestDependencyInjectionBase
|
||||||
|
@ -24,6 +24,10 @@ RPC client interface to Corda, for use both by user-facing client and integratio
|
|||||||
|
|
||||||
Internal, do not use. These APIs and implementations which are currently being revised and are subject to future change.
|
Internal, do not use. These APIs and implementations which are currently being revised and are subject to future change.
|
||||||
|
|
||||||
|
# Package net.corda.core
|
||||||
|
|
||||||
|
Exception types and some utilities for working with observables and futures.
|
||||||
|
|
||||||
# Package net.corda.core.concurrent
|
# Package net.corda.core.concurrent
|
||||||
|
|
||||||
Provides a simplified [java.util.concurrent.Future] class that allows registration of a callback to execute when the future
|
Provides a simplified [java.util.concurrent.Future] class that allows registration of a callback to execute when the future
|
||||||
@ -37,6 +41,10 @@ with [Contract], or see the examples in [net.corda.finance.contracts].
|
|||||||
Corda smart contracts are a combination of state held on the distributed ledger, and verification logic which defines
|
Corda smart contracts are a combination of state held on the distributed ledger, and verification logic which defines
|
||||||
which transformations of state are valid.
|
which transformations of state are valid.
|
||||||
|
|
||||||
|
# Package net.corda.core.cordapp
|
||||||
|
|
||||||
|
Classes that represent metadata about an app.
|
||||||
|
|
||||||
# Package net.corda.core.crypto
|
# Package net.corda.core.crypto
|
||||||
|
|
||||||
Cryptography data and utility classes used for signing, verifying, key management and data integrity checks.
|
Cryptography data and utility classes used for signing, verifying, key management and data integrity checks.
|
||||||
@ -54,10 +62,6 @@ processes such as handling fixing of interest rate swaps.
|
|||||||
|
|
||||||
Data classes which model different forms of identity (potentially with supporting evidence) for legal entities and services.
|
Data classes which model different forms of identity (potentially with supporting evidence) for legal entities and services.
|
||||||
|
|
||||||
# Package net.corda.core.internal
|
|
||||||
|
|
||||||
Internal, do not use. These APIs and implementations which are currently being revised and are subject to future change.
|
|
||||||
|
|
||||||
# Package net.corda.core.messaging
|
# Package net.corda.core.messaging
|
||||||
|
|
||||||
Data types used by the Corda messaging layer to manage state of messaging and sessions between nodes.
|
Data types used by the Corda messaging layer to manage state of messaging and sessions between nodes.
|
||||||
|
@ -61,9 +61,11 @@ Release 1.0
|
|||||||
* About half of the code in test-utils has been moved to a new module ``node-driver``,
|
* About half of the code in test-utils has been moved to a new module ``node-driver``,
|
||||||
and the test scope modules are now located in a ``testing`` directory.
|
and the test scope modules are now located in a ``testing`` directory.
|
||||||
|
|
||||||
* Removed `requireSchemas` CordaPluginRegistry configuration item.
|
* CordaPluginRegistry has been renamed to SerializationWhitelist and moved to the net.corda.core.serialization
|
||||||
Custom schemas are now automatically located using classpath scanning for deployed CorDapps.
|
package. The API for whitelisting types that can't be annotated was slightly simplified. This class used to contain
|
||||||
Improved support for testing custom schemas in MockNode and MockServices using explicit registration.
|
many things, but as we switched to annotations and classpath scanning over time it hollowed out until this was
|
||||||
|
the only functionality left. You also need to rename your services resource file to the new class name.
|
||||||
|
An associated property on ``MockNode`` was renamed from ``testPluginRegistries`` to ``testSerializationWhitelists``.
|
||||||
|
|
||||||
* Contract Upgrades: deprecated RPC authorisation / deauthorisation API calls in favour of equivalent flows in ContractUpgradeFlow.
|
* Contract Upgrades: deprecated RPC authorisation / deauthorisation API calls in favour of equivalent flows in ContractUpgradeFlow.
|
||||||
Implemented contract upgrade persistence using JDBC backed persistent map.
|
Implemented contract upgrade persistence using JDBC backed persistent map.
|
||||||
|
@ -4,9 +4,8 @@ import net.corda.core.contracts.Amount
|
|||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.messaging.vaultQueryBy
|
import net.corda.core.messaging.vaultQueryBy
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.SerializationCustomization
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
@ -16,9 +15,9 @@ import net.corda.finance.flows.CashExitFlow
|
|||||||
import net.corda.finance.flows.CashIssueFlow
|
import net.corda.finance.flows.CashIssueFlow
|
||||||
import net.corda.finance.flows.CashPaymentFlow
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||||
import net.corda.nodeapi.internal.ServiceInfo
|
|
||||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
|
import net.corda.nodeapi.internal.ServiceInfo
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
@ -143,12 +142,8 @@ data class ExampleRPCValue(val foo: String)
|
|||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class ExampleRPCValue2(val bar: Int)
|
data class ExampleRPCValue2(val bar: Int)
|
||||||
|
|
||||||
class ExampleRPCCordaPluginRegistry : CordaPluginRegistry() {
|
class ExampleRPCSerializationWhitelist : SerializationWhitelist {
|
||||||
override fun customizeSerialization(custom: SerializationCustomization): Boolean {
|
// Add classes like this.
|
||||||
// Add classes like this.
|
override val whitelist = listOf(ExampleRPCValue::class.java)
|
||||||
custom.addToWhitelist(ExampleRPCValue::class.java)
|
|
||||||
// You should return true, otherwise your plugin will be ignored for registering classes with Kryo.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// END 7
|
// END 7
|
||||||
|
@ -307,40 +307,9 @@ will propagate to the other side. Any other exception will not propagate.
|
|||||||
|
|
||||||
Taking a step back, we mentioned that the other side has to accept the session request for there to be a communication
|
Taking a step back, we mentioned that the other side has to accept the session request for there to be a communication
|
||||||
channel. A node accepts a session request if it has registered the flow type (the fully-qualified class name) that is
|
channel. A node accepts a session request if it has registered the flow type (the fully-qualified class name) that is
|
||||||
making the request - each session initiation includes the initiating flow type. The registration is done by a CorDapp
|
making the request - each session initiation includes the initiating flow type. The *initiated* (server) flow must name the
|
||||||
which has made available the particular flow communication, using ``PluginServiceHub.registerServiceFlow``. This method
|
*initiating* (client) flow using the ``@InitiatedBy`` annotation and passing the class name that will be starting the
|
||||||
specifies a flow factory for generating the counter-flow to any given initiating flow. If this registration doesn't exist
|
flow session as the annotation parameter.
|
||||||
then no further communication takes place and the initiating flow ends with an exception.
|
|
||||||
|
|
||||||
Going back to our buyer and seller flows, we need a way to initiate communication between the two. This is typically done
|
|
||||||
with one side started manually using the ``startFlowDynamic`` RPC and this initiates the counter-flow on the other side.
|
|
||||||
In this case it doesn't matter which flow is the initiator and which is the initiated. If we choose the seller side as
|
|
||||||
the initiator then the buyer side would need to register their flow, perhaps with something like:
|
|
||||||
|
|
||||||
.. container:: codeset
|
|
||||||
|
|
||||||
.. sourcecode:: kotlin
|
|
||||||
|
|
||||||
class TwoPartyTradeFlowPlugin : CordaPluginRegistry() {
|
|
||||||
override val servicePlugins = listOf(Function(TwoPartyTradeFlowService::Service))
|
|
||||||
}
|
|
||||||
|
|
||||||
object TwoPartyTradeFlowService {
|
|
||||||
class Service(services: PluginServiceHub) {
|
|
||||||
init {
|
|
||||||
services.registerServiceFlow(TwoPartyTradeFlow.Seller::class.java) {
|
|
||||||
TwoPartyTradeFlow.Buyer(
|
|
||||||
it,
|
|
||||||
notary = services.networkMapCache.notaryIdentities[0].party,
|
|
||||||
acceptablePrice = TODO(),
|
|
||||||
typeToBuy = TODO())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
This is telling the buyer node to fire up an instance of ``TwoPartyTradeFlow.Buyer`` (the code in the lambda) when
|
|
||||||
they receive a message from the initiating seller side of the flow (``TwoPartyTradeFlow.Seller::class.java``).
|
|
||||||
|
|
||||||
.. _subflows:
|
.. _subflows:
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ The ``src`` directory of the Template CorDapp, where we define our CorDapp's sou
|
|||||||
│ └── resources
|
│ └── resources
|
||||||
│ ├── META-INF
|
│ ├── META-INF
|
||||||
│ │ └── services
|
│ │ └── services
|
||||||
│ │ ├── net.corda.core.node.CordaPluginRegistry
|
│ │ ├── net.corda.core.serialization.SerializationWhitelist
|
||||||
│ │ └── net.corda.webserver.services.WebServerPluginRegistry
|
│ │ └── net.corda.webserver.services.WebServerPluginRegistry
|
||||||
│ ├── certificates
|
│ ├── certificates
|
||||||
│ │ ├── sslkeystore.jks
|
│ │ ├── sslkeystore.jks
|
||||||
@ -58,40 +58,4 @@ The ``src`` directory of the Template CorDapp, where we define our CorDapp's sou
|
|||||||
└── com
|
└── com
|
||||||
└── template
|
└── template
|
||||||
└── contract
|
└── contract
|
||||||
└── TemplateTests.java
|
└── TemplateTests.java
|
||||||
|
|
||||||
Defining plugins
|
|
||||||
----------------
|
|
||||||
Your CorDapp may need to define two types of plugins:
|
|
||||||
|
|
||||||
* ``CordaPluginRegistry`` subclasses, which define additional serializable classes
|
|
||||||
* ``WebServerPluginRegistry`` subclasses, which define the APIs and static web content served by your CorDapp
|
|
||||||
|
|
||||||
The fully-qualified class path of each ``CordaPluginRegistry`` subclass must then be added to the
|
|
||||||
``net.corda.core.node.CordaPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. Meanwhile,
|
|
||||||
the fully-qualified class path of each ``WebServerPluginRegistry`` subclass must be added to the
|
|
||||||
``net.corda.webserver.services.WebServerPluginRegistry`` file, again in the CorDapp's ``resources/META-INF/services``
|
|
||||||
folder.
|
|
||||||
|
|
||||||
The ``CordaPluginRegistry`` class defines the following:
|
|
||||||
|
|
||||||
* ``customizeSerialization``, which can be overridden to provide a list of the classes to be whitelisted for object
|
|
||||||
serialisation, over and above those tagged with the ``@CordaSerializable`` annotation. See :doc:`serialization`
|
|
||||||
|
|
||||||
The ``WebServerPluginRegistry`` class defines the following:
|
|
||||||
|
|
||||||
* ``webApis``, which can be overridden to return a list of JAX-RS annotated REST access classes. These classes will be
|
|
||||||
constructed by the bundled web server and must have a single argument constructor taking a ``CordaRPCOps`` object.
|
|
||||||
This will allow the API to communicate with the node process via the RPC interface. These web APIs will not be
|
|
||||||
available if the bundled web server is not started
|
|
||||||
|
|
||||||
* ``staticServeDirs``, which can be overridden to map static web content to virtual paths and allow simple web demos to
|
|
||||||
be distributed within the CorDapp jars. This static content will not be available if the bundled web server is not
|
|
||||||
started
|
|
||||||
|
|
||||||
* ``customizeJSONSerialization``, which can be overridden to register custom JSON serializers if required by the REST api.
|
|
||||||
|
|
||||||
* The static web content itself should be placed inside the ``src/main/resources`` directory
|
|
||||||
|
|
||||||
To learn about how to use gradle to build your cordapp against Corda and generate an artifact please read
|
|
||||||
:doc:`cordapp-build-systems`.
|
|
@ -1,5 +0,0 @@
|
|||||||
package net.corda.finance.contracts.isolated
|
|
||||||
|
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
|
||||||
|
|
||||||
class IsolatedPlugin : CordaPluginRegistry()
|
|
@ -1 +0,0 @@
|
|||||||
net.corda.finance.contracts.isolated.IsolatedPlugin
|
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
package net.corda.nodeapi.internal.serialization
|
package net.corda.nodeapi.internal.serialization
|
||||||
|
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
|
||||||
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.nodeapi.internal.serialization.amqp.AmqpHeaderV1_0
|
import net.corda.nodeapi.internal.serialization.amqp.AmqpHeaderV1_0
|
||||||
@ -14,12 +13,6 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
|
|
||||||
val AMQP_ENABLED get() = SerializationDefaults.P2P_CONTEXT.preferredSerializationVersion == AmqpHeaderV1_0
|
val AMQP_ENABLED get() = SerializationDefaults.P2P_CONTEXT.preferredSerializationVersion == AmqpHeaderV1_0
|
||||||
|
|
||||||
class AMQPSerializationCustomization(val factory: SerializerFactory) : SerializationCustomization {
|
|
||||||
override fun addToWhitelist(vararg types: Class<*>) {
|
|
||||||
factory.addToWhitelist(*types)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun SerializerFactory.addToWhitelist(vararg types: Class<*>) {
|
fun SerializerFactory.addToWhitelist(vararg types: Class<*>) {
|
||||||
require(types.toSet().size == types.size) {
|
require(types.toSet().size == types.size) {
|
||||||
val duplicates = types.toMutableList()
|
val duplicates = types.toMutableList()
|
||||||
@ -33,12 +26,12 @@ fun SerializerFactory.addToWhitelist(vararg types: Class<*>) {
|
|||||||
|
|
||||||
abstract class AbstractAMQPSerializationScheme : SerializationScheme {
|
abstract class AbstractAMQPSerializationScheme : SerializationScheme {
|
||||||
internal companion object {
|
internal companion object {
|
||||||
private val pluginRegistries: List<CordaPluginRegistry> by lazy {
|
private val serializationWhitelists: List<SerializationWhitelist> by lazy {
|
||||||
ServiceLoader.load(CordaPluginRegistry::class.java, this::class.java.classLoader).toList()
|
ServiceLoader.load(SerializationWhitelist::class.java, this::class.java.classLoader).toList() + DefaultWhitelist
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerCustomSerializers(factory: SerializerFactory) {
|
fun registerCustomSerializers(factory: SerializerFactory) {
|
||||||
factory.apply {
|
with(factory) {
|
||||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer)
|
register(net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer)
|
||||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(this))
|
register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(this))
|
||||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.X500NameSerializer)
|
register(net.corda.nodeapi.internal.serialization.amqp.custom.X500NameSerializer)
|
||||||
@ -67,8 +60,8 @@ abstract class AbstractAMQPSerializationScheme : SerializationScheme {
|
|||||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.BitSetSerializer(this))
|
register(net.corda.nodeapi.internal.serialization.amqp.custom.BitSetSerializer(this))
|
||||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.EnumSetSerializer(this))
|
register(net.corda.nodeapi.internal.serialization.amqp.custom.EnumSetSerializer(this))
|
||||||
}
|
}
|
||||||
val customizer = AMQPSerializationCustomization(factory)
|
for (whitelistProvider in serializationWhitelists)
|
||||||
pluginRegistries.forEach { it.customizeSerialization(customizer) }
|
factory.addToWhitelist(*whitelistProvider.whitelist.toTypedArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@ import com.esotericsoftware.kryo.io.Output
|
|||||||
import com.esotericsoftware.kryo.serializers.FieldSerializer
|
import com.esotericsoftware.kryo.serializers.FieldSerializer
|
||||||
import com.esotericsoftware.kryo.util.DefaultClassResolver
|
import com.esotericsoftware.kryo.util.DefaultClassResolver
|
||||||
import com.esotericsoftware.kryo.util.Util
|
import com.esotericsoftware.kryo.util.Util
|
||||||
import net.corda.nodeapi.internal.AttachmentsClassLoader
|
|
||||||
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.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import net.corda.nodeapi.internal.AttachmentsClassLoader
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.lang.reflect.Modifier.isAbstract
|
import java.lang.reflect.Modifier.isAbstract
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
@ -160,7 +160,7 @@ class GlobalTransientClassWhiteList(val delegate: ClassWhitelist) : MutableClass
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A whitelist that can be customised via the [net.corda.core.node.CordaPluginRegistry], since implements [MutableClassWhitelist].
|
* A whitelist that can be customised via the [net.corda.core.node.SerializationWhitelist], since implements [MutableClassWhitelist].
|
||||||
*/
|
*/
|
||||||
class TransientClassWhiteList(val delegate: ClassWhitelist) : MutableClassWhitelist, ClassWhitelist by delegate {
|
class TransientClassWhiteList(val delegate: ClassWhitelist) : MutableClassWhitelist, ClassWhitelist by delegate {
|
||||||
val whitelist: MutableSet<String> = Collections.synchronizedSet(mutableSetOf())
|
val whitelist: MutableSet<String> = Collections.synchronizedSet(mutableSetOf())
|
||||||
|
@ -15,7 +15,7 @@ import net.corda.core.contracts.ContractAttachment
|
|||||||
import net.corda.core.contracts.PrivacySalt
|
import net.corda.core.contracts.PrivacySalt
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import net.corda.core.serialization.SerializedBytes
|
import net.corda.core.serialization.SerializedBytes
|
||||||
import net.corda.core.transactions.NotaryChangeWireTransaction
|
import net.corda.core.transactions.NotaryChangeWireTransaction
|
||||||
@ -49,8 +49,8 @@ import java.util.*
|
|||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
object DefaultKryoCustomizer {
|
object DefaultKryoCustomizer {
|
||||||
private val pluginRegistries: List<CordaPluginRegistry> by lazy {
|
private val serializationWhitelists: List<SerializationWhitelist> by lazy {
|
||||||
ServiceLoader.load(CordaPluginRegistry::class.java, this.javaClass.classLoader).toList()
|
ServiceLoader.load(SerializationWhitelist::class.java, this.javaClass.classLoader).toList() + DefaultWhitelist
|
||||||
}
|
}
|
||||||
|
|
||||||
fun customize(kryo: Kryo): Kryo {
|
fun customize(kryo: Kryo): Kryo {
|
||||||
@ -122,8 +122,17 @@ object DefaultKryoCustomizer {
|
|||||||
register(java.lang.invoke.SerializedLambda::class.java)
|
register(java.lang.invoke.SerializedLambda::class.java)
|
||||||
register(ClosureSerializer.Closure::class.java, CordaClosureBlacklistSerializer)
|
register(ClosureSerializer.Closure::class.java, CordaClosureBlacklistSerializer)
|
||||||
|
|
||||||
val customization = KryoSerializationCustomization(this)
|
for (whitelistProvider in serializationWhitelists) {
|
||||||
pluginRegistries.forEach { it.customizeSerialization(customization) }
|
val types = whitelistProvider.whitelist
|
||||||
|
require(types.toSet().size == types.size) {
|
||||||
|
val duplicates = types.toMutableList()
|
||||||
|
types.toSet().forEach { duplicates -= it }
|
||||||
|
"Cannot add duplicate classes to the whitelist ($duplicates)."
|
||||||
|
}
|
||||||
|
for (type in types) {
|
||||||
|
((kryo.classResolver as? CordaClassResolver)?.whitelist as? MutableClassWhitelist)?.add(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package net.corda.nodeapi.internal.serialization
|
package net.corda.nodeapi.internal.serialization
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.KryoException
|
import com.esotericsoftware.kryo.KryoException
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializationCustomization
|
|
||||||
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
|
||||||
import rx.Notification
|
import rx.Notification
|
||||||
@ -12,10 +11,9 @@ import java.util.*
|
|||||||
/**
|
/**
|
||||||
* NOTE: We do not whitelist [HashMap] or [HashSet] since they are unstable under serialization.
|
* NOTE: We do not whitelist [HashMap] or [HashSet] since they are unstable under serialization.
|
||||||
*/
|
*/
|
||||||
class DefaultWhitelist : CordaPluginRegistry() {
|
object DefaultWhitelist : SerializationWhitelist {
|
||||||
override fun customizeSerialization(custom: SerializationCustomization): Boolean {
|
override val whitelist =
|
||||||
custom.apply {
|
listOf(Array<Any>(0, {}).javaClass,
|
||||||
addToWhitelist(Array<Any>(0, {}).javaClass,
|
|
||||||
Notification::class.java,
|
Notification::class.java,
|
||||||
Notification.Kind::class.java,
|
Notification.Kind::class.java,
|
||||||
ArrayList::class.java,
|
ArrayList::class.java,
|
||||||
@ -62,8 +60,6 @@ class DefaultWhitelist : CordaPluginRegistry() {
|
|||||||
java.util.LinkedHashMap::class.java,
|
java.util.LinkedHashMap::class.java,
|
||||||
BitSet::class.java,
|
BitSet::class.java,
|
||||||
OnErrorNotImplementedException::class.java,
|
OnErrorNotImplementedException::class.java,
|
||||||
StackTraceElement::class.java)
|
StackTraceElement::class.java
|
||||||
}
|
)
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package net.corda.nodeapi.internal.serialization
|
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo
|
|
||||||
import net.corda.core.serialization.SerializationCustomization
|
|
||||||
|
|
||||||
class KryoSerializationCustomization(val kryo: Kryo) : SerializationCustomization {
|
|
||||||
override fun addToWhitelist(vararg types: Class<*>) {
|
|
||||||
require(types.toSet().size == types.size) {
|
|
||||||
val duplicates = types.toMutableList()
|
|
||||||
types.toSet().forEach { duplicates -= it }
|
|
||||||
"Cannot add duplicate classes to the whitelist ($duplicates)."
|
|
||||||
}
|
|
||||||
for (type in types) {
|
|
||||||
((kryo.classResolver as? CordaClassResolver)?.whitelist as? MutableClassWhitelist)?.add(type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
# Register a ServiceLoader service extending from net.corda.core.node.CordaPluginRegistry
|
|
||||||
net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
|
@ -22,12 +22,12 @@ import net.corda.core.internal.toX509CertHolder
|
|||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.RPCOps
|
import net.corda.core.messaging.RPCOps
|
||||||
import net.corda.core.messaging.SingleMessageRecipient
|
import net.corda.core.messaging.SingleMessageRecipient
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.node.services.*
|
import net.corda.core.node.services.*
|
||||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
@ -69,7 +69,6 @@ import net.corda.node.utilities.*
|
|||||||
import net.corda.node.utilities.AddOrRemove.ADD
|
import net.corda.node.utilities.AddOrRemove.ADD
|
||||||
import net.corda.nodeapi.internal.ServiceInfo
|
import net.corda.nodeapi.internal.ServiceInfo
|
||||||
import net.corda.nodeapi.internal.ServiceType
|
import net.corda.nodeapi.internal.ServiceType
|
||||||
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
@ -160,8 +159,8 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
CordaX500Name.build(cert.subjectX500Principal).copy(commonName = null)
|
CordaX500Name.build(cert.subjectX500Principal).copy(commonName = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
open val pluginRegistries: List<CordaPluginRegistry> by lazy {
|
open val serializationWhitelists: List<SerializationWhitelist> by lazy {
|
||||||
cordappProvider.cordapps.flatMap { it.plugins } + DefaultWhitelist()
|
cordappProvider.cordapps.flatMap { it.serializationWhitelists }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set to non-null once [start] has been successfully called. */
|
/** Set to non-null once [start] has been successfully called. */
|
||||||
|
@ -7,12 +7,12 @@ import net.corda.core.internal.*
|
|||||||
import net.corda.core.internal.concurrent.thenMatch
|
import net.corda.core.internal.concurrent.thenMatch
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.*
|
import net.corda.node.*
|
||||||
import net.corda.nodeapi.internal.ServiceInfo
|
|
||||||
import net.corda.node.services.config.FullNodeConfiguration
|
import net.corda.node.services.config.FullNodeConfiguration
|
||||||
import net.corda.node.services.transactions.bftSMaRtSerialFilter
|
import net.corda.node.services.transactions.bftSMaRtSerialFilter
|
||||||
import net.corda.node.shell.InteractiveShell
|
import net.corda.node.shell.InteractiveShell
|
||||||
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
||||||
import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
||||||
|
import net.corda.nodeapi.internal.ServiceInfo
|
||||||
import net.corda.nodeapi.internal.addShutdownHook
|
import net.corda.nodeapi.internal.addShutdownHook
|
||||||
import org.fusesource.jansi.Ansi
|
import org.fusesource.jansi.Ansi
|
||||||
import org.fusesource.jansi.AnsiConsole
|
import org.fusesource.jansi.AnsiConsole
|
||||||
@ -264,12 +264,6 @@ open class NodeStartup(val args: Array<String>) {
|
|||||||
if (it.isNotEmpty()) Node.printBasicNodeInfo("Providing network services", it.joinToString())
|
if (it.isNotEmpty()) Node.printBasicNodeInfo("Providing network services", it.joinToString())
|
||||||
}
|
}
|
||||||
Node.printBasicNodeInfo("Loaded CorDapps", node.cordappProvider.cordapps.map { it.name }.joinToString())
|
Node.printBasicNodeInfo("Loaded CorDapps", node.cordappProvider.cordapps.map { it.name }.joinToString())
|
||||||
val plugins = node.pluginRegistries
|
|
||||||
.map { it.javaClass.name }
|
|
||||||
.filterNot { it.startsWith("net.corda.node.") || it.startsWith("net.corda.core.") || it.startsWith("net.corda.nodeapi.") }
|
|
||||||
.map { it.substringBefore('$') }
|
|
||||||
if (plugins.isNotEmpty())
|
|
||||||
Node.printBasicNodeInfo("Loaded plugins", plugins.joinToString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun drawBanner(versionInfo: VersionInfo) {
|
open fun drawBanner(versionInfo: VersionInfo) {
|
||||||
|
@ -8,12 +8,13 @@ import net.corda.core.cordapp.Cordapp
|
|||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.cordapp.CordappImpl
|
import net.corda.core.internal.cordapp.CordappImpl
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
|
||||||
import net.corda.core.node.services.CordaService
|
import net.corda.core.node.services.CordaService
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.internal.classloading.requireAnnotation
|
import net.corda.node.internal.classloading.requireAnnotation
|
||||||
|
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
@ -222,10 +223,10 @@ class CordappLoader private constructor(private val cordappJarPaths: List<URL>)
|
|||||||
return (scanResult.getNamesOfClassesImplementing(Contract::class.java) + scanResult.getNamesOfClassesImplementing(UpgradedContract::class.java)).distinct()
|
return (scanResult.getNamesOfClassesImplementing(Contract::class.java) + scanResult.getNamesOfClassesImplementing(UpgradedContract::class.java)).distinct()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findPlugins(cordappJarPath: URL): List<CordaPluginRegistry> {
|
private fun findPlugins(cordappJarPath: URL): List<SerializationWhitelist> {
|
||||||
return ServiceLoader.load(CordaPluginRegistry::class.java, URLClassLoader(arrayOf(cordappJarPath), appClassLoader)).toList().filter {
|
return ServiceLoader.load(SerializationWhitelist::class.java, URLClassLoader(arrayOf(cordappJarPath), appClassLoader)).toList().filter {
|
||||||
cordappJarPath == it.javaClass.protectionDomain.codeSource.location
|
cordappJarPath == it.javaClass.protectionDomain.codeSource.location
|
||||||
}
|
} + DefaultWhitelist // Always add the DefaultWhitelist to the whitelist for an app.
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findCustomSchemas(scanResult: ScanResult): Set<MappedSchema> {
|
private fun findCustomSchemas(scanResult: ScanResult): Set<MappedSchema> {
|
||||||
|
@ -55,8 +55,6 @@ class CordappLoaderTest {
|
|||||||
assertThat(actualCordapp.rpcFlows).isEmpty()
|
assertThat(actualCordapp.rpcFlows).isEmpty()
|
||||||
assertThat(actualCordapp.schedulableFlows).isEmpty()
|
assertThat(actualCordapp.schedulableFlows).isEmpty()
|
||||||
assertThat(actualCordapp.services).isEmpty()
|
assertThat(actualCordapp.services).isEmpty()
|
||||||
assertThat(actualCordapp.plugins).hasSize(1)
|
|
||||||
assertThat(actualCordapp.plugins.first().javaClass.name).isEqualTo("net.corda.finance.contracts.isolated.IsolatedPlugin")
|
|
||||||
assertThat(actualCordapp.jarPath).isEqualTo(isolatedJAR)
|
assertThat(actualCordapp.jarPath).isEqualTo(isolatedJAR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
# Register a ServiceLoader service extending from net.corda.core.node.CordaPluginRegistry
|
|
||||||
net.corda.irs.plugin.IRSPlugin
|
net.corda.irs.plugin.IRSPlugin
|
||||||
net.corda.irs.plugin.IRSDemoPlugin
|
net.corda.irs.plugin.IRSDemoPlugin
|
@ -1,7 +1,7 @@
|
|||||||
package net.corda.vega.plugin
|
package net.corda.vega.plugin
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.finance.plugin.registerFinanceJSONMappers
|
import net.corda.finance.plugin.registerFinanceJSONMappers
|
||||||
import net.corda.vega.api.PortfolioApi
|
import net.corda.vega.api.PortfolioApi
|
||||||
import net.corda.webserver.services.WebServerPluginRegistry
|
import net.corda.webserver.services.WebServerPluginRegistry
|
||||||
@ -9,7 +9,7 @@ import java.util.function.Function
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* [SimmService] is the object that makes available the flows and services for the Simm agreement / evaluation flow.
|
* [SimmService] is the object that makes available the flows and services for the Simm agreement / evaluation flow.
|
||||||
* It is loaded via discovery - see [CordaPluginRegistry].
|
* It is loaded via discovery - see [SerializationWhitelist].
|
||||||
* It is also the object that enables a human usable web service for demo purpose
|
* It is also the object that enables a human usable web service for demo purpose
|
||||||
* It is loaded via discovery see [WebServerPluginRegistry].
|
* It is loaded via discovery see [WebServerPluginRegistry].
|
||||||
*/
|
*/
|
||||||
|
@ -10,35 +10,30 @@ import com.opengamma.strata.market.curve.CurveName
|
|||||||
import com.opengamma.strata.market.param.CurrencyParameterSensitivities
|
import com.opengamma.strata.market.param.CurrencyParameterSensitivities
|
||||||
import com.opengamma.strata.market.param.CurrencyParameterSensitivity
|
import com.opengamma.strata.market.param.CurrencyParameterSensitivity
|
||||||
import com.opengamma.strata.market.param.TenorDateParameterMetadata
|
import com.opengamma.strata.market.param.TenorDateParameterMetadata
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializationCustomization
|
|
||||||
import net.corda.vega.analytics.CordaMarketData
|
import net.corda.vega.analytics.CordaMarketData
|
||||||
import net.corda.vega.analytics.InitialMarginTriple
|
import net.corda.vega.analytics.InitialMarginTriple
|
||||||
import net.corda.webserver.services.WebServerPluginRegistry
|
import net.corda.webserver.services.WebServerPluginRegistry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [SimmService] is the object that makes available the flows and services for the Simm agreement / evaluation flow.
|
* [SimmService] is the object that makes available the flows and services for the Simm agreement / evaluation flow.
|
||||||
* It is loaded via discovery - see [CordaPluginRegistry].
|
* It is loaded via discovery - see [SerializationWhitelist].
|
||||||
* It is also the object that enables a human usable web service for demo purpose
|
* It is also the object that enables a human usable web service for demo purpose
|
||||||
* It is loaded via discovery see [WebServerPluginRegistry].
|
* It is loaded via discovery see [WebServerPluginRegistry].
|
||||||
*/
|
*/
|
||||||
class SimmPluginRegistry : CordaPluginRegistry() {
|
class SimmPluginRegistry : SerializationWhitelist {
|
||||||
override fun customizeSerialization(custom: SerializationCustomization): Boolean {
|
override val whitelist = listOf(
|
||||||
custom.apply {
|
MultiCurrencyAmount::class.java,
|
||||||
// OpenGamma classes.
|
Ordering.natural<Comparable<Any>>().javaClass,
|
||||||
addToWhitelist(MultiCurrencyAmount::class.java,
|
CurrencyAmount::class.java,
|
||||||
Ordering.natural<Comparable<Any>>().javaClass,
|
Currency::class.java,
|
||||||
CurrencyAmount::class.java,
|
InitialMarginTriple::class.java,
|
||||||
Currency::class.java,
|
CordaMarketData::class.java,
|
||||||
InitialMarginTriple::class.java,
|
CurrencyParameterSensitivities::class.java,
|
||||||
CordaMarketData::class.java,
|
CurrencyParameterSensitivity::class.java,
|
||||||
CurrencyParameterSensitivities::class.java,
|
DoubleArray::class.java,
|
||||||
CurrencyParameterSensitivity::class.java,
|
CurveName::class.java,
|
||||||
DoubleArray::class.java,
|
TenorDateParameterMetadata::class.java,
|
||||||
CurveName::class.java,
|
Tenor::class.java
|
||||||
TenorDateParameterMetadata::class.java,
|
)
|
||||||
Tenor::class.java)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
# Register a ServiceLoader service extending from net.corda.core.node.CordaPluginRegistry
|
|
||||||
net.corda.vega.plugin.SimmPluginRegistry
|
|
@ -0,0 +1 @@
|
|||||||
|
net.corda.vega.plugin.SimmPluginRegistry
|
@ -15,26 +15,32 @@ import net.corda.core.internal.uncheckedCast
|
|||||||
import net.corda.core.messaging.MessageRecipients
|
import net.corda.core.messaging.MessageRecipients
|
||||||
import net.corda.core.messaging.RPCOps
|
import net.corda.core.messaging.RPCOps
|
||||||
import net.corda.core.messaging.SingleMessageRecipient
|
import net.corda.core.messaging.SingleMessageRecipient
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.*
|
import net.corda.core.node.services.KeyManagementService
|
||||||
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
|
import net.corda.core.node.services.NotaryService
|
||||||
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.finance.utils.WorldMapLocation
|
import net.corda.finance.utils.WorldMapLocation
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.nodeapi.internal.ServiceInfo
|
|
||||||
import net.corda.nodeapi.internal.ServiceType
|
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.identity.PersistentIdentityService
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
import net.corda.node.services.keys.E2ETestKeyManagementService
|
import net.corda.node.services.keys.E2ETestKeyManagementService
|
||||||
import net.corda.node.services.messaging.MessagingService
|
import net.corda.node.services.messaging.MessagingService
|
||||||
import net.corda.node.services.network.InMemoryNetworkMapService
|
import net.corda.node.services.network.InMemoryNetworkMapService
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
import net.corda.node.services.transactions.*
|
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||||
|
import net.corda.node.services.transactions.BFTSMaRt
|
||||||
|
import net.corda.node.services.transactions.InMemoryTransactionVerifierService
|
||||||
|
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||||
import net.corda.node.utilities.AffinityExecutor
|
import net.corda.node.utilities.AffinityExecutor
|
||||||
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
|
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
import net.corda.node.utilities.CertificateAndKeyPair
|
||||||
|
import net.corda.nodeapi.internal.ServiceInfo
|
||||||
|
import net.corda.nodeapi.internal.ServiceType
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
@ -231,11 +237,11 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
|
|
||||||
override fun myAddresses() = emptyList<NetworkHostAndPort>()
|
override fun myAddresses() = emptyList<NetworkHostAndPort>()
|
||||||
|
|
||||||
// Allow unit tests to modify the plugin list before the node start,
|
// Allow unit tests to modify the serialization whitelist list before the node start,
|
||||||
// so they don't have to ServiceLoad test plugins into all unit tests.
|
// so they don't have to ServiceLoad test whitelists into all unit tests.
|
||||||
val testPluginRegistries by lazy { super.pluginRegistries.toMutableList() }
|
val testSerializationWhitelists by lazy { super.serializationWhitelists.toMutableList() }
|
||||||
override val pluginRegistries: List<CordaPluginRegistry>
|
override val serializationWhitelists: List<SerializationWhitelist>
|
||||||
get() = testPluginRegistries
|
get() = testSerializationWhitelists
|
||||||
|
|
||||||
// This does not indirect through the NodeInfo object so it can be called before the node is started.
|
// This does not indirect through the NodeInfo object so it can be called before the node is started.
|
||||||
// It is used from the network visualiser tool.
|
// It is used from the network visualiser tool.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user