mirror of
https://github.com/corda/corda.git
synced 2025-06-17 06:38:21 +00:00
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:
@ -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
|
||||
}
|
||||
|
@ -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":
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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()
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user