mirror of
https://github.com/corda/corda.git
synced 2025-06-05 00:50:52 +00:00
CORDA-2178 Signature constraints minimum platform version checking (#4161)
* Minimum platform version checking for new signature constraints feature. * Fix broken JUnit * NP safety checking on network parameters. * Warning and auto-downgrade of signed states that do not meet the minimum network platform version.
This commit is contained in:
parent
99e9864975
commit
74c80aafd6
@ -20,12 +20,15 @@ import org.slf4j.MDC
|
|||||||
const val PLATFORM_VERSION = 4
|
const val PLATFORM_VERSION = 4
|
||||||
|
|
||||||
fun ServicesForResolution.ensureMinimumPlatformVersion(requiredMinPlatformVersion: Int, feature: String) {
|
fun ServicesForResolution.ensureMinimumPlatformVersion(requiredMinPlatformVersion: Int, feature: String) {
|
||||||
val currentMinPlatformVersion = networkParameters.minimumPlatformVersion
|
checkMinimumPlatformVersion(networkParameters.minimumPlatformVersion, requiredMinPlatformVersion, feature)
|
||||||
if (currentMinPlatformVersion < requiredMinPlatformVersion) {
|
}
|
||||||
|
|
||||||
|
fun checkMinimumPlatformVersion(minimumPlatformVersion: Int, requiredMinPlatformVersion: Int, feature: String) {
|
||||||
|
if (minimumPlatformVersion < requiredMinPlatformVersion) {
|
||||||
throw ZoneVersionTooLowException(
|
throw ZoneVersionTooLowException(
|
||||||
"$feature requires all nodes on the Corda compatibility zone to be running at least platform version " +
|
"$feature requires all nodes on the Corda compatibility zone to be running at least platform version " +
|
||||||
"$requiredMinPlatformVersion. The current zone is only enforcing a minimum platform version of " +
|
"$requiredMinPlatformVersion. The current zone is only enforcing a minimum platform version of " +
|
||||||
"$currentMinPlatformVersion. Please contact your zone operator."
|
"$minimumPlatformVersion. Please contact your zone operator."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.core.crypto.isFulfilledBy
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.AttachmentWithContext
|
import net.corda.core.internal.AttachmentWithContext
|
||||||
import net.corda.core.internal.castIfPossible
|
import net.corda.core.internal.castIfPossible
|
||||||
|
import net.corda.core.internal.checkMinimumPlatformVersion
|
||||||
import net.corda.core.internal.uncheckedCast
|
import net.corda.core.internal.uncheckedCast
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
@ -148,6 +149,8 @@ data class LedgerTransaction @JvmOverloads constructor(
|
|||||||
|
|
||||||
val contractAttachment = uniqueAttachmentsForStateContract.first()
|
val contractAttachment = uniqueAttachmentsForStateContract.first()
|
||||||
val constraintAttachment = AttachmentWithContext(contractAttachment, state.contract, networkParameters?.whitelistedContractImplementations)
|
val constraintAttachment = AttachmentWithContext(contractAttachment, state.contract, networkParameters?.whitelistedContractImplementations)
|
||||||
|
if (state.constraint is SignatureAttachmentConstraint)
|
||||||
|
checkMinimumPlatformVersion(networkParameters?.minimumPlatformVersion ?: 1, 4, "Signature constraints")
|
||||||
if (!state.constraint.isSatisfiedBy(constraintAttachment)) {
|
if (!state.constraint.isSatisfiedBy(constraintAttachment)) {
|
||||||
throw TransactionVerificationException.ContractConstraintRejection(id, state.contract)
|
throw TransactionVerificationException.ContractConstraintRejection(id, state.contract)
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,10 @@ open class TransactionBuilder @JvmOverloads constructor(
|
|||||||
private val inputsWithTransactionState = arrayListOf<TransactionState<ContractState>>()
|
private val inputsWithTransactionState = arrayListOf<TransactionState<ContractState>>()
|
||||||
private val referencesWithTransactionState = arrayListOf<TransactionState<ContractState>>()
|
private val referencesWithTransactionState = arrayListOf<TransactionState<ContractState>>()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val log = contextLogger()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a copy of the builder.
|
* Creates a copy of the builder.
|
||||||
*/
|
*/
|
||||||
@ -165,7 +169,21 @@ open class TransactionBuilder @JvmOverloads constructor(
|
|||||||
|
|
||||||
return when {
|
return when {
|
||||||
attachmentSigners.isEmpty() -> HashAttachmentConstraint(attachmentId)
|
attachmentSigners.isEmpty() -> HashAttachmentConstraint(attachmentId)
|
||||||
else -> makeSignatureAttachmentConstraint(attachmentSigners)
|
else -> {
|
||||||
|
// Auto downgrade: signature constraints only available with a corda network minimum platform version of >= 4
|
||||||
|
if (services.networkParameters.minimumPlatformVersion < 4) {
|
||||||
|
log.warn("Signature constraints not available on network requiring a minimum platform version of ${services.networkParameters.minimumPlatformVersion}")
|
||||||
|
if (useWhitelistedByZoneAttachmentConstraint(state.contract, services.networkParameters)) {
|
||||||
|
log.warn("Reverting back to using whitelisted zone constraints")
|
||||||
|
WhitelistedByZoneAttachmentConstraint
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn("Reverting back to using hash constraints")
|
||||||
|
HashAttachmentConstraint(attachmentId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else makeSignatureAttachmentConstraint(attachmentSigners)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import net.corda.core.crypto.CompositeKey
|
|||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.AbstractAttachment
|
import net.corda.core.internal.AbstractAttachment
|
||||||
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
import net.corda.core.node.ServicesForResolution
|
import net.corda.core.node.ServicesForResolution
|
||||||
import net.corda.core.node.ZoneVersionTooLowException
|
import net.corda.core.node.ZoneVersionTooLowException
|
||||||
import net.corda.core.node.services.AttachmentStorage
|
import net.corda.core.node.services.AttachmentStorage
|
||||||
@ -40,7 +41,7 @@ class TransactionBuilderTest {
|
|||||||
val cordappProvider = rigorousMock<CordappProvider>()
|
val cordappProvider = rigorousMock<CordappProvider>()
|
||||||
doReturn(cordappProvider).whenever(services).cordappProvider
|
doReturn(cordappProvider).whenever(services).cordappProvider
|
||||||
doReturn(contractAttachmentId).whenever(cordappProvider).getContractAttachmentID(DummyContract.PROGRAM_ID)
|
doReturn(contractAttachmentId).whenever(cordappProvider).getContractAttachmentID(DummyContract.PROGRAM_ID)
|
||||||
doReturn(testNetworkParameters()).whenever(services).networkParameters
|
doReturn(testNetworkParameters(minimumPlatformVersion = PLATFORM_VERSION)).whenever(services).networkParameters
|
||||||
|
|
||||||
val attachmentStorage = rigorousMock<AttachmentStorage>()
|
val attachmentStorage = rigorousMock<AttachmentStorage>()
|
||||||
doReturn(attachmentStorage).whenever(services).attachments
|
doReturn(attachmentStorage).whenever(services).attachments
|
||||||
|
@ -88,6 +88,10 @@ and the smoothest to deploy: no restarts or contract upgrade transactions are ne
|
|||||||
When CorDapp is build using :ref:`corda-gradle-plugin <cordapp_build_system_signing_cordapp_jar_ref>` the JAR is signed
|
When CorDapp is build using :ref:`corda-gradle-plugin <cordapp_build_system_signing_cordapp_jar_ref>` the JAR is signed
|
||||||
by Corda development key by default, an external keystore can be configured or signing can be disabled.
|
by Corda development key by default, an external keystore can be configured or signing can be disabled.
|
||||||
|
|
||||||
|
.. warning:: CorDapps can only use signature constraints when participating in a Corda network using a minimum platform version of 4.
|
||||||
|
An auto downgrade rule applies to signed CorDapps built and tested with Corda 4 but running on a Corda network of a lower version:
|
||||||
|
if the associated contract class is whitelisted in the network parameters then zone constraints are applied, otherwise hash constraints are used.
|
||||||
|
|
||||||
**Defaults.** The default constraint type is either a zone constraint, if the network parameters in effect when the
|
**Defaults.** The default constraint type is either a zone constraint, if the network parameters in effect when the
|
||||||
transaction is built contain an entry for that contract class, or a hash constraint if not.
|
transaction is built contain an entry for that contract class, or a hash constraint if not.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user