Merge pull request #5 from corda/composite-key-serializer

This commit is contained in:
Andrius Dagys 2016-12-01 10:17:40 +00:00 committed by GitHub
commit 053dd9a1fe
2 changed files with 49 additions and 4 deletions

View File

@ -31,7 +31,13 @@ sealed class CompositeKey {
/** Checks whether any of the given [keys] matches a leaf on the tree */
fun containsAny(otherKeys: Iterable<PublicKey>) = keys.intersect(otherKeys).isNotEmpty()
// TODO: implement a proper encoding/decoding mechanism
/**
* This is generated by serializing the composite key with Kryo, and encoding the resulting bytes in base58.
* A custom serialization format is being used.
*
* 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).
*/
fun toBase58String(): String = Base58.encode(this.serialize().bytes)
companion object {
@ -124,9 +130,8 @@ sealed class CompositeKey {
* Builds the [CompositeKey.Node]. If [threshold] is not specified, it will default to
* the size of the children, effectively generating an "N of N" requirement.
*/
fun build(threshold: Int? = null): CompositeKey {
return if (children.size == 1) children.first()
else Node(threshold ?: children.size, children.toList(), weights.toList())
fun build(threshold: Int? = null): CompositeKey.Node {
return Node(threshold ?: children.size, children.toList(), weights.toList())
}
}

View File

@ -31,6 +31,7 @@ import java.io.ObjectOutputStream
import java.lang.reflect.InvocationTargetException
import java.nio.file.Files
import java.nio.file.Path
import java.security.PublicKey
import java.time.Instant
import java.util.*
import javax.annotation.concurrent.ThreadSafe
@ -302,6 +303,41 @@ object Ed25519PublicKeySerializer : Serializer<EdDSAPublicKey>() {
}
}
/** For serialising composite keys */
@ThreadSafe
object CompositeKeyLeafSerializer : Serializer<CompositeKey.Leaf>() {
override fun write(kryo: Kryo, output: Output, obj: CompositeKey.Leaf) {
val key = obj.publicKey
kryo.writeClassAndObject(output, key)
}
override fun read(kryo: Kryo, input: Input, type: Class<CompositeKey.Leaf>): CompositeKey.Leaf {
val key = kryo.readClassAndObject(input) as PublicKey
return CompositeKey.Leaf(key)
}
}
@ThreadSafe
object CompositeKeyNodeSerializer : Serializer<CompositeKey.Node>() {
override fun write(kryo: Kryo, output: Output, obj: CompositeKey.Node) {
output.writeInt(obj.threshold)
output.writeInt(obj.children.size)
obj.children.forEach { kryo.writeClassAndObject(output, it) }
output.writeInts(obj.weights.toIntArray())
}
override fun read(kryo: Kryo, input: Input, type: Class<CompositeKey.Node>): CompositeKey.Node {
val threshold = input.readInt()
val childCount = input.readInt()
val children = (1..childCount).map { kryo.readClassAndObject(input) as CompositeKey }
val weights = input.readInts(childCount)
val builder = CompositeKey.Builder()
weights.zip(children).forEach { builder.addKey(it.second, it.first) }
return builder.build(threshold)
}
}
/** Marker interface for kotlin object definitions so that they are deserialized as the singleton instance. */
interface DeserializeAsKotlinObjectDef
@ -344,6 +380,10 @@ fun createKryo(k: Kryo = Kryo()): Kryo {
register(keyPair.private.javaClass, Ed25519PrivateKeySerializer)
register(Instant::class.java, ReferencesAwareJavaSerializer)
// Using a custom serializer for compactness
register(CompositeKey.Node::class.java, CompositeKeyNodeSerializer)
register(CompositeKey.Leaf::class.java, CompositeKeyLeafSerializer)
// Some classes have to be handled with the ImmutableClassSerializer because they need to have their
// constructors be invoked (typically for lazy members).
register(SignedTransaction::class.java, ImmutableClassSerializer(SignedTransaction::class))