In checkpoints, serialize hash of attachment instead of its data (#543)

This commit is contained in:
Andrzej Cichocki
2017-04-28 13:50:47 +01:00
committed by GitHub
parent e75a24937d
commit cb3522588f
10 changed files with 293 additions and 74 deletions

View File

@ -3,6 +3,7 @@ package net.corda.node.serialization
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SingletonSerializationToken
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
import java.time.Clock
import java.time.Instant
import java.time.ZoneId
@ -15,9 +16,9 @@ import javax.annotation.concurrent.ThreadSafe
@ThreadSafe
class NodeClock(private val delegateClock: Clock = Clock.systemUTC()) : Clock(), SerializeAsToken {
private val token = SingletonSerializationToken(this)
private val token = singletonSerializationToken(javaClass)
override fun toToken(context: SerializeAsTokenContext) = SingletonSerializationToken.registerWithContext(token, this, context)
override fun toToken(context: SerializeAsTokenContext) = token.registerWithContext(context, this)
override fun instant(): Instant {
return delegateClock.instant()

View File

@ -5,6 +5,7 @@ import com.google.common.annotations.VisibleForTesting
import com.google.common.hash.Hashing
import com.google.common.hash.HashingInputStream
import com.google.common.io.CountingInputStream
import net.corda.core.contracts.AbstractAttachment
import net.corda.core.contracts.Attachment
import net.corda.core.createDirectory
import net.corda.core.crypto.SecureHash
@ -13,6 +14,9 @@ import net.corda.core.extractZipFile
import net.corda.core.isDirectory
import net.corda.core.node.services.AttachmentStorage
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializationToken
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.utilities.loggerFor
import net.corda.node.services.api.AcceptsFileUpload
import net.corda.node.services.database.RequeryConfiguration
@ -82,38 +86,31 @@ class NodeAttachmentService(override var storePath: Path, dataSourceProperties:
}
}
private class AttachmentImpl(override val id: SecureHash,
private val attachment: ByteArray,
private val checkOnLoad: Boolean) : Attachment {
private class AttachmentImpl(override val id: SecureHash, dataLoader: () -> ByteArray, private val checkOnLoad: Boolean) : AbstractAttachment(dataLoader), SerializeAsToken {
override fun open(): InputStream {
val stream = ByteArrayInputStream(attachment)
val stream = super.open()
// This is just an optional safety check. If it slows things down too much it can be disabled.
if (id is SecureHash.SHA256 && checkOnLoad)
return HashCheckingStream(id, attachment.size, stream)
return stream
return if (checkOnLoad && id is SecureHash.SHA256) HashCheckingStream(id, attachmentData.size, stream) else stream
}
override fun equals(other: Any?) = other is Attachment && other.id == id
override fun hashCode(): Int = id.hashCode()
private class Token(private val id: SecureHash, private val checkOnLoad: Boolean) : SerializationToken {
override fun fromToken(context: SerializeAsTokenContext) = AttachmentImpl(id, context.attachmentDataLoader(id), checkOnLoad)
}
override fun toToken(context: SerializeAsTokenContext) = Token(id, checkOnLoad)
}
override fun openAttachment(id: SecureHash): Attachment? {
val attachment = session.withTransaction {
try {
session.select(AttachmentEntity::class)
.where(AttachmentEntity.ATT_ID.eq(id))
.get()
.single()
} catch (e: NoSuchElementException) {
null
}
} ?: return null
return AttachmentImpl(id, attachment.content, checkAttachmentsOnLoad)
}
override fun openAttachment(id: SecureHash): Attachment? = session.withTransaction {
try {
session.select(AttachmentEntity::class)
.where(AttachmentEntity.ATT_ID.eq(id))
.get()
.single()
} catch (e: NoSuchElementException) {
null
}
}?.run { AttachmentImpl(id, { content }, checkAttachmentsOnLoad) }
// TODO: PLT-147: The attachment should be randomised to prevent brute force guessing and thus privacy leaks.
override fun importAttachment(jar: InputStream): SecureHash {

View File

@ -151,7 +151,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
private val recentlyClosedSessions = ConcurrentHashMap<Long, Party>()
// Context for tokenized services in checkpoints
private val serializationContext = SerializeAsTokenContext(tokenizableServices, quasarKryo())
private val serializationContext = SerializeAsTokenContext(tokenizableServices, quasarKryo(), serviceHub)
/** Returns a list of all state machines executing the given flow logic at the top level (subflows do not count) */
fun <P : FlowLogic<T>, T> findStateMachines(flowClass: Class<P>): List<Pair<P, ListenableFuture<T>>> {

View File

@ -3,6 +3,7 @@ package net.corda.node.utilities
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SingletonSerializationToken
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
import java.time.*
import javax.annotation.concurrent.ThreadSafe
@ -12,9 +13,9 @@ import javax.annotation.concurrent.ThreadSafe
@ThreadSafe
class TestClock(private var delegateClock: Clock = Clock.systemUTC()) : MutableClock(), SerializeAsToken {
private val token = SingletonSerializationToken(this)
private val token = singletonSerializationToken(javaClass)
override fun toToken(context: SerializeAsTokenContext) = SingletonSerializationToken.registerWithContext(token, this, context)
override fun toToken(context: SerializeAsTokenContext) = token.registerWithContext(context, this)
@Synchronized fun updateDate(date: LocalDate): Boolean {
val currentDate = LocalDate.now(this)