ENT-1803: Allow change of updateDeadline on parameters update (#814)

* Allow change of updateDeadline on parameters update

ENT-1803. Parameters that where already advertised still need explicit
cancellation.
This commit is contained in:
Katarzyna Streich 2018-05-09 15:01:57 +01:00 committed by GitHub
parent 750e368283
commit 56c6ec967c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 22 deletions

View File

@ -48,7 +48,9 @@ class ParametersUpdateHandler(val csrStorage: CertificateSigningRequestStorage,
private fun handleSetNetworkParameters(setNetParams: NetworkParametersCmd.Set) {
logger.info("maxMessageSize is not currently wired in the nodes")
val activeNetParams = networkMapStorage.getNetworkMaps().publicNetworkMap?.networkParameters?.networkParameters
val activeMap = networkMapStorage.getNetworkMaps().publicNetworkMap
val activeNetParams = activeMap?.networkParameters?.networkParameters
// Setting initial parameters case.
if (activeNetParams == null) {
require(setNetParams.parametersUpdate == null) {
"'parametersUpdate' specified in network parameters file but there are no network parameters to update"
@ -57,27 +59,26 @@ class ParametersUpdateHandler(val csrStorage: CertificateSigningRequestStorage,
logger.info("Saving initial network parameters to be signed:\n$initialNetParams")
networkMapStorage.saveNetworkParameters(initialNetParams, null)
println("Saved initial network parameters to be signed:\n$initialNetParams")
} else {
} else { // An update.
val parametersUpdate = requireNotNull(setNetParams.parametersUpdate) {
"'parametersUpdate' not specified in network parameters file but there is already an active set of network parameters"
}
setNetParams.checkCompatibility(activeNetParams)
val latestNetParams = checkNotNull(networkMapStorage.getLatestNetworkParameters()?.networkParameters) {
"Something has gone wrong! We have an active set of network parameters ($activeNetParams) but apparently no latest network parameters!"
}
// It's not necessary that latestNetParams is the current active network parameters. It can be the network
// parameters from a previous update attempt which has't activated yet. We still take the epoch value for this
// parameters from a previous update attempt which hasn't activated yet. We still take the epoch value for this
// new set from latestNetParams to make sure the advertised update attempts have incrementing epochs.
// This has the implication that *active* network parameters may have gaps in their epochs.
val newNetParams = setNetParams.toNetworkParameters(modifiedTime = Instant.now(), epoch = latestNetParams.epoch + 1)
val activeUpdate = activeMap.networkMap.parametersUpdate
if (sameNetworkParameters(latestNetParams, newNetParams) && activeUpdate != null) {
// TODO We don't have cancel event propagation on client side.
throw IllegalArgumentException("New network parameters are the same as the latest ones and there is an update scheduled: $activeUpdate\n" +
"If you want to just change updateDeadline or update description - cancel old update first.")
}
logger.info("Enabling update to network parameters:\n$newNetParams\n$parametersUpdate")
require(!sameNetworkParameters(latestNetParams, newNetParams)) { "New network parameters are the same as the latest ones" }
networkMapStorage.saveNewParametersUpdate(newNetParams, parametersUpdate.description, parametersUpdate.updateDeadline)
logger.info("Update enabled")

View File

@ -3,6 +3,8 @@ package com.r3.corda.networkmanage
import com.r3.corda.networkmanage.common.persistence.NetworkMaps
import com.r3.corda.networkmanage.common.persistence.entity.NetworkMapEntity
import com.r3.corda.networkmanage.common.persistence.entity.NetworkParametersEntity
import com.r3.corda.networkmanage.doorman.NetworkParametersCmd
import com.r3.corda.networkmanage.doorman.ParametersUpdateConfig
import net.corda.core.crypto.SecureHash
import net.corda.core.node.NetworkParameters
import net.corda.core.serialization.serialize
@ -71,3 +73,13 @@ fun createNetworkMaps(signingCertAndKeyPair: CertificateAndKeyPair = createDevNe
val netParamsEntity = createNetworkParametersEntity(signingCertAndKeyPair, networkParameters)
return createNetworkMaps(signingCertAndKeyPair, netParamsEntity, nodeInfoHashes, privateNodeInfoHashes, timestamp = timestamp)
}
fun NetworkParameters.toCmd(parametersUpdate: ParametersUpdateConfig? = null): NetworkParametersCmd.Set {
return NetworkParametersCmd.Set(
minimumPlatformVersion = minimumPlatformVersion,
notaries = notaries,
maxMessageSize = maxMessageSize,
maxTransactionSize = maxTransactionSize,
parametersUpdate = parametersUpdate
)
}

View File

@ -1,8 +1,8 @@
package com.r3.corda.networkmanage.doorman
import com.r3.corda.networkmanage.toCmd
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.node.NetworkParameters
import net.corda.core.node.NotaryInfo
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.ALICE_NAME
@ -56,15 +56,5 @@ class NetworkParametersCmdTest {
.withMessageContaining("notaries")
}
private fun NetworkParameters.toCmd(): NetworkParametersCmd.Set {
return NetworkParametersCmd.Set(
minimumPlatformVersion = minimumPlatformVersion,
notaries = notaries,
maxMessageSize = maxMessageSize,
maxTransactionSize = maxTransactionSize,
parametersUpdate = null
)
}
private fun freshParty(name: CordaX500Name) = TestIdentity(name).party
}

View File

@ -2,22 +2,34 @@ package com.r3.corda.networkmanage.doorman
import com.nhaarman.mockito_kotlin.mock
import com.r3.corda.networkmanage.common.persistence.*
import com.r3.corda.networkmanage.toCmd
import com.typesafe.config.*
import net.corda.core.crypto.SecureHash
import net.corda.core.internal.*
import net.corda.core.node.NetworkParameters
import net.corda.core.serialization.serialize
import net.corda.core.utilities.days
import net.corda.nodeapi.internal.createDevNetworkMapCa
import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.NetworkMapAndSigned
import net.corda.nodeapi.internal.network.ParametersUpdate
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.internal.createDevIntermediateCaCertPath
import net.corda.testing.internal.signWith
import net.corda.testing.node.MockServices
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import java.nio.file.Path
import java.time.Instant
import java.util.*
class ParametersUpdateHandlerTest {
@ -31,12 +43,14 @@ class ParametersUpdateHandlerTest {
private lateinit var persistence: CordaPersistence
private lateinit var csrStorage: CertificateSigningRequestStorage
private lateinit var netParamsUpdateHandler: ParametersUpdateHandler
private lateinit var networkMapStorage: PersistentNetworkMapStorage
@Before
fun init() {
persistence = configureDatabase(MockServices.makeTestDataSourceProperties(), DatabaseConfig(runMigration = true))
csrStorage = PersistentCertificateSigningRequestStorage(persistence)
netParamsUpdateHandler = ParametersUpdateHandler(csrStorage, mock())
networkMapStorage = PersistentNetworkMapStorage(persistence)
netParamsUpdateHandler = ParametersUpdateHandler(csrStorage, networkMapStorage)
}
@After
@ -75,6 +89,69 @@ class ParametersUpdateHandlerTest {
.hasMessageContaining("is not registered with the doorman")
}
@Test
fun `set twice initial parameters`() {
val testParams = testNetworkParameters()
val setInitialCmd = testParams.toCmd()
netParamsUpdateHandler.processNetworkParameters(setInitialCmd)
val testParams2 = testParams.copy(minimumPlatformVersion = 7)
netParamsUpdateHandler.processNetworkParameters(testParams2.toCmd())
assertThat(networkMapStorage.getLatestNetworkParameters()!!.networkParameters.minimumPlatformVersion).isEqualTo(7)
assertThatThrownBy { netParamsUpdateHandler.processNetworkParameters(
testParams2.toCmd(parametersUpdate = ParametersUpdateConfig("It needs changing. Now!", updateDeadline = Instant.now())))
}.hasMessageContaining("'parametersUpdate' specified in network parameters file but there are no network parameters to update")
}
@Test
fun `cancel parameters and then set the same`() {
loadInitialParams()
val paramsForUpdate = testNetworkParameters(minimumPlatformVersion = 101)
val updateDeadline1 = Instant.now() + 10.days
val updateParamsCmd = paramsForUpdate.toCmd(ParametersUpdateConfig("Update", updateDeadline1))
netParamsUpdateHandler.processNetworkParameters(updateParamsCmd)
val cancelCmd = NetworkParametersCmd.CancelUpdate
netParamsUpdateHandler.processNetworkParameters(cancelCmd)
// Use just cancelled parameters
netParamsUpdateHandler.processNetworkParameters(updateParamsCmd)
}
@Test
fun `set parameters update and then change update deadline`() {
loadInitialParams()
val paramsForUpdate = testNetworkParameters(minimumPlatformVersion = 101)
val updateDeadline1 = Instant.now() + 10.days
val updateParamsCmd = paramsForUpdate.toCmd(ParametersUpdateConfig("Update", updateDeadline1))
netParamsUpdateHandler.processNetworkParameters(updateParamsCmd)
// Just change description
netParamsUpdateHandler.processNetworkParameters(paramsForUpdate.toCmd(ParametersUpdateConfig("Update again", updateDeadline1)))
// Just change update deadline
netParamsUpdateHandler.processNetworkParameters(paramsForUpdate.toCmd(ParametersUpdateConfig("Update again", updateDeadline1 + 10.days)))
}
@Test
fun `try to change active update`() {
val paramsForUpdate = testNetworkParameters(minimumPlatformVersion = 101)
val updateDeadline = Instant.now() + 10.days
val description = "Update"
val paramsUpdate = ParametersUpdate(paramsForUpdate.serialize().hash, description, updateDeadline)
loadInitialParams(parametersUpdate = paramsUpdate)
networkMapStorage.saveNetworkParameters(paramsForUpdate, null)
val updateParamsCmd = paramsForUpdate.toCmd(ParametersUpdateConfig(description, updateDeadline))
assertThatThrownBy { netParamsUpdateHandler.processNetworkParameters(updateParamsCmd) }
.hasMessageContaining("New network parameters are the same as the latest ones")
}
// Load initial parameters to db and sign them, set them to be in active network map.
private fun loadInitialParams(params: NetworkParameters = testNetworkParameters(), parametersUpdate: ParametersUpdate? = null) {
val (rootCa) = createDevIntermediateCaCertPath()
val networkMapCertAndKeyPair = createDevNetworkMapCa(rootCa)
val networkParametersSig = networkMapCertAndKeyPair.sign(params).sig
val networkParametersHash = networkMapStorage.saveNetworkParameters(params, networkParametersSig).hash
val networkMap = NetworkMap(emptyList(), SecureHash.parse(networkParametersHash), parametersUpdate)
val networkMapAndSigned = NetworkMapAndSigned(networkMap) { networkMapCertAndKeyPair.sign(networkMap).sig }
networkMapStorage.saveNewNetworkMap(networkMapAndSigned = networkMapAndSigned)
}
private fun saveConfig(configFile: Path, notaryFiles: List<Path>) {
val config = ConfigValueFactory.fromMap(
mapOf("minimumPlatformVersion" to 1,