CORDA-961 Wire up and enforce max transaction size (#2465)

* wire up and enforce max transaction size

* fixup after rebase
moved network parameter from AbstractNode to NodeProperties

* removed TODO

* fix broken import

* address PR issues

* remove API breaking change
address PR issue

* added max transaction size to driver and mock network.
address PR issues

* fix failing test

* added TODO

* fix verifier test

* fix spring driver build error
This commit is contained in:
Patrick Kuo
2018-02-09 14:48:45 +00:00
committed by GitHub
parent 1902a4f11e
commit c8cf46c657
23 changed files with 251 additions and 35 deletions

View File

@ -50,4 +50,9 @@ interface Attachment : NamedByHash {
* Can be empty, for example non-contract attachments won't be necessarily be signed.
*/
val signers: List<Party>
/**
* Attachment size in bytes.
*/
val size: Int
}

View File

@ -27,6 +27,10 @@ abstract class AbstractAttachment(dataLoader: () -> ByteArray) : Attachment {
}
protected val attachmentData: ByteArray by lazy(dataLoader)
// TODO: read file size information from metadata instead of loading the data.
override val size: Int get() = attachmentData.size
override fun open(): InputStream = attachmentData.inputStream()
override val signers by lazy {
// Can't start with empty set if we're doing intersections. Logically the null means "all possible signers":

View File

@ -0,0 +1,14 @@
package net.corda.core.internal
import net.corda.core.node.NetworkParameters
// TODO: This will cause problems when we run tests in parallel, make each node have its own properties.
object GlobalProperties {
private var _networkParameters: NetworkParameters? = null
var networkParameters: NetworkParameters
get() = checkNotNull(_networkParameters) { "Property 'networkParameters' has not been initialised." }
set(value) {
_networkParameters = value
}
}

View File

@ -17,7 +17,6 @@ import java.time.Instant
*/
// TODO Add eventHorizon - how many days a node can be offline before being automatically ejected from the network.
// It needs separate design.
// TODO Currently maxTransactionSize is not wired.
@CordaSerializable
data class NetworkParameters(
val minimumPlatformVersion: Int,

View File

@ -5,6 +5,7 @@ import net.corda.core.contracts.ComponentGroupEnum.*
import net.corda.core.crypto.*
import net.corda.core.identity.Party
import net.corda.core.internal.Emoji
import net.corda.core.internal.GlobalProperties
import net.corda.core.node.ServicesForResolution
import net.corda.core.node.services.AttachmentId
import net.corda.core.serialization.CordaSerializable
@ -118,7 +119,24 @@ class WireTransaction(componentGroups: List<ComponentGroup>, val privacySalt: Pr
val contractAttachments = findAttachmentContracts(resolvedInputs, resolveContractAttachment, resolveAttachment)
// Order of attachments is important since contracts may refer to indexes so only append automatic attachments
val attachments = (attachments.map { resolveAttachment(it) ?: throw AttachmentResolutionException(it) } + contractAttachments).distinct()
return LedgerTransaction(resolvedInputs, outputs, authenticatedArgs, attachments, id, notary, timeWindow, privacySalt)
val ltx = LedgerTransaction(resolvedInputs, outputs, authenticatedArgs, attachments, id, notary, timeWindow, privacySalt)
checkTransactionSize(ltx)
return ltx
}
private fun checkTransactionSize(ltx: LedgerTransaction) {
var remainingTransactionSize = GlobalProperties.networkParameters.maxTransactionSize
fun minus(size: Int) {
require(remainingTransactionSize > size) { "Transaction exceeded network's maximum transaction size limit : ${GlobalProperties.networkParameters.maxTransactionSize} bytes." }
remainingTransactionSize -= size
}
// Check attachment size first as they are most likely to go over the limit.
ltx.attachments.forEach { minus(it.size) }
minus(ltx.inputs.serialize().size)
minus(ltx.commands.serialize().size)
minus(ltx.outputs.serialize().size)
}
/**

View File

@ -31,6 +31,7 @@ class AttachmentTest {
override val id get() = throw UnsupportedOperationException()
override fun open() = inputStream
override val signers get() = throw UnsupportedOperationException()
override val size: Int = 512
}
try {
attachment.openAsJAR()

View File

@ -114,6 +114,7 @@ class AttachmentSerializationTest {
private class CustomAttachment(override val id: SecureHash, internal val customContent: String) : Attachment {
override fun open() = throw UnsupportedOperationException("Not implemented.")
override val signers get() = throw UnsupportedOperationException()
override val size get() = throw UnsupportedOperationException()
}
private class CustomAttachmentLogic(serverIdentity: Party, private val attachmentId: SecureHash, private val customContent: String) : ClientLogic(serverIdentity) {