From da8dec0d6303e2cd353e0c9d9da545b29bbf770e Mon Sep 17 00:00:00 2001 From: Konstantinos Chalkias Date: Wed, 7 Nov 2018 09:48:13 +0000 Subject: [PATCH 1/9] [CORDA-2192] Corda specific OID for AliasPrivateKey (#4175) --- .idea/compiler.xml | 4 ---- core/src/main/kotlin/net/corda/core/CordaOID.kt | 13 +++++++++---- .../net/corda/core/crypto/CordaSecurityProvider.kt | 4 +++- .../corda/core/crypto/internal/AliasPrivateKey.kt | 13 ++++++------- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 091dccdacc..51247be08d 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -73,10 +73,6 @@ - - - - diff --git a/core/src/main/kotlin/net/corda/core/CordaOID.kt b/core/src/main/kotlin/net/corda/core/CordaOID.kt index 644ade5fef..0a6bf3b658 100644 --- a/core/src/main/kotlin/net/corda/core/CordaOID.kt +++ b/core/src/main/kotlin/net/corda/core/CordaOID.kt @@ -1,18 +1,23 @@ package net.corda.core +import net.corda.core.crypto.internal.AliasPrivateKey + /** - * OIDs used for the Corda platform. Entries MUST NOT be removed from this file; if an OID is incorrectly assigned it - * should be marked deprecated. + * OIDs used for the Corda platform. All entries MUST be defined in this file only and they MUST NOT be removed. + * If an OID is incorrectly assigned, it should be marked deprecated and NEVER be reused again. */ @KeepForDJVM object CordaOID { /** Assigned to R3, see http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.4.1.50530&action=display */ const val R3_ROOT = "1.3.6.1.4.1.50530" - /** OIDs issued for the Corda platform */ + /** OIDs issued for the Corda platform. */ const val CORDA_PLATFORM = "$R3_ROOT.1" /** * Identifier for the X.509 certificate extension specifying the Corda role. See * https://r3-cev.atlassian.net/wiki/spaces/AWG/pages/156860572/Certificate+identity+type+extension for details. */ const val X509_EXTENSION_CORDA_ROLE = "$CORDA_PLATFORM.1" -} \ No newline at end of file + + /** OID for [AliasPrivateKey]. */ + const val ALIAS_PRIVATE_KEY = "$CORDA_PLATFORM.2" +} diff --git a/core/src/main/kotlin/net/corda/core/crypto/CordaSecurityProvider.kt b/core/src/main/kotlin/net/corda/core/crypto/CordaSecurityProvider.kt index ae44036600..1b0a8e47a1 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/CordaSecurityProvider.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/CordaSecurityProvider.kt @@ -34,7 +34,9 @@ private fun provideNonDeterministic(provider: Provider) { @KeepForDJVM object CordaObjectIdentifier { // UUID-based OID - // TODO: Register for an OID space and issue our own shorter OID. + // TODO define and use an official Corda OID in [CordaOID]. We didn't do yet for backwards compatibility purposes, + // because key.encoded (serialised version of keys) and [PublicKey.hash] for already stored [CompositeKey]s + // will not match. @JvmField val COMPOSITE_KEY = ASN1ObjectIdentifier("2.25.30086077608615255153862931087626791002") @JvmField diff --git a/core/src/main/kotlin/net/corda/core/crypto/internal/AliasPrivateKey.kt b/core/src/main/kotlin/net/corda/core/crypto/internal/AliasPrivateKey.kt index 50d75fdb31..ee872bf72b 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/internal/AliasPrivateKey.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/internal/AliasPrivateKey.kt @@ -1,5 +1,6 @@ package net.corda.core.crypto.internal +import net.corda.core.CordaOID import org.bouncycastle.asn1.* import org.bouncycastle.asn1.pkcs.PrivateKeyInfo import org.bouncycastle.asn1.x509.AlgorithmIdentifier @@ -17,12 +18,7 @@ import java.security.spec.PKCS8EncodedKeySpec data class AliasPrivateKey(val alias: String): PrivateKey { companion object { - // UUID-based OID - // TODO: Register for an OID space and issue our own shorter OID. - @JvmField - val ALIAS_PRIVATE_KEY = ASN1ObjectIdentifier("2.26.40086077608615255153862931087626791001") - - const val ALIAS_KEY_ALGORITHM = "ALIAS" + const val ALIAS_KEY_ALGORITHM = "AliasPrivateKey" } override fun getAlgorithm() = ALIAS_KEY_ALGORITHM @@ -30,7 +26,10 @@ data class AliasPrivateKey(val alias: String): PrivateKey { override fun getEncoded(): ByteArray { val keyVector = ASN1EncodableVector() keyVector.add(DERUTF8String(alias)) - val privateKeyInfoBytes = PrivateKeyInfo(AlgorithmIdentifier(ALIAS_PRIVATE_KEY), DERSequence(keyVector)).getEncoded(ASN1Encoding.DER) + val privateKeyInfoBytes = PrivateKeyInfo( + AlgorithmIdentifier(ASN1ObjectIdentifier(CordaOID.ALIAS_PRIVATE_KEY)), + DERSequence(keyVector) + ).getEncoded(ASN1Encoding.DER) val keySpec = PKCS8EncodedKeySpec(privateKeyInfoBytes) return keySpec.encoded } From ba9852bbe9ea4357e2855b3625bfe9caba537654 Mon Sep 17 00:00:00 2001 From: Stefano Franz Date: Wed, 7 Nov 2018 11:40:10 +0100 Subject: [PATCH 2/9] add documentation for initiating flow modification (#4180) --- docs/source/flow-overriding.rst | 61 ++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/docs/source/flow-overriding.rst b/docs/source/flow-overriding.rst index 273ff7fa03..7c12b1d471 100644 --- a/docs/source/flow-overriding.rst +++ b/docs/source/flow-overriding.rst @@ -138,4 +138,63 @@ the ``SubResponder`` with ``BaseResponder`` flowOverride("net.corda.Initiator", "net.corda.BaseResponder") } -This will generate the corresponding ``flowOverrides`` section and place it in the configuration for that node. \ No newline at end of file +This will generate the corresponding ``flowOverrides`` section and place it in the configuration for that node. + +Modifying the behaviour of @InitiatingFlow(s) +--------------------------------------------- + +It is likely that initiating flows will also require changes to reflect the different systems that are likely to be encountered. +At the moment, corda provides the ability to subclass an Initiator, and ensures that the correct responder will be invoked. +In the below example, we will change the behaviour of an Initiator from filtering Notaries out from comms, to only communicating with Notaries + + .. code-block:: kotlin + + @InitiatingFlow + @StartableByRPC + @StartableByService + open class BaseInitiator : FlowLogic() { + @Suspendable + override fun call(): String { + val partiesToTalkTo = serviceHub.networkMapCache.allNodes + .filterNot { it.legalIdentities.first() in serviceHub.networkMapCache.notaryIdentities } + .filterNot { it.legalIdentities.first().name == ourIdentity.name }.map { it.legalIdentities.first() } + val responses = ArrayList() + for (party in partiesToTalkTo) { + val session = initiateFlow(party) + val received = session.receive().unwrap { it } + responses.add(party.name.toString() + " responded with backend: " + received) + } + return "${getFLowName()} received the following \n" + responses.joinToString("\n") { it } + } + + open fun getFLowName(): String { + return "Normal Computer" + } + } + + @StartableByRPC + @StartableByService + class NotaryOnlyInitiator : BaseInitiator() { + @Suspendable + override fun call(): String { + return "Notary Communicator received:\n" + serviceHub.networkMapCache.notaryIdentities.map { + "Notary: ${it.name.organisation} is using a " + initiateFlow(it).receive().unwrap { it } + }.joinToString("\n") { it } + } + +.. warning:: The subclass must not have the @InitiatingFlow annotation. + +Corda will use the first annotation detected in the class hierarchy to determine which responder should be invoked. So for a Responder similar to + + .. code-block:: kotlin + + @InitiatedBy(BaseInitiator::class) + class BobbyResponder(othersideSession: FlowSession) : BaseResponder(othersideSession) { + override fun getMessageFromBackend(): String { + return "Robert'); DROP TABLE STATES;" + } + } + +it would be possible to invoke either ``BaseInitiator`` or ``NotaryOnlyInitiator`` and ``BobbyResponder`` would be used to reply. + +.. warning:: You must ensure the sequence of sends/receives/subFlows in a subclass are compatible with the parent. \ No newline at end of file From 7f01f9ca61ade8231054aedea7770c7c55bd96c7 Mon Sep 17 00:00:00 2001 From: szymonsztuka Date: Wed, 7 Nov 2018 13:38:03 +0000 Subject: [PATCH 3/9] Added new static method to API Stability check (related to CORDA-2011/CORDA-2057). (#4186) --- .ci/api-current.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.ci/api-current.txt b/.ci/api-current.txt index 3c04117395..46c29041ca 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -1256,6 +1256,8 @@ public final class net.corda.core.crypto.Crypto extends java.lang.Object @NotNull public static final java.security.Provider findProvider(String) @NotNull + public static final net.corda.core.crypto.SignatureScheme findSignatureScheme(int) + @NotNull public static final net.corda.core.crypto.SignatureScheme findSignatureScheme(String) @NotNull public static final net.corda.core.crypto.SignatureScheme findSignatureScheme(java.security.PrivateKey) From f3b372d31d862f76ab7c1696b99927641ed6218e Mon Sep 17 00:00:00 2001 From: Dominic Fox <40790090+distributedleetravis@users.noreply.github.com> Date: Wed, 7 Nov 2018 13:48:45 +0000 Subject: [PATCH 4/9] CORDA-2099 make serializer factory interface (#4137) * Separate SerializerFactory construction from concrete implementation * Fewer build methods * Method naming that doesn't fatally confuse determinisation * Extract SerializerFactory interface * Reset to master's version of compiler.xml * Un-ignore flickering test * Remove unnecessary build method * Whitespace * Unused import * Change build method * Formatting fixes * Fix test --- .../client/jackson/internal/CordaModule.kt | 7 +- .../amqp/AMQPClientSerializationScheme.kt | 7 +- constants.properties | 2 +- ...VerificationExceptionSerialisationTests.kt | 4 +- .../amqp/AMQPServerSerializationScheme.kt | 3 +- .../RpcServerObservableSerializerTests.kt | 6 +- .../testutils/AMQPTestSerialiationScheme.kt | 5 +- serialization-deterministic/build.gradle | 1 + .../internal/amqp/AMQPSerializerFactories.kt | 12 +- .../internal/model/DefaultCacheProvider.kt | 9 + .../internal/amqp/AMQPSerializerFactories.kt | 5 +- .../internal/amqp/SerializerFactory.kt | 232 ++++++------ .../internal/amqp/SerializerFactoryBuilder.kt | 53 +++ .../internal/model/DefaultCacheProvider.kt | 11 + .../amqp/JavaPrivatePropertyTests.java | 9 +- .../internal/ListsSerializationTest.kt | 4 +- .../internal/amqp/CorDappSerializerTests.kt | 32 +- .../amqp/DeserializeNeedingCarpentryTests.kt | 4 +- .../serialization/internal/amqp/EnumTests.kt | 29 +- .../internal/amqp/FingerPrinterTesting.kt | 9 +- .../internal/amqp/GenericsTests.kt | 57 ++- .../amqp/OptionalSerializationTests.kt | 5 +- .../internal/amqp/PrivatePropertyTests.kt | 19 +- .../internal/amqp/SerializationOutputTests.kt | 334 +++++++++++++----- .../amqp/SerializationPropertyOrdering.kt | 3 +- .../internal/amqp/SerializationSchemaTests.kt | 3 +- ...ticInitialisationOfSerializedObjectTest.kt | 15 +- .../internal/amqp/testutils/AMQPTestUtils.kt | 15 +- .../carpenter/CarpenterExceptionTests.kt | 7 +- .../carpenter/ClassCarpenterTestUtils.kt | 6 +- 30 files changed, 599 insertions(+), 309 deletions(-) create mode 100644 serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt create mode 100644 serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactoryBuilder.kt create mode 100644 serialization/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt diff --git a/client/jackson/src/main/kotlin/net/corda/client/jackson/internal/CordaModule.kt b/client/jackson/src/main/kotlin/net/corda/client/jackson/internal/CordaModule.kt index e56711a50d..6eef15668a 100644 --- a/client/jackson/src/main/kotlin/net/corda/client/jackson/internal/CordaModule.kt +++ b/client/jackson/src/main/kotlin/net/corda/client/jackson/internal/CordaModule.kt @@ -38,10 +38,7 @@ import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.parseAsHex import net.corda.core.utilities.toHexString import net.corda.serialization.internal.AllWhitelist -import net.corda.serialization.internal.amqp.SerializerFactory -import net.corda.serialization.internal.amqp.constructorForDeserialization -import net.corda.serialization.internal.amqp.hasCordaSerializable -import net.corda.serialization.internal.amqp.propertiesForSerialization +import net.corda.serialization.internal.amqp.* import java.math.BigDecimal import java.security.PublicKey import java.security.cert.CertPath @@ -88,7 +85,7 @@ class CordaModule : SimpleModule("corda-core") { */ private class CordaSerializableBeanSerializerModifier : BeanSerializerModifier() { // We need to pass in a SerializerFactory when scanning for properties, but don't actually do any serialisation so any will do. - private val serializerFactory = SerializerFactory(AllWhitelist, javaClass.classLoader) + private val serializerFactory = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader) override fun changeProperties(config: SerializationConfig, beanDesc: BeanDescription, diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/serialization/amqp/AMQPClientSerializationScheme.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/serialization/amqp/AMQPClientSerializationScheme.kt index 3ef215f9e8..6e094e87ee 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/serialization/amqp/AMQPClientSerializationScheme.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/serialization/amqp/AMQPClientSerializationScheme.kt @@ -8,10 +8,7 @@ import net.corda.core.serialization.SerializationCustomSerializer import net.corda.core.serialization.internal.SerializationEnvironment import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.serialization.internal.* -import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme -import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap -import net.corda.serialization.internal.amqp.SerializerFactory -import net.corda.serialization.internal.amqp.amqpMagic +import net.corda.serialization.internal.amqp.* import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer /** @@ -52,7 +49,7 @@ class AMQPClientSerializationScheme( } override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory { - return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply { + return SerializerFactoryBuilder.build(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply { register(RpcClientObservableDeSerializer) register(RpcClientCordaFutureSerializer(this)) register(RxNotificationSerializer(this)) diff --git a/constants.properties b/constants.properties index 9ed2417171..d0817917ec 100644 --- a/constants.properties +++ b/constants.properties @@ -1,4 +1,4 @@ -gradlePluginsVersion=4.0.33 +gradlePluginsVersion=4.0.34 kotlinVersion=1.2.71 # ***************************************************************# # When incrementing platformVersion make sure to update # diff --git a/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt b/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt index 59b2801bb1..6ee97c6031 100644 --- a/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt +++ b/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt @@ -6,7 +6,7 @@ import net.corda.serialization.internal.AMQP_RPC_CLIENT_CONTEXT import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.amqp.DeserializationInput import net.corda.serialization.internal.amqp.SerializationOutput -import net.corda.serialization.internal.amqp.SerializerFactory +import net.corda.serialization.internal.amqp.SerializerFactoryBuilder import net.corda.serialization.internal.amqp.custom.PublicKeySerializer import net.corda.testing.core.DUMMY_BANK_A_NAME import net.corda.testing.core.DUMMY_NOTARY_NAME @@ -15,7 +15,7 @@ import org.junit.Test import kotlin.test.assertEquals class TransactionVerificationExceptionSerialisationTests { - private fun defaultFactory() = SerializerFactory( + private fun defaultFactory() = SerializerFactoryBuilder.build( AllWhitelist, ClassLoader.getSystemClassLoader() ) diff --git a/node/src/main/kotlin/net/corda/node/serialization/amqp/AMQPServerSerializationScheme.kt b/node/src/main/kotlin/net/corda/node/serialization/amqp/AMQPServerSerializationScheme.kt index dfe6b6fafd..1cb164b0eb 100644 --- a/node/src/main/kotlin/net/corda/node/serialization/amqp/AMQPServerSerializationScheme.kt +++ b/node/src/main/kotlin/net/corda/node/serialization/amqp/AMQPServerSerializationScheme.kt @@ -8,6 +8,7 @@ import net.corda.serialization.internal.CordaSerializationMagic import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap import net.corda.serialization.internal.amqp.SerializerFactory +import net.corda.serialization.internal.amqp.SerializerFactoryBuilder import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer /** @@ -28,7 +29,7 @@ class AMQPServerSerializationScheme( } override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory { - return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply { + return SerializerFactoryBuilder.build(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply { register(RpcServerObservableSerializer()) register(RpcServerCordaFutureSerializer(this)) register(RxNotificationSerializer(this)) diff --git a/node/src/test/kotlin/net/corda/node/internal/serialization/RpcServerObservableSerializerTests.kt b/node/src/test/kotlin/net/corda/node/internal/serialization/RpcServerObservableSerializerTests.kt index 720d147eac..a12cf73042 100644 --- a/node/src/test/kotlin/net/corda/node/internal/serialization/RpcServerObservableSerializerTests.kt +++ b/node/src/test/kotlin/net/corda/node/internal/serialization/RpcServerObservableSerializerTests.kt @@ -10,7 +10,7 @@ import net.corda.node.serialization.amqp.RpcServerObservableSerializer import net.corda.node.services.messaging.ObservableSubscription import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.amqp.SerializationOutput -import net.corda.serialization.internal.amqp.SerializerFactory +import net.corda.serialization.internal.amqp.SerializerFactoryBuilder import org.apache.activemq.artemis.api.core.SimpleString import org.junit.Test import rx.Observable @@ -34,7 +34,7 @@ class RpcServerObservableSerializerTests { @Test fun canSerializerBeRegistered() { - val sf = SerializerFactory(AllWhitelist, javaClass.classLoader) + val sf = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader) try { sf.register(RpcServerObservableSerializer()) @@ -67,7 +67,7 @@ class RpcServerObservableSerializerTests { deduplicationIdentity = "thisIsATest", clientAddress = SimpleString(testClientAddress)) - val sf = SerializerFactory(AllWhitelist, javaClass.classLoader).apply { + val sf = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader).apply { register(RpcServerObservableSerializer()) } diff --git a/node/src/test/kotlin/net/corda/node/internal/serialization/testutils/AMQPTestSerialiationScheme.kt b/node/src/test/kotlin/net/corda/node/internal/serialization/testutils/AMQPTestSerialiationScheme.kt index d17755fa4c..7a803cb661 100644 --- a/node/src/test/kotlin/net/corda/node/internal/serialization/testutils/AMQPTestSerialiationScheme.kt +++ b/node/src/test/kotlin/net/corda/node/internal/serialization/testutils/AMQPTestSerialiationScheme.kt @@ -12,6 +12,7 @@ import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap +import net.corda.serialization.internal.amqp.SerializerFactoryBuilder import net.corda.client.rpc.internal.ObservableContext as ClientObservableContext /** @@ -28,13 +29,13 @@ class AMQPRoundTripRPCSerializationScheme( cordappCustomSerializers, serializerFactoriesForContexts ) { override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory { - return SerializerFactory(AllWhitelist, javaClass.classLoader).apply { + return SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader).apply { register(RpcClientObservableDeSerializer) } } override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory { - return SerializerFactory(AllWhitelist, javaClass.classLoader).apply { + return SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader).apply { register(RpcServerObservableSerializer()) } } diff --git a/serialization-deterministic/build.gradle b/serialization-deterministic/build.gradle index 74190fd20a..36242351b5 100644 --- a/serialization-deterministic/build.gradle +++ b/serialization-deterministic/build.gradle @@ -50,6 +50,7 @@ task patchSerialization(type: Zip, dependsOn: serializationJarTask) { exclude 'net/corda/serialization/internal/amqp/AMQPSerializerFactories*' exclude 'net/corda/serialization/internal/amqp/AMQPStreams*' exclude 'net/corda/serialization/internal/amqp/AMQPSerializationThreadContext*' + exclude 'net/corda/serialization/internal/model/DefaultCacheProvider*' } reproducibleFileOrder = true diff --git a/serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt b/serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt index e3f74f2db9..d0bb4b4798 100644 --- a/serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt +++ b/serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt @@ -15,15 +15,9 @@ fun createSerializerFactoryFactory(): SerializerFactoryFactory = DeterministicSe private class DeterministicSerializerFactoryFactory : SerializerFactoryFactory { override fun make(context: SerializationContext) = - SerializerFactory( - whitelist = context.whitelist, - classCarpenter = DummyClassCarpenter(context.whitelist, context.deserializationClassLoader), - serializersByType = mutableMapOf(), - serializersByDescriptor = mutableMapOf(), - customSerializers = ArrayList(), - customSerializersCache = mutableMapOf(), - transformsCache = mutableMapOf() - ) + SerializerFactoryBuilder.build( + whitelist = context.whitelist, + classCarpenter = DummyClassCarpenter(context.whitelist, context.deserializationClassLoader)) } private class DummyClassCarpenter( diff --git a/serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt b/serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt new file mode 100644 index 0000000000..022c045e87 --- /dev/null +++ b/serialization-deterministic/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt @@ -0,0 +1,9 @@ +package net.corda.serialization.internal.model + +/** + * We can't have [ConcurrentHashMap]s in the DJVM, so it must supply its own version of this object which returns + * plain old [MutableMap]s instead. + */ +object DefaultCacheProvider { + fun createCache(): MutableMap = mutableMapOf() +} \ No newline at end of file diff --git a/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt b/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt index aacde49dac..93e82dfe0a 100644 --- a/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt +++ b/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/AMQPSerializerFactories.kt @@ -3,11 +3,14 @@ package net.corda.serialization.internal.amqp import net.corda.core.serialization.SerializationContext +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl fun createSerializerFactoryFactory(): SerializerFactoryFactory = SerializerFactoryFactoryImpl() open class SerializerFactoryFactoryImpl : SerializerFactoryFactory { override fun make(context: SerializationContext): SerializerFactory { - return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled) + return SerializerFactoryBuilder.build(context.whitelist, + ClassCarpenterImpl(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled) + ) } } diff --git a/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactory.kt b/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactory.kt index c8d4b14891..1cfa23f1eb 100644 --- a/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactory.kt +++ b/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactory.kt @@ -1,7 +1,6 @@ package net.corda.serialization.internal.amqp import com.google.common.primitives.Primitives -import net.corda.core.DeleteForDJVM import net.corda.core.KeepForDJVM import net.corda.core.StubOutForDJVM import net.corda.core.internal.kotlinObjectInstance @@ -12,12 +11,11 @@ import net.corda.core.utilities.debug import net.corda.core.utilities.loggerFor import net.corda.core.utilities.trace import net.corda.serialization.internal.carpenter.* +import net.corda.serialization.internal.model.DefaultCacheProvider import org.apache.qpid.proton.amqp.* import java.io.NotSerializableException import java.lang.reflect.* import java.util.* -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.CopyOnWriteArrayList import javax.annotation.concurrent.ThreadSafe @KeepForDJVM @@ -49,54 +47,122 @@ data class CustomSerializersCacheKey(val clazz: Class<*>, val declaredType: Type // TODO: need to support super classes as well as interfaces with our current code base... what's involved? If we continue to ban, what is the impact? @KeepForDJVM @ThreadSafe -open class SerializerFactory( - val whitelist: ClassWhitelist, - val classCarpenter: ClassCarpenter, - private val evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider, - val fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter, - private val serializersByType: MutableMap>, - val serializersByDescriptor: MutableMap>, - private val customSerializers: MutableList, - private val customSerializersCache: MutableMap?>, - val transformsCache: MutableMap>>, +interface SerializerFactory { + val whitelist: ClassWhitelist + val classCarpenter: ClassCarpenter + val fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter + // Caches + val serializersByType: MutableMap> + val serializersByDescriptor: MutableMap> + val transformsCache: MutableMap>> + val fingerPrinter: FingerPrinter + val classloader: ClassLoader + /** + * Look up, and manufacture if necessary, a serializer for the given type. + * + * @param actualClass Will be null if there isn't an actual object instance available (e.g. for + * restricted type processing). + */ + @Throws(NotSerializableException::class) + fun get(actualClass: Class<*>?, declaredType: Type): AMQPSerializer + + /** + * Lookup and manufacture a serializer for the given AMQP type descriptor, assuming we also have the necessary types + * contained in the [Schema]. + */ + @Throws(NotSerializableException::class) + fun get(typeDescriptor: Any, schema: SerializationSchemas): AMQPSerializer + + /** + * Register a custom serializer for any type that cannot be serialized or deserialized by the default serializer + * that expects to find getters and a constructor with a parameter for each property. + */ + fun register(customSerializer: CustomSerializer) + + fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer? + fun registerExternal(customSerializer: CorDappCustomSerializer) + fun registerByDescriptor(name: Symbol, serializerCreator: () -> AMQPSerializer): AMQPSerializer + + object AnyType : WildcardType { + override fun getUpperBounds(): Array = arrayOf(Object::class.java) + + override fun getLowerBounds(): Array = emptyArray() + + override fun toString(): String = "?" + } + + companion object { + fun isPrimitive(type: Type): Boolean = primitiveTypeName(type) != null + + fun primitiveTypeName(type: Type): String? { + val clazz = type as? Class<*> ?: return null + return primitiveTypeNames[Primitives.unwrap(clazz)] + } + + fun primitiveType(type: String): Class<*>? { + return namesOfPrimitiveTypes[type] + } + + private val primitiveTypeNames: Map, String> = mapOf( + Character::class.java to "char", + Char::class.java to "char", + Boolean::class.java to "boolean", + Byte::class.java to "byte", + UnsignedByte::class.java to "ubyte", + Short::class.java to "short", + UnsignedShort::class.java to "ushort", + Int::class.java to "int", + UnsignedInteger::class.java to "uint", + Long::class.java to "long", + UnsignedLong::class.java to "ulong", + Float::class.java to "float", + Double::class.java to "double", + Decimal32::class.java to "decimal32", + Decimal64::class.java to "decimal62", + Decimal128::class.java to "decimal128", + Date::class.java to "timestamp", + UUID::class.java to "uuid", + ByteArray::class.java to "binary", + String::class.java to "string", + Symbol::class.java to "symbol") + + private val namesOfPrimitiveTypes: Map> = primitiveTypeNames.map { it.value to it.key }.toMap() + + fun nameForType(type: Type): String = when (type) { + is Class<*> -> { + primitiveTypeName(type) ?: if (type.isArray) { + "${nameForType(type.componentType)}${if (type.componentType.isPrimitive) "[p]" else "[]"}" + } else type.name + } + is ParameterizedType -> { + "${nameForType(type.rawType)}<${type.actualTypeArguments.joinToString { nameForType(it) }}>" + } + is GenericArrayType -> "${nameForType(type.genericComponentType)}[]" + is WildcardType -> "?" + is TypeVariable<*> -> "?" + else -> throw AMQPNotSerializableException(type, "Unable to render type $type to a string.") + } + } +} + +open class DefaultSerializerFactory( + override val whitelist: ClassWhitelist, + override val classCarpenter: ClassCarpenter, + private val evolutionSerializerProvider: EvolutionSerializerProvider, + override val fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter, private val onlyCustomSerializers: Boolean = false -) { - @DeleteForDJVM - constructor(whitelist: ClassWhitelist, - classCarpenter: ClassCarpenter, - evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider, - fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter, - onlyCustomSerializers: Boolean = false - ) : this( - whitelist, - classCarpenter, - evolutionSerializerProvider, - fingerPrinterConstructor, - ConcurrentHashMap(), - ConcurrentHashMap(), - CopyOnWriteArrayList(), - ConcurrentHashMap(), - ConcurrentHashMap(), - onlyCustomSerializers - ) +) : SerializerFactory { - @DeleteForDJVM - constructor(whitelist: ClassWhitelist, - carpenterClassLoader: ClassLoader, - lenientCarpenter: Boolean = false, - evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider, - fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter, - onlyCustomSerializers: Boolean = false - ) : this( - whitelist, - ClassCarpenterImpl(whitelist, carpenterClassLoader, lenientCarpenter), - evolutionSerializerProvider, - fingerPrinterConstructor, - onlyCustomSerializers) + // Caches + override val serializersByType: MutableMap> = DefaultCacheProvider.createCache() + override val serializersByDescriptor: MutableMap> = DefaultCacheProvider.createCache() + private var customSerializers: List = emptyList() + private val customSerializersCache: MutableMap?> = DefaultCacheProvider.createCache() + override val transformsCache: MutableMap>> = DefaultCacheProvider.createCache() - val fingerPrinter by lazy { fingerPrinterConstructor(this) } + override val fingerPrinter by lazy { fingerPrinterConstructor(this) } - val classloader: ClassLoader get() = classCarpenter.classloader + override val classloader: ClassLoader get() = classCarpenter.classloader // Used to short circuit any computation for a given input, for performance. private data class MemoType(val actualClass: Class<*>?, val declaredType: Type) : Type @@ -108,7 +174,7 @@ open class SerializerFactory( * restricted type processing). */ @Throws(NotSerializableException::class) - fun get(actualClass: Class<*>?, declaredType: Type): AMQPSerializer { + override fun get(actualClass: Class<*>?, declaredType: Type): AMQPSerializer { // can be useful to enable but will be *extremely* chatty if you do logger.trace { "Get Serializer for $actualClass ${declaredType.typeName}" } @@ -169,7 +235,7 @@ open class SerializerFactory( * contained in the [Schema]. */ @Throws(NotSerializableException::class) - fun get(typeDescriptor: Any, schema: SerializationSchemas): AMQPSerializer { + override fun get(typeDescriptor: Any, schema: SerializationSchemas): AMQPSerializer { return serializersByDescriptor[typeDescriptor] ?: { logger.trace("get Serializer descriptor=${typeDescriptor}") processSchema(FactorySchemaAndDescriptor(schema, typeDescriptor)) @@ -182,7 +248,7 @@ open class SerializerFactory( * Register a custom serializer for any type that cannot be serialized or deserialized by the default serializer * that expects to find getters and a constructor with a parameter for each property. */ - open fun register(customSerializer: CustomSerializer) { + override fun register(customSerializer: CustomSerializer) { logger.trace("action=\"Registering custom serializer\", class=\"${customSerializer.type}\"") if (!serializersByDescriptor.containsKey(customSerializer.typeDescriptor)) { customSerializers += customSerializer @@ -193,7 +259,7 @@ open class SerializerFactory( } } - fun registerExternal(customSerializer: CorDappCustomSerializer) { + override fun registerExternal(customSerializer: CorDappCustomSerializer) { logger.trace("action=\"Registering external serializer\", class=\"${customSerializer.type}\"") if (!serializersByDescriptor.containsKey(customSerializer.typeDescriptor)) { customSerializers += customSerializer @@ -319,7 +385,7 @@ open class SerializerFactory( throw AMQPNotSerializableException( type, "Serializer does not support synthetic classes") - } else if (isPrimitive(clazz)) { + } else if (SerializerFactory.isPrimitive(clazz)) { AMQPPrimitiveSerializer(clazz) } else { findCustomSerializer(clazz, declaredType) ?: run { @@ -344,7 +410,7 @@ open class SerializerFactory( } } - internal fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer? { + override fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer? { return customSerializersCache.computeIfAbsent(CustomSerializersCacheKey(clazz, declaredType), ::doFindCustomSerializer) } @@ -383,69 +449,11 @@ open class SerializerFactory( return MapSerializer(declaredType, this) } - fun registerByDescriptor(name: Symbol, serializerCreator: () -> AMQPSerializer): AMQPSerializer = + override fun registerByDescriptor(name: Symbol, serializerCreator: () -> AMQPSerializer): AMQPSerializer = serializersByDescriptor.computeIfAbsent(name) { _ -> serializerCreator() } companion object { private val logger = contextLogger() - - fun isPrimitive(type: Type): Boolean = primitiveTypeName(type) != null - - fun primitiveTypeName(type: Type): String? { - val clazz = type as? Class<*> ?: return null - return primitiveTypeNames[Primitives.unwrap(clazz)] - } - - fun primitiveType(type: String): Class<*>? { - return namesOfPrimitiveTypes[type] - } - - private val primitiveTypeNames: Map, String> = mapOf( - Character::class.java to "char", - Char::class.java to "char", - Boolean::class.java to "boolean", - Byte::class.java to "byte", - UnsignedByte::class.java to "ubyte", - Short::class.java to "short", - UnsignedShort::class.java to "ushort", - Int::class.java to "int", - UnsignedInteger::class.java to "uint", - Long::class.java to "long", - UnsignedLong::class.java to "ulong", - Float::class.java to "float", - Double::class.java to "double", - Decimal32::class.java to "decimal32", - Decimal64::class.java to "decimal62", - Decimal128::class.java to "decimal128", - Date::class.java to "timestamp", - UUID::class.java to "uuid", - ByteArray::class.java to "binary", - String::class.java to "string", - Symbol::class.java to "symbol") - - private val namesOfPrimitiveTypes: Map> = primitiveTypeNames.map { it.value to it.key }.toMap() - - fun nameForType(type: Type): String = when (type) { - is Class<*> -> { - primitiveTypeName(type) ?: if (type.isArray) { - "${nameForType(type.componentType)}${if (type.componentType.isPrimitive) "[p]" else "[]"}" - } else type.name - } - is ParameterizedType -> { - "${nameForType(type.rawType)}<${type.actualTypeArguments.joinToString { nameForType(it) }}>" - } - is GenericArrayType -> "${nameForType(type.genericComponentType)}[]" - is WildcardType -> "?" - is TypeVariable<*> -> "?" - else -> throw AMQPNotSerializableException(type, "Unable to render type $type to a string.") - } } - object AnyType : WildcardType { - override fun getUpperBounds(): Array = arrayOf(Object::class.java) - - override fun getLowerBounds(): Array = emptyArray() - - override fun toString(): String = "?" - } } \ No newline at end of file diff --git a/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactoryBuilder.kt b/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactoryBuilder.kt new file mode 100644 index 0000000000..0d05d4e0de --- /dev/null +++ b/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/SerializerFactoryBuilder.kt @@ -0,0 +1,53 @@ +package net.corda.serialization.internal.amqp + +import net.corda.core.DeleteForDJVM +import net.corda.core.KeepForDJVM +import net.corda.core.serialization.ClassWhitelist +import net.corda.serialization.internal.carpenter.ClassCarpenter +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl + +@KeepForDJVM +object SerializerFactoryBuilder { + + @JvmStatic + @JvmOverloads + fun build( + whitelist: ClassWhitelist, + classCarpenter: ClassCarpenter, + evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider, + fingerPrinterProvider: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter, + onlyCustomSerializers: Boolean = false): SerializerFactory { + return makeFactory( + whitelist, + classCarpenter, + evolutionSerializerProvider, + fingerPrinterProvider, + onlyCustomSerializers) + } + + @JvmStatic + @JvmOverloads + @DeleteForDJVM + fun build( + whitelist: ClassWhitelist, + carpenterClassLoader: ClassLoader, + lenientCarpenterEnabled: Boolean = false, + evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider, + fingerPrinterProvider: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter, + onlyCustomSerializers: Boolean = false): SerializerFactory { + return makeFactory( + whitelist, + ClassCarpenterImpl(whitelist, carpenterClassLoader, lenientCarpenterEnabled), + evolutionSerializerProvider, + fingerPrinterProvider, + onlyCustomSerializers) + } + + private fun makeFactory(whitelist: ClassWhitelist, + classCarpenter: ClassCarpenter, + evolutionSerializerProvider: EvolutionSerializerProvider, + fingerPrinterProvider: (SerializerFactory) -> FingerPrinter, + onlyCustomSerializers: Boolean) = + DefaultSerializerFactory(whitelist, classCarpenter, evolutionSerializerProvider, fingerPrinterProvider, + onlyCustomSerializers) +} \ No newline at end of file diff --git a/serialization/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt b/serialization/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt new file mode 100644 index 0000000000..4995c1dbb2 --- /dev/null +++ b/serialization/src/main/kotlin/net/corda/serialization/internal/model/DefaultCacheProvider.kt @@ -0,0 +1,11 @@ +package net.corda.serialization.internal.model + +import java.util.concurrent.ConcurrentHashMap + +/** + * We can't have [ConcurrentHashMap]s in the DJVM, so it must supply its own version of this object which returns + * plain old [MutableMap]s instead. + */ +object DefaultCacheProvider { + fun createCache(): MutableMap = ConcurrentHashMap() +} \ No newline at end of file diff --git a/serialization/src/test/java/net/corda/serialization/internal/amqp/JavaPrivatePropertyTests.java b/serialization/src/test/java/net/corda/serialization/internal/amqp/JavaPrivatePropertyTests.java index e96763360d..a68e14b572 100644 --- a/serialization/src/test/java/net/corda/serialization/internal/amqp/JavaPrivatePropertyTests.java +++ b/serialization/src/test/java/net/corda/serialization/internal/amqp/JavaPrivatePropertyTests.java @@ -147,10 +147,7 @@ public class JavaPrivatePropertyTests { // // Now ensure we actually got a private property serializer // - Field f = SerializerFactory.class.getDeclaredField("serializersByDescriptor"); - f.setAccessible(true); - - Map> serializersByDescriptor = uncheckedCast(f.get(factory)); + Map> serializersByDescriptor = factory.getSerializersByDescriptor(); assertEquals(1, serializersByDescriptor.size()); ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]); @@ -175,9 +172,7 @@ public class JavaPrivatePropertyTests { // // Now ensure we actually got a private property serializer // - Field f = SerializerFactory.class.getDeclaredField("serializersByDescriptor"); - f.setAccessible(true); - Map> serializersByDescriptor = uncheckedCast(f.get(factory)); + Map> serializersByDescriptor = factory.getSerializersByDescriptor(); assertEquals(1, serializersByDescriptor.size()); ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]); diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/ListsSerializationTest.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/ListsSerializationTest.kt index 60f71520fe..0164664800 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/ListsSerializationTest.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/ListsSerializationTest.kt @@ -7,7 +7,7 @@ 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.amqp.SerializerFactoryBuilder import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.internal.amqpSpecific import net.corda.testing.internal.kryoSpecific @@ -28,7 +28,7 @@ class ListsSerializationTest { fun verifyEnvelope(serBytes: SerializedBytes, envVerBody: (Envelope) -> Unit) = amqpSpecific("AMQP specific envelope verification") { val context = SerializationFactory.defaultFactory.defaultContext - val envelope = DeserializationInput(SerializerFactory(context.whitelist, context.deserializationClassLoader)).getEnvelope(serBytes, context) + val envelope = DeserializationInput(SerializerFactoryBuilder.build(context.whitelist, context.deserializationClassLoader)).getEnvelope(serBytes, context) envVerBody(envelope) } } diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/CorDappSerializerTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/CorDappSerializerTests.kt index 55aa7ca1a8..d38187f6b7 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/CorDappSerializerTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/CorDappSerializerTests.kt @@ -4,6 +4,7 @@ import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.SerializationCustomSerializer import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.amqp.testutils.* +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl import org.assertj.core.api.Assertions import org.junit.Test import java.io.NotSerializableException @@ -12,16 +13,16 @@ import kotlin.test.assertEquals class CorDappSerializerTests { data class NeedsProxy(val a: String) - private fun proxyFactory( - serializers: List> - ) = SerializerFactory( - AllWhitelist, - ClassLoader.getSystemClassLoader(), - onlyCustomSerializers = true - ).apply { + private fun proxyFactory(serializers: List>): SerializerFactory { + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()), + DefaultEvolutionSerializerProvider) + serializers.forEach { - registerExternal(CorDappCustomSerializer(it, this)) + factory.registerExternal(CorDappCustomSerializer(it, factory)) } + + return factory } class NeedsProxyProxySerializer : SerializationCustomSerializer { @@ -101,7 +102,10 @@ class CorDappSerializerTests { override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses } - val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) + val whitelist = WL() + val factory = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory)) val tv1 = 100 @@ -123,7 +127,10 @@ class CorDappSerializerTests { override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses } - val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) + val whitelist = WL() + val factory = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory)) val tv1 = 100 @@ -148,7 +155,10 @@ class CorDappSerializerTests { override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses } - val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) + val whitelist = WL() + val factory = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory)) val tv1 = 100 diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/DeserializeNeedingCarpentryTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/DeserializeNeedingCarpentryTests.kt index 1b6642bdd5..1d7fa23dd6 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/DeserializeNeedingCarpentryTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/DeserializeNeedingCarpentryTests.kt @@ -94,7 +94,9 @@ class DeserializeNeedingCarpentryTests : AmqpCarpenterBase(AllWhitelist) { // won't already exist and it will be carpented a second time showing that when A and B are the // same underlying class that we didn't create a second instance of the class with the // second deserialisation - val lfactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val lfactory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) val deserialisedC = DeserializationInput(lfactory).deserialize( TestSerializationOutput(VERBOSE, lfactory).serialize(concreteC)) diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EnumTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EnumTests.kt index 4221aeff61..badb31c2cd 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EnumTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EnumTests.kt @@ -9,6 +9,7 @@ import net.corda.serialization.internal.amqp.testutils.deserializeAndReturnEnvel import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryNoEvolution import net.corda.serialization.internal.amqp.testutils.testName +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl import org.assertj.core.api.Assertions import org.junit.Test import java.io.NotSerializableException @@ -205,7 +206,10 @@ class EnumTests { } } - val factory = SerializerFactory(WL(classTestName("C")), ClassLoader.getSystemClassLoader()) + val whitelist = WL(classTestName("C")) + val factory = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) Assertions.assertThatThrownBy { TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE)) @@ -223,7 +227,10 @@ class EnumTests { } } - val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) + val whitelist = WL() + val factory = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) // if it all works, this won't explode TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE)) @@ -237,7 +244,10 @@ class EnumTests { override fun hasListed(type: Class<*>) = false } - val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) + val whitelist = WL() + val factory = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) // if it all works, this won't explode TestSerializationOutput(VERBOSE, factory).serialize(C(AnnotatedBras.UNDERWIRE)) @@ -252,14 +262,19 @@ class EnumTests { } // first serialise the class using a context in which Bras are whitelisted - val factory = SerializerFactory(WL(listOf(classTestName("C"), - "net.corda.serialization.internal.amqp.EnumTests\$Bras")), - ClassLoader.getSystemClassLoader()) + val whitelist = WL(listOf(classTestName("C"), + "net.corda.serialization.internal.amqp.EnumTests\$Bras")) + val factory = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) val bytes = TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE)) // then take that serialised object and attempt to deserialize it in a context that // disallows the Bras enum - val factory2 = SerializerFactory(WL(listOf(classTestName("C"))), ClassLoader.getSystemClassLoader()) + val whitelist1 = WL(listOf(classTestName("C"))) + val factory2 = SerializerFactoryBuilder.build(whitelist1, + ClassCarpenterImpl(whitelist1, ClassLoader.getSystemClassLoader()) + ) Assertions.assertThatThrownBy { DeserializationInput(factory2).deserialize(bytes) }.isInstanceOf(NotSerializableException::class.java) diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/FingerPrinterTesting.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/FingerPrinterTesting.kt index 6d88f3ccf2..1e5f7c3d82 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/FingerPrinterTesting.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/FingerPrinterTesting.kt @@ -6,6 +6,7 @@ import kotlin.test.assertEquals import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl class FingerPrinterTesting : FingerPrinter { private var index = 0 @@ -39,11 +40,9 @@ class FingerPrinterTestingTests { fun worksAsReplacement() { data class C(val a: Int, val b: Long) - val factory = SerializerFactory( - AllWhitelist, - ClassLoader.getSystemClassLoader(), - evolutionSerializerProvider = FailIfEvolutionAttempted, - fingerPrinterConstructor = { _ -> FingerPrinterTesting() }) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()), + fingerPrinterProvider = { _ -> FingerPrinterTesting() }) val blob = TestSerializationOutput(VERBOSE, factory).serializeAndReturnSchema(C(1, 2L)) diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/GenericsTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/GenericsTests.kt index af68f8d669..544d467bd8 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/GenericsTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/GenericsTests.kt @@ -9,6 +9,7 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.serialization.SerializedBytes import net.corda.serialization.internal.amqp.testutils.* import net.corda.serialization.internal.AllWhitelist +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl import net.corda.testing.common.internal.ProjectStructure.projectRootDir import net.corda.testing.core.TestIdentity import org.junit.Test @@ -120,8 +121,12 @@ class GenericsTests { data class G(val a: Int) data class Wrapper(val a: Int, val b: SerializedBytes) - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) val ser = SerializationOutput(factory) val gBytes = ser.serialize(G(1)) @@ -145,8 +150,12 @@ class GenericsTests { data class Container(val b: T) data class Wrapper(val c: Container) - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) - val factories = listOf(factory, SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) + val factories = listOf(factory, SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )) val ser = SerializationOutput(factory) ser.serialize(Wrapper(Container(InnerA(1)))).apply { @@ -178,8 +187,12 @@ class GenericsTests { data class Wrapper(val c: Container) val factorys = listOf( - SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()), - SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) + SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ), + SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )) val ser = SerializationOutput(factorys[0]) @@ -200,7 +213,9 @@ class GenericsTests { private fun forceWildcardSerialize( a: ForceWildcard<*>, - factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())): SerializedBytes<*> { + factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )): SerializedBytes<*> { val bytes = SerializationOutput(factory).serializeAndReturnSchema(a) factory.serializersByDescriptor.printKeyToType() bytes.printSchema() @@ -210,21 +225,27 @@ class GenericsTests { @Suppress("UNCHECKED_CAST") private fun forceWildcardDeserializeString( bytes: SerializedBytes<*>, - factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) { + factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )) { DeserializationInput(factory).deserialize(bytes as SerializedBytes>) } @Suppress("UNCHECKED_CAST") private fun forceWildcardDeserializeDouble( bytes: SerializedBytes<*>, - factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) { + factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )) { DeserializationInput(factory).deserialize(bytes as SerializedBytes>) } @Suppress("UNCHECKED_CAST") private fun forceWildcardDeserialize( bytes: SerializedBytes<*>, - factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) { + factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )) { DeserializationInput(factory).deserialize(bytes as SerializedBytes>) } @@ -236,7 +257,9 @@ class GenericsTests { @Test fun forceWildcardSharedFactory() { - val f = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val f = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) forceWildcardDeserializeString(forceWildcardSerialize(ForceWildcard("hello"), f), f) forceWildcardDeserializeDouble(forceWildcardSerialize(ForceWildcard(3.0), f), f) } @@ -250,7 +273,9 @@ class GenericsTests { @Test fun forceWildcardDeserializeSharedFactory() { - val f = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val f = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard("hello"), f), f) forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard(10), f), f) forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard(20.0), f), f) @@ -288,7 +313,9 @@ class GenericsTests { // possibly altering how we serialise things val altClassLoader = cl() - val factory2 = SerializerFactory(AllWhitelist, altClassLoader) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, altClassLoader) + ) factory2.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) val ser2 = TestSerializationOutput(VERBOSE, factory2).serializeAndReturnSchema(state) @@ -297,7 +324,9 @@ class GenericsTests { factory3.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) DeserializationInput(factory3).deserializeAndReturnEnvelope(ser1.obj) - val factory4 = SerializerFactory(AllWhitelist, cl()) + val factory4 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, cl()) + ) factory4.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) DeserializationInput(factory4).deserializeAndReturnEnvelope(ser2.obj) } diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/OptionalSerializationTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/OptionalSerializationTests.kt index 10b154863f..cf12f740a8 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/OptionalSerializationTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/OptionalSerializationTests.kt @@ -5,6 +5,7 @@ import net.corda.serialization.internal.amqp.custom.OptionalSerializer import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput import net.corda.serialization.internal.amqp.testutils.deserialize import net.corda.serialization.internal.amqp.testutils.testDefaultFactory +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl import org.hamcrest.Matchers.`is` import org.hamcrest.Matchers.equalTo import org.junit.Assert @@ -17,7 +18,9 @@ class OptionalSerializationTests { fun setupEnclosedSerializationTest() { @Test fun `java optionals should serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(OptionalSerializer(factory)) val obj = Optional.ofNullable("YES") val bytes = TestSerializationOutput(true, factory).serialize(obj) diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/PrivatePropertyTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/PrivatePropertyTests.kt index 5a62f66c4f..b4012b5c00 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/PrivatePropertyTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/PrivatePropertyTests.kt @@ -17,15 +17,6 @@ import java.util.* class PrivatePropertyTests { private val factory = testDefaultFactoryNoEvolution() - companion object { - val fields : Map = mapOf ( - "serializersByDesc" to SerializerFactory::class.java.getDeclaredField("serializersByDescriptor")).apply { - this.values.forEach { - it.isAccessible = true - } - } - } - @Test fun testWithOnePrivateProperty() { data class C(private val b: String) @@ -134,8 +125,7 @@ class PrivatePropertyTests { val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1) assertEquals(1, schemaAndBlob.schema.types.size) - @Suppress("UNCHECKED_CAST") - val serializersByDescriptor = fields["serializersByDesc"]?.get(factory) as ConcurrentHashMap> + val serializersByDescriptor = factory.serializersByDescriptor val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { @@ -163,8 +153,7 @@ class PrivatePropertyTests { val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1) assertEquals(1, schemaAndBlob.schema.types.size) - @Suppress("UNCHECKED_CAST") - val serializersByDescriptor = fields["serializersByDesc"]?.get(factory) as ConcurrentHashMap> + val serializersByDescriptor = factory.serializersByDescriptor val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { @@ -192,7 +181,7 @@ class PrivatePropertyTests { val output = SerializationOutput(factory).serializeAndReturnSchema(c1) println (output.schema) - val serializersByDescriptor = fields["serializersByDesc"]!!.get(factory) as ConcurrentHashMap> + val serializersByDescriptor = factory.serializersByDescriptor // Inner and Outer assertEquals(2, serializersByDescriptor.size) @@ -212,7 +201,7 @@ class PrivatePropertyTests { val output = SerializationOutput(factory).serializeAndReturnSchema(C("this is nice")) - val serializersByDescriptor = fields["serializersByDesc"]!!.get(factory) as ConcurrentHashMap> + val serializersByDescriptor = factory.serializersByDescriptor val schemaDescriptor = output.schema.types.first().descriptor.name serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationOutputTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationOutputTests.kt index a0259ca36c..0ee30b0373 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationOutputTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationOutputTests.kt @@ -23,6 +23,7 @@ import net.corda.nodeapi.internal.crypto.ContentSignerBuilder import net.corda.serialization.internal.* import net.corda.serialization.internal.amqp.SerializerFactory.Companion.isPrimitive import net.corda.serialization.internal.amqp.testutils.* +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl import net.corda.testing.contracts.DummyContract import net.corda.testing.core.BOB_NAME import net.corda.testing.core.SerializationEnvironmentRule @@ -207,9 +208,8 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi } private fun defaultFactory(): SerializerFactory { - return SerializerFactory( - AllWhitelist, - ClassLoader.getSystemClassLoader(), + return SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()), evolutionSerializerProvider = FailIfEvolutionAttempted ) } @@ -368,13 +368,17 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test(expected = NotSerializableException::class) fun `test whitelist`() { val obj = Woo2(4) - serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())) + serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist, + ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader()) + )) } @Test fun `test annotation whitelisting`() { val obj = AnnotatedWoo(5) - serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())) + serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist, + ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader()) + )) } @Test(expected = NotSerializableException::class) @@ -471,7 +475,9 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `class constructor is invoked on deserialisation`() { compression == null || return // Manipulation of serialized bytes is invalid if they're compressed. - val ser = SerializationOutput(SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) + val ser = SerializationOutput(SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )) val des = DeserializationInput(ser.serializerFactory) val serialisedOne = ser.serialize(NonZeroByte(1), compression).bytes val serialisedTwo = ser.serialize(NonZeroByte(2), compression).bytes @@ -496,9 +502,13 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test custom serializers on public key`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) val obj = MEGA_CORP_PUBKEY serdes(obj, factory, factory2) @@ -507,21 +517,29 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test annotation is inherited`() { val obj = InheritAnnotation("blah") - serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())) + serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist, + ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader()) + )) } @Test fun `generics from java are supported`() { val obj = DummyOptional("YES") - serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())) + serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist, + ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader()) + )) } @Test fun `test throwables serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) val t = IllegalAccessException("message").fillInStackTrace() @@ -537,10 +555,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test complex throwables serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) try { @@ -567,10 +589,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test suppressed throwables serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) try { @@ -589,10 +615,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test flow corda exception subclasses serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) val obj = FlowException("message").fillInStackTrace() @@ -601,10 +631,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test RPC corda exception subclasses serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) val obj = RPCException("message").fillInStackTrace() @@ -666,10 +700,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi SerializerFactory::class.java) func.isAccessible = true - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) func.invoke(scheme, testSerializationContext, factory) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) func.invoke(scheme, testSerializationContext, factory2) val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false) @@ -680,10 +718,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test currencies serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.CurrencySerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.CurrencySerializer) val obj = Currency.getInstance("USD") @@ -692,10 +734,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test big decimals serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) val obj = BigDecimal("100000000000000000000000000000.00") @@ -704,10 +750,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test instants serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.InstantSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.InstantSerializer(factory2)) val obj = Instant.now() @@ -716,10 +766,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test durations serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.DurationSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.DurationSerializer(factory2)) val obj = Duration.of(1000000L, ChronoUnit.MILLIS) @@ -728,10 +782,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test local date serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(factory2)) val obj = LocalDate.now() @@ -740,10 +798,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test local time serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(factory2)) val obj = LocalTime.now() @@ -752,10 +814,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test local date time serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(factory2)) val obj = LocalDateTime.now() @@ -764,10 +830,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test zoned date time serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(factory2)) val obj = ZonedDateTime.now() @@ -776,10 +846,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test offset time serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(factory2)) val obj = OffsetTime.now() @@ -788,10 +862,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test offset date time serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(factory2)) val obj = OffsetDateTime.now() @@ -800,10 +878,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test year serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.YearSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.YearSerializer(factory2)) val obj = Year.now() @@ -812,10 +894,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test year month serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(factory2)) val obj = YearMonth.now() @@ -824,10 +910,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test month day serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(factory2)) val obj = MonthDay.now() @@ -836,10 +926,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test period serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(factory2)) val obj = Period.of(99, 98, 97) @@ -866,10 +960,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test X509 certificate serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer) val obj = BOB_IDENTITY.certificate @@ -878,10 +976,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test cert path serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(factory2)) val obj = BOB_IDENTITY.certPath @@ -905,9 +1007,13 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test StateRef serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) val obj = StateRef(SecureHash.randomSHA256(), 0) serdes(obj, factory, factory2) @@ -953,8 +1059,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi val b = ByteArray(2) val obj = Bob(listOf(a, b, a)) - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) val obj2 = serdes(obj, factory, factory2, false, false) assertNotSame(obj2.byteArrays[0], obj2.byteArrays[2]) @@ -967,8 +1077,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi val a = listOf("a", "b") val obj = Vic(a, a) - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) val objCopy = serdes(obj, factory, factory2) assertSame(objCopy.a, objCopy.b) } @@ -984,8 +1098,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi fun `test private constructor`() { val obj = Spike() - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) serdes(obj, factory, factory2) } @@ -993,10 +1111,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test toString custom serializer`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) val obj = BigDecimals(BigDecimal.TEN, BigDecimal.TEN) @@ -1008,10 +1130,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test BigInteger custom serializer`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer) val obj = BigIntegers(BigInteger.TEN, BigInteger.TEN) @@ -1028,10 +1154,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test X509CRL custom serializer`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer) val obj = emptyCrl() @@ -1042,10 +1172,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test byte arrays not reference counted`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) val bytes = ByteArray(1) @@ -1056,10 +1190,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test StringBuffer serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer) val obj = StringBuffer("Bob") @@ -1069,10 +1207,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test SimpleString serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer) val obj = SimpleString("Bob") @@ -1093,10 +1235,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test InputStream serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer) val bytes = ByteArray(10) { it.toByte() } val obj = bytes.inputStream() @@ -1108,10 +1254,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test EnumSet serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(factory2)) val obj = EnumSet.of(Month.APRIL, Month.AUGUST) @@ -1120,10 +1270,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test BitSet serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(factory2)) val obj = BitSet.valueOf(kotlin.ByteArray(16) { it.toByte() }).get(0, 123) @@ -1140,10 +1294,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test contract attachment serialize`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory2)) val obj = ContractAttachment(GeneratedAttachment("test".toByteArray()), DummyContract.PROGRAM_ID) @@ -1156,10 +1314,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `test contract attachment throws if missing attachment`() { - val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory)) - val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val factory2 = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) factory2.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory2)) val obj = ContractAttachment(object : AbstractAttachment({ throw Exception() }) { @@ -1351,7 +1513,9 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi @Test fun `compression reduces number of bytes significantly`() { - val ser = SerializationOutput(SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) + val ser = SerializationOutput(SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + )) val obj = ByteArray(20000) val uncompressedSize = ser.serialize(obj).bytes.size val compressedSize = ser.serialize(obj, CordaSerializationEncoding.SNAPPY).bytes.size diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationPropertyOrdering.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationPropertyOrdering.kt index 0e1f8788f3..750a2f2c5c 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationPropertyOrdering.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationPropertyOrdering.kt @@ -102,14 +102,13 @@ class SerializationPropertyOrdering { // Test needs to look at a bunch of private variables, change the access semantics for them val fields : Map = mapOf ( - "serializersByDesc" to SerializerFactory::class.java.getDeclaredField("serializersByDescriptor"), "setter" to PropertyAccessorGetterSetter::class.java.getDeclaredField("setter")).apply { this.values.forEach { it.isAccessible = true } } - val serializersByDescriptor = fields["serializersByDesc"]!!.get(sf) as ConcurrentHashMap> + val serializersByDescriptor = sf.serializersByDescriptor val schemaDescriptor = output.schema.types.first().descriptor.name // make sure that each property accessor has a setter to ensure we're using getter / setter instantiation diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationSchemaTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationSchemaTests.kt index a5f4925f24..7a56cbb953 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationSchemaTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationSchemaTests.kt @@ -6,6 +6,7 @@ import net.corda.serialization.internal.BuiltInExceptionsWhitelist import net.corda.serialization.internal.CordaSerializationMagic import net.corda.serialization.internal.GlobalTransientClassWhiteList import net.corda.serialization.internal.SerializationContextImpl +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl import org.junit.Test import kotlin.test.assertEquals @@ -22,7 +23,7 @@ val TESTING_CONTEXT = SerializationContextImpl(amqpMagic, class TestSerializerFactory( wl: ClassWhitelist, cl: ClassLoader -) : SerializerFactory(wl, cl) { +) : DefaultSerializerFactory(wl, ClassCarpenterImpl(wl, cl, false), DefaultEvolutionSerializerProvider, ::SerializerFingerPrinter) { var registerCount = 0 override fun register(customSerializer: CustomSerializer) { diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/StaticInitialisationOfSerializedObjectTest.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/StaticInitialisationOfSerializedObjectTest.kt index 800f5e87c7..f8450faf49 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/StaticInitialisationOfSerializedObjectTest.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/StaticInitialisationOfSerializedObjectTest.kt @@ -48,7 +48,9 @@ class StaticInitialisationOfSerializedObjectTest { fun kotlinObjectWithCompanionObject() { data class D(val c: C) - val sf = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) + val sf = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) + ) val typeMap = sf::class.java.getDeclaredField("serializersByType") typeMap.isAccessible = true @@ -87,7 +89,10 @@ class StaticInitialisationOfSerializedObjectTest { ".StaticInitialisationOfSerializedObjectTest\$deserializeTest\$D" } - val sf2 = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) + val whitelist = WL() + val sf2 = SerializerFactoryBuilder.build(whitelist, + ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader()) + ) val bytes = url.readBytes() assertThatThrownBy { @@ -97,8 +102,8 @@ class StaticInitialisationOfSerializedObjectTest { // Version of a serializer factory that will allow the class carpenter living on the // factory to have a different whitelist applied to it than the factory - class TestSerializerFactory(wl1: ClassWhitelist, wl2: ClassWhitelist) : - SerializerFactory(wl1, ClassCarpenterImpl(wl2, ClassLoader.getSystemClassLoader())) + private fun testSerializerFactory(wl1: ClassWhitelist, wl2: ClassWhitelist) = + SerializerFactoryBuilder.build(wl1, ClassCarpenterImpl(wl2, ClassLoader.getSystemClassLoader())) // This time have the serialization factory and the carpenter use different whitelists @Test @@ -126,7 +131,7 @@ class StaticInitialisationOfSerializedObjectTest { override fun hasListed(type: Class<*>) = true } - val sf2 = TestSerializerFactory(WL1(), WL2()) + val sf2 = testSerializerFactory(WL1(), WL2()) val bytes = url.readBytes() // Deserializing should throw because C is not on the whitelist NOT because diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/testutils/AMQPTestUtils.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/testutils/AMQPTestUtils.kt index ea81448da7..b248d11c2d 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/testutils/AMQPTestUtils.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/testutils/AMQPTestUtils.kt @@ -10,6 +10,7 @@ import net.corda.core.utilities.OpaqueBytes import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.EmptyWhitelist import net.corda.serialization.internal.amqp.* +import net.corda.serialization.internal.carpenter.ClassCarpenterImpl import net.corda.testing.common.internal.ProjectStructure import org.apache.qpid.proton.codec.Data import org.junit.Test @@ -17,16 +18,20 @@ import java.io.File.separatorChar import java.io.NotSerializableException import java.nio.file.StandardCopyOption.REPLACE_EXISTING -fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) +fun testDefaultFactory() = SerializerFactoryBuilder.build(AllWhitelist, + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()) +) fun testDefaultFactoryNoEvolution(): SerializerFactory { - return SerializerFactory( + return SerializerFactoryBuilder.build( AllWhitelist, - ClassLoader.getSystemClassLoader(), - evolutionSerializerProvider = FailIfEvolutionAttempted) + ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()), + FailIfEvolutionAttempted) } -fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()) +fun testDefaultFactoryWithWhitelist() = SerializerFactoryBuilder.build(EmptyWhitelist, + ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader()) +) class TestSerializationOutput( private val verbose: Boolean, diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/CarpenterExceptionTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/CarpenterExceptionTests.kt index 8aeaa99ac7..fd1e737e5a 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/CarpenterExceptionTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/CarpenterExceptionTests.kt @@ -5,7 +5,6 @@ import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.amqp.* import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput import net.corda.serialization.internal.amqp.testutils.deserialize -import net.corda.serialization.internal.amqp.testutils.serialize import net.corda.serialization.internal.amqp.testutils.testDefaultFactory import org.assertj.core.api.Assertions import org.junit.Test @@ -33,8 +32,8 @@ interface TestInterface { // Create a custom serialization factory where we need to be able to both specify a carpenter // but also have the class loader used by the carpenter be substantially different from the // one used by the factory so as to ensure we can control their behaviour independently. -class TestFactory(classCarpenter: ClassCarpenter) - : SerializerFactory(classCarpenter.whitelist, classCarpenter) +private fun testFactory(classCarpenter: ClassCarpenter) + = SerializerFactoryBuilder.build(classCarpenter.whitelist, classCarpenter) class CarpenterExceptionTests { companion object { @@ -90,7 +89,7 @@ class CarpenterExceptionTests { // we set the class loader of the ClassCarpenter to reject one of them, resulting in a CarpentryError // which we then want the code to wrap in a NotSerializeableException val cc = ClassCarpenterImpl(AllWhitelist, TestClassLoader(listOf(C2::class.jvmName))) - val factory = TestFactory(cc) + val factory = testFactory(cc) Assertions.assertThatThrownBy { DeserializationInput(factory).deserialize(ser) diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/ClassCarpenterTestUtils.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/ClassCarpenterTestUtils.kt index 5c3701dc49..0068399ed6 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/ClassCarpenterTestUtils.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/carpenter/ClassCarpenterTestUtils.kt @@ -41,12 +41,12 @@ fun Schema.mangleNames(names: List): Schema { * Custom implementation of a [SerializerFactory] where we need to give it a class carpenter * rather than have it create its own */ -class SerializerFactoryExternalCarpenter(classCarpenter: ClassCarpenter) - : SerializerFactory(classCarpenter.whitelist, classCarpenter) +private fun serializerFactoryExternalCarpenter(classCarpenter: ClassCarpenter) + = SerializerFactoryBuilder.build(classCarpenter.whitelist, classCarpenter) open class AmqpCarpenterBase(whitelist: ClassWhitelist) { var cc = ClassCarpenterImpl(whitelist = whitelist) - var factory = SerializerFactoryExternalCarpenter(cc) + var factory = serializerFactoryExternalCarpenter(cc) fun serialise(obj: T): SerializedBytes = SerializationOutput(factory).serialize(obj) @Suppress("NOTHING_TO_INLINE") From 459b330ebd374efcfbb7c3b356e121c74384b801 Mon Sep 17 00:00:00 2001 From: Patrick Kuo Date: Wed, 7 Nov 2018 14:14:58 +0000 Subject: [PATCH 6/9] Add programmatic print help to CordaCliWrapper (#4177) * add programmatic print help to CordaCliWrapper * address PR issues * bug fix --- .../net/corda/cliutils/CordaCliWrapper.kt | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tools/cliutils/src/main/kotlin/net/corda/cliutils/CordaCliWrapper.kt b/tools/cliutils/src/main/kotlin/net/corda/cliutils/CordaCliWrapper.kt index fd7fa5fd11..c2c6586145 100644 --- a/tools/cliutils/src/main/kotlin/net/corda/cliutils/CordaCliWrapper.kt +++ b/tools/cliutils/src/main/kotlin/net/corda/cliutils/CordaCliWrapper.kt @@ -2,17 +2,15 @@ package net.corda.cliutils import net.corda.core.internal.rootMessage import net.corda.core.utilities.contextLogger -import net.corda.core.utilities.loggerFor - import org.fusesource.jansi.AnsiConsole import org.slf4j.event.Level import picocli.CommandLine import picocli.CommandLine.* import java.nio.file.Path import java.nio.file.Paths -import kotlin.system.exitProcess import java.util.* import java.util.concurrent.Callable +import kotlin.system.exitProcess /** * When we have errors in command line flags that are not handled by picocli (e.g. non existing files), an error is thrown @@ -64,18 +62,6 @@ fun CordaCliWrapper.start(args: Array) { // This line makes sure ANSI escapes work on Windows, where they aren't supported out of the box. AnsiConsole.systemInstall() - val cmd = CommandLine(this) - // Make sure any provided paths are absolute. Relative paths have caused issues and are less clear in logs. - cmd.registerConverter(Path::class.java) { Paths.get(it).toAbsolutePath().normalize() } - cmd.commandSpec.name(alias) - cmd.commandSpec.usageMessage().description(description) - this.subCommands().forEach { - val subCommand = CommandLine(it) - it.args = args - subCommand.commandSpec.usageMessage().description(it.description) - cmd.commandSpec.addSubcommand(it.alias, subCommand) - } - try { val defaultAnsiMode = if (CordaSystemUtils.isOsWindows()) { Help.Ansi.ON @@ -97,7 +83,7 @@ fun CordaCliWrapper.start(args: Array) { exitProcess(ExitCodes.SUCCESS) } catch (e: ExecutionException) { val throwable = e.cause ?: e - if (this.verbose || this.subCommands().any { it.verbose} ) { + if (this.verbose || this.subCommands().any { it.verbose }) { throwable.printStackTrace() } else { System.err.println("*ERROR*: ${throwable.rootMessage ?: "Use --verbose for more details"}") @@ -171,6 +157,21 @@ abstract class CordaCliWrapper(alias: String, description: String) : CliWrapperB protected open fun additionalSubCommands(): Set = emptySet() + val cmd by lazy { + CommandLine(this).apply { + // Make sure any provided paths are absolute. Relative paths have caused issues and are less clear in logs. + registerConverter(Path::class.java) { Paths.get(it).toAbsolutePath().normalize() } + commandSpec.name(alias) + commandSpec.usageMessage().description(description) + subCommands().forEach { + val subCommand = CommandLine(it) + it.args = args + subCommand.commandSpec.usageMessage().description(it.description) + commandSpec.addSubcommand(it.alias, subCommand) + } + } + } + fun subCommands(): Set { return additionalSubCommands() + installShellExtensionsParser } @@ -181,6 +182,8 @@ abstract class CordaCliWrapper(alias: String, description: String) : CliWrapperB installShellExtensionsParser.updateShellExtensions() return runProgram() } + + fun printHelp() = cmd.usage(System.out) } /** From df954d36d223689655429ccb8de09fb115b86a26 Mon Sep 17 00:00:00 2001 From: Christian Sailer Date: Wed, 7 Nov 2018 16:37:42 +0000 Subject: [PATCH 7/9] Make the shell test pass when it happens to find the Integer constructor (#4187) --- .../test/kotlin/net/corda/tools/shell/InteractiveShellTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/shell/src/test/kotlin/net/corda/tools/shell/InteractiveShellTest.kt b/tools/shell/src/test/kotlin/net/corda/tools/shell/InteractiveShellTest.kt index e184c6ae86..b7b76ef401 100644 --- a/tools/shell/src/test/kotlin/net/corda/tools/shell/InteractiveShellTest.kt +++ b/tools/shell/src/test/kotlin/net/corda/tools/shell/InteractiveShellTest.kt @@ -29,7 +29,7 @@ class InteractiveShellTest { @Suppress("UNUSED") class FlowA(val a: String) : FlowLogic() { - constructor(b: Int) : this(b.toString()) + constructor(b: Int?) : this(b.toString()) constructor(b: Int?, c: String) : this(b.toString() + c) constructor(amount: Amount) : this(amount.toString()) constructor(pair: Pair, SecureHash.SHA256>) : this(pair.toString()) @@ -115,7 +115,7 @@ class InteractiveShellTest { "[b: String[]]: missing parameter b", "[b: Integer, c: String]: missing parameter b", "[a: String]: missing parameter a", - "[b: int]: missing parameter b" + "[b: Integer]: missing parameter b" ) val errors = e.errors.toHashSet() errors.removeAll(correct) From e956c0f5fe96130bc36ebbe4a631ed289900909f Mon Sep 17 00:00:00 2001 From: szymonsztuka Date: Wed, 7 Nov 2018 16:48:31 +0000 Subject: [PATCH 8/9] Docs - link from the page about signing Cordapp to the page about node configuration regarding enabling Cordapp signed by dev key to be run in production mode (related to CORDA-1915). (#4172) --- docs/source/corda-configuration-file.rst | 2 ++ docs/source/cordapp-build-systems.rst | 3 +++ 2 files changed, 5 insertions(+) diff --git a/docs/source/corda-configuration-file.rst b/docs/source/corda-configuration-file.rst index 7af075efed..9ba3067fcc 100644 --- a/docs/source/corda-configuration-file.rst +++ b/docs/source/corda-configuration-file.rst @@ -239,6 +239,8 @@ absolute path to the node's base directory. .. _Dropwizard: https://metrics.dropwizard.io/3.2.3/manual/third-party.html .. _Introduction to New Relic for Java: https://docs.newrelic.com/docs/agents/java-agent/getting-started/introduction-new-relic-java +.. _corda_configuration_file_signer_blacklist: + :cordappSignerKeyFingerprintBlacklist: List of public keys fingerprints (SHA-256 of public key hash) not allowed as Cordapp JARs signers. Node will not load Cordapps signed by those keys. The option takes effect only in production mode and defaults to Corda development keys (``["56CA54E803CB87C8472EBD3FBC6A2F1876E814CEEBF74860BD46997F40729367", diff --git a/docs/source/cordapp-build-systems.rst b/docs/source/cordapp-build-systems.rst index 7c02b7648d..10d620376d 100644 --- a/docs/source/cordapp-build-systems.rst +++ b/docs/source/cordapp-build-systems.rst @@ -162,6 +162,9 @@ without need to create a keystore and configure the ``cordapp`` plugin. For production deployment ensure to sign the CorDapp using your own certificate e.g. by setting system properties to point to an external keystore or by disabling signing in ``cordapp`` plugin and signing the CordDapp JAR downstream in your build pipeline. CorDapp signed by Corda development certificate is accepted by Corda node only when running in the development mode. +In case CordDapp signed by the (default) development key is run on node in the production mode (e.g. for testing), +the node may be set to accept the development key by adding the ``cordappSignerKeyFingerprintBlacklist = []`` property set to empty list +(see :ref:`Configuring a node `). Signing options can be contextually overwritten by the relevant system properties as described above. This allows the single ``build.gradle`` file to be used for a development build (defaulting to the Corda development keystore) From ecbf23ab734cebf1fc1a4d3ae4442b3c687a2a4e Mon Sep 17 00:00:00 2001 From: Stefano Franz Date: Wed, 7 Nov 2018 19:05:50 +0100 Subject: [PATCH 9/9] CORDA-2106: Print node info gen log on bootstrap failure (#4184) * print node-gen log when nodeInfo generation fails during bootstrapping * add logic to print out the legal name of the node which failed to generate nodeInfo --- .../internal/network/NetworkBootstrapper.kt | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt index ff94acacae..c3a7fd71e9 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt @@ -1,6 +1,7 @@ package net.corda.nodeapi.internal.network import com.typesafe.config.Config +import com.typesafe.config.ConfigException import com.typesafe.config.ConfigFactory import net.corda.core.crypto.toStringShort import net.corda.core.identity.CordaX500Name @@ -30,6 +31,7 @@ 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 java.io.File import java.io.InputStream import java.nio.file.Path import java.nio.file.StandardCopyOption.REPLACE_EXISTING @@ -96,21 +98,36 @@ internal constructor(private val initSerEnv: Boolean, private fun generateNodeInfo(nodeDir: Path): Path { val logsDir = (nodeDir / LOGS_DIR_NAME).createDirectories() + val nodeInfoGenFile = (logsDir / "node-info-gen.log").toFile() val process = ProcessBuilder(nodeInfoGenCmd) .directory(nodeDir.toFile()) .redirectErrorStream(true) - .redirectOutput((logsDir / "node-info-gen.log").toFile()) + .redirectOutput(nodeInfoGenFile) .apply { environment()["CAPSULE_CACHE_DIR"] = "../.cache" } .start() if (!process.waitFor(3, TimeUnit.MINUTES)) { process.destroyForcibly() - throw IllegalStateException("Error while generating node info file. Please check the logs in $logsDir.") + printNodeInfoGenLogToConsole(nodeInfoGenFile) } - check(process.exitValue() == 0) { "Error while generating node info file. Please check the logs in $logsDir." } + printNodeInfoGenLogToConsole(nodeInfoGenFile) { process.exitValue() == 0 } return nodeDir.list { paths -> paths.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }.findFirst().get() } } + + private fun printNodeInfoGenLogToConsole(nodeInfoGenFile: File, check: (() -> Boolean) = { true }) { + if (!check.invoke()) { + val nodeDir = nodeInfoGenFile.parent + val nodeIdentifier = try { + ConfigFactory.parseFile((nodeDir / "node.conf").toFile()).getString("myLegalName") + } catch (e: ConfigException) { + nodeDir + } + System.err.println("#### Error while generating node info file $nodeIdentifier ####") + nodeInfoGenFile.inputStream().copyTo(System.err) + throw IllegalStateException("Error while generating node info file. Please check the logs in $nodeDir.") + } + } } sealed class NotaryCluster { @@ -142,7 +159,7 @@ internal constructor(private val initSerEnv: Boolean, private fun isBFTNotary(config: Config): Boolean { // TODO: pass a commandline parameter to the bootstrapper instead. Better yet, a notary config map // specifying the notary identities and the type (single-node, CFT, BFT) of each notary to set up. - return config.getString ("notary.className").contains("BFT", true) + return config.getString("notary.className").contains("BFT", true) } private fun generateServiceIdentitiesForNotaryClusters(configs: Map) { @@ -172,7 +189,7 @@ internal constructor(private val initSerEnv: Boolean, } /** Entry point for the tool */ - fun bootstrap(directory: Path, copyCordapps: Boolean, minimumPlatformVersion: Int, packageOwnership : Map = emptyMap()) { + fun bootstrap(directory: Path, copyCordapps: Boolean, minimumPlatformVersion: Int, packageOwnership: Map = emptyMap()) { require(minimumPlatformVersion <= PLATFORM_VERSION) { "Minimum platform version cannot be greater than $PLATFORM_VERSION" } // Don't accidently include the bootstrapper jar as a CorDapp! val bootstrapperJar = javaClass.location.toPath() @@ -188,7 +205,7 @@ internal constructor(private val initSerEnv: Boolean, copyCordapps: Boolean, fromCordform: Boolean, minimumPlatformVersion: Int = PLATFORM_VERSION, - packageOwnership : Map = emptyMap() + packageOwnership: Map = emptyMap() ) { directory.createDirectories() println("Bootstrapping local test network in $directory") @@ -361,21 +378,20 @@ internal constructor(private val initSerEnv: Boolean, existingNetParams: NetworkParameters?, nodeDirs: List, minimumPlatformVersion: Int, - packageOwnership : Map + packageOwnership: Map ): NetworkParameters { // TODO Add config for maxMessageSize and maxTransactionSize val netParams = if (existingNetParams != null) { if (existingNetParams.whitelistedContractImplementations == whitelist && existingNetParams.notaries == notaryInfos && - existingNetParams.packageOwnership.entries.containsAll(packageOwnership.entries)) { + existingNetParams.packageOwnership.entries.containsAll(packageOwnership.entries)) { existingNetParams } else { - var updatePackageOwnership = mutableMapOf(*existingNetParams.packageOwnership.map { Pair(it.key,it.value) }.toTypedArray()) + var updatePackageOwnership = mutableMapOf(*existingNetParams.packageOwnership.map { Pair(it.key, it.value) }.toTypedArray()) packageOwnership.forEach { key, value -> if (value == null) { if (updatePackageOwnership.remove(key) != null) println("Unregistering package $key") - } - else { + } else { if (updatePackageOwnership.put(key, value) == null) println("Registering package $key for owner ${value.toStringShort()}") }