mirror of
https://github.com/corda/corda.git
synced 2025-06-14 13:18:18 +00:00
CORDA-1593 Extracting the whitelist logic and making it public (#3317)
* CORDA-1539 Extracting the whitelist logic and making it public * Addressing review comments
This commit is contained in:
@ -3,7 +3,6 @@ package net.corda.nodeapi.internal.network
|
|||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
import net.corda.core.contracts.ContractClassName
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
@ -55,7 +54,6 @@ class NetworkBootstrapper {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private const val LOGS_DIR_NAME = "logs"
|
private const val LOGS_DIR_NAME = "logs"
|
||||||
private const val EXCLUDE_WHITELIST_FILE_NAME = "exclude_whitelist.txt"
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
@ -291,35 +289,6 @@ class NetworkBootstrapper {
|
|||||||
return networkParameters
|
return networkParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
internal fun generateWhitelist(networkParameters: NetworkParameters?,
|
|
||||||
excludeContracts: List<ContractClassName>,
|
|
||||||
cordappJars: List<ContractsJar>): Map<ContractClassName, List<AttachmentId>> {
|
|
||||||
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<String> {
|
|
||||||
val file = directory / EXCLUDE_WHITELIST_FILE_NAME
|
|
||||||
return if (file.exists()) file.readAllLines().map(String::trim) else emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun NodeInfo.notaryIdentity(): Party {
|
private fun NodeInfo.notaryIdentity(): Party {
|
||||||
return when (legalIdentities.size) {
|
return when (legalIdentities.size) {
|
||||||
// Single node notaries have just one identity like all other nodes. This identity is the notary identity
|
// Single node notaries have just one identity like all other nodes. This identity is the notary identity
|
||||||
|
@ -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<ContractClassName>,
|
||||||
|
cordappJars: List<ContractsJar>): Map<ContractClassName, List<AttachmentId>> {
|
||||||
|
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<String> {
|
||||||
|
val file = directory / EXCLUDE_WHITELIST_FILE_NAME
|
||||||
|
return if (file.exists()) file.readAllLines().map(String::trim) else emptyList()
|
||||||
|
}
|
@ -127,7 +127,7 @@ class NetworkBootstrapperTest {
|
|||||||
private fun generateWhitelist(existingWhitelist: Map<String, List<AttachmentId>>,
|
private fun generateWhitelist(existingWhitelist: Map<String, List<AttachmentId>>,
|
||||||
excludeContracts: List<ContractClassName>,
|
excludeContracts: List<ContractClassName>,
|
||||||
contractJars: List<TestContractsJar>): Map<String, List<AttachmentId>> {
|
contractJars: List<TestContractsJar>): Map<String, List<AttachmentId>> {
|
||||||
return NetworkBootstrapper().generateWhitelist(
|
return generateWhitelist(
|
||||||
testNetworkParameters(whitelistedContractImplementations = existingWhitelist),
|
testNetworkParameters(whitelistedContractImplementations = existingWhitelist),
|
||||||
excludeContracts,
|
excludeContracts,
|
||||||
contractJars
|
contractJars
|
||||||
|
@ -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<ContractsJar> {
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user