Remove Kryo from core module completely, including gradle dependencies (#1161)

This commit is contained in:
Rick Parker 2017-08-09 14:53:46 +01:00 committed by GitHub
parent f81f374377
commit 28610868c4
84 changed files with 450 additions and 387 deletions

View File

@ -9,9 +9,9 @@ import net.corda.core.utilities.NetworkHostAndPort
import net.corda.nodeapi.ArtemisTcpTransport.Companion.tcpTransport import net.corda.nodeapi.ArtemisTcpTransport.Companion.tcpTransport
import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.ConnectionDirection
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import net.corda.nodeapi.serialization.KRYO_P2P_CONTEXT import net.corda.nodeapi.internal.serialization.KRYO_P2P_CONTEXT
import net.corda.nodeapi.serialization.KRYO_RPC_CLIENT_CONTEXT import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT
import net.corda.nodeapi.serialization.SerializationFactoryImpl import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
import java.time.Duration import java.time.Duration
/** @see RPCClient.RPCConnection */ /** @see RPCClient.RPCConnection */

View File

@ -2,12 +2,12 @@ package net.corda.client.rpc.serialization
import com.esotericsoftware.kryo.pool.KryoPool import com.esotericsoftware.kryo.pool.KryoPool
import net.corda.client.rpc.internal.RpcClientObservableSerializer import net.corda.client.rpc.internal.RpcClientObservableSerializer
import net.corda.core.serialization.DefaultKryoCustomizer
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.nodeapi.RPCKryo import net.corda.nodeapi.RPCKryo
import net.corda.nodeapi.serialization.AbstractKryoSerializationScheme import net.corda.nodeapi.internal.serialization.AbstractKryoSerializationScheme
import net.corda.nodeapi.serialization.KryoHeaderV0_1 import net.corda.nodeapi.internal.serialization.DefaultKryoCustomizer
import net.corda.nodeapi.internal.serialization.KryoHeaderV0_1
class KryoClientSerializationScheme : AbstractKryoSerializationScheme() { class KryoClientSerializationScheme : AbstractKryoSerializationScheme() {
override fun canDeserializeVersion(byteSequence: ByteSequence, target: SerializationContext.UseCase): Boolean { override fun canDeserializeVersion(byteSequence: ByteSequence, target: SerializationContext.UseCase): Boolean {

View File

@ -53,10 +53,6 @@ dependencies {
// RxJava: observable streams of events. // RxJava: observable streams of events.
compile "io.reactivex:rxjava:$rxjava_version" compile "io.reactivex:rxjava:$rxjava_version"
// Kryo: object graph serialization.
compile "com.esotericsoftware:kryo:4.0.0"
compile "de.javakaffee:kryo-serializers:0.41"
// Apache JEXL: An embeddable expression evaluation library. // Apache JEXL: An embeddable expression evaluation library.
// This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API. // This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API.
compile "org.apache.commons:commons-jexl3:3.0" compile "org.apache.commons:commons-jexl3:3.0"

View File

@ -58,9 +58,9 @@ open class CordaException internal constructor(override var originalExceptionCla
} }
} }
open class CordaRuntimeException internal constructor(override var originalExceptionClassName: String?, open class CordaRuntimeException(override var originalExceptionClassName: String?,
private var _message: String? = null, private var _message: String? = null,
private var _cause: Throwable? = null) : RuntimeException(null, null, true, true), CordaThrowable { private var _cause: Throwable? = null) : RuntimeException(null, null, true, true), CordaThrowable {
constructor(message: String?, cause: Throwable?) : this(null, message, cause) constructor(message: String?, cause: Throwable?) : this(null, message, cause)
override val message: String? override val message: String?

View File

@ -283,7 +283,7 @@ object Crypto {
/** /**
* Decode a PKCS8 encoded key to its [PrivateKey] object based on the input scheme code name. * Decode a PKCS8 encoded key to its [PrivateKey] object based on the input scheme code name.
* This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. * This should be used when the type key is known, e.g. during deserialisation or with key caches or key managers.
* @param schemeCodeName a [String] that should match a key in supportedSignatureSchemes map (e.g. ECDSA_SECP256K1_SHA256). * @param schemeCodeName a [String] that should match a key in supportedSignatureSchemes map (e.g. ECDSA_SECP256K1_SHA256).
* @param encodedKey a PKCS8 encoded private key. * @param encodedKey a PKCS8 encoded private key.
* @throws IllegalArgumentException on not supported scheme or if the given key specification * @throws IllegalArgumentException on not supported scheme or if the given key specification
@ -294,7 +294,7 @@ object Crypto {
/** /**
* Decode a PKCS8 encoded key to its [PrivateKey] object based on the input scheme code name. * Decode a PKCS8 encoded key to its [PrivateKey] object based on the input scheme code name.
* This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. * This should be used when the type key is known, e.g. during deserialisation or with key caches or key managers.
* @param signatureScheme a signature scheme (e.g. ECDSA_SECP256K1_SHA256). * @param signatureScheme a signature scheme (e.g. ECDSA_SECP256K1_SHA256).
* @param encodedKey a PKCS8 encoded private key. * @param encodedKey a PKCS8 encoded private key.
* @throws IllegalArgumentException on not supported scheme or if the given key specification * @throws IllegalArgumentException on not supported scheme or if the given key specification
@ -326,7 +326,7 @@ object Crypto {
/** /**
* Decode an X509 encoded key to its [PrivateKey] object based on the input scheme code name. * Decode an X509 encoded key to its [PrivateKey] object based on the input scheme code name.
* This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. * This should be used when the type key is known, e.g. during deserialisation or with key caches or key managers.
* @param schemeCodeName a [String] that should match a key in supportedSignatureSchemes map (e.g. ECDSA_SECP256K1_SHA256). * @param schemeCodeName a [String] that should match a key in supportedSignatureSchemes map (e.g. ECDSA_SECP256K1_SHA256).
* @param encodedKey an X509 encoded public key. * @param encodedKey an X509 encoded public key.
* @throws IllegalArgumentException if the requested scheme is not supported. * @throws IllegalArgumentException if the requested scheme is not supported.
@ -338,7 +338,7 @@ object Crypto {
/** /**
* Decode an X509 encoded key to its [PrivateKey] object based on the input scheme code name. * Decode an X509 encoded key to its [PrivateKey] object based on the input scheme code name.
* This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. * This should be used when the type key is known, e.g. during deserialisation or with key caches or key managers.
* @param signatureScheme a signature scheme (e.g. ECDSA_SECP256K1_SHA256). * @param signatureScheme a signature scheme (e.g. ECDSA_SECP256K1_SHA256).
* @param encodedKey an X509 encoded public key. * @param encodedKey an X509 encoded public key.
* @throws IllegalArgumentException if the requested scheme is not supported. * @throws IllegalArgumentException if the requested scheme is not supported.

View File

@ -60,7 +60,7 @@ fun String.hexToBase58(): String = hexToByteArray().toBase58()
/** Encoding changer. Hex-[String] to Base64-[String], i.e. "48656C6C6F20576F726C64" -> "SGVsbG8gV29ybGQ=" */ /** Encoding changer. Hex-[String] to Base64-[String], i.e. "48656C6C6F20576F726C64" -> "SGVsbG8gV29ybGQ=" */
fun String.hexToBase64(): String = hexToByteArray().toBase64() fun String.hexToBase64(): String = hexToByteArray().toBase64()
// TODO We use for both CompositeKeys and EdDSAPublicKey custom Kryo serializers and deserializers. We need to specify encoding. // TODO We use for both CompositeKeys and EdDSAPublicKey custom serializers and deserializers. We need to specify encoding.
// TODO: follow the crypto-conditions ASN.1 spec, some changes are needed to be compatible with the condition // TODO: follow the crypto-conditions ASN.1 spec, some changes are needed to be compatible with the condition
// structure, e.g. mapping a PublicKey to a condition with the specific feature (ED25519). // structure, e.g. mapping a PublicKey to a condition with the specific feature (ED25519).
fun parsePublicKeyBase58(base58String: String): PublicKey = base58String.base58ToByteArray().deserialize<PublicKey>() fun parsePublicKeyBase58(base58String: String): PublicKey = base58String.base58ToByteArray().deserialize<PublicKey>()

View File

@ -5,7 +5,7 @@ import net.corda.core.serialization.CordaSerializable
/** /**
* Custom class for holding signature data. This exists for later extension work to provide a standardised cross-platform * Custom class for holding signature data. This exists for later extension work to provide a standardised cross-platform
* serialization format (i.e. not Kryo). * serialization format.
*/ */
@CordaSerializable @CordaSerializable
data class CompositeSignaturesWithKeys(val sigs: List<TransactionSignature>) { data class CompositeSignaturesWithKeys(val sigs: List<TransactionSignature>) {

View File

@ -1,12 +1,12 @@
package net.corda.core.node package net.corda.core.node
import net.corda.core.contracts.ContractState
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.services.VaultQueryService
import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.QueryableState
import net.corda.core.serialization.SerializationCustomization import net.corda.core.serialization.SerializationCustomization
import java.util.function.Function import java.util.function.Function
import net.corda.core.schemas.QueryableState
import net.corda.core.contracts.ContractState
import net.corda.core.node.services.VaultQueryService
/** /**
* Implement this interface on a class advertised in a META-INF/services/net.corda.core.node.CordaPluginRegistry file * Implement this interface on a class advertised in a META-INF/services/net.corda.core.node.CordaPluginRegistry file

View File

@ -2,7 +2,6 @@ package net.corda.core.node.services
import net.corda.core.contracts.PartyAndReference import net.corda.core.contracts.PartyAndReference
import net.corda.core.identity.* import net.corda.core.identity.*
import net.corda.core.identity.AnonymousPartyAndPath
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.cert.X509CertificateHolder import org.bouncycastle.cert.X509CertificateHolder
import java.security.InvalidAlgorithmParameterException import java.security.InvalidAlgorithmParameterException

View File

@ -4,9 +4,9 @@ import net.corda.core.concurrent.CordaFuture
import net.corda.core.contracts.Contract import net.corda.core.contracts.Contract
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.randomOrNull
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.internal.randomOrNull
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import rx.Observable import rx.Observable

View File

@ -0,0 +1,7 @@
package net.corda.core.serialization
import net.corda.core.crypto.SecureHash
/** Thrown during deserialisation to indicate that an attachment needed to construct the [WireTransaction] is not found */
@CordaSerializable
class MissingAttachmentsException(val ids: List<SecureHash>) : Exception()

View File

@ -5,7 +5,6 @@ import net.corda.core.crypto.sha256
import net.corda.core.internal.WriteOnceProperty import net.corda.core.internal.WriteOnceProperty
import net.corda.core.serialization.SerializationDefaults.P2P_CONTEXT import net.corda.core.serialization.SerializationDefaults.P2P_CONTEXT
import net.corda.core.serialization.SerializationDefaults.SERIALIZATION_FACTORY import net.corda.core.serialization.SerializationDefaults.SERIALIZATION_FACTORY
import net.corda.core.transactions.WireTransaction
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.sequence import net.corda.core.utilities.sequence
@ -135,3 +134,7 @@ class SerializedBytes<T : Any>(bytes: ByteArray) : OpaqueBytes(bytes) {
// It's OK to use lazy here because SerializedBytes is configured to use the ImmutableClassSerializer. // It's OK to use lazy here because SerializedBytes is configured to use the ImmutableClassSerializer.
val hash: SecureHash by lazy { bytes.sha256() } val hash: SecureHash by lazy { bytes.sha256() }
} }
interface ClassWhitelist {
fun hasListed(type: Class<*>): Boolean
}

View File

@ -1,13 +1,6 @@
package net.corda.core.serialization package net.corda.core.serialization
import com.esotericsoftware.kryo.Kryo
interface SerializationCustomization { interface SerializationCustomization {
fun addToWhitelist(type: Class<*>) fun addToWhitelist(type: Class<*>)
} }
class KryoSerializationCustomization(val kryo: Kryo) : SerializationCustomization {
override fun addToWhitelist(type: Class<*>) {
kryo.addToWhitelist(type)
}
}

View File

@ -1,11 +1,5 @@
package net.corda.core.serialization package net.corda.core.serialization
import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.KryoException
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import net.corda.core.internal.castIfPossible
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
@ -36,70 +30,13 @@ interface SerializationToken {
fun fromToken(context: SerializeAsTokenContext): Any fun fromToken(context: SerializeAsTokenContext): Any
} }
/**
* A Kryo serializer for [SerializeAsToken] implementations.
*/
class SerializeAsTokenSerializer<T : SerializeAsToken> : Serializer<T>() {
override fun write(kryo: Kryo, output: Output, obj: T) {
kryo.writeClassAndObject(output, obj.toToken(kryo.serializationContext() ?: throw KryoException("Attempt to write a ${SerializeAsToken::class.simpleName} instance of ${obj.javaClass.name} without initialising a context")))
}
override fun read(kryo: Kryo, input: Input, type: Class<T>): T {
val token = (kryo.readClassAndObject(input) as? SerializationToken) ?: throw KryoException("Non-token read for tokenized type: ${type.name}")
val fromToken = token.fromToken(kryo.serializationContext() ?: throw KryoException("Attempt to read a token for a ${SerializeAsToken::class.simpleName} instance of ${type.name} without initialising a context"))
return type.castIfPossible(fromToken) ?: throw KryoException("Token read ($token) did not return expected tokenized type: ${type.name}")
}
}
private val serializationContextKey = SerializeAsTokenContext::class.java
fun SerializationContext.withTokenContext(serializationContext: SerializeAsTokenContext): SerializationContext = this.withProperty(serializationContextKey, serializationContext)
fun Kryo.serializationContext(): SerializeAsTokenContext? = context.get(serializationContextKey) as? SerializeAsTokenContext
/** /**
* A context for mapping SerializationTokens to/from SerializeAsTokens. * A context for mapping SerializationTokens to/from SerializeAsTokens.
*
* A context is initialised with an object containing all the instances of [SerializeAsToken] to eagerly register all the tokens.
* In our case this can be the [ServiceHub].
*
* Then it is a case of using the companion object methods on [SerializeAsTokenSerializer] to set and clear context as necessary
* on the Kryo instance when serializing to enable/disable tokenization.
*/ */
class SerializeAsTokenContext internal constructor(val serviceHub: ServiceHub, init: SerializeAsTokenContext.() -> Unit) { interface SerializeAsTokenContext {
constructor(toBeTokenized: Any, serializationFactory: SerializationFactory, context: SerializationContext, serviceHub: ServiceHub) : this(serviceHub, { val serviceHub: ServiceHub
serializationFactory.serialize(toBeTokenized, context.withTokenContext(this)) fun putSingleton(toBeTokenized: SerializeAsToken)
}) fun getSingleton(className: String): SerializeAsToken
private val classNameToSingleton = mutableMapOf<String, SerializeAsToken>()
private var readOnly = false
init {
/**
* Go ahead and eagerly serialize the object to register all of the tokens in the context.
*
* This results in the toToken() method getting called for any [SingletonSerializeAsToken] instances which
* are encountered in the object graph as they are serialized by Kryo and will therefore register the token to
* object mapping for those instances. We then immediately set the readOnly flag to stop further adhoc or
* accidental registrations from occuring as these could not be deserialized in a deserialization-first
* scenario if they are not part of this iniital context construction serialization.
*/
init(this)
readOnly = true
}
internal fun putSingleton(toBeTokenized: SerializeAsToken) {
val className = toBeTokenized.javaClass.name
if (className !in classNameToSingleton) {
// Only allowable if we are in SerializeAsTokenContext init (readOnly == false)
if (readOnly) {
throw UnsupportedOperationException("Attempt to write token for lazy registered ${className}. All tokens should be registered during context construction.")
}
classNameToSingleton[className] = toBeTokenized
}
}
internal fun getSingleton(className: String) = classNameToSingleton[className] ?: throw IllegalStateException("Unable to find tokenized instance of $className in context $this")
} }
/** /**

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp; package net.corda.nodeapi.internal.serialization.amqp;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.DecoderImpl;

View File

@ -86,7 +86,7 @@ class CompositeKeyTests : TestDependencyInjectionBase() {
} }
@Test @Test
fun `kryo encoded tree decodes correctly`() { fun `encoded tree decodes correctly`() {
val aliceAndBob = CompositeKey.Builder().addKeys(alicePublicKey, bobPublicKey).build() val aliceAndBob = CompositeKey.Builder().addKeys(alicePublicKey, bobPublicKey).build()
val aliceAndBobOrCharlie = CompositeKey.Builder().addKeys(aliceAndBob, charliePublicKey).build(threshold = 1) val aliceAndBobOrCharlie = CompositeKey.Builder().addKeys(aliceAndBob, charliePublicKey).build(threshold = 1)

View File

@ -1,6 +1,6 @@
package net.corda.core.crypto package net.corda.core.crypto
import com.esotericsoftware.kryo.KryoException
import net.corda.contracts.asset.Cash import net.corda.contracts.asset.Cash
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash.Companion.zeroHash import net.corda.core.crypto.SecureHash.Companion.zeroHash
@ -232,7 +232,7 @@ class PartialMerkleTreeTest : TestDependencyInjectionBase() {
assertFalse(pmt.verify(wrongRoot, inclHashes)) assertFalse(pmt.verify(wrongRoot, inclHashes))
} }
@Test(expected = KryoException::class) @Test(expected = Exception::class)
fun `hash map serialization not allowed`() { fun `hash map serialization not allowed`() {
val hm1 = hashMapOf("a" to 1, "b" to 2, "c" to 3, "e" to 4) val hm1 = hashMapOf("a" to 1, "b" to 2, "c" to 3, "e" to 4)
hm1.serialize() hm1.serialize()

View File

@ -1,6 +1,6 @@
package net.corda.core.node package net.corda.core.node
import org.junit.Assert.* import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
class CityDatabaseTest { class CityDatabaseTest {

View File

@ -1,10 +1,8 @@
package net.corda.core.node package net.corda.core.node
import net.corda.core.crypto.X509Utilities
import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.ServiceType import net.corda.core.node.services.ServiceType
import net.corda.testing.getTestX509Name import net.corda.testing.getTestX509Name
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith

View File

@ -1,16 +1,5 @@
package net.corda.core.utilities package net.corda.core.utilities
import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.KryoSerializable
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import net.corda.core.serialization.AllWhitelist
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.serialize
import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.nodeapi.serialization.KryoHeaderV0_1
import net.corda.nodeapi.serialization.SerializationContextImpl
import net.corda.nodeapi.serialization.SerializationFactoryImpl
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
@ -99,34 +88,4 @@ class ProgressTrackerTest {
pt.currentStep = SimpleSteps.ONE pt.currentStep = SimpleSteps.ONE
assertEquals(SimpleSteps.TWO, pt.nextStep()) assertEquals(SimpleSteps.TWO, pt.nextStep())
} }
@Test
fun rxSubscriptionsAreNotSerialized() {
class Unserializable : KryoSerializable {
override fun write(kryo: Kryo?, output: Output?) = throw AssertionError("not called")
override fun read(kryo: Kryo?, input: Input?) = throw AssertionError("not called")
fun foo() {
println("bar")
}
}
pt.setChildProgressTracker(SimpleSteps.TWO, pt2)
class Tmp {
val unserializable = Unserializable()
init {
pt2.changes.subscribe { unserializable.foo() }
}
}
Tmp()
val factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme()) }
val context = SerializationContextImpl(KryoHeaderV0_1,
javaClass.classLoader,
AllWhitelist,
emptyMap(),
true,
SerializationContext.UseCase.P2P)
pt.serialize(factory, context)
}
} }

View File

@ -6,12 +6,11 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.nodeapi.DummyContractBackdoor
// The dummy contract doesn't do anything useful. It exists for testing purposes.
val ANOTHER_DUMMY_PROGRAM_ID = AnotherDummyContract() val ANOTHER_DUMMY_PROGRAM_ID = AnotherDummyContract()
class AnotherDummyContract : Contract, net.corda.core.node.DummyContractBackdoor { class AnotherDummyContract : Contract, DummyContractBackdoor {
data class State(val magicNumber: Int = 0) : ContractState { data class State(val magicNumber: Int = 0) : ContractState {
override val contract = ANOTHER_DUMMY_PROGRAM_ID override val contract = ANOTHER_DUMMY_PROGRAM_ID
override val participants: List<AbstractParty> override val participants: List<AbstractParty>

View File

@ -1,4 +1,4 @@
package net.corda.core.node package net.corda.nodeapi
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.contracts.PartyAndReference import net.corda.core.contracts.PartyAndReference

View File

@ -27,6 +27,10 @@ dependencies {
// TypeSafe Config: for simple and human friendly config files. // TypeSafe Config: for simple and human friendly config files.
compile "com.typesafe:config:$typesafe_config_version" compile "com.typesafe:config:$typesafe_config_version"
// Kryo: object graph serialization.
compile "com.esotericsoftware:kryo:4.0.0"
compile "de.javakaffee:kryo-serializers:0.41"
// Unit testing helpers. // Unit testing helpers.
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"

View File

@ -6,10 +6,12 @@ import com.esotericsoftware.kryo.Registration
import com.esotericsoftware.kryo.Serializer import com.esotericsoftware.kryo.Serializer
import net.corda.core.concurrent.CordaFuture import net.corda.core.concurrent.CordaFuture
import net.corda.core.CordaRuntimeException import net.corda.core.CordaRuntimeException
import net.corda.core.serialization.* import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.toObservable import net.corda.core.toObservable
import net.corda.nodeapi.config.OldConfig import net.corda.nodeapi.config.OldConfig
import net.corda.nodeapi.internal.serialization.*
import rx.Observable import rx.Observable
import java.io.InputStream import java.io.InputStream

View File

@ -1,12 +1,22 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import net.corda.core.serialization.ClassWhitelist
import sun.misc.Unsafe import sun.misc.Unsafe
import sun.security.util.Password import sun.security.util.Password
import java.io.* import java.io.*
import java.lang.invoke.* import java.lang.invoke.*
import java.lang.reflect.* import java.lang.reflect.AccessibleObject
import java.net.* import java.lang.reflect.Modifier
import java.security.* import java.lang.reflect.Parameter
import java.lang.reflect.ReflectPermission
import java.net.DatagramSocket
import java.net.ServerSocket
import java.net.Socket
import java.net.URLConnection
import java.security.AccessController
import java.security.KeyStore
import java.security.Permission
import java.security.Provider
import java.sql.Connection import java.sql.Connection
import java.util.* import java.util.*
import java.util.logging.Handler import java.util.logging.Handler

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.* import com.esotericsoftware.kryo.*
import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Input
@ -6,6 +6,9 @@ import com.esotericsoftware.kryo.io.Output
import com.esotericsoftware.kryo.serializers.FieldSerializer import com.esotericsoftware.kryo.serializers.FieldSerializer
import com.esotericsoftware.kryo.util.DefaultClassResolver import com.esotericsoftware.kryo.util.DefaultClassResolver
import com.esotericsoftware.kryo.util.Util import com.esotericsoftware.kryo.util.Util
import net.corda.core.serialization.AttachmentsClassLoader
import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import java.io.PrintWriter import java.io.PrintWriter
import java.lang.reflect.Modifier.isAbstract import java.lang.reflect.Modifier.isAbstract
@ -145,10 +148,6 @@ class CordaClassResolver(val whitelist: ClassWhitelist, val amqpEnabled: Boolean
} }
} }
interface ClassWhitelist {
fun hasListed(type: Class<*>): Boolean
}
interface MutableClassWhitelist : ClassWhitelist { interface MutableClassWhitelist : ClassWhitelist {
fun add(entry: Class<*>) fun add(entry: Class<*>)
} }

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.Serializer import com.esotericsoftware.kryo.Serializer
@ -13,6 +13,8 @@ import de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer
import de.javakaffee.kryoserializers.guava.* import de.javakaffee.kryoserializers.guava.*
import net.corda.core.crypto.composite.CompositeKey import net.corda.core.crypto.composite.CompositeKey
import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.CordaPluginRegistry
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializedBytes
import net.corda.core.transactions.NotaryChangeWireTransaction import net.corda.core.transactions.NotaryChangeWireTransaction
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.WireTransaction import net.corda.core.transactions.WireTransaction
@ -32,6 +34,7 @@ import org.objenesis.instantiator.ObjectInstantiator
import org.objenesis.strategy.InstantiatorStrategy import org.objenesis.strategy.InstantiatorStrategy
import org.objenesis.strategy.StdInstantiatorStrategy import org.objenesis.strategy.StdInstantiatorStrategy
import org.slf4j.Logger import org.slf4j.Logger
import sun.security.ec.ECPublicKeyImpl
import sun.security.provider.certpath.X509CertPath import sun.security.provider.certpath.X509CertPath
import java.io.BufferedInputStream import java.io.BufferedInputStream
import java.io.FileInputStream import java.io.FileInputStream
@ -82,7 +85,7 @@ object DefaultKryoCustomizer {
noReferencesWithin<WireTransaction>() noReferencesWithin<WireTransaction>()
register(sun.security.ec.ECPublicKeyImpl::class.java, ECPublicKeyImplSerializer) register(ECPublicKeyImpl::class.java, ECPublicKeyImplSerializer)
register(EdDSAPublicKey::class.java, Ed25519PublicKeySerializer) register(EdDSAPublicKey::class.java, Ed25519PublicKeySerializer)
register(EdDSAPrivateKey::class.java, Ed25519PrivateKeySerializer) register(EdDSAPrivateKey::class.java, Ed25519PrivateKeySerializer)

View File

@ -1,4 +1,4 @@
package net.corda.nodeapi.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.KryoException import com.esotericsoftware.kryo.KryoException
import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.CordaPluginRegistry

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.* import com.esotericsoftware.kryo.*
import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Input
@ -11,6 +11,10 @@ import net.corda.core.crypto.TransactionSignature
import net.corda.core.crypto.composite.CompositeKey import net.corda.core.crypto.composite.CompositeKey
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.VisibleForTesting import net.corda.core.internal.VisibleForTesting
import net.corda.core.serialization.AttachmentsClassLoader
import net.corda.core.serialization.MissingAttachmentsException
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SerializedBytes
import net.corda.core.transactions.CoreTransaction import net.corda.core.transactions.CoreTransaction
import net.corda.core.transactions.NotaryChangeWireTransaction import net.corda.core.transactions.NotaryChangeWireTransaction
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
@ -25,6 +29,8 @@ import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.cert.X509CertificateHolder import org.bouncycastle.cert.X509CertificateHolder
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import sun.security.ec.ECPublicKeyImpl
import sun.security.util.DerValue
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.InputStream import java.io.InputStream
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
@ -229,10 +235,6 @@ fun Input.readBytesWithLength(): ByteArray {
return this.readBytes(size) return this.readBytes(size)
} }
/** Thrown during deserialisation to indicate that an attachment needed to construct the [WireTransaction] is not found */
@CordaSerializable
class MissingAttachmentsException(val ids: List<SecureHash>) : Exception()
/** A serialisation engine that knows how to deserialise code inside a sandbox */ /** A serialisation engine that knows how to deserialise code inside a sandbox */
@ThreadSafe @ThreadSafe
object WireTransactionSerializer : Serializer<WireTransaction>() { object WireTransactionSerializer : Serializer<WireTransaction>() {
@ -343,15 +345,15 @@ object Ed25519PublicKeySerializer : Serializer<EdDSAPublicKey>() {
/** For serialising an ed25519 public key */ /** For serialising an ed25519 public key */
@ThreadSafe @ThreadSafe
object ECPublicKeyImplSerializer : Serializer<sun.security.ec.ECPublicKeyImpl>() { object ECPublicKeyImplSerializer : Serializer<ECPublicKeyImpl>() {
override fun write(kryo: Kryo, output: Output, obj: sun.security.ec.ECPublicKeyImpl) { override fun write(kryo: Kryo, output: Output, obj: ECPublicKeyImpl) {
output.writeBytesWithLength(obj.encoded) output.writeBytesWithLength(obj.encoded)
} }
override fun read(kryo: Kryo, input: Input, type: Class<sun.security.ec.ECPublicKeyImpl>): sun.security.ec.ECPublicKeyImpl { override fun read(kryo: Kryo, input: Input, type: Class<ECPublicKeyImpl>): ECPublicKeyImpl {
val A = input.readBytesWithLength() val A = input.readBytesWithLength()
val der = sun.security.util.DerValue(A) val der = DerValue(A)
return sun.security.ec.ECPublicKeyImpl.parse(der) as sun.security.ec.ECPublicKeyImpl return ECPublicKeyImpl.parse(der) as ECPublicKeyImpl
} }
} }
@ -562,3 +564,5 @@ object X509CertificateSerializer : Serializer<X509CertificateHolder>() {
output.writeBytes(obj.encoded) output.writeBytes(obj.encoded)
} }
} }
fun Kryo.serializationContext(): SerializeAsTokenContext? = context.get(serializationContextKey) as? SerializeAsTokenContext

View File

@ -1,12 +1,13 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.Serializer import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output
import net.corda.core.serialization.amqp.DeserializationInput import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.amqp.SerializationOutput import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import net.corda.core.serialization.amqp.SerializerFactory import net.corda.nodeapi.internal.serialization.amqp.SerializationOutput
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
/** /**
* This [Kryo] custom [Serializer] switches the object graph of anything annotated with `@CordaSerializable` * This [Kryo] custom [Serializer] switches the object graph of anything annotated with `@CordaSerializable`
@ -17,12 +18,12 @@ import net.corda.core.serialization.amqp.SerializerFactory
object KryoAMQPSerializer : Serializer<Any>() { object KryoAMQPSerializer : Serializer<Any>() {
internal fun registerCustomSerializers(factory: SerializerFactory) { internal fun registerCustomSerializers(factory: SerializerFactory) {
factory.apply { factory.apply {
register(net.corda.core.serialization.amqp.custom.PublicKeySerializer) register(net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer)
register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(this)) register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(this))
register(net.corda.core.serialization.amqp.custom.X500NameSerializer) register(net.corda.nodeapi.internal.serialization.amqp.custom.X500NameSerializer)
register(net.corda.core.serialization.amqp.custom.BigDecimalSerializer) register(net.corda.nodeapi.internal.serialization.amqp.custom.BigDecimalSerializer)
register(net.corda.core.serialization.amqp.custom.CurrencySerializer) register(net.corda.nodeapi.internal.serialization.amqp.custom.CurrencySerializer)
register(net.corda.core.serialization.amqp.custom.InstantSerializer(this)) register(net.corda.nodeapi.internal.serialization.amqp.custom.InstantSerializer(this))
} }
} }

View File

@ -0,0 +1,10 @@
package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.Kryo
import net.corda.core.serialization.SerializationCustomization
class KryoSerializationCustomization(val kryo: Kryo) : SerializationCustomization {
override fun addToWhitelist(type: Class<*>) {
kryo.addToWhitelist(type)
}
}

View File

@ -1,4 +1,4 @@
package net.corda.nodeapi.serialization package net.corda.nodeapi.internal.serialization
import co.paralleluniverse.fibers.Fiber import co.paralleluniverse.fibers.Fiber
import co.paralleluniverse.io.serialization.kryo.KryoSerializer import co.paralleluniverse.io.serialization.kryo.KryoSerializer

View File

@ -0,0 +1,56 @@
package net.corda.nodeapi.internal.serialization
import net.corda.core.node.ServiceHub
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationFactory
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
val serializationContextKey = SerializeAsTokenContext::class.java
fun SerializationContext.withTokenContext(serializationContext: SerializeAsTokenContext): SerializationContext = this.withProperty(serializationContextKey, serializationContext)
/**
* A context for mapping SerializationTokens to/from SerializeAsTokens.
*
* A context is initialised with an object containing all the instances of [SerializeAsToken] to eagerly register all the tokens.
* In our case this can be the [ServiceHub].
*
* Then it is a case of using the companion object methods on [SerializeAsTokenSerializer] to set and clear context as necessary
* when serializing to enable/disable tokenization.
*/
class SerializeAsTokenContextImpl(override val serviceHub: ServiceHub, init: SerializeAsTokenContext.() -> Unit) : SerializeAsTokenContext {
constructor(toBeTokenized: Any, serializationFactory: SerializationFactory, context: SerializationContext, serviceHub: ServiceHub) : this(serviceHub, {
serializationFactory.serialize(toBeTokenized, context.withTokenContext(this))
})
private val classNameToSingleton = mutableMapOf<String, SerializeAsToken>()
private var readOnly = false
init {
/**
* Go ahead and eagerly serialize the object to register all of the tokens in the context.
*
* This results in the toToken() method getting called for any [SingletonSerializeAsToken] instances which
* are encountered in the object graph as they are serialized and will therefore register the token to
* object mapping for those instances. We then immediately set the readOnly flag to stop further adhoc or
* accidental registrations from occuring as these could not be deserialized in a deserialization-first
* scenario if they are not part of this iniital context construction serialization.
*/
init(this)
readOnly = true
}
override fun putSingleton(toBeTokenized: SerializeAsToken) {
val className = toBeTokenized.javaClass.name
if (className !in classNameToSingleton) {
// Only allowable if we are in SerializeAsTokenContext init (readOnly == false)
if (readOnly) {
throw UnsupportedOperationException("Attempt to write token for lazy registered ${className}. All tokens should be registered during context construction.")
}
classNameToSingleton[className] = toBeTokenized
}
}
override fun getSingleton(className: String) = classNameToSingleton[className] ?: throw IllegalStateException("Unable to find tokenized instance of $className in context $this")
}

View File

@ -0,0 +1,25 @@
package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.KryoException
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import net.corda.core.internal.castIfPossible
import net.corda.core.serialization.SerializationToken
import net.corda.core.serialization.SerializeAsToken
/**
* A Kryo serializer for [SerializeAsToken] implementations.
*/
class SerializeAsTokenSerializer<T : SerializeAsToken> : Serializer<T>() {
override fun write(kryo: Kryo, output: Output, obj: T) {
kryo.writeClassAndObject(output, obj.toToken(kryo.serializationContext() ?: throw KryoException("Attempt to write a ${SerializeAsToken::class.simpleName} instance of ${obj.javaClass.name} without initialising a context")))
}
override fun read(kryo: Kryo, input: Input, type: Class<T>): T {
val token = (kryo.readClassAndObject(input) as? SerializationToken) ?: throw KryoException("Non-token read for tokenized type: ${type.name}")
val fromToken = token.fromToken(kryo.serializationContext() ?: throw KryoException("Attempt to read a token for a ${SerializeAsToken::class.simpleName} instance of ${type.name} without initialising a context"))
return type.castIfPossible(fromToken) ?: throw KryoException("Token read ($token) did not return expected tokenized type: ${type.name}")
}
}

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.amqp.Binary import org.apache.qpid.proton.amqp.Binary
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type import java.lang.reflect.Type

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException import java.io.NotSerializableException

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException import java.io.NotSerializableException

View File

@ -1,6 +1,6 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.amqp.SerializerFactory.Companion.nameForType import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type import java.lang.reflect.Type

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.getStackTraceAsString import net.corda.core.internal.getStackTraceAsString
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import java.lang.reflect.GenericArrayType import java.lang.reflect.GenericArrayType
import java.lang.reflect.Type import java.lang.reflect.Type

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import com.google.common.primitives.Primitives import com.google.common.primitives.Primitives
import java.io.NotSerializableException import java.io.NotSerializableException

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException import java.io.NotSerializableException

View File

@ -1,6 +1,6 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.amqp.SerializerFactory.Companion.nameForType import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
import org.apache.qpid.proton.amqp.UnsignedInteger import org.apache.qpid.proton.amqp.UnsignedInteger
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException import java.io.NotSerializableException

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.amqp.Binary import org.apache.qpid.proton.amqp.Binary
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import com.google.common.hash.Hasher import com.google.common.hash.Hasher
import com.google.common.hash.Hashing import com.google.common.hash.Hashing
@ -14,9 +14,8 @@ import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type import java.lang.reflect.Type
import java.lang.reflect.TypeVariable import java.lang.reflect.TypeVariable
import java.util.* import java.util.*
import net.corda.nodeapi.internal.serialization.carpenter.Field as CarpenterField
import net.corda.core.serialization.carpenter.Schema as CarpenterSchema import net.corda.nodeapi.internal.serialization.carpenter.Schema as CarpenterSchema
import net.corda.core.serialization.carpenter.Field as CarpenterField
// TODO: get an assigned number as per AMQP spec // TODO: get an assigned number as per AMQP spec
val DESCRIPTOR_TOP_32BITS: Long = 0xc0da0000 val DESCRIPTOR_TOP_32BITS: Long = 0xc0da0000

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import com.google.common.reflect.TypeToken import com.google.common.reflect.TypeToken
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data

View File

@ -1,10 +1,10 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import com.google.common.primitives.Primitives import com.google.common.primitives.Primitives
import com.google.common.reflect.TypeResolver import com.google.common.reflect.TypeResolver
import net.corda.core.serialization.AllWhitelist
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.nodeapi.internal.serialization.AllWhitelist
import org.apache.qpid.proton.amqp.* import org.apache.qpid.proton.amqp.*
import java.io.NotSerializableException import java.io.NotSerializableException
import java.lang.reflect.GenericArrayType import java.lang.reflect.GenericArrayType

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type import java.lang.reflect.Type

View File

@ -1,6 +1,6 @@
package net.corda.core.serialization.amqp.custom package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.serialization.amqp.CustomSerializer import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import java.math.BigDecimal import java.math.BigDecimal
/** /**

View File

@ -1,6 +1,6 @@
package net.corda.core.serialization.amqp.custom package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.serialization.amqp.CustomSerializer import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import java.util.* import java.util.*
/** /**

View File

@ -1,7 +1,7 @@
package net.corda.core.serialization.amqp.custom package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.serialization.amqp.CustomSerializer import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.core.serialization.amqp.SerializerFactory import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
import java.time.Instant import java.time.Instant
/** /**

View File

@ -1,7 +1,7 @@
package net.corda.core.serialization.amqp.custom package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.*
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type import java.lang.reflect.Type
import java.security.PublicKey import java.security.PublicKey

View File

@ -1,11 +1,11 @@
package net.corda.core.serialization.amqp.custom package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.serialization.amqp.CustomSerializer
import net.corda.core.serialization.amqp.SerializerFactory
import net.corda.core.serialization.amqp.constructorForDeserialization
import net.corda.core.serialization.amqp.propertiesForSerialization
import net.corda.core.CordaRuntimeException import net.corda.core.CordaRuntimeException
import net.corda.core.CordaThrowable import net.corda.core.CordaThrowable
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
import net.corda.nodeapi.internal.serialization.amqp.constructorForDeserialization
import net.corda.nodeapi.internal.serialization.amqp.propertiesForSerialization
import java.io.NotSerializableException import java.io.NotSerializableException
class ThrowableSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Throwable, ThrowableSerializer.ThrowableProxy>(Throwable::class.java, ThrowableProxy::class.java, factory) { class ThrowableSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Throwable, ThrowableSerializer.ThrowableProxy>(Throwable::class.java, ThrowableProxy::class.java, factory) {

View File

@ -1,6 +1,6 @@
package net.corda.core.serialization.amqp.custom package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.*
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import org.bouncycastle.asn1.ASN1InputStream import org.bouncycastle.asn1.ASN1InputStream
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name

View File

@ -1,8 +1,8 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.serialization.amqp.Schema as AMQPSchema import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.core.serialization.amqp.Field as AMQPField import net.corda.nodeapi.internal.serialization.amqp.Field as AMQPField
import net.corda.core.serialization.amqp.CompositeType import net.corda.nodeapi.internal.serialization.amqp.Schema as AMQPSchema
fun AMQPSchema.carpenterSchema( fun AMQPSchema.carpenterSchema(
loaders : List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader())) loaders : List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader()))
@ -41,7 +41,7 @@ private fun CompositeType.validatePropertyTypes(
*/ */
fun CompositeType.carpenterSchema( fun CompositeType.carpenterSchema(
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader()), classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader()),
carpenterSchemas : CarpenterSchemas, carpenterSchemas: CarpenterSchemas,
force : Boolean = false) { force : Boolean = false) {
if (classLoaders.exists(name)) { if (classLoaders.exists(name)) {
validatePropertyTypes(classLoaders) validatePropertyTypes(classLoaders)
@ -68,7 +68,7 @@ fun CompositeType.carpenterSchema(
} }
} }
val m : MutableMap<String, Field> = mutableMapOf() val m: MutableMap<String, Field> = mutableMapOf()
fields.forEach { fields.forEach {
try { try {

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import org.objectweb.asm.ClassWriter import org.objectweb.asm.ClassWriter
import org.objectweb.asm.MethodVisitor import org.objectweb.asm.MethodVisitor
@ -303,7 +303,7 @@ class ClassCarpenter {
it.name.startsWith("get") -> it.name.substring(3).decapitalize() it.name.startsWith("get") -> it.name.substring(3).decapitalize()
else -> throw InterfaceMismatchException( else -> throw InterfaceMismatchException(
"Requested interfaces must consist only of methods that start " "Requested interfaces must consist only of methods that start "
+ "with 'get': ${itf.name}.${it.name}") + "with 'get': ${itf.name}.${it.name}")
} }
// If we're trying to carpent a class that prior to serialisation / deserialisation // If we're trying to carpent a class that prior to serialisation / deserialisation
@ -314,7 +314,7 @@ class ClassCarpenter {
if ((schema is ClassSchema) and (fieldNameFromItf !in allFields)) if ((schema is ClassSchema) and (fieldNameFromItf !in allFields))
throw InterfaceMismatchException( throw InterfaceMismatchException(
"Interface ${itf.name} requires a field named $fieldNameFromItf but that " "Interface ${itf.name} requires a field named $fieldNameFromItf but that "
+ "isn't found in the schema or any superclass schemas") + "isn't found in the schema or any superclass schemas")
} }
} }
} }

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
class DuplicateNameException : RuntimeException ( class DuplicateNameException : RuntimeException (
"An attempt was made to register two classes with the same name within the same ClassCarpenter namespace.") "An attempt was made to register two classes with the same name within the same ClassCarpenter namespace.")

View File

@ -1,7 +1,7 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.serialization.amqp.CompositeType import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.core.serialization.amqp.TypeNotation import net.corda.nodeapi.internal.serialization.amqp.TypeNotation
/** /**
* Generated from an AMQP schema this class represents the classes unknown to the deserialiser and that thusly * Generated from an AMQP schema this class represents the classes unknown to the deserialiser and that thusly
@ -23,9 +23,9 @@ import net.corda.core.serialization.amqp.TypeNotation
* and if that list is reduced to zero know we can now generate a [Schema] for them and carpent them up * and if that list is reduced to zero know we can now generate a [Schema] for them and carpent them up
*/ */
data class CarpenterSchemas ( data class CarpenterSchemas (
val carpenterSchemas : MutableList<Schema>, val carpenterSchemas: MutableList<Schema>,
val dependencies : MutableMap<String, Pair<TypeNotation, MutableList<String>>>, val dependencies: MutableMap<String, Pair<TypeNotation, MutableList<String>>>,
val dependsOn : MutableMap<String, MutableList<String>>) { val dependsOn: MutableMap<String, MutableList<String>>) {
companion object CarpenterSchemaConstructor { companion object CarpenterSchemaConstructor {
fun newInstance(): CarpenterSchemas { fun newInstance(): CarpenterSchemas {
return CarpenterSchemas( return CarpenterSchemas(
@ -57,7 +57,7 @@ abstract class MetaCarpenterBase (val schemas : CarpenterSchemas) {
private val cc = ClassCarpenter() private val cc = ClassCarpenter()
val objects = mutableMapOf<String, Class<*>>() val objects = mutableMapOf<String, Class<*>>()
fun step (newObject : Schema) { fun step(newObject: Schema) {
objects[newObject.name] = cc.build (newObject) objects[newObject.name] = cc.build (newObject)
// go over the list of everything that had a dependency on the newly // go over the list of everything that had a dependency on the newly
@ -82,7 +82,7 @@ abstract class MetaCarpenterBase (val schemas : CarpenterSchemas) {
abstract fun build() abstract fun build()
} }
class MetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) { class MetaCarpenter(schemas: CarpenterSchemas) : MetaCarpenterBase(schemas) {
override fun build() { override fun build() {
while (schemas.carpenterSchemas.isNotEmpty()) { while (schemas.carpenterSchemas.isNotEmpty()) {
val newObject = schemas.carpenterSchemas.removeAt(0) val newObject = schemas.carpenterSchemas.removeAt(0)
@ -91,7 +91,7 @@ class MetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) {
} }
} }
class TestMetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) { class TestMetaCarpenter(schemas: CarpenterSchemas) : MetaCarpenterBase(schemas) {
override fun build() { override fun build() {
if (schemas.carpenterSchemas.isEmpty()) return if (schemas.carpenterSchemas.isEmpty()) return
step (schemas.carpenterSchemas.removeAt(0)) step (schemas.carpenterSchemas.removeAt(0))

View File

@ -1,12 +1,10 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import jdk.internal.org.objectweb.asm.Opcodes.* import jdk.internal.org.objectweb.asm.Opcodes.*
import org.objectweb.asm.ClassWriter import org.objectweb.asm.ClassWriter
import org.objectweb.asm.MethodVisitor import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Type import org.objectweb.asm.Type
import java.util.LinkedHashMap import java.util.*
/** /**
* A Schema represents a desired class. * A Schema represents a desired class.
@ -35,18 +33,18 @@ abstract class Schema(
} }
class ClassSchema( class ClassSchema(
name: String, name: String,
fields: Map<String, Field>, fields: Map<String, Field>,
superclass: Schema? = null, superclass: Schema? = null,
interfaces: List<Class<*>> = emptyList() interfaces: List<Class<*>> = emptyList()
) : Schema (name, fields, superclass, interfaces) ) : Schema(name, fields, superclass, interfaces)
class InterfaceSchema( class InterfaceSchema(
name: String, name: String,
fields: Map<String, Field>, fields: Map<String, Field>,
superclass: Schema? = null, superclass: Schema? = null,
interfaces: List<Class<*>> = emptyList() interfaces: List<Class<*>> = emptyList()
) : Schema (name, fields, superclass, interfaces) ) : Schema(name, fields, superclass, interfaces)
object CarpenterSchemaFactory { object CarpenterSchemaFactory {
fun newInstance ( fun newInstance (

View File

@ -1,2 +1,2 @@
# Register a ServiceLoader service extending from net.corda.core.node.CordaPluginRegistry # Register a ServiceLoader service extending from net.corda.core.node.CordaPluginRegistry
net.corda.nodeapi.serialization.DefaultWhitelist net.corda.nodeapi.internal.serialization.DefaultWhitelist

View File

@ -1,4 +1,4 @@
package net.corda.core.node package net.corda.nodeapi
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
@ -6,11 +6,15 @@ import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.AttachmentStorage import net.corda.core.node.services.AttachmentStorage
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.serialization.SerializationDefaults.P2P_CONTEXT import net.corda.core.serialization.SerializationDefaults.P2P_CONTEXT
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.nodeapi.internal.serialization.SerializeAsTokenContextImpl
import net.corda.nodeapi.internal.serialization.WireTransactionSerializer
import net.corda.nodeapi.internal.serialization.withTokenContext
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP
import net.corda.testing.TestDependencyInjectionBase import net.corda.testing.TestDependencyInjectionBase
@ -43,7 +47,7 @@ class AttachmentClassLoaderTests : TestDependencyInjectionBase() {
private fun SerializationContext.withAttachmentStorage(attachmentStorage: AttachmentStorage): SerializationContext { private fun SerializationContext.withAttachmentStorage(attachmentStorage: AttachmentStorage): SerializationContext {
val serviceHub = mock<ServiceHub>() val serviceHub = mock<ServiceHub>()
whenever(serviceHub.attachments).thenReturn(attachmentStorage) whenever(serviceHub.attachments).thenReturn(attachmentStorage)
return this.withTokenContext(SerializeAsTokenContext(serviceHub) {}).withProperty(WireTransactionSerializer.attachmentsClassLoaderEnabled, true) return this.withTokenContext(SerializeAsTokenContextImpl(serviceHub) {}).withProperty(WireTransactionSerializer.attachmentsClassLoaderEnabled, true)
} }
} }
@ -192,7 +196,7 @@ class AttachmentClassLoaderTests : TestDependencyInjectionBase() {
@Test @Test
fun `verify that contract DummyContract is in classPath`() { fun `verify that contract DummyContract is in classPath`() {
val contractClass = Class.forName("net.corda.core.node.AttachmentClassLoaderTests\$AttachmentDummyContract") val contractClass = Class.forName("net.corda.nodeapi.AttachmentClassLoaderTests\$AttachmentDummyContract")
val contract = contractClass.newInstance() as Contract val contract = contractClass.newInstance() as Contract
assertNotNull(contract) assertNotNull(contract)

View File

@ -1,11 +1,13 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.* import com.esotericsoftware.kryo.*
import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output
import com.esotericsoftware.kryo.util.MapReferenceResolver import com.esotericsoftware.kryo.util.MapReferenceResolver
import net.corda.core.node.AttachmentClassLoaderTests
import net.corda.core.node.services.AttachmentStorage import net.corda.core.node.services.AttachmentStorage
import net.corda.core.serialization.AttachmentsClassLoader
import net.corda.core.serialization.CordaSerializable
import net.corda.nodeapi.AttachmentClassLoaderTests
import net.corda.testing.node.MockAttachmentStorage import net.corda.testing.node.MockAttachmentStorage
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -182,7 +184,7 @@ class CordaClassResolverTests {
@Test @Test
fun `Check blacklisted subclass`() { fun `Check blacklisted subclass`() {
expectedEx.expect(IllegalStateException::class.java) expectedEx.expect(IllegalStateException::class.java)
expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.core.serialization.CordaClassResolverTests\$SubHashSet is blacklisted, so it cannot be used in serialization.") expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$SubHashSet is blacklisted, so it cannot be used in serialization.")
val resolver = CordaClassResolver(AllButBlacklisted) val resolver = CordaClassResolver(AllButBlacklisted)
// SubHashSet extends the blacklisted HashSet. // SubHashSet extends the blacklisted HashSet.
resolver.getRegistration(SubHashSet::class.java) resolver.getRegistration(SubHashSet::class.java)
@ -192,7 +194,7 @@ class CordaClassResolverTests {
@Test @Test
fun `Check blacklisted subsubclass`() { fun `Check blacklisted subsubclass`() {
expectedEx.expect(IllegalStateException::class.java) expectedEx.expect(IllegalStateException::class.java)
expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.core.serialization.CordaClassResolverTests\$SubSubHashSet is blacklisted, so it cannot be used in serialization.") expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$SubSubHashSet is blacklisted, so it cannot be used in serialization.")
val resolver = CordaClassResolver(AllButBlacklisted) val resolver = CordaClassResolver(AllButBlacklisted)
// SubSubHashSet extends SubHashSet, which extends the blacklisted HashSet. // SubSubHashSet extends SubHashSet, which extends the blacklisted HashSet.
resolver.getRegistration(SubSubHashSet::class.java) resolver.getRegistration(SubSubHashSet::class.java)
@ -202,7 +204,7 @@ class CordaClassResolverTests {
@Test @Test
fun `Check blacklisted interface impl`() { fun `Check blacklisted interface impl`() {
expectedEx.expect(IllegalStateException::class.java) expectedEx.expect(IllegalStateException::class.java)
expectedEx.expectMessage("The superinterface java.sql.Connection of net.corda.core.serialization.CordaClassResolverTests\$ConnectionImpl is blacklisted, so it cannot be used in serialization.") expectedEx.expectMessage("The superinterface java.sql.Connection of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$ConnectionImpl is blacklisted, so it cannot be used in serialization.")
val resolver = CordaClassResolver(AllButBlacklisted) val resolver = CordaClassResolver(AllButBlacklisted)
// ConnectionImpl implements blacklisted Connection. // ConnectionImpl implements blacklisted Connection.
resolver.getRegistration(ConnectionImpl::class.java) resolver.getRegistration(ConnectionImpl::class.java)
@ -213,7 +215,7 @@ class CordaClassResolverTests {
@Test @Test
fun `Check blacklisted super-interface impl`() { fun `Check blacklisted super-interface impl`() {
expectedEx.expect(IllegalStateException::class.java) expectedEx.expect(IllegalStateException::class.java)
expectedEx.expectMessage("The superinterface java.sql.Connection of net.corda.core.serialization.CordaClassResolverTests\$SubConnectionImpl is blacklisted, so it cannot be used in serialization.") expectedEx.expectMessage("The superinterface java.sql.Connection of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$SubConnectionImpl is blacklisted, so it cannot be used in serialization.")
val resolver = CordaClassResolver(AllButBlacklisted) val resolver = CordaClassResolver(AllButBlacklisted)
// SubConnectionImpl implements SubConnection, which extends the blacklisted Connection. // SubConnectionImpl implements SubConnection, which extends the blacklisted Connection.
resolver.getRegistration(SubConnectionImpl::class.java) resolver.getRegistration(SubConnectionImpl::class.java)
@ -231,7 +233,7 @@ class CordaClassResolverTests {
@Test @Test
fun `Check blacklist precedes CordaSerializable`() { fun `Check blacklist precedes CordaSerializable`() {
expectedEx.expect(IllegalStateException::class.java) expectedEx.expect(IllegalStateException::class.java)
expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.core.serialization.CordaClassResolverTests\$CordaSerializableHashSet is blacklisted, so it cannot be used in serialization.") expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$CordaSerializableHashSet is blacklisted, so it cannot be used in serialization.")
val resolver = CordaClassResolver(AllButBlacklisted) val resolver = CordaClassResolver(AllButBlacklisted)
// CordaSerializableHashSet is @CordaSerializable, but extends the blacklisted HashSet. // CordaSerializableHashSet is @CordaSerializable, but extends the blacklisted HashSet.
resolver.getRegistration(CordaSerializableHashSet::class.java) resolver.getRegistration(CordaSerializableHashSet::class.java)

View File

@ -1,13 +1,16 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.KryoSerializable
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import com.google.common.primitives.Ints import com.google.common.primitives.Ints
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.serialization.*
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.sequence import net.corda.core.utilities.sequence
import net.corda.node.serialization.KryoServerSerializationScheme import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.node.services.persistence.NodeAttachmentService import net.corda.node.services.persistence.NodeAttachmentService
import net.corda.nodeapi.serialization.KryoHeaderV0_1
import net.corda.nodeapi.serialization.SerializationContextImpl
import net.corda.nodeapi.serialization.SerializationFactoryImpl
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.ALICE_PUBKEY import net.corda.testing.ALICE_PUBKEY
import net.corda.testing.BOB import net.corda.testing.BOB
@ -182,4 +185,53 @@ class KryoTests {
@CordaSerializable @CordaSerializable
private object TestSingleton private object TestSingleton
object SimpleSteps {
object ONE : ProgressTracker.Step("one")
object TWO : ProgressTracker.Step("two")
object THREE : ProgressTracker.Step("three")
object FOUR : ProgressTracker.Step("four")
fun tracker() = ProgressTracker(ONE, TWO, THREE, FOUR)
}
object ChildSteps {
object AYY : ProgressTracker.Step("ayy")
object BEE : ProgressTracker.Step("bee")
object SEA : ProgressTracker.Step("sea")
fun tracker() = ProgressTracker(AYY, BEE, SEA)
}
@Test
fun rxSubscriptionsAreNotSerialized() {
val pt: ProgressTracker = SimpleSteps.tracker()
val pt2: ProgressTracker = ChildSteps.tracker()
class Unserializable : KryoSerializable {
override fun write(kryo: Kryo?, output: Output?) = throw AssertionError("not called")
override fun read(kryo: Kryo?, input: Input?) = throw AssertionError("not called")
fun foo() {
println("bar")
}
}
pt.setChildProgressTracker(SimpleSteps.TWO, pt2)
class Tmp {
val unserializable = Unserializable()
init {
pt2.changes.subscribe { unserializable.foo() }
}
}
Tmp()
val factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme()) }
val context = SerializationContextImpl(KryoHeaderV0_1,
javaClass.classLoader,
AllWhitelist,
emptyMap(),
true,
SerializationContext.UseCase.P2P)
pt.serialize(factory, context)
}
} }

View File

@ -1,15 +1,13 @@
package net.corda.core.serialization package net.corda.nodeapi.internal.serialization
import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.KryoException import com.esotericsoftware.kryo.KryoException
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.serialization.*
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.node.serialization.KryoServerSerializationScheme import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.nodeapi.serialization.KryoHeaderV0_1
import net.corda.nodeapi.serialization.SerializationContextImpl
import net.corda.nodeapi.serialization.SerializationFactoryImpl
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -43,7 +41,7 @@ class SerializationTokenTest {
override fun equals(other: Any?) = other is LargeTokenizable && other.bytes.size == this.bytes.size override fun equals(other: Any?) = other is LargeTokenizable && other.bytes.size == this.bytes.size
} }
private fun serializeAsTokenContext(toBeTokenized: Any) = SerializeAsTokenContext(toBeTokenized, factory, context, mock<ServiceHub>()) private fun serializeAsTokenContext(toBeTokenized: Any) = SerializeAsTokenContextImpl(toBeTokenized, factory, context, mock<ServiceHub>())
@Test @Test
fun `write token and read tokenizable`() { fun `write token and read tokenizable`() {

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import org.junit.Test import org.junit.Test

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import org.junit.Test import org.junit.Test
import java.io.NotSerializableException import java.io.NotSerializableException

View File

@ -1,4 +1,4 @@
package net.corda.core.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.CordaRuntimeException import net.corda.core.CordaRuntimeException
import net.corda.core.contracts.Contract import net.corda.core.contracts.Contract
@ -9,11 +9,12 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowException import net.corda.core.flows.FlowException
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.EmptyWhitelist
import net.corda.core.serialization.KryoAMQPSerializer
import net.corda.core.serialization.amqp.SerializerFactory.Companion.isPrimitive
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
import net.corda.nodeapi.RPCException import net.corda.nodeapi.RPCException
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
import net.corda.nodeapi.internal.serialization.KryoAMQPSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.isPrimitive
import net.corda.nodeapi.internal.serialization.amqp.custom.*
import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP
import net.corda.testing.MEGA_CORP_PUBKEY import net.corda.testing.MEGA_CORP_PUBKEY
import org.apache.qpid.proton.amqp.* import org.apache.qpid.proton.amqp.*
@ -387,9 +388,9 @@ class SerializationOutputTests {
@Test @Test
fun `test custom serializers on public key`() { fun `test custom serializers on public key`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.PublicKeySerializer) factory.register(PublicKeySerializer)
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.PublicKeySerializer) factory2.register(PublicKeySerializer)
val obj = MEGA_CORP_PUBKEY val obj = MEGA_CORP_PUBKEY
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
} }
@ -403,10 +404,10 @@ class SerializationOutputTests {
@Test @Test
fun `test throwables serialize`() { fun `test throwables serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory)) factory.register(ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory2)) factory2.register(ThrowableSerializer(factory2))
val t = IllegalAccessException("message").fillInStackTrace() val t = IllegalAccessException("message").fillInStackTrace()
val desThrowable = serdes(t, factory, factory2, false) as Throwable val desThrowable = serdes(t, factory, factory2, false) as Throwable
@ -416,10 +417,10 @@ class SerializationOutputTests {
@Test @Test
fun `test complex throwables serialize`() { fun `test complex throwables serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory)) factory.register(ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory2)) factory2.register(ThrowableSerializer(factory2))
try { try {
try { try {
@ -447,10 +448,10 @@ class SerializationOutputTests {
@Test @Test
fun `test suppressed throwables serialize`() { fun `test suppressed throwables serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory)) factory.register(ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory2)) factory2.register(ThrowableSerializer(factory2))
try { try {
try { try {
@ -469,10 +470,10 @@ class SerializationOutputTests {
@Test @Test
fun `test flow corda exception subclasses serialize`() { fun `test flow corda exception subclasses serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory)) factory.register(ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory2)) factory2.register(ThrowableSerializer(factory2))
val obj = FlowException("message").fillInStackTrace() val obj = FlowException("message").fillInStackTrace()
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -481,10 +482,10 @@ class SerializationOutputTests {
@Test @Test
fun `test RPC corda exception subclasses serialize`() { fun `test RPC corda exception subclasses serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory)) factory.register(ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.ThrowableSerializer(factory2)) factory2.register(ThrowableSerializer(factory2))
val obj = RPCException("message").fillInStackTrace() val obj = RPCException("message").fillInStackTrace()
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -542,10 +543,10 @@ class SerializationOutputTests {
@Test @Test
fun `test currencies serialize`() { fun `test currencies serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.CurrencySerializer) factory.register(CurrencySerializer)
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.CurrencySerializer) factory2.register(CurrencySerializer)
val obj = Currency.getInstance("USD") val obj = Currency.getInstance("USD")
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -554,10 +555,10 @@ class SerializationOutputTests {
@Test @Test
fun `test big decimals serialize`() { fun `test big decimals serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.BigDecimalSerializer) factory.register(BigDecimalSerializer)
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.BigDecimalSerializer) factory2.register(BigDecimalSerializer)
val obj = BigDecimal("100000000000000000000000000000.00") val obj = BigDecimal("100000000000000000000000000000.00")
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -566,10 +567,10 @@ class SerializationOutputTests {
@Test @Test
fun `test instants serialize`() { fun `test instants serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.InstantSerializer(factory)) factory.register(InstantSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.InstantSerializer(factory2)) factory2.register(InstantSerializer(factory2))
val obj = Instant.now() val obj = Instant.now()
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -578,10 +579,10 @@ class SerializationOutputTests {
@Test @Test
fun `test StateRef serialize`() { fun `test StateRef serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory()
factory.register(net.corda.core.serialization.amqp.custom.InstantSerializer(factory)) factory.register(InstantSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory()
factory2.register(net.corda.core.serialization.amqp.custom.InstantSerializer(factory2)) factory2.register(InstantSerializer(factory2))
val obj = StateRef(SecureHash.randomSHA256(), 0) val obj = StateRef(SecureHash.randomSHA256(), 0)
serdes(obj, factory, factory2) serdes(obj, factory, factory2)

View File

@ -1,10 +1,12 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import org.junit.Test import org.junit.Test
import java.beans.Introspector
import java.lang.reflect.Field import java.lang.reflect.Field
import java.lang.reflect.Method import java.lang.reflect.Method
import javax.annotation.Nonnull
import javax.annotation.Nullable
import kotlin.test.assertEquals import kotlin.test.assertEquals
import java.beans.Introspector
import kotlin.test.assertNotEquals import kotlin.test.assertNotEquals
class ClassCarpenterTest { class ClassCarpenterTest {
@ -42,7 +44,7 @@ class ClassCarpenterTest {
"floatMyBoat" to Float::class.javaPrimitiveType!!, "floatMyBoat" to Float::class.javaPrimitiveType!!,
"byteMe" to Byte::class.javaPrimitiveType!!, "byteMe" to Byte::class.javaPrimitiveType!!,
"booleanField" to Boolean::class.javaPrimitiveType!!).mapValues { "booleanField" to Boolean::class.javaPrimitiveType!!).mapValues {
NonNullableField (it.value) NonNullableField(it.value)
})) }))
assertEquals(8, clazz.nonSyntheticFields.size) assertEquals(8, clazz.nonSyntheticFields.size)
assertEquals(10, clazz.nonSyntheticMethods.size) assertEquals(10, clazz.nonSyntheticMethods.size)
@ -72,7 +74,7 @@ class ClassCarpenterTest {
val clazz = cc.build(ClassSchema("gen.Person", mapOf( val clazz = cc.build(ClassSchema("gen.Person", mapOf(
"age" to Int::class.javaPrimitiveType!!, "age" to Int::class.javaPrimitiveType!!,
"name" to String::class.java "name" to String::class.java
).mapValues { NonNullableField (it.value) } )) ).mapValues { NonNullableField(it.value) }))
val i = clazz.constructors[0].newInstance(32, "Mike") val i = clazz.constructors[0].newInstance(32, "Mike")
return Pair(clazz, i) return Pair(clazz, i)
} }
@ -100,7 +102,7 @@ class ClassCarpenterTest {
fun `can refer to each other`() { fun `can refer to each other`() {
val (clazz1, i) = genPerson() val (clazz1, i) = genPerson()
val clazz2 = cc.build(ClassSchema("gen.Referee", mapOf( val clazz2 = cc.build(ClassSchema("gen.Referee", mapOf(
"ref" to NonNullableField (clazz1) "ref" to NonNullableField(clazz1)
))) )))
val i2 = clazz2.constructors[0].newInstance(i) val i2 = clazz2.constructors[0].newInstance(i)
assertEquals(i, (i2 as SimpleFieldAccess)["ref"]) assertEquals(i, (i2 as SimpleFieldAccess)["ref"])
@ -110,11 +112,11 @@ class ClassCarpenterTest {
fun superclasses() { fun superclasses() {
val schema1 = ClassSchema( val schema1 = ClassSchema(
"gen.A", "gen.A",
mapOf("a" to NonNullableField (String::class.java))) mapOf("a" to NonNullableField(String::class.java)))
val schema2 = ClassSchema( val schema2 = ClassSchema(
"gen.B", "gen.B",
mapOf("b" to NonNullableField (String::class.java)), mapOf("b" to NonNullableField(String::class.java)),
schema1) schema1)
val clazz = cc.build(schema2) val clazz = cc.build(schema2)
@ -162,7 +164,7 @@ class ClassCarpenterTest {
fun `generate interface`() { fun `generate interface`() {
val schema1 = InterfaceSchema( val schema1 = InterfaceSchema(
"gen.Interface", "gen.Interface",
mapOf("a" to NonNullableField (Int::class.java))) mapOf("a" to NonNullableField(Int::class.java)))
val iface = cc.build(schema1) val iface = cc.build(schema1)
@ -173,7 +175,7 @@ class ClassCarpenterTest {
val schema2 = ClassSchema( val schema2 = ClassSchema(
"gen.Derived", "gen.Derived",
mapOf("a" to NonNullableField (Int::class.java)), mapOf("a" to NonNullableField(Int::class.java)),
interfaces = listOf(iface)) interfaces = listOf(iface))
val clazz = cc.build(schema2) val clazz = cc.build(schema2)
@ -224,7 +226,7 @@ class ClassCarpenterTest {
val iFace1 = InterfaceSchema( val iFace1 = InterfaceSchema(
"gen.Interface1", "gen.Interface1",
mapOf( mapOf(
"a" to NonNullableField (Int::class.java), "a" to NonNullableField(Int::class.java),
"b" to NonNullableField(String::class.java))) "b" to NonNullableField(String::class.java)))
val iFace2 = InterfaceSchema( val iFace2 = InterfaceSchema(
@ -261,7 +263,7 @@ class ClassCarpenterTest {
val className = "iEnjoySwede" val className = "iEnjoySwede"
val schema = ClassSchema( val schema = ClassSchema(
"gen.$className", "gen.$className",
mapOf("a" to NonNullableField (Int::class.java))) mapOf("a" to NonNullableField(Int::class.java)))
val clazz = cc.build(schema) val clazz = cc.build(schema)
val a : Int? = null val a : Int? = null
@ -273,7 +275,7 @@ class ClassCarpenterTest {
val className = "iEnjoySwede" val className = "iEnjoySwede"
val schema = ClassSchema( val schema = ClassSchema(
"gen.$className", "gen.$className",
mapOf("a" to NullableField (Int::class.java))) mapOf("a" to NullableField(Int::class.java)))
cc.build(schema) cc.build(schema)
} }
@ -283,7 +285,7 @@ class ClassCarpenterTest {
val className = "iEnjoyWibble" val className = "iEnjoyWibble"
val schema = ClassSchema( val schema = ClassSchema(
"gen.$className", "gen.$className",
mapOf("a" to NullableField (Integer::class.java))) mapOf("a" to NullableField(Integer::class.java)))
val clazz = cc.build(schema) val clazz = cc.build(schema)
val a1 : Int? = null val a1 : Int? = null
@ -298,7 +300,7 @@ class ClassCarpenterTest {
val className = "iEnjoyWibble" val className = "iEnjoyWibble"
val schema = ClassSchema( val schema = ClassSchema(
"gen.$className", "gen.$className",
mapOf("a" to NonNullableField (Integer::class.java))) mapOf("a" to NonNullableField(Integer::class.java)))
val clazz = cc.build(schema) val clazz = cc.build(schema)
@ -311,7 +313,7 @@ class ClassCarpenterTest {
val className = "iEnjoyWibble" val className = "iEnjoyWibble"
val schema = ClassSchema( val schema = ClassSchema(
"gen.$className", "gen.$className",
mapOf("a" to NonNullableField (Integer::class.java))) mapOf("a" to NonNullableField(Integer::class.java)))
val clazz = cc.build(schema) val clazz = cc.build(schema)
@ -440,7 +442,7 @@ class ClassCarpenterTest {
mapOf( mapOf(
"a" to Array<String>::class.java, "a" to Array<String>::class.java,
"b" to String::class.java, "b" to String::class.java,
"c" to Array<String>::class.java).mapValues { NullableField (it.value) }) "c" to Array<String>::class.java).mapValues { NullableField(it.value) })
val clazz = cc.build(schema) val clazz = cc.build(schema)
@ -466,19 +468,19 @@ class ClassCarpenterTest {
val schema = ClassSchema( val schema = ClassSchema(
"gen.$className", "gen.$className",
mapOf("a" to NullableField(String::class.java), mapOf("a" to NullableField(String::class.java),
"b" to NonNullableField(String::class.java))) "b" to NonNullableField(String::class.java)))
val clazz = cc.build(schema) val clazz = cc.build(schema)
assertEquals (2, clazz.declaredFields.size) assertEquals (2, clazz.declaredFields.size)
assertEquals (1, clazz.getDeclaredField("a").annotations.size) assertEquals (1, clazz.getDeclaredField("a").annotations.size)
assertEquals (javax.annotation.Nullable::class.java, clazz.getDeclaredField("a").annotations[0].annotationClass.java) assertEquals(Nullable::class.java, clazz.getDeclaredField("a").annotations[0].annotationClass.java)
assertEquals (1, clazz.getDeclaredField("b").annotations.size) assertEquals (1, clazz.getDeclaredField("b").annotations.size)
assertEquals (javax.annotation.Nonnull::class.java, clazz.getDeclaredField("b").annotations[0].annotationClass.java) assertEquals(Nonnull::class.java, clazz.getDeclaredField("b").annotations[0].annotationClass.java)
assertEquals (1, clazz.getMethod("getA").annotations.size) assertEquals (1, clazz.getMethod("getA").annotations.size)
assertEquals (javax.annotation.Nullable::class.java, clazz.getMethod("getA").annotations[0].annotationClass.java) assertEquals(Nullable::class.java, clazz.getMethod("getA").annotations[0].annotationClass.java)
assertEquals (1, clazz.getMethod("getB").annotations.size) assertEquals (1, clazz.getMethod("getB").annotations.size)
assertEquals (javax.annotation.Nonnull::class.java, clazz.getMethod("getB").annotations[0].annotationClass.java) assertEquals(Nonnull::class.java, clazz.getMethod("getB").annotations[0].annotationClass.java)
} }
@Test @Test

View File

@ -1,8 +1,8 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.*
import net.corda.core.serialization.amqp.Field import net.corda.nodeapi.internal.serialization.amqp.Schema
import net.corda.core.serialization.amqp.Schema import net.corda.nodeapi.internal.serialization.amqp.Field
fun mangleName(name: String) = "${name}__carpenter" fun mangleName(name: String) = "${name}__carpenter"

View File

@ -1,8 +1,8 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFalse import kotlin.test.assertFalse

View File

@ -1,8 +1,7 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import org.junit.Test import org.junit.Test
import kotlin.test.* import kotlin.test.*
@ -43,7 +42,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(testJ, a.j) assertEquals(testJ, a.j)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assertTrue(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
assertEquals(2, serSchema.types.size) assertEquals(2, serSchema.types.size)
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema()
@ -60,7 +59,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
assertEquals(mangleName(classTestName("A")), aSchema!!.name) assertEquals(mangleName(classTestName("A")), aSchema!!.name)
assertEquals(1, aSchema.interfaces.size) assertEquals(1, aSchema.interfaces.size)
assertEquals(net.corda.core.serialization.carpenter.J::class.java, aSchema.interfaces[0]) assertEquals(J::class.java, aSchema.interfaces[0])
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val objJ = aBuilder.constructors[0].newInstance(testJ) val objJ = aBuilder.constructors[0].newInstance(testJ)
@ -83,7 +82,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assertTrue(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
@ -105,7 +104,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(aName, aSchema!!.name) assertEquals(aName, aSchema!!.name)
assertEquals(1, aSchema.interfaces.size) assertEquals(1, aSchema.interfaces.size)
assertEquals(net.corda.core.serialization.carpenter.J::class.java, aSchema.interfaces[0]) assertEquals(J::class.java, aSchema.interfaces[0])
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val objJ = aBuilder.constructors[0].newInstance(testJ, testJJ) val objJ = aBuilder.constructors[0].newInstance(testJ, testJJ)
@ -127,7 +126,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val a = A(testI, testII) val a = A(testI, testII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assertTrue(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
@ -152,8 +151,8 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
assertEquals(aName, aSchema!!.name) assertEquals(aName, aSchema!!.name)
assertEquals(2, aSchema.interfaces.size) assertEquals(2, aSchema.interfaces.size)
assert(net.corda.core.serialization.carpenter.I::class.java in aSchema.interfaces) assertTrue(I::class.java in aSchema.interfaces)
assert(net.corda.core.serialization.carpenter.II::class.java in aSchema.interfaces) assertTrue(II::class.java in aSchema.interfaces)
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val objA = aBuilder.constructors[0].newInstance(testI, testII) val objA = aBuilder.constructors[0].newInstance(testI, testII)
@ -175,7 +174,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val a = A(testI, testIII) val a = A(testI, testIII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assertTrue(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
@ -198,8 +197,8 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
assertEquals(aName, aSchema!!.name) assertEquals(aName, aSchema!!.name)
assertEquals(2, aSchema.interfaces.size) assertEquals(2, aSchema.interfaces.size)
assert(net.corda.core.serialization.carpenter.I::class.java in aSchema.interfaces) assertTrue(I::class.java in aSchema.interfaces)
assert(net.corda.core.serialization.carpenter.III::class.java in aSchema.interfaces) assertTrue(III::class.java in aSchema.interfaces)
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val objA = aBuilder.constructors[0].newInstance(testI, testIII) val objA = aBuilder.constructors[0].newInstance(testI, testIII)
@ -224,7 +223,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val b = B(a, testIIII) val b = B(a, testIIII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assertTrue(obj.obj is B)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
@ -280,7 +279,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val b = B(a, testIIII) val b = B(a, testIIII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assertTrue(obj.obj is B)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
@ -304,7 +303,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val a = A(testI) val a = A(testI)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assertTrue(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
@ -324,12 +323,12 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotEquals(null, carpenterSchema.carpenterSchemas.find { it.name == iName }) assertNotEquals(null, carpenterSchema.carpenterSchemas.find { it.name == iName })
// since we can't build A it should list I as a dependency // since we can't build A it should list I as a dependency
assert(aName in carpenterSchema.dependencies) assertTrue(aName in carpenterSchema.dependencies)
assertEquals(1, carpenterSchema.dependencies[aName]!!.second.size) assertEquals(1, carpenterSchema.dependencies[aName]!!.second.size)
assertEquals(iName, carpenterSchema.dependencies[aName]!!.second[0]) assertEquals(iName, carpenterSchema.dependencies[aName]!!.second[0])
// and conversly I should have A listed as a dependent // and conversly I should have A listed as a dependent
assert(iName in carpenterSchema.dependsOn) assertTrue(iName in carpenterSchema.dependsOn)
assertEquals(1, carpenterSchema.dependsOn[iName]!!.size) assertEquals(1, carpenterSchema.dependsOn[iName]!!.size)
assertEquals(aName, carpenterSchema.dependsOn[iName]!![0]) assertEquals(aName, carpenterSchema.dependsOn[iName]!![0])
@ -340,8 +339,8 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(0, mc.schemas.dependencies.size) assertEquals(0, mc.schemas.dependencies.size)
assertEquals(0, mc.schemas.dependsOn.size) assertEquals(0, mc.schemas.dependsOn.size)
assertEquals(2, mc.objects.size) assertEquals(2, mc.objects.size)
assert(aName in mc.objects) assertTrue(aName in mc.objects)
assert(iName in mc.objects) assertTrue(iName in mc.objects)
mc.objects[aName]!!.constructors[0].newInstance(testI) mc.objects[aName]!!.constructors[0].newInstance(testI)
} }
@ -373,15 +372,15 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iiName }) assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iiName })
assertNull(carpenterSchema.carpenterSchemas.find { it.name == aName }) assertNull(carpenterSchema.carpenterSchemas.find { it.name == aName })
assert(iName in carpenterSchema.dependsOn) assertTrue(iName in carpenterSchema.dependsOn)
assertEquals(1, carpenterSchema.dependsOn[iName]?.size) assertEquals(1, carpenterSchema.dependsOn[iName]?.size)
assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == aName })) assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == aName }))
assert(iiName in carpenterSchema.dependsOn) assertTrue(iiName in carpenterSchema.dependsOn)
assertEquals(1, carpenterSchema.dependsOn[iiName]?.size) assertEquals(1, carpenterSchema.dependsOn[iiName]?.size)
assertNotNull(carpenterSchema.dependsOn[iiName]?.find { it == aName }) assertNotNull(carpenterSchema.dependsOn[iiName]?.find { it == aName })
assert(aName in carpenterSchema.dependencies) assertTrue(aName in carpenterSchema.dependencies)
assertEquals(2, carpenterSchema.dependencies[aName]!!.second.size) assertEquals(2, carpenterSchema.dependencies[aName]!!.second.size)
assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iName }) assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iName })
assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiName }) assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiName })
@ -393,9 +392,9 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(0, mc.schemas.dependencies.size) assertEquals(0, mc.schemas.dependencies.size)
assertEquals(0, mc.schemas.dependsOn.size) assertEquals(0, mc.schemas.dependsOn.size)
assertEquals(3, mc.objects.size) assertEquals(3, mc.objects.size)
assert(aName in mc.objects) assertTrue(aName in mc.objects)
assert(iName in mc.objects) assertTrue(iName in mc.objects)
assert(iiName in mc.objects) assertTrue(iiName in mc.objects)
} }
@Test @Test
@ -425,23 +424,23 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNull(carpenterSchema.carpenterSchemas.find { it.name == aName }) assertNull(carpenterSchema.carpenterSchemas.find { it.name == aName })
// I has III as a direct dependent and A as an indirect one // I has III as a direct dependent and A as an indirect one
assert(iName in carpenterSchema.dependsOn) assertTrue(iName in carpenterSchema.dependsOn)
assertEquals(2, carpenterSchema.dependsOn[iName]?.size) assertEquals(2, carpenterSchema.dependsOn[iName]?.size)
assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == iiiName })) assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == iiiName }))
assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == aName })) assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == aName }))
// III has A as a dependent // III has A as a dependent
assert(iiiName in carpenterSchema.dependsOn) assertTrue(iiiName in carpenterSchema.dependsOn)
assertEquals(1, carpenterSchema.dependsOn[iiiName]?.size) assertEquals(1, carpenterSchema.dependsOn[iiiName]?.size)
assertNotNull(carpenterSchema.dependsOn[iiiName]?.find { it == aName }) assertNotNull(carpenterSchema.dependsOn[iiiName]?.find { it == aName })
// conversly III depends on I // conversly III depends on I
assert(iiiName in carpenterSchema.dependencies) assertTrue(iiiName in carpenterSchema.dependencies)
assertEquals(1, carpenterSchema.dependencies[iiiName]!!.second.size) assertEquals(1, carpenterSchema.dependencies[iiiName]!!.second.size)
assertNotNull(carpenterSchema.dependencies[iiiName]!!.second.find { it == iName }) assertNotNull(carpenterSchema.dependencies[iiiName]!!.second.find { it == iName })
// and A depends on III and I // and A depends on III and I
assert(aName in carpenterSchema.dependencies) assertTrue(aName in carpenterSchema.dependencies)
assertEquals(2, carpenterSchema.dependencies[aName]!!.second.size) assertEquals(2, carpenterSchema.dependencies[aName]!!.second.size)
assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiiName }) assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiiName })
assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iName }) assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iName })
@ -453,8 +452,8 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(0, mc.schemas.dependencies.size) assertEquals(0, mc.schemas.dependencies.size)
assertEquals(0, mc.schemas.dependsOn.size) assertEquals(0, mc.schemas.dependsOn.size)
assertEquals(3, mc.objects.size) assertEquals(3, mc.objects.size)
assert(aName in mc.objects) assertTrue(aName in mc.objects)
assert(iName in mc.objects) assertTrue(iName in mc.objects)
assert(iiiName in mc.objects) assertTrue(iiiName in mc.objects)
} }
} }

View File

@ -1,8 +1,8 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals import kotlin.test.assertNotEquals

View File

@ -1,8 +1,8 @@
package net.corda.core.serialization.carpenter package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -32,7 +32,7 @@ import net.corda.nodeapi.ArtemisTcpTransport
import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.ConnectionDirection
import net.corda.nodeapi.internal.ShutdownHook import net.corda.nodeapi.internal.ShutdownHook
import net.corda.nodeapi.internal.addShutdownHook import net.corda.nodeapi.internal.addShutdownHook
import net.corda.nodeapi.serialization.* import net.corda.nodeapi.internal.serialization.*
import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException
import org.apache.activemq.artemis.api.core.RoutingType import org.apache.activemq.artemis.api.core.RoutingType
import org.apache.activemq.artemis.api.core.client.ActiveMQClient import org.apache.activemq.artemis.api.core.client.ActiveMQClient

View File

@ -1,17 +1,17 @@
package net.corda.node.serialization package net.corda.node.serialization
import com.esotericsoftware.kryo.pool.KryoPool import com.esotericsoftware.kryo.pool.KryoPool
import net.corda.core.serialization.DefaultKryoCustomizer
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.node.services.messaging.RpcServerObservableSerializer import net.corda.node.services.messaging.RpcServerObservableSerializer
import net.corda.nodeapi.RPCKryo import net.corda.nodeapi.RPCKryo
import net.corda.nodeapi.serialization.AbstractKryoSerializationScheme import net.corda.nodeapi.internal.serialization.AbstractKryoSerializationScheme
import net.corda.nodeapi.serialization.KryoHeaderV0_1 import net.corda.nodeapi.internal.serialization.DefaultKryoCustomizer
import net.corda.nodeapi.internal.serialization.KryoHeaderV0_1
class KryoServerSerializationScheme : AbstractKryoSerializationScheme() { class KryoServerSerializationScheme : AbstractKryoSerializationScheme() {
override fun canDeserializeVersion(byteSequence: ByteSequence, target: SerializationContext.UseCase): Boolean { override fun canDeserializeVersion(byteSequence: ByteSequence, target: SerializationContext.UseCase): Boolean {
return byteSequence.equals(KryoHeaderV0_1) && target != SerializationContext.UseCase.RPCClient return byteSequence == KryoHeaderV0_1 && target != SerializationContext.UseCase.RPCClient
} }
override fun rpcClientKryoPool(context: SerializationContext): KryoPool { override fun rpcClientKryoPool(context: SerializationContext): KryoPool {

View File

@ -19,9 +19,11 @@ import net.corda.core.internal.ThreadBox
import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.castIfPossible import net.corda.core.internal.castIfPossible
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.serialization.*
import net.corda.core.serialization.SerializationDefaults.CHECKPOINT_CONTEXT import net.corda.core.serialization.SerializationDefaults.CHECKPOINT_CONTEXT
import net.corda.core.serialization.SerializationDefaults.SERIALIZATION_FACTORY import net.corda.core.serialization.SerializationDefaults.SERIALIZATION_FACTORY
import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.Try import net.corda.core.utilities.Try
import net.corda.core.utilities.debug import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
@ -35,6 +37,8 @@ import net.corda.node.utilities.AffinityExecutor
import net.corda.node.utilities.CordaPersistence import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.bufferUntilDatabaseCommit import net.corda.node.utilities.bufferUntilDatabaseCommit
import net.corda.node.utilities.wrapWithDatabaseTransaction import net.corda.node.utilities.wrapWithDatabaseTransaction
import net.corda.nodeapi.internal.serialization.SerializeAsTokenContextImpl
import net.corda.nodeapi.internal.serialization.withTokenContext
import org.apache.activemq.artemis.utils.ReusableLatch import org.apache.activemq.artemis.utils.ReusableLatch
import org.slf4j.Logger import org.slf4j.Logger
import rx.Observable import rx.Observable
@ -137,7 +141,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
internal val tokenizableServices = ArrayList<Any>() internal val tokenizableServices = ArrayList<Any>()
// Context for tokenized services in checkpoints // Context for tokenized services in checkpoints
private val serializationContext by lazy { private val serializationContext by lazy {
SerializeAsTokenContext(tokenizableServices, SERIALIZATION_FACTORY, CHECKPOINT_CONTEXT, serviceHub) SerializeAsTokenContextImpl(tokenizableServices, SERIALIZATION_FACTORY, CHECKPOINT_CONTEXT, serviceHub)
} }
fun findServices(predicate: (Any) -> Boolean) = tokenizableServices.filter(predicate) fun findServices(predicate: (Any) -> Boolean) = tokenizableServices.filter(predicate)

View File

@ -8,14 +8,13 @@ import net.corda.client.rpc.CordaRPCClient
import net.corda.client.rpc.internal.RPCClient import net.corda.client.rpc.internal.RPCClient
import net.corda.client.rpc.internal.RPCClientConfiguration import net.corda.client.rpc.internal.RPCClientConfiguration
import net.corda.core.concurrent.CordaFuture import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.random63BitValue
import net.corda.core.internal.concurrent.fork
import net.corda.core.internal.concurrent.map
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.messaging.RPCOps import net.corda.core.messaging.RPCOps
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.parseNetworkHostAndPort import net.corda.core.utilities.parseNetworkHostAndPort
import net.corda.core.crypto.random63BitValue
import net.corda.core.internal.concurrent.fork
import net.corda.core.internal.concurrent.map
import net.corda.testing.driver.ProcessUtilities
import net.corda.node.services.RPCUserService import net.corda.node.services.RPCUserService
import net.corda.node.services.messaging.ArtemisMessagingServer import net.corda.node.services.messaging.ArtemisMessagingServer
import net.corda.node.services.messaging.RPCServer import net.corda.node.services.messaging.RPCServer
@ -24,7 +23,7 @@ import net.corda.nodeapi.ArtemisTcpTransport
import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.ConnectionDirection
import net.corda.nodeapi.RPCApi import net.corda.nodeapi.RPCApi
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.serialization.KRYO_RPC_CLIENT_CONTEXT import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT
import net.corda.testing.driver.* import net.corda.testing.driver.*
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.apache.activemq.artemis.api.core.TransportConfiguration import org.apache.activemq.artemis.api.core.TransportConfiguration

View File

@ -4,7 +4,7 @@ import net.corda.client.rpc.serialization.KryoClientSerializationScheme
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.node.serialization.KryoServerSerializationScheme import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.nodeapi.serialization.* import net.corda.nodeapi.internal.serialization.*
fun <T> withTestSerialization(block: () -> T): T { fun <T> withTestSerialization(block: () -> T): T {
initialiseTestSerialization() initialiseTestSerialization()

View File

@ -18,10 +18,10 @@ import net.corda.nodeapi.VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME
import net.corda.nodeapi.config.NodeSSLConfiguration import net.corda.nodeapi.config.NodeSSLConfiguration
import net.corda.nodeapi.config.getValue import net.corda.nodeapi.config.getValue
import net.corda.nodeapi.internal.addShutdownHook import net.corda.nodeapi.internal.addShutdownHook
import net.corda.nodeapi.serialization.AbstractKryoSerializationScheme import net.corda.nodeapi.internal.serialization.AbstractKryoSerializationScheme
import net.corda.nodeapi.serialization.KRYO_P2P_CONTEXT import net.corda.nodeapi.internal.serialization.KRYO_P2P_CONTEXT
import net.corda.nodeapi.serialization.KryoHeaderV0_1 import net.corda.nodeapi.internal.serialization.KryoHeaderV0_1
import net.corda.nodeapi.serialization.SerializationFactoryImpl import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
import org.apache.activemq.artemis.api.core.client.ActiveMQClient import org.apache.activemq.artemis.api.core.client.ActiveMQClient
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths