mirror of
https://github.com/corda/corda.git
synced 2025-02-26 11:20:44 +00:00
commit
ff41f7f1ba
@ -42,7 +42,7 @@ dependencies {
|
|||||||
compile project(':finance')
|
compile project(':finance')
|
||||||
compile project(':client:rpc')
|
compile project(':client:rpc')
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "com.google.guava:guava:$guava_version"
|
compile "com.google.guava:guava:$guava_version"
|
||||||
|
|
||||||
// ReactFX: Functional reactive UI programming.
|
// ReactFX: Functional reactive UI programming.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
# Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
|
# Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
|
||||||
#
|
#
|
||||||
|
|
||||||
gradlePluginsVersion=4.0.13
|
gradlePluginsVersion=4.0.14
|
||||||
kotlinVersion=1.2.20
|
kotlinVersion=1.2.20
|
||||||
platformVersion=4
|
platformVersion=4
|
||||||
guavaVersion=21.0
|
guavaVersion=21.0
|
||||||
|
@ -83,7 +83,7 @@ dependencies {
|
|||||||
testCompile project(":node")
|
testCompile project(":node")
|
||||||
testCompile project(":node-driver")
|
testCompile project(":node-driver")
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ import rx.subjects.PublishSubject
|
|||||||
import rx.subjects.UnicastSubject
|
import rx.subjects.UnicastSubject
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.HttpURLConnection.HTTP_OK
|
import java.net.HttpURLConnection.HTTP_OK
|
||||||
@ -316,6 +317,10 @@ fun TransactionBuilder.toLedgerTransaction(services: ServicesForResolution, seri
|
|||||||
/** Convenience method to get the package name of a class literal. */
|
/** Convenience method to get the package name of a class literal. */
|
||||||
val KClass<*>.packageName: String get() = java.`package`.name
|
val KClass<*>.packageName: String get() = java.`package`.name
|
||||||
|
|
||||||
|
inline val Class<*>.isAbstractClass: Boolean get() = Modifier.isAbstract(modifiers)
|
||||||
|
|
||||||
|
inline val Class<*>.isConcreteClass: Boolean get() = !isInterface && !isAbstractClass
|
||||||
|
|
||||||
fun URI.toPath(): Path = Paths.get(this)
|
fun URI.toPath(): Path = Paths.get(this)
|
||||||
|
|
||||||
fun URL.toPath(): Path = toURI().toPath()
|
fun URL.toPath(): Path = toURI().toPath()
|
||||||
|
@ -58,7 +58,7 @@ dependencies {
|
|||||||
|
|
||||||
// Library
|
// Library
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
|
|
||||||
compile("com.github.corda.crash:crash.shell:$crash_version") {
|
compile("com.github.corda.crash:crash.shell:$crash_version") {
|
||||||
|
@ -41,7 +41,7 @@ description 'A javaagent to allow hooking into Kryo'
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':node')
|
compile project(':node')
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
compile "javassist:javassist:$javaassist_version"
|
compile "javassist:javassist:$javaassist_version"
|
||||||
compile "com.esotericsoftware:kryo:4.0.0"
|
compile "com.esotericsoftware:kryo:4.0.0"
|
||||||
|
@ -40,7 +40,7 @@ apply plugin: 'idea'
|
|||||||
description 'A javaagent to allow hooking into Kryo'
|
description 'A javaagent to allow hooking into Kryo'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
compile "javassist:javassist:$javaassist_version"
|
compile "javassist:javassist:$javaassist_version"
|
||||||
compile "com.esotericsoftware:kryo:4.0.0"
|
compile "com.esotericsoftware:kryo:4.0.0"
|
||||||
|
@ -40,7 +40,7 @@ apply plugin: 'idea'
|
|||||||
description 'A javaagent to allow hooking into the instrumentation by Quasar'
|
description 'A javaagent to allow hooking into the instrumentation by Quasar'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
compile "javassist:javassist:$javaassist_version"
|
compile "javassist:javassist:$javaassist_version"
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ dependencies {
|
|||||||
|
|
||||||
compile project(':node-api')
|
compile project(':node-api')
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
// Log4J: logging framework (with SLF4J bindings)
|
// Log4J: logging framework (with SLF4J bindings)
|
||||||
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
|
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
|
||||||
@ -84,7 +84,7 @@ dependencies {
|
|||||||
compile "net.sf.jopt-simple:jopt-simple:5.0.2"
|
compile "net.sf.jopt-simple:jopt-simple:5.0.2"
|
||||||
|
|
||||||
// TypeSafe Config: for simple and human friendly config files.
|
// TypeSafe Config: for simple and human friendly config files.
|
||||||
compile "com.typesafe:config:1.3.0"
|
compile "com.typesafe:config:$typesafe_config_version"
|
||||||
|
|
||||||
// Hibernate audit plugin
|
// Hibernate audit plugin
|
||||||
compile "org.hibernate:hibernate-envers:5.2.11.Final"
|
compile "org.hibernate:hibernate-envers:5.2.11.Final"
|
||||||
@ -96,7 +96,7 @@ dependencies {
|
|||||||
testCompile project(':node-driver')
|
testCompile project(':node-driver')
|
||||||
|
|
||||||
// Unit testing helpers.
|
// Unit testing helpers.
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile "junit:junit:$junit_version"
|
||||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||||
testCompile "com.nhaarman:mockito-kotlin:0.6.1"
|
testCompile "com.nhaarman:mockito-kotlin:0.6.1"
|
||||||
testCompile "com.spotify:docker-client:8.9.1"
|
testCompile "com.spotify:docker-client:8.9.1"
|
||||||
|
@ -20,7 +20,7 @@ description 'Corda node API'
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
@ -15,13 +15,10 @@ import net.corda.core.contracts.Contract
|
|||||||
import net.corda.core.contracts.ContractClassName
|
import net.corda.core.contracts.ContractClassName
|
||||||
import net.corda.core.contracts.UpgradedContract
|
import net.corda.core.contracts.UpgradedContract
|
||||||
import net.corda.core.contracts.UpgradedContractWithLegacyConstraint
|
import net.corda.core.contracts.UpgradedContractWithLegacyConstraint
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.internal.deleteIfExists
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.logElapsedTime
|
|
||||||
import net.corda.core.internal.read
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.lang.reflect.Modifier
|
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -32,22 +29,33 @@ import java.util.Collections.singleton
|
|||||||
// relationships between those interfaces, therefore they have to be listed explicitly.
|
// relationships between those interfaces, therefore they have to be listed explicitly.
|
||||||
val coreContractClasses = setOf(Contract::class, UpgradedContractWithLegacyConstraint::class, UpgradedContract::class)
|
val coreContractClasses = setOf(Contract::class, UpgradedContractWithLegacyConstraint::class, UpgradedContract::class)
|
||||||
|
|
||||||
/**
|
interface ContractsJar {
|
||||||
* Scans the jar for contracts.
|
val hash: SecureHash
|
||||||
* @returns: found contract class names or null if none found
|
fun scan(): List<ContractClassName>
|
||||||
*/
|
}
|
||||||
fun scanJarForContracts(cordappJar: Path): List<ContractClassName> {
|
|
||||||
|
class ContractsJarFile(private val file: Path) : ContractsJar {
|
||||||
|
override val hash: SecureHash by lazy(LazyThreadSafetyMode.NONE, file::hash)
|
||||||
|
|
||||||
|
override fun scan(): List<ContractClassName> {
|
||||||
val scanResult = FastClasspathScanner()
|
val scanResult = FastClasspathScanner()
|
||||||
// A set of a single element may look odd, but if this is removed "Path" which itself is an `Iterable`
|
// A set of a single element may look odd, but if this is removed "Path" which itself is an `Iterable`
|
||||||
// is getting broken into pieces to scan individually, which doesn't yield desired effect.
|
// is getting broken into pieces to scan individually, which doesn't yield desired effect.
|
||||||
.overrideClasspath(singleton(cordappJar))
|
.overrideClasspath(singleton(file))
|
||||||
.scan()
|
.scan()
|
||||||
val contracts = coreContractClasses.flatMap { contractClass -> scanResult.getNamesOfClassesImplementing(contractClass.qualifiedName) }.distinct()
|
|
||||||
|
|
||||||
|
val contractClassNames = coreContractClasses
|
||||||
|
.flatMap { scanResult.getNamesOfClassesImplementing(it.qualifiedName) }
|
||||||
|
.toSet()
|
||||||
|
|
||||||
|
return URLClassLoader(arrayOf(file.toUri().toURL()), Contract::class.java.classLoader).use { cl ->
|
||||||
|
contractClassNames.mapNotNull {
|
||||||
|
val contractClass = cl.loadClass(it)
|
||||||
// Only keep instantiable contracts
|
// Only keep instantiable contracts
|
||||||
return URLClassLoader(arrayOf(cordappJar.toUri().toURL()), Contract::class.java.classLoader).use {
|
if (contractClass.isConcreteClass) contractClass.name else null
|
||||||
contracts.map(it::loadClass).filter { !it.isInterface && !Modifier.isAbstract(it.modifiers) }
|
}
|
||||||
}.map { it.name }
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger("ClassloaderUtils")
|
private val logger = LoggerFactory.getLogger("ClassloaderUtils")
|
||||||
@ -58,7 +66,7 @@ fun <T> withContractsInJar(jarInputStream: InputStream, withContracts: (List<Con
|
|||||||
jarInputStream.copyTo(tempFile, StandardCopyOption.REPLACE_EXISTING)
|
jarInputStream.copyTo(tempFile, StandardCopyOption.REPLACE_EXISTING)
|
||||||
val cordappJar = tempFile.toAbsolutePath()
|
val cordappJar = tempFile.toAbsolutePath()
|
||||||
val contracts = logElapsedTime("Contracts loading for '$cordappJar'", logger) {
|
val contracts = logElapsedTime("Contracts loading for '$cordappJar'", logger) {
|
||||||
scanJarForContracts(cordappJar)
|
ContractsJarFile(tempFile.toAbsolutePath()).scan()
|
||||||
}
|
}
|
||||||
return tempFile.read { withContracts(contracts, it) }
|
return tempFile.read { withContracts(contracts, it) }
|
||||||
} finally {
|
} finally {
|
@ -12,6 +12,7 @@ package net.corda.nodeapi.internal.network
|
|||||||
|
|
||||||
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.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.concurrent.fork
|
import net.corda.core.internal.concurrent.fork
|
||||||
@ -26,10 +27,11 @@ import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
|||||||
import net.corda.core.serialization.internal._contextSerializationEnv
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
|
import net.corda.nodeapi.internal.ContractsJar
|
||||||
|
import net.corda.nodeapi.internal.ContractsJarFile
|
||||||
import net.corda.nodeapi.internal.DEV_ROOT_CA
|
import net.corda.nodeapi.internal.DEV_ROOT_CA
|
||||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||||
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier.Companion.NODE_INFO_FILE_NAME_PREFIX
|
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier.Companion.NODE_INFO_FILE_NAME_PREFIX
|
||||||
import net.corda.nodeapi.internal.scanJarForContracts
|
|
||||||
import net.corda.nodeapi.internal.serialization.AMQP_P2P_CONTEXT
|
import net.corda.nodeapi.internal.serialization.AMQP_P2P_CONTEXT
|
||||||
import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
||||||
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
||||||
@ -88,7 +90,7 @@ class NetworkBootstrapper {
|
|||||||
println("Gathering notary identities")
|
println("Gathering notary identities")
|
||||||
val notaryInfos = gatherNotaryInfos(nodeInfoFiles)
|
val notaryInfos = gatherNotaryInfos(nodeInfoFiles)
|
||||||
println("Generating contract implementations whitelist")
|
println("Generating contract implementations whitelist")
|
||||||
val newWhitelist = generateWhitelist(existingNetParams, directory / EXCLUDE_WHITELIST_FILE_NAME, cordappJars)
|
val newWhitelist = generateWhitelist(existingNetParams, readExcludeWhitelist(directory), cordappJars.map(::ContractsJarFile))
|
||||||
val netParams = installNetworkParameters(notaryInfos, newWhitelist, existingNetParams, nodeDirs)
|
val netParams = installNetworkParameters(notaryInfos, newWhitelist, existingNetParams, nodeDirs)
|
||||||
println("${if (existingNetParams == null) "New" else "Updated"} $netParams")
|
println("${if (existingNetParams == null) "New" else "Updated"} $netParams")
|
||||||
println("Bootstrapping complete!")
|
println("Bootstrapping complete!")
|
||||||
@ -238,29 +240,32 @@ class NetworkBootstrapper {
|
|||||||
return networkParameters
|
return networkParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateWhitelist(networkParameters: NetworkParameters?,
|
@VisibleForTesting
|
||||||
excludeWhitelistFile: Path,
|
internal fun generateWhitelist(networkParameters: NetworkParameters?,
|
||||||
cordappJars: List<Path>): Map<String, List<AttachmentId>> {
|
excludeContracts: List<ContractClassName>,
|
||||||
|
cordappJars: List<ContractsJar>): Map<ContractClassName, List<AttachmentId>> {
|
||||||
val existingWhitelist = networkParameters?.whitelistedContractImplementations ?: emptyMap()
|
val existingWhitelist = networkParameters?.whitelistedContractImplementations ?: emptyMap()
|
||||||
|
|
||||||
val excludeContracts = readExcludeWhitelist(excludeWhitelistFile)
|
|
||||||
if (excludeContracts.isNotEmpty()) {
|
if (excludeContracts.isNotEmpty()) {
|
||||||
println("Exclude contracts from whitelist: ${excludeContracts.joinToString()}")
|
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 { cordappJar ->
|
val newWhiteList = cordappJars
|
||||||
val jarHash = cordappJar.hash
|
.flatMap { jar -> (jar.scan() - excludeContracts).map { it to jar.hash } }
|
||||||
scanJarForContracts(cordappJar).map { contract -> contract to jarHash }
|
.toMultiMap()
|
||||||
}.filter { (contractClassName, _) -> contractClassName !in excludeContracts }.toMap()
|
|
||||||
|
|
||||||
return (newWhiteList.keys + existingWhitelist.keys).map { contractClassName ->
|
return (newWhiteList.keys + existingWhitelist.keys).associateBy({ it }) {
|
||||||
val existing = existingWhitelist[contractClassName] ?: emptyList()
|
val existingHashes = existingWhitelist[it] ?: emptyList()
|
||||||
val newHash = newWhiteList[contractClassName]
|
val newHashes = newWhiteList[it] ?: emptyList()
|
||||||
contractClassName to (if (newHash == null || newHash in existing) existing else existing + newHash)
|
(existingHashes + newHashes).distinct()
|
||||||
}.toMap()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readExcludeWhitelist(file: Path): List<String> {
|
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()
|
return if (file.exists()) file.readAllLines().map(String::trim) else emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,141 @@
|
|||||||
|
package net.corda.nodeapi.internal.network
|
||||||
|
|
||||||
|
import net.corda.core.contracts.ContractClassName
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.node.services.AttachmentId
|
||||||
|
import net.corda.nodeapi.internal.ContractsJar
|
||||||
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class NetworkBootstrapperTest {
|
||||||
|
@Test
|
||||||
|
fun `no jars against empty whitelist`() {
|
||||||
|
val whitelist = generateWhitelist(emptyMap(), emptyList(), emptyList())
|
||||||
|
assertThat(whitelist).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `no jars against single whitelist`() {
|
||||||
|
val existingWhitelist = mapOf("class1" to listOf(SecureHash.randomSHA256()))
|
||||||
|
val newWhitelist = generateWhitelist(existingWhitelist, emptyList(), emptyList())
|
||||||
|
assertThat(newWhitelist).isEqualTo(existingWhitelist)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `empty jar against empty whitelist`() {
|
||||||
|
val whitelist = generateWhitelist(emptyMap(), emptyList(), listOf(TestContractsJar(contractClassNames = emptyList())))
|
||||||
|
assertThat(whitelist).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `empty jar against single whitelist`() {
|
||||||
|
val existingWhitelist = mapOf("class1" to listOf(SecureHash.randomSHA256()))
|
||||||
|
val newWhitelist = generateWhitelist(existingWhitelist, emptyList(), listOf(TestContractsJar(contractClassNames = emptyList())))
|
||||||
|
assertThat(newWhitelist).isEqualTo(existingWhitelist)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `jar with single contract against empty whitelist`() {
|
||||||
|
val jar = TestContractsJar(contractClassNames = listOf("class1"))
|
||||||
|
val whitelist = generateWhitelist(emptyMap(), emptyList(), listOf(jar))
|
||||||
|
assertThat(whitelist).isEqualTo(mapOf(
|
||||||
|
"class1" to listOf(jar.hash)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `single contract jar against single whitelist of different contract`() {
|
||||||
|
val class1JarHash = SecureHash.randomSHA256()
|
||||||
|
val existingWhitelist = mapOf("class1" to listOf(class1JarHash))
|
||||||
|
val jar = TestContractsJar(contractClassNames = listOf("class2"))
|
||||||
|
val whitelist = generateWhitelist(existingWhitelist, emptyList(), listOf(jar))
|
||||||
|
assertThat(whitelist).isEqualTo(mapOf(
|
||||||
|
"class1" to listOf(class1JarHash),
|
||||||
|
"class2" to listOf(jar.hash)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `same jar with single contract`() {
|
||||||
|
val jarHash = SecureHash.randomSHA256()
|
||||||
|
val existingWhitelist = mapOf("class1" to listOf(jarHash))
|
||||||
|
val jar = TestContractsJar(hash = jarHash, contractClassNames = listOf("class1"))
|
||||||
|
val newWhitelist = generateWhitelist(existingWhitelist, emptyList(), listOf(jar))
|
||||||
|
assertThat(newWhitelist).isEqualTo(existingWhitelist)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `jar with updated contract`() {
|
||||||
|
val previousJarHash = SecureHash.randomSHA256()
|
||||||
|
val existingWhitelist = mapOf("class1" to listOf(previousJarHash))
|
||||||
|
val newContractsJar = TestContractsJar(contractClassNames = listOf("class1"))
|
||||||
|
val newWhitelist = generateWhitelist(existingWhitelist, emptyList(), listOf(newContractsJar))
|
||||||
|
assertThat(newWhitelist).isEqualTo(mapOf(
|
||||||
|
"class1" to listOf(previousJarHash, newContractsJar.hash)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `jar with one existing contract and one new one`() {
|
||||||
|
val previousJarHash = SecureHash.randomSHA256()
|
||||||
|
val existingWhitelist = mapOf("class1" to listOf(previousJarHash))
|
||||||
|
val newContractsJar = TestContractsJar(contractClassNames = listOf("class1", "class2"))
|
||||||
|
val newWhitelist = generateWhitelist(existingWhitelist, emptyList(), listOf(newContractsJar))
|
||||||
|
assertThat(newWhitelist).isEqualTo(mapOf(
|
||||||
|
"class1" to listOf(previousJarHash, newContractsJar.hash),
|
||||||
|
"class2" to listOf(newContractsJar.hash)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `two versions of the same contract`() {
|
||||||
|
val version1Jar = TestContractsJar(contractClassNames = listOf("class1"))
|
||||||
|
val version2Jar = TestContractsJar(contractClassNames = listOf("class1"))
|
||||||
|
val newWhitelist = generateWhitelist(emptyMap(), emptyList(), listOf(version1Jar, version2Jar))
|
||||||
|
assertThat(newWhitelist).isEqualTo(mapOf(
|
||||||
|
"class1" to listOf(version1Jar.hash, version2Jar.hash)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `jar with single new contract that's excluded`() {
|
||||||
|
val jar = TestContractsJar(contractClassNames = listOf("class1"))
|
||||||
|
val whitelist = generateWhitelist(emptyMap(), listOf("class1"), listOf(jar))
|
||||||
|
assertThat(whitelist).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `jar with two new contracts, one of which is excluded`() {
|
||||||
|
val jar = TestContractsJar(contractClassNames = listOf("class1", "class2"))
|
||||||
|
val whitelist = generateWhitelist(emptyMap(), listOf("class1"), listOf(jar))
|
||||||
|
assertThat(whitelist).isEqualTo(mapOf(
|
||||||
|
"class2" to listOf(jar.hash)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `jar with updated contract but it's excluded`() {
|
||||||
|
val existingWhitelist = mapOf("class1" to listOf(SecureHash.randomSHA256()))
|
||||||
|
val jar = TestContractsJar(contractClassNames = listOf("class1"))
|
||||||
|
assertThatIllegalArgumentException().isThrownBy {
|
||||||
|
generateWhitelist(existingWhitelist, listOf("class1"), listOf(jar))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateWhitelist(existingWhitelist: Map<String, List<AttachmentId>>,
|
||||||
|
excludeContracts: List<ContractClassName>,
|
||||||
|
contractJars: List<TestContractsJar>): Map<String, List<AttachmentId>> {
|
||||||
|
return NetworkBootstrapper().generateWhitelist(
|
||||||
|
testNetworkParameters(whitelistedContractImplementations = existingWhitelist),
|
||||||
|
excludeContracts,
|
||||||
|
contractJars
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class TestContractsJar(override val hash: SecureHash = SecureHash.randomSHA256(),
|
||||||
|
private val contractClassNames: List<ContractClassName>) : ContractsJar {
|
||||||
|
override fun scan(): List<ContractClassName> = contractClassNames
|
||||||
|
}
|
||||||
|
}
|
@ -85,7 +85,7 @@ dependencies {
|
|||||||
compile "org.apache.logging.log4j:log4j-web:${log4j_version}"
|
compile "org.apache.logging.log4j:log4j-web:${log4j_version}"
|
||||||
compile "org.slf4j:jul-to-slf4j:$slf4j_version"
|
compile "org.slf4j:jul-to-slf4j:$slf4j_version"
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
testCompile "junit:junit:$junit_version"
|
testCompile "junit:junit:$junit_version"
|
||||||
|
|
||||||
// Corda integration dependencies
|
// Corda integration dependencies
|
||||||
|
@ -36,7 +36,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
// The bank of corda CorDapp depends upon Cash CorDapp features
|
// The bank of corda CorDapp depends upon Cash CorDapp features
|
||||||
cordapp project(':finance')
|
cordapp project(':finance')
|
||||||
|
@ -27,7 +27,7 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
// For CSV parsing.
|
// For CSV parsing.
|
||||||
compile "com.opencsv:opencsv:4.0"
|
compile "com.opencsv:opencsv:4.0"
|
||||||
|
@ -25,7 +25,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
testCompile "junit:junit:$junit_version"
|
testCompile "junit:junit:$junit_version"
|
||||||
|
|
||||||
// Corda integration dependencies
|
// Corda integration dependencies
|
||||||
|
@ -40,7 +40,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
// The SIMM demo CorDapp depends upon Cash CorDapp features
|
// The SIMM demo CorDapp depends upon Cash CorDapp features
|
||||||
cordapp project(':finance')
|
cordapp project(':finance')
|
||||||
|
@ -36,7 +36,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
// The trader demo CorDapp depends upon Cash CorDapp features
|
// The trader demo CorDapp depends upon Cash CorDapp features
|
||||||
cordapp project(':finance')
|
cordapp project(':finance')
|
||||||
|
@ -34,7 +34,7 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
compile fileTree(dir: 'libs', include: '*.jar')
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ dependencies {
|
|||||||
compile "com.typesafe:config:$typesafe_config_version"
|
compile "com.typesafe:config:$typesafe_config_version"
|
||||||
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
|
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
|
||||||
|
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
testCompile group: 'junit', name: 'junit', version: junit_version
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
testCompile "junit:junit:$junit_version"
|
testCompile "junit:junit:$junit_version"
|
||||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ package net.corda.testing.common.internal
|
|||||||
|
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.node.NotaryInfo
|
import net.corda.core.node.NotaryInfo
|
||||||
|
import net.corda.core.node.services.AttachmentId
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
fun testNetworkParameters(
|
fun testNetworkParameters(
|
||||||
@ -21,15 +22,16 @@ fun testNetworkParameters(
|
|||||||
maxMessageSize: Int = 10485760,
|
maxMessageSize: Int = 10485760,
|
||||||
// TODO: Make this configurable and consistence across driver, bootstrapper, demobench and NetworkMapServer
|
// TODO: Make this configurable and consistence across driver, bootstrapper, demobench and NetworkMapServer
|
||||||
maxTransactionSize: Int = maxMessageSize,
|
maxTransactionSize: Int = maxMessageSize,
|
||||||
|
whitelistedContractImplementations: Map<String, List<AttachmentId>> = emptyMap(),
|
||||||
epoch: Int = 1
|
epoch: Int = 1
|
||||||
): NetworkParameters {
|
): NetworkParameters {
|
||||||
return NetworkParameters(
|
return NetworkParameters(
|
||||||
minimumPlatformVersion = minimumPlatformVersion,
|
minimumPlatformVersion = minimumPlatformVersion,
|
||||||
notaries = notaries,
|
notaries = notaries,
|
||||||
modifiedTime = modifiedTime,
|
|
||||||
maxMessageSize = maxMessageSize,
|
maxMessageSize = maxMessageSize,
|
||||||
maxTransactionSize = maxTransactionSize,
|
maxTransactionSize = maxTransactionSize,
|
||||||
epoch = epoch,
|
whitelistedContractImplementations = whitelistedContractImplementations,
|
||||||
whitelistedContractImplementations = emptyMap()
|
modifiedTime = modifiedTime,
|
||||||
|
epoch = epoch
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -22,7 +22,7 @@ dependencies {
|
|||||||
compile project(':node')
|
compile project(':node')
|
||||||
compile project(':client:mock')
|
compile project(':client:mock')
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ processResources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
testCompile "junit:junit:$junit_version"
|
testCompile "junit:junit:$junit_version"
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ apply plugin: 'net.corda.plugins.cordformation'
|
|||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
testCompile "junit:junit:$junit_version"
|
testCompile "junit:junit:$junit_version"
|
||||||
|
|
||||||
// Corda integration dependencies
|
// Corda integration dependencies
|
||||||
|
@ -49,7 +49,7 @@ dependencies {
|
|||||||
// TODO think about this.
|
// TODO think about this.
|
||||||
compile project(':node-api')
|
compile project(':node-api')
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user