mirror of
https://github.com/corda/corda.git
synced 2025-05-04 17:53:05 +00:00
Backport contract key rotation to 4.9.
This commit is contained in:
parent
282ee95188
commit
828066a646
@ -77,6 +77,9 @@ def patchCore = tasks.register('patchCore', Zip) {
|
|||||||
exclude 'net/corda/core/serialization/internal/AttachmentsHolderImpl.class'
|
exclude 'net/corda/core/serialization/internal/AttachmentsHolderImpl.class'
|
||||||
exclude 'net/corda/core/serialization/internal/CheckpointSerializationFactory*.class'
|
exclude 'net/corda/core/serialization/internal/CheckpointSerializationFactory*.class'
|
||||||
exclude 'net/corda/core/internal/rules/*.class'
|
exclude 'net/corda/core/internal/rules/*.class'
|
||||||
|
exclude 'net/corda/core/contracts/CordaRotatedKeys.class'
|
||||||
|
exclude 'net/corda/core/contracts/RotatedKeysKt.class'
|
||||||
|
exclude 'net/corda/core/contracts/RotatedKeys.class'
|
||||||
}
|
}
|
||||||
|
|
||||||
reproducibleFileOrder = true
|
reproducibleFileOrder = true
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.sha256
|
import net.corda.core.crypto.sha256
|
||||||
import net.corda.core.internal.hash
|
import net.corda.core.internal.hash
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.ConcurrentMap
|
import java.util.concurrent.ConcurrentMap
|
||||||
|
|
||||||
@DeleteForDJVM
|
|
||||||
object CordaRotatedKeys {
|
object CordaRotatedKeys {
|
||||||
val keys = RotatedKeys()
|
val keys = RotatedKeys()
|
||||||
}
|
}
|
||||||
@ -47,8 +43,7 @@ private val CORDA_SIGNING_KEY_ROTATIONS = listOf(
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@DeleteForDJVM
|
data class RotatedKeys(val rotatedSigningKeys: List<List<SecureHash>> = emptyList()) {
|
||||||
data class RotatedKeys(val rotatedSigningKeys: List<List<SecureHash>> = emptyList()): SingletonSerializeAsToken() {
|
|
||||||
private val canBeTransitionedMap: ConcurrentMap<Pair<PublicKey, PublicKey>, Boolean> = ConcurrentHashMap()
|
private val canBeTransitionedMap: ConcurrentMap<Pair<PublicKey, PublicKey>, Boolean> = ConcurrentHashMap()
|
||||||
private val rotateMap: Map<SecureHash, SecureHash> = HashMap<SecureHash, SecureHash>().apply {
|
private val rotateMap: Map<SecureHash, SecureHash> = HashMap<SecureHash, SecureHash>().apply {
|
||||||
(rotatedSigningKeys + CORDA_SIGNING_KEY_ROTATIONS).forEach { rotatedKeyList ->
|
(rotatedSigningKeys + CORDA_SIGNING_KEY_ROTATIONS).forEach { rotatedKeyList ->
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.coretests.contracts
|
package net.corda.coretests.contracts
|
||||||
|
|
||||||
<
|
|
||||||
import com.nhaarman.mockito_kotlin.doReturn
|
import com.nhaarman.mockito_kotlin.doReturn
|
||||||
import com.nhaarman.mockito_kotlin.mock
|
import com.nhaarman.mockito_kotlin.mock
|
||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
package net.corda.coretests.transactions
|
package net.corda.coretests.transactions
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry
|
import com.codahale.metrics.MetricRegistry
|
||||||
|
import com.nhaarman.mockito_kotlin.doReturn
|
||||||
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import net.corda.core.contracts.TransactionVerificationException
|
import net.corda.core.contracts.TransactionVerificationException
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.internal.AttachmentTrustCalculator
|
import net.corda.core.internal.AttachmentTrustCalculator
|
||||||
import net.corda.core.internal.hash
|
import net.corda.core.internal.hash
|
||||||
import net.corda.core.internal.verification.NodeVerificationSupport
|
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
|
import net.corda.core.node.ServicesForResolution
|
||||||
import net.corda.core.node.services.AttachmentId
|
import net.corda.core.node.services.AttachmentId
|
||||||
import net.corda.core.serialization.internal.AttachmentsClassLoader
|
import net.corda.core.serialization.internal.AttachmentsClassLoader
|
||||||
import net.corda.coretesting.internal.rigorousMock
|
import net.corda.coretesting.internal.rigorousMock
|
||||||
import net.corda.node.services.attachments.NodeAttachmentTrustCalculator
|
import net.corda.node.services.attachments.NodeAttachmentTrustCalculator
|
||||||
import net.corda.node.services.persistence.NodeAttachmentService
|
import net.corda.node.services.persistence.NodeAttachmentService
|
||||||
import net.corda.node.services.persistence.toInternal
|
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
@ -30,8 +31,6 @@ import net.corda.testing.node.MockServices
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.kotlin.doReturn
|
|
||||||
import org.mockito.kotlin.whenever
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
@ -49,12 +48,11 @@ class AttachmentsClassLoaderWithStoragePersistenceTests {
|
|||||||
|
|
||||||
private lateinit var database: CordaPersistence
|
private lateinit var database: CordaPersistence
|
||||||
private lateinit var storage: NodeAttachmentService
|
private lateinit var storage: NodeAttachmentService
|
||||||
private lateinit var attachmentTrustCalculator: AttachmentTrustCalculator
|
|
||||||
private lateinit var attachmentTrustCalculator2: AttachmentTrustCalculator
|
private lateinit var attachmentTrustCalculator2: AttachmentTrustCalculator
|
||||||
private val networkParameters = testNetworkParameters()
|
private val networkParameters = testNetworkParameters()
|
||||||
private val cacheFactory = TestingNamedCacheFactory(1)
|
private val cacheFactory = TestingNamedCacheFactory(1)
|
||||||
private val cacheFactory2 = TestingNamedCacheFactory()
|
private val cacheFactory2 = TestingNamedCacheFactory()
|
||||||
private val nodeVerificationSupport = rigorousMock<NodeVerificationSupport>().also {
|
private val services = rigorousMock<ServicesForResolution>().also {
|
||||||
doReturn(testNetworkParameters()).whenever(it).networkParameters
|
doReturn(testNetworkParameters()).whenever(it).networkParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +84,7 @@ class AttachmentsClassLoaderWithStoragePersistenceTests {
|
|||||||
it.start()
|
it.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
storage.nodeVerificationSupport = nodeVerificationSupport
|
storage.servicesForResolution = services
|
||||||
attachmentTrustCalculator = NodeAttachmentTrustCalculator(storage.toInternal(), cacheFactory)
|
|
||||||
attachmentTrustCalculator2 = NodeAttachmentTrustCalculator(storage, database, cacheFactory2)
|
attachmentTrustCalculator2 = NodeAttachmentTrustCalculator(storage, database, cacheFactory2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.node.services
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.sha256
|
import net.corda.core.crypto.sha256
|
||||||
@ -45,7 +44,6 @@ private val CORDA_SIGNING_KEY_ROTATIONS = listOf(
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
data class RotatedKeys(val rotatedSigningKeys: List<List<SecureHash>> = emptyList()): SingletonSerializeAsToken() {
|
data class RotatedKeys(val rotatedSigningKeys: List<List<SecureHash>> = emptyList()): SingletonSerializeAsToken() {
|
||||||
private val canBeTransitionedMap: ConcurrentMap<Pair<PublicKey, PublicKey>, Boolean> = ConcurrentHashMap()
|
private val canBeTransitionedMap: ConcurrentMap<Pair<PublicKey, PublicKey>, Boolean> = ConcurrentHashMap()
|
||||||
private val rotateMap: Map<SecureHash, SecureHash> = HashMap<SecureHash, SecureHash>().apply {
|
private val rotateMap: Map<SecureHash, SecureHash> = HashMap<SecureHash, SecureHash>().apply {
|
||||||
|
@ -3,6 +3,7 @@ package net.corda.core.internal
|
|||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.keys
|
import net.corda.core.crypto.keys
|
||||||
import net.corda.core.internal.cordapp.CordappImpl
|
import net.corda.core.internal.cordapp.CordappImpl
|
||||||
|
import net.corda.core.contracts.RotatedKeys
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,6 +90,7 @@ abstract class AbstractVerifier(
|
|||||||
/**
|
/**
|
||||||
* Because we create a separate [LedgerTransaction] onto which we need to perform verification, it becomes important we don't verify the
|
* Because we create a separate [LedgerTransaction] onto which we need to perform verification, it becomes important we don't verify the
|
||||||
* wrong object instance. This class helps
|
* wrong object instance. This class helps
|
||||||
|
*/
|
||||||
private class Validator(private val ltx: LedgerTransaction, private val transactionClassLoader: ClassLoader, private val rotatedKeys: RotatedKeys) {
|
private class Validator(private val ltx: LedgerTransaction, private val transactionClassLoader: ClassLoader, private val rotatedKeys: RotatedKeys) {
|
||||||
private val inputStates: List<TransactionState<*>> = ltx.inputs.map(StateAndRef<ContractState>::state)
|
private val inputStates: List<TransactionState<*>> = ltx.inputs.map(StateAndRef<ContractState>::state)
|
||||||
private val allStates: List<TransactionState<*>> = inputStates + ltx.references.map(StateAndRef<ContractState>::state) + ltx.outputs
|
private val allStates: List<TransactionState<*>> = inputStates + ltx.references.map(StateAndRef<ContractState>::state) + ltx.outputs
|
||||||
@ -438,7 +439,7 @@ private class Validator(private val ltx: LedgerTransaction, private val transact
|
|||||||
private fun verifyConstraintUsingRotatedKeys(constraint: AttachmentConstraint, constraintAttachment: AttachmentWithContext, contract: ContractClassName ) {
|
private fun verifyConstraintUsingRotatedKeys(constraint: AttachmentConstraint, constraintAttachment: AttachmentWithContext, contract: ContractClassName ) {
|
||||||
// constraint could be an input constraint so we manually have to rotate to updated constraint
|
// constraint could be an input constraint so we manually have to rotate to updated constraint
|
||||||
if (constraint is SignatureAttachmentConstraint && rotatedKeys.canBeTransitioned(constraint.key, constraintAttachment.signerKeys)) {
|
if (constraint is SignatureAttachmentConstraint && rotatedKeys.canBeTransitioned(constraint.key, constraintAttachment.signerKeys)) {
|
||||||
val constraintWithRotatedKeys = SignatureAttachmentConstraint.create(CompositeKey.Builder().addKeys(constraintAttachment.signerKeys).build())
|
val constraintWithRotatedKeys = SignatureAttachmentConstraint(CompositeKey.Builder().addKeys(constraintAttachment.signerKeys).build())
|
||||||
if (!constraintWithRotatedKeys.isSatisfiedBy(constraintAttachment)) throw ContractConstraintRejection(ltx.id, contract)
|
if (!constraintWithRotatedKeys.isSatisfiedBy(constraintAttachment)) throw ContractConstraintRejection(ltx.id, contract)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -171,6 +171,12 @@ interface ServiceHub : ServicesForResolution {
|
|||||||
*/
|
*/
|
||||||
val transactionVerifierService: TransactionVerifierService
|
val transactionVerifierService: TransactionVerifierService
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL. DO NOT USE.
|
||||||
|
* @suppress
|
||||||
|
*/
|
||||||
|
val rotatedKeys: RotatedKeys
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [Clock] representing the node's current time. This should be used in preference to directly accessing the
|
* A [Clock] representing the node's current time. This should be used in preference to directly accessing the
|
||||||
* clock so the current time can be controlled during unit testing.
|
* clock so the current time can be controlled during unit testing.
|
||||||
|
@ -2,7 +2,6 @@ package net.corda.core.serialization.internal
|
|||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache
|
import com.github.benmanes.caffeine.cache.Cache
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine
|
import com.github.benmanes.caffeine.cache.Caffeine
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.contracts.Attachment
|
import net.corda.core.contracts.Attachment
|
||||||
import net.corda.core.contracts.ContractAttachment
|
import net.corda.core.contracts.ContractAttachment
|
||||||
import net.corda.core.contracts.CordaRotatedKeys
|
import net.corda.core.contracts.CordaRotatedKeys
|
||||||
@ -359,7 +358,7 @@ object AttachmentsClassLoaderBuilder {
|
|||||||
|
|
||||||
val cache = if (attachmentsClassLoaderCache is AttachmentsClassLoaderForRotatedKeysOnlyImpl) fallBackCache else
|
val cache = if (attachmentsClassLoaderCache is AttachmentsClassLoaderForRotatedKeysOnlyImpl) fallBackCache else
|
||||||
attachmentsClassLoaderCache ?: fallBackCache
|
attachmentsClassLoaderCache ?: fallBackCache
|
||||||
val cachedSerializationContext = cache.computeIfAbsent(AttachmentsClassLoaderKey(attachmentIds, params)), Function { key ->
|
val cachedSerializationContext = cache.computeIfAbsent(AttachmentsClassLoaderKey(attachmentIds, params), Function { key ->
|
||||||
// Create classloader and load serializers, whitelisted classes
|
// Create classloader and load serializers, whitelisted classes
|
||||||
val transactionClassLoader = AttachmentsClassLoader(attachments, key.params, txId, isAttachmentTrusted, parent)
|
val transactionClassLoader = AttachmentsClassLoader(attachments, key.params, txId, isAttachmentTrusted, parent)
|
||||||
val serializers = try {
|
val serializers = try {
|
||||||
@ -539,7 +538,7 @@ class AttachmentsClassLoaderSimpleCacheImpl(cacheSize: Int, override val rotated
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AttachmentsClassLoaderForRotatedKeysOnlyImpl(override val rotatedKeys: RotatedKeys = CordaRotatedKeys.keys) : AttachmentsClassLoaderCache {
|
class AttachmentsClassLoaderForRotatedKeysOnlyImpl(override val rotatedKeys: RotatedKeys = CordaRotatedKeys.keys) : AttachmentsClassLoaderCache {
|
||||||
override fun computeIfAbsent(key: AttachmentsClassLoaderKey, mappingFunction: (AttachmentsClassLoaderKey) -> SerializationContext): SerializationContext {
|
override fun computeIfAbsent(key: AttachmentsClassLoaderKey, mappingFunction: Function<in AttachmentsClassLoaderKey, out SerializationContext>): SerializationContext {
|
||||||
throw NotImplementedError("AttachmentsClassLoaderForRotatedKeysOnlyImpl.computeIfAbsent should never be called. Should be replaced by the fallback cache")
|
throw NotImplementedError("AttachmentsClassLoaderForRotatedKeysOnlyImpl.computeIfAbsent should never be called. Should be replaced by the fallback cache")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,9 @@ import net.corda.core.node.ServiceHub
|
|||||||
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.AttachmentId
|
import net.corda.core.node.services.AttachmentId
|
||||||
|
import net.corda.core.contracts.CordaRotatedKeys
|
||||||
import net.corda.core.node.services.KeyManagementService
|
import net.corda.core.node.services.KeyManagementService
|
||||||
|
import net.corda.core.contracts.RotatedKeys
|
||||||
import net.corda.core.serialization.CustomSerializationScheme
|
import net.corda.core.serialization.CustomSerializationScheme
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
import net.corda.core.serialization.SerializationDefaults
|
import net.corda.core.serialization.SerializationDefaults
|
||||||
@ -524,11 +526,11 @@ open class TransactionBuilder(
|
|||||||
|
|
||||||
// This is the logic to determine the constraint which will replace the AutomaticPlaceholderConstraint.
|
// This is the logic to determine the constraint which will replace the AutomaticPlaceholderConstraint.
|
||||||
val (defaultOutputConstraint, constraintAttachment) = selectDefaultOutputConstraintAndConstraintAttachment(contractClassName,
|
val (defaultOutputConstraint, constraintAttachment) = selectDefaultOutputConstraintAndConstraintAttachment(contractClassName,
|
||||||
inputStates, selectedAttachment.currentAttachment, serviceHub)
|
inputStates, attachmentToUse, services)
|
||||||
|
|
||||||
// Sanity check that the selected attachment actually passes.
|
// Sanity check that the selected attachment actually passes.
|
||||||
require(defaultOutputConstraint.isSatisfiedBy(constraintAttachment)) {
|
require(defaultOutputConstraint.isSatisfiedBy(constraintAttachment)) {
|
||||||
"Selected output constraint: $defaultOutputConstraint not satisfying $selectedAttachment"
|
"Selected output constraint: $defaultOutputConstraint not satisfying $attachmentToUse"
|
||||||
}
|
}
|
||||||
|
|
||||||
val resolvedOutputStates = outputStates.map {
|
val resolvedOutputStates = outputStates.map {
|
||||||
@ -538,7 +540,7 @@ open class TransactionBuilder(
|
|||||||
} else {
|
} else {
|
||||||
// If the constraint on the output state is already set, and is not a valid transition or can't be transitioned, then fail early.
|
// If the constraint on the output state is already set, and is not a valid transition or can't be transitioned, then fail early.
|
||||||
inputStates?.forEach { input ->
|
inputStates?.forEach { input ->
|
||||||
require(outputConstraint.canBeTransitionedFrom(input.constraint, selectedAttachment.currentAttachment, serviceHub.toVerifyingServiceHub().rotatedKeys)) {
|
require(outputConstraint.canBeTransitionedFrom(input.constraint, attachmentToUse, getRotatedKeys(serviceHub))) {
|
||||||
"Output state constraint $outputConstraint cannot be transitioned from ${input.constraint}"
|
"Output state constraint $outputConstraint cannot be transitioned from ${input.constraint}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -550,6 +552,14 @@ open class TransactionBuilder(
|
|||||||
return Pair(selectedAttachmentId, resolvedOutputStates)
|
return Pair(selectedAttachmentId, resolvedOutputStates)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getRotatedKeys(services: ServiceHub?): RotatedKeys {
|
||||||
|
return services?.rotatedKeys ?: CordaRotatedKeys.keys.also {
|
||||||
|
log.warn("WARNING: You must pass in a ServiceHub reference to TransactionBuilder to resolve " +
|
||||||
|
"rotated keys defined in configuration. If you are writing a unit test then pass in a " +
|
||||||
|
"MockServices instance.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun selectDefaultOutputConstraintAndConstraintAttachment( contractClassName: ContractClassName,
|
private fun selectDefaultOutputConstraintAndConstraintAttachment( contractClassName: ContractClassName,
|
||||||
inputStates: List<TransactionState<ContractState>>?,
|
inputStates: List<TransactionState<ContractState>>?,
|
||||||
attachmentToUse: ContractAttachment,
|
attachmentToUse: ContractAttachment,
|
||||||
@ -564,7 +574,7 @@ open class TransactionBuilder(
|
|||||||
|
|
||||||
if (!defaultOutputConstraint.isSatisfiedBy(constraintAttachment)) {
|
if (!defaultOutputConstraint.isSatisfiedBy(constraintAttachment)) {
|
||||||
// The defaultOutputConstraint is the input constraint by the attachment in use currently may have a rotated key
|
// The defaultOutputConstraint is the input constraint by the attachment in use currently may have a rotated key
|
||||||
if (defaultOutputConstraint is SignatureAttachmentConstraint && services.toVerifyingServiceHub().rotatedKeys.canBeTransitioned(defaultOutputConstraint.key, constraintAttachment.signerKeys)) {
|
if (defaultOutputConstraint is SignatureAttachmentConstraint && (getRotatedKeys(serviceHub).canBeTransitioned(defaultOutputConstraint.key, constraintAttachment.signerKeys))) {
|
||||||
return Pair(makeSignatureAttachmentConstraint(attachmentToUse.signerKeys), constraintAttachment)
|
return Pair(makeSignatureAttachmentConstraint(attachmentToUse.signerKeys), constraintAttachment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,12 @@ import net.corda.core.KeepForDJVM
|
|||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.contracts.ComponentGroupEnum.COMMANDS_GROUP
|
import net.corda.core.contracts.ComponentGroupEnum.COMMANDS_GROUP
|
||||||
import net.corda.core.contracts.ComponentGroupEnum.OUTPUTS_GROUP
|
import net.corda.core.contracts.ComponentGroupEnum.OUTPUTS_GROUP
|
||||||
import net.corda.core.contracts.ComponentGroupEnum.SIGNERS_GROUP
|
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.contracts.PrivacySalt
|
import net.corda.core.contracts.PrivacySalt
|
||||||
import net.corda.core.contracts.RotatedKeys
|
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.TimeWindow
|
import net.corda.core.contracts.TimeWindow
|
||||||
import net.corda.core.contracts.TransactionResolutionException
|
import net.corda.core.contracts.TransactionResolutionException
|
||||||
import net.corda.core.contracts.TransactionState
|
import net.corda.core.contracts.TransactionState
|
||||||
import net.corda.core.contracts.TransactionVerificationException
|
|
||||||
import net.corda.core.crypto.DigestService
|
import net.corda.core.crypto.DigestService
|
||||||
import net.corda.core.crypto.MerkleTree
|
import net.corda.core.crypto.MerkleTree
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
|
@ -5,6 +5,7 @@ import net.corda.core.contracts.Attachment
|
|||||||
import net.corda.core.contracts.CommandData
|
import net.corda.core.contracts.CommandData
|
||||||
import net.corda.core.contracts.CommandWithParties
|
import net.corda.core.contracts.CommandWithParties
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
|
import net.corda.core.contracts.CordaRotatedKeys
|
||||||
import net.corda.core.contracts.PrivacySalt
|
import net.corda.core.contracts.PrivacySalt
|
||||||
import net.corda.core.contracts.StateAndRef
|
import net.corda.core.contracts.StateAndRef
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
@ -54,7 +55,8 @@ class LtxSupplierFactory : Function<Array<out Any?>, Supplier<LedgerTransaction>
|
|||||||
privacySalt = txArgs[TX_PRIVACY_SALT] as PrivacySalt,
|
privacySalt = txArgs[TX_PRIVACY_SALT] as PrivacySalt,
|
||||||
networkParameters = networkParameters,
|
networkParameters = networkParameters,
|
||||||
references = referencesProvider.get(),
|
references = referencesProvider.get(),
|
||||||
digestService = txArgs[TX_DIGEST_SERVICE] as DigestService
|
digestService = txArgs[TX_DIGEST_SERVICE] as DigestService,
|
||||||
|
rotatedKeys = CordaRotatedKeys.keys
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,8 @@ import org.apache.commons.io.FileUtils.deleteDirectory
|
|||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.kotlin.doReturn
|
import com.nhaarman.mockito_kotlin.doReturn
|
||||||
import org.mockito.kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import kotlin.io.path.div
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class ContractWithRotatedKeyTest {
|
class ContractWithRotatedKeyTest {
|
||||||
@ -62,7 +61,7 @@ class ContractWithRotatedKeyTest {
|
|||||||
): TestStartedNode {
|
): TestStartedNode {
|
||||||
node.internals.disableDBCloseOnStop()
|
node.internals.disableDBCloseOnStop()
|
||||||
node.dispose()
|
node.dispose()
|
||||||
val cordappsDir = network.baseDirectory(node) / "cordapps"
|
val cordappsDir = network.baseDirectory(node).resolve("cordapps")
|
||||||
deleteDirectory(cordappsDir.toFile())
|
deleteDirectory(cordappsDir.toFile())
|
||||||
return network.createNode(
|
return network.createNode(
|
||||||
parameters.copy(legalName = node.internals.configuration.myLegalName, forcedID = node.internals.id),
|
parameters.copy(legalName = node.internals.configuration.myLegalName, forcedID = node.internals.id),
|
||||||
@ -75,8 +74,8 @@ class ContractWithRotatedKeyTest {
|
|||||||
val keyStoreDir1 = SelfCleaningDir()
|
val keyStoreDir1 = SelfCleaningDir()
|
||||||
val keyStoreDir2 = SelfCleaningDir()
|
val keyStoreDir2 = SelfCleaningDir()
|
||||||
|
|
||||||
val packageOwnerKey1 = keyStoreDir1.path.generateKey(alias="1-testcordapp-rsa")
|
val packageOwnerKey1 = keyStoreDir1.path.generateKey(alias="alias1")
|
||||||
val packageOwnerKey2 = keyStoreDir2.path.generateKey(alias="1-testcordapp-rsa")
|
val packageOwnerKey2 = keyStoreDir2.path.generateKey(alias="alias1")
|
||||||
|
|
||||||
val unsignedFinanceCorDapp1 = cordappWithPackages("net.corda.finance", "migration", "META-INF.services")
|
val unsignedFinanceCorDapp1 = cordappWithPackages("net.corda.finance", "migration", "META-INF.services")
|
||||||
val unsignedFinanceCorDapp2 = cordappWithPackages("net.corda.finance", "migration", "META-INF.services").copy(versionId = 2)
|
val unsignedFinanceCorDapp2 = cordappWithPackages("net.corda.finance", "migration", "META-INF.services").copy(versionId = 2)
|
||||||
|
@ -6,6 +6,7 @@ import io.github.classgraph.ScanResult
|
|||||||
import net.corda.common.logging.errorReporting.CordappErrors
|
import net.corda.common.logging.errorReporting.CordappErrors
|
||||||
import net.corda.common.logging.errorReporting.ErrorCode
|
import net.corda.common.logging.errorReporting.ErrorCode
|
||||||
import net.corda.core.CordaRuntimeException
|
import net.corda.core.CordaRuntimeException
|
||||||
|
import net.corda.core.contracts.CordaRotatedKeys
|
||||||
import net.corda.core.contracts.RotatedKeys
|
import net.corda.core.contracts.RotatedKeys
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
@ -90,9 +91,9 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
* @param scanJars Uses the JAR URLs provided for classpath scanning and Cordapp detection.
|
* @param scanJars Uses the JAR URLs provided for classpath scanning and Cordapp detection.
|
||||||
*/
|
*/
|
||||||
fun fromJarUrls(scanJars: List<URL>, versionInfo: VersionInfo = VersionInfo.UNKNOWN, extraCordapps: List<CordappImpl> = emptyList(),
|
fun fromJarUrls(scanJars: List<URL>, versionInfo: VersionInfo = VersionInfo.UNKNOWN, extraCordapps: List<CordappImpl> = emptyList(),
|
||||||
cordappsSignerKeyFingerprintBlacklist: List<SecureHash> = emptyList()): JarScanningCordappLoader {
|
cordappsSignerKeyFingerprintBlacklist: List<SecureHash> = emptyList(), rotatedKeys: RotatedKeys = CordaRotatedKeys.keys): JarScanningCordappLoader {
|
||||||
val paths = scanJars.map { it.restricted() }
|
val paths = scanJars.map { it.restricted() }
|
||||||
return JarScanningCordappLoader(paths, versionInfo, extraCordapps, cordappsSignerKeyFingerprintBlacklist)
|
return JarScanningCordappLoader(paths, versionInfo, extraCordapps, cordappsSignerKeyFingerprintBlacklist, rotatedKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun URL.restricted(rootPackageName: String? = null) = RestrictedURL(this, rootPackageName)
|
private fun URL.restricted(rootPackageName: String? = null) = RestrictedURL(this, rootPackageName)
|
||||||
|
@ -10,7 +10,6 @@ import net.corda.core.flows.FlowException
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.notary.NotaryService
|
import net.corda.core.internal.notary.NotaryService
|
||||||
|
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.node.ServicesForResolution
|
import net.corda.core.node.ServicesForResolution
|
||||||
import net.corda.core.node.services.AttachmentId
|
import net.corda.core.node.services.AttachmentId
|
||||||
|
Loading…
x
Reference in New Issue
Block a user