From 02884e6c816ae3d8fac510fbf8edae76cd04b1bf Mon Sep 17 00:00:00 2001 From: Michal Kit Date: Tue, 12 Jun 2018 09:31:06 +0100 Subject: [PATCH] CORDA-1593 Extracting the whitelist logic and making it public (#3317) * CORDA-1539 Extracting the whitelist logic and making it public * Addressing review comments --- .../internal/network/NetworkBootstrapper.kt | 31 ------------- .../internal/network/WhitelisGenerator.kt | 43 +++++++++++++++++++ .../network/NetworkBootstrapperTest.kt | 2 +- .../network/WhitelistGeneratorTest.kt | 41 ++++++++++++++++++ 4 files changed, 85 insertions(+), 32 deletions(-) create mode 100644 node-api/src/main/kotlin/net/corda/nodeapi/internal/network/WhitelisGenerator.kt create mode 100644 node-api/src/test/kotlin/net/corda/nodeapi/internal/network/WhitelistGeneratorTest.kt diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt index 6636b2374c..5438953cf5 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapper.kt @@ -3,7 +3,6 @@ package net.corda.nodeapi.internal.network import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import net.corda.cordform.CordformNode -import net.corda.core.contracts.ContractClassName import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.internal.* @@ -55,7 +54,6 @@ class NetworkBootstrapper { ) private const val LOGS_DIR_NAME = "logs" - private const val EXCLUDE_WHITELIST_FILE_NAME = "exclude_whitelist.txt" @JvmStatic fun main(args: Array) { @@ -291,35 +289,6 @@ class NetworkBootstrapper { return networkParameters } - @VisibleForTesting - internal fun generateWhitelist(networkParameters: NetworkParameters?, - excludeContracts: List, - cordappJars: List): Map> { - val existingWhitelist = networkParameters?.whitelistedContractImplementations ?: emptyMap() - - if (excludeContracts.isNotEmpty()) { - println("Exclude contracts from whitelist: ${excludeContracts.joinToString()}") - existingWhitelist.keys.forEach { - require(it !in excludeContracts) { "$it is already part of the existing whitelist and cannot be excluded." } - } - } - - val newWhiteList = cordappJars - .flatMap { jar -> (jar.scan() - excludeContracts).map { it to jar.hash } } - .toMultiMap() - - return (newWhiteList.keys + existingWhitelist.keys).associateBy({ it }) { - val existingHashes = existingWhitelist[it] ?: emptyList() - val newHashes = newWhiteList[it] ?: emptyList() - (existingHashes + newHashes).distinct() - } - } - - private fun readExcludeWhitelist(directory: Path): List { - val file = directory / EXCLUDE_WHITELIST_FILE_NAME - return if (file.exists()) file.readAllLines().map(String::trim) else emptyList() - } - private fun NodeInfo.notaryIdentity(): Party { return when (legalIdentities.size) { // Single node notaries have just one identity like all other nodes. This identity is the notary identity diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/WhitelisGenerator.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/WhitelisGenerator.kt new file mode 100644 index 0000000000..9979337386 --- /dev/null +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/WhitelisGenerator.kt @@ -0,0 +1,43 @@ +package net.corda.nodeapi.internal.network + +import net.corda.core.contracts.ContractClassName +import net.corda.core.internal.div +import net.corda.core.internal.exists +import net.corda.core.internal.readAllLines +import net.corda.core.internal.toMultiMap +import net.corda.core.node.NetworkParameters +import net.corda.core.node.services.AttachmentId +import net.corda.nodeapi.internal.ContractsJar +import org.slf4j.LoggerFactory +import java.nio.file.Path + +private const val EXCLUDE_WHITELIST_FILE_NAME = "exclude_whitelist.txt" +private val logger = LoggerFactory.getLogger("net.corda.nodeapi.internal.network.WhitelistGenerator") + +fun generateWhitelist(networkParameters: NetworkParameters?, + excludeContracts: List, + cordappJars: List): Map> { + val existingWhitelist = networkParameters?.whitelistedContractImplementations ?: emptyMap() + + if (excludeContracts.isNotEmpty()) { + logger.info("Exclude contracts from whitelist: ${excludeContracts.joinToString()}") + existingWhitelist.keys.forEach { + require(it !in excludeContracts) { "$it is already part of the existing whitelist and cannot be excluded." } + } + } + + val newWhiteList = cordappJars + .flatMap { jar -> (jar.scan() - excludeContracts).map { it to jar.hash } } + .toMultiMap() + + return (newWhiteList.keys + existingWhitelist.keys).associateBy({ it }) { + val existingHashes = existingWhitelist[it] ?: emptyList() + val newHashes = newWhiteList[it] ?: emptyList() + (existingHashes + newHashes).distinct() + } +} + +fun readExcludeWhitelist(directory: Path): List { + val file = directory / EXCLUDE_WHITELIST_FILE_NAME + return if (file.exists()) file.readAllLines().map(String::trim) else emptyList() +} \ No newline at end of file diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapperTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapperTest.kt index 59452aa0b2..b57c177d61 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapperTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/network/NetworkBootstrapperTest.kt @@ -127,7 +127,7 @@ class NetworkBootstrapperTest { private fun generateWhitelist(existingWhitelist: Map>, excludeContracts: List, contractJars: List): Map> { - return NetworkBootstrapper().generateWhitelist( + return generateWhitelist( testNetworkParameters(whitelistedContractImplementations = existingWhitelist), excludeContracts, contractJars diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/network/WhitelistGeneratorTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/network/WhitelistGeneratorTest.kt new file mode 100644 index 0000000000..67f4bb9641 --- /dev/null +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/network/WhitelistGeneratorTest.kt @@ -0,0 +1,41 @@ +package net.corda.nodeapi.internal.network + +import com.nhaarman.mockito_kotlin.mock +import com.nhaarman.mockito_kotlin.verify +import net.corda.core.crypto.SecureHash +import net.corda.nodeapi.internal.ContractsJar +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class WhitelistGeneratorTest { + + @Test + fun `whitelist generator builds the correct whitelist map`() { + // given + val jars = (0..9).map { + val index = it + mock { + val secureHash = SecureHash.randomSHA256() + on { scan() }.then { + listOf(index.toString()) + } + on { hash }.then { + secureHash + } + } + } + + // when + val result = generateWhitelist(null, emptyList(), jars) + + // then + jars.forEachIndexed { index, item -> + verify(item).scan() + val attachmentIds = requireNotNull(result[index.toString()]) + assertEquals(1, attachmentIds.size) + assertTrue { attachmentIds.contains(item.hash) } + } + } + +} \ No newline at end of file