mirror of
https://github.com/corda/corda.git
synced 2025-01-17 18:29:49 +00:00
CORDA-2128: Moved all the helper methods added to NetworkParameters.kt into internal (#4466)
This commit is contained in:
parent
0388872175
commit
c08f65a92c
@ -1,12 +1,14 @@
|
||||
package net.corda.core.internal
|
||||
|
||||
import net.corda.core.DeleteForDJVM
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.cordapp.Cordapp
|
||||
import net.corda.core.cordapp.CordappConfig
|
||||
import net.corda.core.cordapp.CordappContext
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.DataVendingFlow
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.ServicesForResolution
|
||||
import net.corda.core.node.ZoneVersionTooLowException
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
@ -16,6 +18,7 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import org.slf4j.MDC
|
||||
import java.security.PublicKey
|
||||
|
||||
// *Internal* Corda-specific utilities.
|
||||
|
||||
@ -71,9 +74,7 @@ private fun isPackageValid(packageName: String): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is a legal Java package name.
|
||||
*/
|
||||
/** Check if a string is a legal Java package name. */
|
||||
fun requirePackageValid(name: String) {
|
||||
require(isPackageValid(name)) { "Invalid Java package name: `$name`." }
|
||||
}
|
||||
@ -85,3 +86,33 @@ fun requirePackageValid(name: String) {
|
||||
*/
|
||||
@CordaSerializable
|
||||
object RetrieveAnyTransactionPayload : ArrayList<Any>()
|
||||
|
||||
/**
|
||||
* Returns true if the [fullClassName] is in a subpackage of [packageName].
|
||||
* E.g.: "com.megacorp" owns "com.megacorp.tokens.MegaToken"
|
||||
*
|
||||
* Note: The ownership check is ignoring case to prevent people from just releasing a jar with: "com.megaCorp.megatoken" and pretend they are MegaCorp.
|
||||
* By making the check case insensitive, the node will require that the jar is signed by MegaCorp, so the attack fails.
|
||||
*/
|
||||
private fun owns(packageName: String, fullClassName: String): Boolean = fullClassName.startsWith("$packageName.", ignoreCase = true)
|
||||
|
||||
/** Returns the public key of the package owner of the [contractClassName], or null if not owned. */
|
||||
internal fun NetworkParameters.getPackageOwnerOf(contractClassName: ContractClassName): PublicKey? {
|
||||
return packageOwnership.entries.singleOrNull { owns(it.key, contractClassName) }?.value
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public key of the package owner if any of [contractClassNames] match, or null if not owned.
|
||||
*/
|
||||
internal fun NetworkParameters.getPackageOwnerOf(contractClassNames: Set<ContractClassName>): PublicKey? {
|
||||
for (contractClassName in contractClassNames) {
|
||||
val owner = getPackageOwnerOf(contractClassName)
|
||||
if (owner != null) return owner
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Make sure that packages don't overlap so that ownership is clear.
|
||||
fun noPackageOverlap(packages: Collection<String>): Boolean {
|
||||
return packages.all { outer -> packages.none { inner -> inner != outer && inner.startsWith("$outer.") } }
|
||||
}
|
||||
|
@ -2,23 +2,17 @@ package net.corda.core.node
|
||||
|
||||
import net.corda.core.CordaRuntimeException
|
||||
import net.corda.core.KeepForDJVM
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.crypto.toStringShort
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.noPackageOverlap
|
||||
import net.corda.core.internal.requirePackageValid
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.DeprecatedConstructorForDeserialization
|
||||
import net.corda.core.utilities.days
|
||||
import java.lang.reflect.Method
|
||||
import java.security.PublicKey
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.declaredMemberProperties
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.jvm.javaGetter
|
||||
|
||||
// DOCSTART 1
|
||||
/**
|
||||
@ -54,13 +48,13 @@ data class NetworkParameters(
|
||||
) {
|
||||
// DOCEND 1
|
||||
@DeprecatedConstructorForDeserialization(1)
|
||||
constructor (minimumPlatformVersion: Int,
|
||||
notaries: List<NotaryInfo>,
|
||||
maxMessageSize: Int,
|
||||
maxTransactionSize: Int,
|
||||
modifiedTime: Instant,
|
||||
epoch: Int,
|
||||
whitelistedContractImplementations: Map<String, List<AttachmentId>>
|
||||
constructor(minimumPlatformVersion: Int,
|
||||
notaries: List<NotaryInfo>,
|
||||
maxMessageSize: Int,
|
||||
maxTransactionSize: Int,
|
||||
modifiedTime: Instant,
|
||||
epoch: Int,
|
||||
whitelistedContractImplementations: Map<String, List<AttachmentId>>
|
||||
) : this(minimumPlatformVersion,
|
||||
notaries,
|
||||
maxMessageSize,
|
||||
@ -73,14 +67,14 @@ data class NetworkParameters(
|
||||
)
|
||||
|
||||
@DeprecatedConstructorForDeserialization(2)
|
||||
constructor (minimumPlatformVersion: Int,
|
||||
notaries: List<NotaryInfo>,
|
||||
maxMessageSize: Int,
|
||||
maxTransactionSize: Int,
|
||||
modifiedTime: Instant,
|
||||
epoch: Int,
|
||||
whitelistedContractImplementations: Map<String, List<AttachmentId>>,
|
||||
eventHorizon: Duration
|
||||
constructor(minimumPlatformVersion: Int,
|
||||
notaries: List<NotaryInfo>,
|
||||
maxMessageSize: Int,
|
||||
maxTransactionSize: Int,
|
||||
modifiedTime: Instant,
|
||||
epoch: Int,
|
||||
whitelistedContractImplementations: Map<String, List<AttachmentId>>,
|
||||
eventHorizon: Duration
|
||||
) : this(minimumPlatformVersion,
|
||||
notaries,
|
||||
maxMessageSize,
|
||||
@ -92,32 +86,6 @@ data class NetworkParameters(
|
||||
emptyMap()
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val memberPropertyPartition = NetworkParameters::class.declaredMemberProperties.asSequence()
|
||||
.partition { it.isAutoAcceptable() }
|
||||
private val autoAcceptableNamesAndGetters = memberPropertyPartition.first.associateBy({ it.name }, { it.javaGetter })
|
||||
private val nonAutoAcceptableGetters = memberPropertyPartition.second.map { it.javaGetter }
|
||||
val autoAcceptablePropertyNames = autoAcceptableNamesAndGetters.keys
|
||||
|
||||
/**
|
||||
* Returns true if the [fullClassName] is in a subpackage of [packageName].
|
||||
* E.g.: "com.megacorp" owns "com.megacorp.tokens.MegaToken"
|
||||
*
|
||||
* Note: The ownership check is ignoring case to prevent people from just releasing a jar with: "com.megaCorp.megatoken" and pretend they are MegaCorp.
|
||||
* By making the check case insensitive, the node will require that the jar is signed by MegaCorp, so the attack fails.
|
||||
*/
|
||||
private fun owns(packageName: String, fullClassName: String) = fullClassName.startsWith("$packageName.", ignoreCase = true)
|
||||
|
||||
// Make sure that packages don't overlap so that ownership is clear.
|
||||
fun noOverlap(packages: Collection<String>) = packages.all { currentPackage ->
|
||||
packages.none { otherPackage -> otherPackage != currentPackage && otherPackage.startsWith("$currentPackage.") }
|
||||
}
|
||||
|
||||
private fun KProperty1<out NetworkParameters, Any?>.isAutoAcceptable(): Boolean {
|
||||
return this.findAnnotation<AutoAcceptable>() != null
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
require(minimumPlatformVersion > 0) { "Minimum platform level must be at least 1" }
|
||||
require(notaries.distinctBy { it.identity } == notaries) { "Duplicate notary identities" }
|
||||
@ -126,7 +94,7 @@ data class NetworkParameters(
|
||||
require(maxTransactionSize > 0) { "Maximum transaction size must be at least 1" }
|
||||
require(!eventHorizon.isNegative) { "Event Horizon must be a positive value" }
|
||||
packageOwnership.keys.forEach(::requirePackageValid)
|
||||
require(noOverlap(packageOwnership.keys)) { "Multiple packages added to the packageOwnership overlap." }
|
||||
require(noPackageOverlap(packageOwnership.keys)) { "Multiple packages added to the packageOwnership overlap." }
|
||||
}
|
||||
|
||||
fun copy(minimumPlatformVersion: Int,
|
||||
@ -137,14 +105,16 @@ data class NetworkParameters(
|
||||
epoch: Int,
|
||||
whitelistedContractImplementations: Map<String, List<AttachmentId>>
|
||||
): NetworkParameters {
|
||||
return copy(minimumPlatformVersion = minimumPlatformVersion,
|
||||
return copy(
|
||||
minimumPlatformVersion = minimumPlatformVersion,
|
||||
notaries = notaries,
|
||||
maxMessageSize = maxMessageSize,
|
||||
maxTransactionSize = maxTransactionSize,
|
||||
modifiedTime = modifiedTime,
|
||||
epoch = epoch,
|
||||
whitelistedContractImplementations = whitelistedContractImplementations,
|
||||
eventHorizon = eventHorizon)
|
||||
eventHorizon = eventHorizon
|
||||
)
|
||||
}
|
||||
|
||||
fun copy(minimumPlatformVersion: Int,
|
||||
@ -156,14 +126,16 @@ data class NetworkParameters(
|
||||
whitelistedContractImplementations: Map<String, List<AttachmentId>>,
|
||||
eventHorizon: Duration
|
||||
): NetworkParameters {
|
||||
return copy(minimumPlatformVersion = minimumPlatformVersion,
|
||||
return copy(
|
||||
minimumPlatformVersion = minimumPlatformVersion,
|
||||
notaries = notaries,
|
||||
maxMessageSize = maxMessageSize,
|
||||
maxTransactionSize = maxTransactionSize,
|
||||
modifiedTime = modifiedTime,
|
||||
epoch = epoch,
|
||||
whitelistedContractImplementations = whitelistedContractImplementations,
|
||||
eventHorizon = eventHorizon)
|
||||
eventHorizon = eventHorizon
|
||||
)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
@ -176,43 +148,13 @@ data class NetworkParameters(
|
||||
${whitelistedContractImplementations.entries.joinToString("\n ")}
|
||||
}
|
||||
eventHorizon=$eventHorizon
|
||||
modifiedTime=$modifiedTime
|
||||
epoch=$epoch,
|
||||
packageOwnership= {
|
||||
packageOwnership {
|
||||
${packageOwnership.entries.joinToString("\n ") { "$it.key -> ${it.value.toStringShort()}" }}
|
||||
}
|
||||
modifiedTime=$modifiedTime
|
||||
epoch=$epoch
|
||||
}"""
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public key of the package owner of the [contractClassName], or null if not owned.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun getPackageOwnerOf(contractClassName: ContractClassName): PublicKey? = this.packageOwnership.filterKeys { packageName -> owns(packageName, contractClassName) }.values.singleOrNull()
|
||||
|
||||
/**
|
||||
* Returns the public key of the package owner if any of [contractClassName] match, or null if not owned.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun getPackageOwnerOf(contractClassNames: Set<ContractClassName>): PublicKey? {
|
||||
val ownerKeys = contractClassNames.map { getPackageOwnerOf(it) }
|
||||
return ownerKeys.find { it != null }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the only properties changed in [newNetworkParameters] are [AutoAcceptable] and not
|
||||
* included in the [excludedParameterNames]
|
||||
*/
|
||||
fun canAutoAccept(newNetworkParameters: NetworkParameters, excludedParameterNames: Set<String>): Boolean {
|
||||
return nonAutoAcceptableGetters.none { valueChanged(newNetworkParameters, it) } &&
|
||||
autoAcceptableNamesAndGetters.none { excludedParameterNames.contains(it.key) && valueChanged(newNetworkParameters, it.value) }
|
||||
}
|
||||
|
||||
private fun valueChanged(newNetworkParameters: NetworkParameters, getter: Method?): Boolean {
|
||||
val propertyValue = getter?.invoke(this)
|
||||
val newPropertyValue = getter?.invoke(newNetworkParameters)
|
||||
return propertyValue != newPropertyValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,7 +171,3 @@ data class NotaryInfo(val identity: Party, val validating: Boolean)
|
||||
* version.
|
||||
*/
|
||||
class ZoneVersionTooLowException(message: String) : CordaRuntimeException(message)
|
||||
|
||||
private fun KProperty1<out NetworkParameters, Any?>.isAutoAcceptable(): Boolean {
|
||||
return this.findAnnotation<AutoAcceptable>() != null
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package net.corda.core.node
|
||||
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.core.internal.getPackageOwnerOf
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.days
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -32,7 +32,8 @@ import kotlin.test.assertFails
|
||||
class NetworkParametersTest {
|
||||
private val mockNet = InternalMockNetwork(
|
||||
defaultParameters = MockNetworkParameters(networkSendManuallyPumped = true),
|
||||
notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME)))
|
||||
notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME))
|
||||
)
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
@ -129,44 +130,8 @@ class NetworkParametersTest {
|
||||
assertEquals(params.getPackageOwnerOf("com.exam.something.MyClass"), null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `auto acceptance checks are correct`() {
|
||||
val packageOwnership = mapOf(
|
||||
"com.example1" to generateKeyPair().public,
|
||||
"com.example2" to generateKeyPair().public)
|
||||
val whitelistedContractImplementations = mapOf(
|
||||
"example1" to listOf(AttachmentId.randomSHA256()),
|
||||
"example2" to listOf(AttachmentId.randomSHA256()))
|
||||
|
||||
val netParams = testNetworkParameters()
|
||||
val netParamsAutoAcceptable = netParams.copy(
|
||||
packageOwnership = packageOwnership,
|
||||
whitelistedContractImplementations = whitelistedContractImplementations)
|
||||
val netParamsNotAutoAcceptable = netParamsAutoAcceptable.copy(
|
||||
maxMessageSize = netParams.maxMessageSize + 1)
|
||||
|
||||
assert(netParams.canAutoAccept(netParams, emptySet())) {
|
||||
"auto-acceptable if identical"
|
||||
}
|
||||
assert(netParams.canAutoAccept(netParams, NetworkParameters.autoAcceptablePropertyNames)) {
|
||||
"auto acceptable if identical regardless of exclusions"
|
||||
}
|
||||
assert(netParams.canAutoAccept(netParamsAutoAcceptable, emptySet())) {
|
||||
"auto-acceptable if only AutoAcceptable params have changed"
|
||||
}
|
||||
assert(netParams.canAutoAccept(netParamsAutoAcceptable, setOf("modifiedTime"))) {
|
||||
"auto-acceptable if only AutoAcceptable params have changed and excluded param has not changed"
|
||||
}
|
||||
assert(!netParams.canAutoAccept(netParamsNotAutoAcceptable, emptySet())) {
|
||||
"not auto-acceptable if non-AutoAcceptable param has changed"
|
||||
}
|
||||
assert(!netParams.canAutoAccept(netParamsAutoAcceptable, setOf("whitelistedContractImplementations"))) {
|
||||
"not auto-acceptable if only AutoAcceptable params have changed but one has been added to the exclusion set"
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
private fun dropParametersToDir(dir: Path, params: NetworkParameters) {
|
||||
NetworkParametersCopier(params).install(dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.crypto.SignedData
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import net.corda.core.messaging.ParametersUpdateInfo
|
||||
import net.corda.core.node.AutoAcceptable
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.services.KeyManagementService
|
||||
import net.corda.core.serialization.serialize
|
||||
@ -21,6 +22,7 @@ import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.network.*
|
||||
import rx.Subscription
|
||||
import rx.subjects.PublishSubject
|
||||
import java.lang.reflect.Method
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.security.cert.X509Certificate
|
||||
@ -28,6 +30,10 @@ import java.time.Duration
|
||||
import java.util.*
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.declaredMemberProperties
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.jvm.javaGetter
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
|
||||
@ -78,7 +84,7 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
|
||||
this.autoAcceptNetworkParameters = networkParameterAcceptanceSettings.autoAcceptEnabled
|
||||
this.excludedAutoAcceptNetworkParameters = networkParameterAcceptanceSettings.excludedAutoAcceptableParameters
|
||||
|
||||
val autoAcceptNetworkParametersNames = NetworkParameters.autoAcceptablePropertyNames - excludedAutoAcceptNetworkParameters
|
||||
val autoAcceptNetworkParametersNames = autoAcceptablePropertyNames - excludedAutoAcceptNetworkParameters
|
||||
if (autoAcceptNetworkParameters && autoAcceptNetworkParametersNames.isNotEmpty()) {
|
||||
logger.info("Auto-accept enabled for network parameter changes which modify only: $autoAcceptNetworkParametersNames")
|
||||
}
|
||||
@ -250,3 +256,27 @@ The node will shutdown now.""")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val memberPropertyPartition = NetworkParameters::class.declaredMemberProperties.partition { it.isAutoAcceptable() }
|
||||
private val autoAcceptableNamesAndGetters = memberPropertyPartition.first.associateBy({ it.name }, { it.javaGetter })
|
||||
@VisibleForTesting
|
||||
internal val autoAcceptablePropertyNames = autoAcceptableNamesAndGetters.keys
|
||||
private val nonAutoAcceptableGetters = memberPropertyPartition.second.map { it.javaGetter }
|
||||
|
||||
/**
|
||||
* Returns true if the only properties changed in [newNetworkParameters] are [AutoAcceptable] and not
|
||||
* included in the [excludedParameterNames]
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun NetworkParameters.canAutoAccept(newNetworkParameters: NetworkParameters, excludedParameterNames: Set<String>): Boolean {
|
||||
return nonAutoAcceptableGetters.none { valueChanged(newNetworkParameters, it) } &&
|
||||
autoAcceptableNamesAndGetters.none { it.key in excludedParameterNames && valueChanged(newNetworkParameters, it.value) }
|
||||
}
|
||||
|
||||
private fun KProperty1<out NetworkParameters, Any?>.isAutoAcceptable(): Boolean = findAnnotation<AutoAcceptable>() != null
|
||||
|
||||
private fun NetworkParameters.valueChanged(newNetworkParameters: NetworkParameters, getter: Method?): Boolean {
|
||||
val propertyValue = getter?.invoke(this)
|
||||
val newPropertyValue = getter?.invoke(newNetworkParameters)
|
||||
return propertyValue != newPropertyValue
|
||||
}
|
@ -5,6 +5,7 @@ import com.google.common.jimfs.Jimfs
|
||||
import com.nhaarman.mockito_kotlin.*
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.crypto.sign
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
@ -13,17 +14,20 @@ import net.corda.core.internal.concurrent.openFuture
|
||||
import net.corda.core.messaging.ParametersUpdateInfo
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.millis
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.internal.NetworkParametersStorageInternal
|
||||
import net.corda.node.services.api.NetworkMapCacheInternal
|
||||
import net.corda.node.services.config.NetworkParameterAcceptanceSettings
|
||||
import net.corda.core.internal.NODE_INFO_DIRECTORY
|
||||
import net.corda.node.internal.NetworkParametersStorageInternal
|
||||
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.nodeapi.internal.network.*
|
||||
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME
|
||||
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
|
||||
import net.corda.nodeapi.internal.network.SignedNetworkParameters
|
||||
import net.corda.nodeapi.internal.network.verifiedNetworkParametersCert
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.DEV_ROOT_CA
|
||||
@ -48,6 +52,8 @@ import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class NetworkMapUpdaterTest {
|
||||
@Rule
|
||||
@ -68,7 +74,7 @@ class NetworkMapUpdaterTest {
|
||||
private val networkParametersStorage: NetworkParametersStorageInternal = mock()
|
||||
private lateinit var server: NetworkMapServer
|
||||
private lateinit var networkMapClient: NetworkMapClient
|
||||
private lateinit var updater: NetworkMapUpdater
|
||||
private var updater: NetworkMapUpdater? = null
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
@ -82,7 +88,7 @@ class NetworkMapUpdaterTest {
|
||||
|
||||
@After
|
||||
fun cleanUp() {
|
||||
updater.close()
|
||||
updater?.close()
|
||||
fs.close()
|
||||
server.close()
|
||||
}
|
||||
@ -95,7 +101,7 @@ class NetworkMapUpdaterTest {
|
||||
networkParameters: NetworkParameters = server.networkParameters,
|
||||
autoAcceptNetworkParameters: Boolean = true,
|
||||
excludedAutoAcceptNetworkParameters: Set<String> = emptySet()) {
|
||||
updater.start(DEV_ROOT_CA.certificate,
|
||||
updater!!.start(DEV_ROOT_CA.certificate,
|
||||
server.networkParameters.serialize().hash,
|
||||
ourNodeInfo,
|
||||
networkParameters,
|
||||
@ -206,7 +212,7 @@ class NetworkMapUpdaterTest {
|
||||
@Test
|
||||
fun `emit new parameters update info on parameters update from network map`() {
|
||||
setUpdater()
|
||||
val paramsFeed = updater.trackParametersUpdate()
|
||||
val paramsFeed = updater!!.trackParametersUpdate()
|
||||
val snapshot = paramsFeed.snapshot
|
||||
val updates = paramsFeed.updates.bufferUntilSubscribed()
|
||||
assertEquals(null, snapshot)
|
||||
@ -237,7 +243,7 @@ class NetworkMapUpdaterTest {
|
||||
val newHash = newParameters.serialize().hash
|
||||
val updateFile = baseDir / NETWORK_PARAMS_UPDATE_FILE_NAME
|
||||
assert(!updateFile.exists()) { "network parameters should not be auto accepted" }
|
||||
updater.acceptNewNetworkParameters(newHash) { it.serialize().sign(ourKeyPair) }
|
||||
updater!!.acceptNewNetworkParameters(newHash) { it.serialize().sign(ourKeyPair) }
|
||||
verify(networkParametersStorage, times(1)).saveParameters(any())
|
||||
val signedNetworkParams = updateFile.readObject<SignedNetworkParameters>()
|
||||
val paramsFromFile = signedNetworkParams.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
|
||||
@ -411,6 +417,32 @@ class NetworkMapUpdaterTest {
|
||||
assert(networkMapCache.allNodeHashes.size == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `auto acceptance checks are correct`() {
|
||||
val packageOwnership = mapOf(
|
||||
"com.example1" to generateKeyPair().public,
|
||||
"com.example2" to generateKeyPair().public
|
||||
)
|
||||
val whitelistedContractImplementations = mapOf(
|
||||
"example1" to listOf(AttachmentId.randomSHA256()),
|
||||
"example2" to listOf(AttachmentId.randomSHA256())
|
||||
)
|
||||
|
||||
val netParams = testNetworkParameters()
|
||||
val netParamsAutoAcceptable = netParams.copy(
|
||||
packageOwnership = packageOwnership,
|
||||
whitelistedContractImplementations = whitelistedContractImplementations
|
||||
)
|
||||
val netParamsNotAutoAcceptable = netParamsAutoAcceptable.copy(maxMessageSize = netParams.maxMessageSize + 1)
|
||||
|
||||
assertTrue(netParams.canAutoAccept(netParams, emptySet()), "auto-acceptable if identical")
|
||||
assertTrue(netParams.canAutoAccept(netParams, autoAcceptablePropertyNames), "auto acceptable if identical regardless of exclusions")
|
||||
assertTrue(netParams.canAutoAccept(netParamsAutoAcceptable, emptySet()), "auto-acceptable if only AutoAcceptable params have changed")
|
||||
assertTrue(netParams.canAutoAccept(netParamsAutoAcceptable, setOf("modifiedTime")), "auto-acceptable if only AutoAcceptable params have changed and excluded param has not changed")
|
||||
assertFalse(netParams.canAutoAccept(netParamsNotAutoAcceptable, emptySet()), "not auto-acceptable if non-AutoAcceptable param has changed")
|
||||
assertFalse(netParams.canAutoAccept(netParamsAutoAcceptable, setOf("whitelistedContractImplementations")), "not auto-acceptable if only AutoAcceptable params have changed but one has been added to the exclusion set")
|
||||
}
|
||||
|
||||
private fun createMockNetworkMapCache(): NetworkMapCacheInternal {
|
||||
return mock {
|
||||
on { nodeReady }.thenReturn(nodeReadyFuture)
|
||||
|
@ -6,9 +6,8 @@ import net.corda.common.configuration.parsing.internal.get
|
||||
import net.corda.common.configuration.parsing.internal.mapValid
|
||||
import net.corda.common.configuration.parsing.internal.nested
|
||||
import net.corda.common.validation.internal.Validated
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.noPackageOverlap
|
||||
import net.corda.core.internal.requirePackageValid
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.nodeapi.internal.crypto.loadKeyStore
|
||||
import net.corda.nodeapi.internal.network.NetworkParametersOverrides
|
||||
import net.corda.nodeapi.internal.network.PackageOwner
|
||||
@ -84,8 +83,12 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification<Netw
|
||||
|
||||
override fun parseValid(configuration: Config): Valid<NetworkParametersOverrides> {
|
||||
val packageOwnership = configuration[packageOwnership]
|
||||
if (packageOwnership != null && !NetworkParameters.noOverlap(packageOwnership.map { it.javaPackageName })) {
|
||||
return Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of("Package namespaces must not overlap", keyName = "packageOwnership", containingPath = listOf())).toSet())
|
||||
if (packageOwnership != null && !noPackageOverlap(packageOwnership.map { it.javaPackageName })) {
|
||||
return Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of(
|
||||
"Package namespaces must not overlap",
|
||||
keyName = "packageOwnership",
|
||||
containingPath = listOf()
|
||||
)).toSet())
|
||||
}
|
||||
return valid(NetworkParametersOverrides(
|
||||
minimumPlatformVersion = configuration[minimumPlatformVersion],
|
||||
|
Loading…
Reference in New Issue
Block a user