mirror of
https://github.com/corda/corda.git
synced 2025-02-20 17:33:15 +00:00
Various cleanups to AMQP and Kryo serialisation:
* PartyAndCertificate serialiser has been converted to deal with just CertPath * Removed X500Name serialiser as we no longer use the BC implementation and have our own CordaX500Name * Converted X509 cert serialiser to use Java certs and not BC X509 cert holder * Added to test to AMQP serialisation to make sure c'tor is invoked on deserialisation
This commit is contained in:
parent
288eb5fcc4
commit
f7e51a9ae1
@ -0,0 +1,13 @@
|
||||
package net.corda.core.contracts
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.junit.Test
|
||||
|
||||
class PrivacySaltTest {
|
||||
@Test
|
||||
fun `all-zero PrivacySalt not allowed`() {
|
||||
assertThatExceptionOfType(IllegalArgumentException::class.java).isThrownBy {
|
||||
PrivacySalt(ByteArray(32))
|
||||
}.withMessage("Privacy salt should not be all zeros.")
|
||||
}
|
||||
}
|
@ -36,7 +36,6 @@ abstract class AbstractAMQPSerializationScheme : SerializationScheme {
|
||||
register(publicKeySerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.PrivateKeySerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.X500NameSerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.BigDecimalSerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.CurrencySerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.OpaqueBytesSubSequenceSerializer(this))
|
||||
@ -54,8 +53,8 @@ abstract class AbstractAMQPSerializationScheme : SerializationScheme {
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.MonthDaySerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.PeriodSerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.ClassSerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateHolderSerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.PartyAndCertificateSerializer(factory))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateSerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.CertPathSerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.StringBufferSerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.SimpleStringSerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.InputStreamSerializer)
|
||||
|
@ -0,0 +1,27 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.io.NotSerializableException
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.CertificateFactory
|
||||
|
||||
class CertPathSerializer(factory: SerializerFactory)
|
||||
: CustomSerializer.Proxy<CertPath, CertPathSerializer.CertPathProxy>(CertPath::class.java, CertPathProxy::class.java, factory) {
|
||||
override fun toProxy(obj: CertPath): CertPathProxy = CertPathProxy(obj.type, obj.encoded)
|
||||
|
||||
override fun fromProxy(proxy: CertPathProxy): CertPath {
|
||||
try {
|
||||
val cf = CertificateFactory.getInstance(proxy.type)
|
||||
return cf.generateCertPath(proxy.encoded.inputStream())
|
||||
} catch (ce: CertificateException) {
|
||||
val nse = NotSerializableException("java.security.cert.CertPath: $type")
|
||||
nse.initCause(ce)
|
||||
throw nse
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ArrayInDataClass")
|
||||
data class CertPathProxy(val type: String, val encoded: ByteArray)
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.NotSerializableException
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.CertificateFactory
|
||||
|
||||
/**
|
||||
* A serializer that writes out a party and certificate in encoded format.
|
||||
*/
|
||||
class PartyAndCertificateSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<PartyAndCertificate, PartyAndCertificateSerializer.PartyAndCertificateProxy>(PartyAndCertificate::class.java, PartyAndCertificateProxy::class.java, factory) {
|
||||
override fun toProxy(obj: PartyAndCertificate): PartyAndCertificateProxy = PartyAndCertificateProxy(obj.certPath.type, obj.certPath.encoded)
|
||||
|
||||
override fun fromProxy(proxy: PartyAndCertificateProxy): PartyAndCertificate {
|
||||
try {
|
||||
val cf = CertificateFactory.getInstance(proxy.type)
|
||||
return PartyAndCertificate(cf.generateCertPath(ByteArrayInputStream(proxy.encoded)))
|
||||
} catch (ce: CertificateException) {
|
||||
val nse = NotSerializableException("java.security.cert.CertPath: " + type)
|
||||
nse.initCause(ce)
|
||||
throw nse
|
||||
}
|
||||
}
|
||||
|
||||
data class PartyAndCertificateProxy(val type: String, val encoded: ByteArray)
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import org.bouncycastle.asn1.ASN1InputStream
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* Custom serializer for X500 names that utilizes their ASN.1 encoding on the wire.
|
||||
*/
|
||||
object X500NameSerializer : CustomSerializer.Implements<X500Name>(X500Name::class.java) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), SerializerFactory.primitiveTypeName(ByteArray::class.java)!!, descriptor, emptyList())))
|
||||
|
||||
override fun writeDescribedObject(obj: X500Name, data: Data, type: Type, output: SerializationOutput) {
|
||||
output.writeObject(obj.encoded, data, clazz)
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): X500Name {
|
||||
val binary = input.readObject(obj, schema, ByteArray::class.java) as ByteArray
|
||||
return X500Name.getInstance(ASN1InputStream(binary).readObject())
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* A serializer that writes out a certificate in X.509 format.
|
||||
*/
|
||||
object X509CertificateHolderSerializer : CustomSerializer.Implements<X509CertificateHolder>(X509CertificateHolder::class.java) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), SerializerFactory.primitiveTypeName(ByteArray::class.java)!!, descriptor, emptyList())))
|
||||
|
||||
override fun writeDescribedObject(obj: X509CertificateHolder, data: Data, type: Type, output: SerializationOutput) {
|
||||
output.writeObject(obj.encoded, data, clazz)
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): X509CertificateHolder {
|
||||
val bits = input.readObject(obj, schema, ByteArray::class.java) as ByteArray
|
||||
return X509CertificateHolder(bits)
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
object X509CertificateSerializer : CustomSerializer.Implements<X509Certificate>(X509Certificate::class.java) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(
|
||||
type.toString(),
|
||||
"",
|
||||
listOf(type.toString()),
|
||||
SerializerFactory.primitiveTypeName(ByteArray::class.java)!!,
|
||||
descriptor,
|
||||
emptyList()
|
||||
)))
|
||||
|
||||
override fun writeDescribedObject(obj: X509Certificate, data: Data, type: Type, output: SerializationOutput) {
|
||||
output.writeObject(obj.encoded, data, clazz)
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): X509Certificate {
|
||||
val bits = input.readObject(obj, schema, ByteArray::class.java) as ByteArray
|
||||
return CertificateFactory.getInstance("X.509").generateCertificate(bits.inputStream()) as X509Certificate
|
||||
}
|
||||
}
|
@ -32,8 +32,6 @@ import net.corda.nodeapi.internal.serialization.GeneratedAttachment
|
||||
import net.corda.nodeapi.internal.serialization.MutableClassWhitelist
|
||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey
|
||||
@ -53,6 +51,7 @@ import java.io.InputStream
|
||||
import java.lang.reflect.Modifier.isPublic
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@ -109,8 +108,7 @@ object DefaultKryoCustomizer {
|
||||
register(FileInputStream::class.java, InputStreamSerializer)
|
||||
register(CertPath::class.java, CertPathSerializer)
|
||||
register(X509CertPath::class.java, CertPathSerializer)
|
||||
register(X500Name::class.java, X500NameSerializer)
|
||||
register(X509CertificateHolder::class.java, X509CertificateSerializer)
|
||||
register(X509Certificate::class.java, X509CertificateSerializer)
|
||||
register(BCECPrivateKey::class.java, PrivateKeySerializer)
|
||||
register(BCECPublicKey::class.java, publicKeySerializer)
|
||||
register(BCRSAPrivateCrtKey::class.java, PrivateKeySerializer)
|
||||
|
@ -15,7 +15,8 @@ import net.corda.core.crypto.TransactionSignature
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationContext.UseCase.*
|
||||
import net.corda.core.serialization.SerializationContext.UseCase.Checkpoint
|
||||
import net.corda.core.serialization.SerializationContext.UseCase.Storage
|
||||
import net.corda.core.serialization.SerializeAsTokenContext
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.toFuture
|
||||
@ -23,9 +24,6 @@ import net.corda.core.toObservable
|
||||
import net.corda.core.transactions.*
|
||||
import net.corda.nodeapi.internal.serialization.CordaClassResolver
|
||||
import net.corda.nodeapi.internal.serialization.serializationContextKey
|
||||
import org.bouncycastle.asn1.ASN1InputStream
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import rx.Observable
|
||||
@ -36,6 +34,7 @@ import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
import kotlin.reflect.KClass
|
||||
@ -471,46 +470,28 @@ object ClassSerializer : Serializer<Class<*>>() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For serialising an [X500Name] without touching Sun internal classes.
|
||||
*/
|
||||
@ThreadSafe
|
||||
object X500NameSerializer : Serializer<X500Name>() {
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<X500Name>): X500Name {
|
||||
return X500Name.getInstance(ASN1InputStream(input.readBytes()).readObject())
|
||||
}
|
||||
|
||||
override fun write(kryo: Kryo, output: Output, obj: X500Name) {
|
||||
output.writeBytes(obj.encoded)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For serialising an [CertPath] in an X.500 standard format.
|
||||
*/
|
||||
@ThreadSafe
|
||||
object CertPathSerializer : Serializer<CertPath>() {
|
||||
val factory: CertificateFactory = CertificateFactory.getInstance("X.509")
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<CertPath>): CertPath {
|
||||
return factory.generateCertPath(input)
|
||||
val factory = CertificateFactory.getInstance(input.readString())
|
||||
return factory.generateCertPath(input.readBytesWithLength().inputStream())
|
||||
}
|
||||
|
||||
override fun write(kryo: Kryo, output: Output, obj: CertPath) {
|
||||
output.writeBytes(obj.encoded)
|
||||
output.writeString(obj.type)
|
||||
output.writeBytesWithLength(obj.encoded)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For serialising an [X509CertificateHolder] in an X.500 standard format.
|
||||
*/
|
||||
@ThreadSafe
|
||||
object X509CertificateSerializer : Serializer<X509CertificateHolder>() {
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<X509CertificateHolder>): X509CertificateHolder {
|
||||
return X509CertificateHolder(input.readBytes())
|
||||
object X509CertificateSerializer : Serializer<X509Certificate>() {
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<X509Certificate>): X509Certificate {
|
||||
val factory = CertificateFactory.getInstance("X.509")
|
||||
return factory.generateCertificate(input.readBytesWithLength().inputStream()) as X509Certificate
|
||||
}
|
||||
|
||||
override fun write(kryo: Kryo, output: Output, obj: X509CertificateHolder) {
|
||||
output.writeBytes(obj.encoded)
|
||||
override fun write(kryo: Kryo, output: Output, obj: X509Certificate) {
|
||||
output.writeBytesWithLength(obj.encoded)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,14 @@ import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExpectedException
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStream
|
||||
import java.time.Instant
|
||||
import java.util.Collections
|
||||
import kotlin.test.*
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class KryoTests {
|
||||
@Rule
|
||||
@ -36,9 +37,6 @@ class KryoTests {
|
||||
private lateinit var factory: SerializationFactory
|
||||
private lateinit var context: SerializationContext
|
||||
|
||||
@get:Rule
|
||||
val expectedEx: ExpectedException = ExpectedException.none()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme()) }
|
||||
@ -51,7 +49,7 @@ class KryoTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ok() {
|
||||
fun `simple data class`() {
|
||||
val birthday = Instant.parse("1984-04-17T00:30:00.00Z")
|
||||
val mike = Person("mike", birthday)
|
||||
val bits = mike.serialize(factory, context)
|
||||
@ -59,7 +57,7 @@ class KryoTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nullables() {
|
||||
fun `null values`() {
|
||||
val bob = Person("bob", null)
|
||||
val bits = bob.serialize(factory, context)
|
||||
assertThat(bits.deserialize(factory, context)).isEqualTo(Person("bob", null))
|
||||
@ -202,13 +200,6 @@ class KryoTests {
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `all-zero PrivacySalt not allowed`() {
|
||||
expectedEx.expect(IllegalArgumentException::class.java)
|
||||
expectedEx.expectMessage("Privacy salt should not be all zeros.")
|
||||
PrivacySalt(ByteArray(32))
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
private object TestSingleton
|
||||
|
||||
|
@ -2,16 +2,16 @@ package net.corda.nodeapi.internal.serialization
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
import com.esotericsoftware.kryo.util.DefaultClassResolver
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.node.services.statemachine.SessionData
|
||||
import net.corda.nodeapi.internal.serialization.kryo.KryoHeaderV0_1
|
||||
import net.corda.testing.SerializationEnvironmentRule
|
||||
import net.corda.testing.amqpSpecific
|
||||
import net.corda.testing.kryoSpecific
|
||||
import net.corda.testing.SerializationEnvironmentRule
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -53,7 +53,7 @@ class MapsSerializationTest {
|
||||
fun `check throws for forbidden declared type`() = amqpSpecific("Such exceptions are not expected in Kryo mode.") {
|
||||
val payload = HashMap<String, String>(smallMap)
|
||||
val wrongPayloadType = WrongPayloadType(payload)
|
||||
Assertions.assertThatThrownBy { wrongPayloadType.serialize() }
|
||||
assertThatThrownBy { wrongPayloadType.serialize() }
|
||||
.isInstanceOf(IllegalArgumentException::class.java).hasMessageContaining(
|
||||
"Map type class java.util.HashMap is unstable under iteration. Suggested fix: use java.util.LinkedHashMap instead.")
|
||||
}
|
||||
@ -62,27 +62,29 @@ class MapsSerializationTest {
|
||||
data class MyKey(val keyContent: Double)
|
||||
|
||||
@CordaSerializable
|
||||
data class MyValue(val valueContent: X500Name)
|
||||
data class MyValue(val valueContent: CordaX500Name)
|
||||
|
||||
@Test
|
||||
fun `check map serialization works with custom types`() {
|
||||
val myMap = mapOf(
|
||||
MyKey(1.0) to MyValue(X500Name("CN=one")),
|
||||
MyKey(10.0) to MyValue(X500Name("CN=ten")))
|
||||
MyKey(1.0) to MyValue(CordaX500Name("OOO", "LLL", "CC")),
|
||||
MyKey(10.0) to MyValue(CordaX500Name("OO", "LL", "CC")))
|
||||
assertEqualAfterRoundTripSerialization(myMap)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check empty map serialises as Java emptyMap`() = kryoSpecific("Specifically checks Kryo serialization") {
|
||||
val nameID = 0
|
||||
val serializedForm = emptyMap<Int, Int>().serialize()
|
||||
val output = ByteArrayOutputStream().apply {
|
||||
write(KryoHeaderV0_1.bytes)
|
||||
write(DefaultClassResolver.NAME + 2)
|
||||
write(nameID)
|
||||
write(javaEmptyMapClass.name.toAscii())
|
||||
write(Kryo.NOT_NULL.toInt())
|
||||
fun `check empty map serialises as Java emptyMap`() {
|
||||
kryoSpecific("Specifically checks Kryo serialization") {
|
||||
val nameID = 0
|
||||
val serializedForm = emptyMap<Int, Int>().serialize()
|
||||
val output = ByteArrayOutputStream().apply {
|
||||
write(KryoHeaderV0_1.bytes)
|
||||
write(DefaultClassResolver.NAME + 2)
|
||||
write(nameID)
|
||||
write(javaEmptyMapClass.name.toAscii())
|
||||
write(Kryo.NOT_NULL.toInt())
|
||||
}
|
||||
assertArrayEquals(output.toByteArray(), serializedForm.bytes)
|
||||
}
|
||||
assertArrayEquals(output.toByteArray(), serializedForm.bytes)
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,20 @@
|
||||
@file:Suppress("unused", "MemberVisibilityCanPrivate")
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.client.rpc.RPCException
|
||||
import net.corda.core.CordaRuntimeException
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.secureRandomBytes
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.internal.toX509CertHolder
|
||||
import net.corda.core.internal.AbstractAttachment
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.MissingAttachmentsException
|
||||
import net.corda.core.serialization.SerializationFactory
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.client.rpc.RPCException
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.internal.AbstractAttachment
|
||||
import net.corda.core.serialization.MissingAttachmentsException
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
||||
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
|
||||
import net.corda.nodeapi.internal.serialization.GeneratedAttachment
|
||||
@ -25,10 +28,8 @@ import org.apache.activemq.artemis.api.core.SimpleString
|
||||
import org.apache.qpid.proton.amqp.*
|
||||
import org.apache.qpid.proton.codec.DecoderImpl
|
||||
import org.apache.qpid.proton.codec.EncoderImpl
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import org.junit.Assert.assertNotSame
|
||||
import org.junit.Assert.assertSame
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.assertj.core.api.Assertions.*
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.io.ByteArrayInputStream
|
||||
@ -39,10 +40,7 @@ import java.nio.ByteBuffer
|
||||
import java.time.*
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.*
|
||||
import kotlin.reflect.full.declaredFunctions
|
||||
import kotlin.reflect.full.declaredMemberFunctions
|
||||
import kotlin.reflect.full.superclasses
|
||||
import kotlin.reflect.jvm.javaMethod
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
@ -79,7 +77,6 @@ class SerializationOutputTests {
|
||||
}
|
||||
|
||||
data class Woo(val fred: Int) {
|
||||
@Suppress("unused")
|
||||
val bob = "Bob"
|
||||
}
|
||||
|
||||
@ -89,7 +86,6 @@ class SerializationOutputTests {
|
||||
|
||||
@CordaSerializable
|
||||
data class AnnotatedWoo(val fred: Int) {
|
||||
@Suppress("unused")
|
||||
val bob = "Bob"
|
||||
}
|
||||
|
||||
@ -151,6 +147,13 @@ class SerializationOutputTests {
|
||||
|
||||
data class PolymorphicProperty(val foo: FooInterface?)
|
||||
|
||||
@CordaSerializable
|
||||
class NonZeroByte(val value: Byte) {
|
||||
init {
|
||||
require(value.toInt() != 0) { "Zero not allowed" }
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : Any> serdes(obj: T,
|
||||
factory: SerializerFactory = SerializerFactory(
|
||||
AllWhitelist, ClassLoader.getSystemClassLoader()),
|
||||
@ -406,6 +409,32 @@ class SerializationOutputTests {
|
||||
serdes(obj)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `class constructor is invoked on deserialisation`() {
|
||||
val ser = SerializationOutput(SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()))
|
||||
val des = DeserializationInput(ser.serializerFactory)
|
||||
|
||||
val serialisedOne = ser.serialize(NonZeroByte(1)).bytes
|
||||
val serialisedTwo = ser.serialize(NonZeroByte(2)).bytes
|
||||
|
||||
// Find the index that holds the value byte
|
||||
val valueIndex = serialisedOne.zip(serialisedTwo).mapIndexedNotNull { index, (oneByte, twoByte) ->
|
||||
if (oneByte.toInt() == 1 && twoByte.toInt() == 2) index else null
|
||||
}.single()
|
||||
|
||||
val copy = serialisedTwo.clone()
|
||||
|
||||
// Double check
|
||||
copy[valueIndex] = 0x03
|
||||
assertThat(des.deserialize(OpaqueBytes(copy), NonZeroByte::class.java).value).isEqualTo(3)
|
||||
|
||||
// Now use the forbidden value
|
||||
copy[valueIndex] = 0x00
|
||||
assertThatExceptionOfType(NotSerializableException::class.java).isThrownBy {
|
||||
des.deserialize(OpaqueBytes(copy), NonZeroByte::class.java)
|
||||
}.withMessageContaining("Zero not allowed")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test custom serializers on public key`() {
|
||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
@ -762,26 +791,32 @@ class SerializationOutputTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test certificate holder serialize`() {
|
||||
fun `test privacy salt serialize`() {
|
||||
serdes(PrivacySalt())
|
||||
serdes(PrivacySalt(secureRandomBytes(32)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test X509 certificate serialize`() {
|
||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateHolderSerializer)
|
||||
factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateSerializer)
|
||||
|
||||
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateHolderSerializer)
|
||||
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateSerializer)
|
||||
|
||||
val obj = BOB_IDENTITY.certificate.toX509CertHolder()
|
||||
val obj = BOB_IDENTITY.certificate
|
||||
serdes(obj, factory, factory2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test party and certificate serialize`() {
|
||||
fun `test cert path serialize`() {
|
||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.PartyAndCertificateSerializer(factory))
|
||||
factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.CertPathSerializer(factory))
|
||||
|
||||
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.PartyAndCertificateSerializer(factory2))
|
||||
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.CertPathSerializer(factory2))
|
||||
|
||||
val obj = BOB_IDENTITY
|
||||
val obj = BOB_IDENTITY.certPath
|
||||
serdes(obj, factory, factory2)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user