mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
ENT-3256 Small performance enhancement and OS preparation for ENT changes (#4857)
This commit is contained in:
parent
96b23eea6f
commit
1c38ecee7b
@ -436,7 +436,7 @@ object Crypto {
|
|||||||
"Unsupported key/algorithm for schemeCodeName: ${signatureScheme.schemeCodeName}"
|
"Unsupported key/algorithm for schemeCodeName: ${signatureScheme.schemeCodeName}"
|
||||||
}
|
}
|
||||||
require(clearData.isNotEmpty()) { "Signing of an empty array is not permitted!" }
|
require(clearData.isNotEmpty()) { "Signing of an empty array is not permitted!" }
|
||||||
val signature = Signature.getInstance(signatureScheme.signatureName, providerMap[signatureScheme.providerName])
|
val signature = Instances.getSignatureInstance(signatureScheme.signatureName, providerMap[signatureScheme.providerName])
|
||||||
// Note that deterministic signature schemes, such as EdDSA, original SPHINCS-256 and RSA PKCS#1, do not require
|
// Note that deterministic signature schemes, such as EdDSA, original SPHINCS-256 and RSA PKCS#1, do not require
|
||||||
// extra randomness, but we have to ensure that non-deterministic algorithms (i.e., ECDSA) use non-blocking
|
// extra randomness, but we have to ensure that non-deterministic algorithms (i.e., ECDSA) use non-blocking
|
||||||
// SecureRandom implementation. Also, SPHINCS-256 implementation in BouncyCastle 1.60 fails with
|
// SecureRandom implementation. Also, SPHINCS-256 implementation in BouncyCastle 1.60 fails with
|
||||||
@ -640,7 +640,7 @@ object Crypto {
|
|||||||
require(isSupportedSignatureScheme(signatureScheme)) {
|
require(isSupportedSignatureScheme(signatureScheme)) {
|
||||||
"Unsupported key/algorithm for schemeCodeName: ${signatureScheme.schemeCodeName}"
|
"Unsupported key/algorithm for schemeCodeName: ${signatureScheme.schemeCodeName}"
|
||||||
}
|
}
|
||||||
val signature = Signature.getInstance(signatureScheme.signatureName, providerMap[signatureScheme.providerName])
|
val signature = Instances.getSignatureInstance(signatureScheme.signatureName, providerMap[signatureScheme.providerName])
|
||||||
signature.initVerify(publicKey)
|
signature.initVerify(publicKey)
|
||||||
signature.update(clearData)
|
signature.update(clearData)
|
||||||
return signature.verify(signatureData)
|
return signature.verify(signatureData)
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package net.corda.core.crypto.internal
|
||||||
|
|
||||||
|
import java.security.Provider
|
||||||
|
import java.security.Signature
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a collection of crypto related getInstance methods that tend to be quite inefficient and we want to be able to
|
||||||
|
* optimise them en masse.
|
||||||
|
*/
|
||||||
|
object Instances {
|
||||||
|
fun getSignatureInstance(algorithm: String, provider: Provider?) = Signature.getInstance(algorithm, provider)
|
||||||
|
}
|
@ -387,7 +387,17 @@ val Class<*>.location: URL get() = protectionDomain.codeSource.location
|
|||||||
|
|
||||||
/** 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.packageName
|
val KClass<*>.packageName: String get() = java.packageName
|
||||||
val Class<*>.packageName: String get() = requireNotNull(`package`?.name) { "$this not defined inside a package" }
|
val Class<*>.packageName: String get() = requireNotNull(this.packageNameOrNull) { "$this not defined inside a package" }
|
||||||
|
val Class<*>.packageNameOrNull: String? // This intentionally does not go via `package` as that code path is slow and contended and just ends up doing this.
|
||||||
|
get() {
|
||||||
|
val name = this.getName()
|
||||||
|
val i = name.lastIndexOf('.')
|
||||||
|
if (i != -1) {
|
||||||
|
return name.substring(0, i)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline val Class<*>.isAbstractClass: Boolean get() = Modifier.isAbstract(modifiers)
|
inline val Class<*>.isAbstractClass: Boolean get() = Modifier.isAbstract(modifiers)
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class StatePointerSearch(val state: ContractState) {
|
|||||||
val fieldsWithObjects = fields.mapNotNull { field ->
|
val fieldsWithObjects = fields.mapNotNull { field ->
|
||||||
// Ignore classes which have not been loaded.
|
// Ignore classes which have not been loaded.
|
||||||
// Assumption: all required state classes are already loaded.
|
// Assumption: all required state classes are already loaded.
|
||||||
val packageName = field.type.`package`?.name
|
val packageName = field.type.packageNameOrNull
|
||||||
if (packageName == null) {
|
if (packageName == null) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
@ -72,7 +72,7 @@ class StatePointerSearch(val state: ContractState) {
|
|||||||
is StatePointer<*> -> statePointers.add(obj)
|
is StatePointer<*> -> statePointers.add(obj)
|
||||||
is Iterable<*> -> handleIterable(obj)
|
is Iterable<*> -> handleIterable(obj)
|
||||||
else -> {
|
else -> {
|
||||||
val packageName = obj.javaClass.`package`.name
|
val packageName = obj.javaClass.packageNameOrNull ?: ""
|
||||||
val isBlackListed = blackListedPackages.any { packageName.startsWith(it) }
|
val isBlackListed = blackListedPackages.any { packageName.startsWith(it) }
|
||||||
if (isBlackListed.not()) fieldQueue.addAllFields(obj)
|
if (isBlackListed.not()) fieldQueue.addAllFields(obj)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.nodeapi.internal.crypto
|
|||||||
|
|
||||||
import net.corda.core.crypto.Crypto.SPHINCS256_SHA256
|
import net.corda.core.crypto.Crypto.SPHINCS256_SHA256
|
||||||
import net.corda.core.crypto.SignatureScheme
|
import net.corda.core.crypto.SignatureScheme
|
||||||
|
import net.corda.core.crypto.internal.Instances
|
||||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
||||||
import org.bouncycastle.operator.ContentSigner
|
import org.bouncycastle.operator.ContentSigner
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
@ -17,7 +18,7 @@ import java.security.Signature
|
|||||||
object ContentSignerBuilder {
|
object ContentSignerBuilder {
|
||||||
fun build(signatureScheme: SignatureScheme, privateKey: PrivateKey, provider: Provider, random: SecureRandom? = null): ContentSigner {
|
fun build(signatureScheme: SignatureScheme, privateKey: PrivateKey, provider: Provider, random: SecureRandom? = null): ContentSigner {
|
||||||
val sigAlgId = signatureScheme.signatureOID
|
val sigAlgId = signatureScheme.signatureOID
|
||||||
val sig = Signature.getInstance(signatureScheme.signatureName, provider).apply {
|
val sig = Instances.getSignatureInstance(signatureScheme.signatureName, provider).apply {
|
||||||
// TODO special handling for Sphincs due to a known BouncyCastle's Sphincs bug we reported.
|
// TODO special handling for Sphincs due to a known BouncyCastle's Sphincs bug we reported.
|
||||||
// It is fixed in BC 161b12, so consider updating the below if-statement after updating BouncyCastle.
|
// It is fixed in BC 161b12, so consider updating the below if-statement after updating BouncyCastle.
|
||||||
if (random != null && signatureScheme != SPHINCS256_SHA256) {
|
if (random != null && signatureScheme != SPHINCS256_SHA256) {
|
||||||
|
@ -35,7 +35,6 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.core.utilities.minutes
|
import net.corda.core.utilities.minutes
|
||||||
import net.corda.node.CordaClock
|
import net.corda.node.CordaClock
|
||||||
import net.corda.node.VersionInfo
|
import net.corda.node.VersionInfo
|
||||||
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
|
||||||
import net.corda.node.internal.classloading.requireAnnotation
|
import net.corda.node.internal.classloading.requireAnnotation
|
||||||
import net.corda.node.internal.cordapp.*
|
import net.corda.node.internal.cordapp.*
|
||||||
import net.corda.node.internal.rpc.proxies.AuthenticatedRpcOpsProxy
|
import net.corda.node.internal.rpc.proxies.AuthenticatedRpcOpsProxy
|
||||||
@ -74,6 +73,7 @@ import net.corda.node.utilities.*
|
|||||||
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
||||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||||
import net.corda.nodeapi.internal.config.CertificateStore
|
import net.corda.nodeapi.internal.config.CertificateStore
|
||||||
|
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
||||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||||
@ -184,7 +184,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
|||||||
@Suppress("LeakingThis")
|
@Suppress("LeakingThis")
|
||||||
val vaultService = makeVaultService(keyManagementService, servicesForResolution, database, cordappLoader).tokenize()
|
val vaultService = makeVaultService(keyManagementService, servicesForResolution, database, cordappLoader).tokenize()
|
||||||
val nodeProperties = NodePropertiesPersistentStore(StubbedNodeUniqueIdProvider::value, database, cacheFactory)
|
val nodeProperties = NodePropertiesPersistentStore(StubbedNodeUniqueIdProvider::value, database, cacheFactory)
|
||||||
val flowLogicRefFactory = FlowLogicRefFactoryImpl(cordappLoader.appClassLoader)
|
open val flowLogicRefFactory = FlowLogicRefFactoryImpl(cordappLoader.appClassLoader)
|
||||||
// TODO Cancelling parameters updates - if we do that, how we ensure that no one uses cancelled parameters in the transactions?
|
// TODO Cancelling parameters updates - if we do that, how we ensure that no one uses cancelled parameters in the transactions?
|
||||||
val networkMapUpdater = NetworkMapUpdater(
|
val networkMapUpdater = NetworkMapUpdater(
|
||||||
networkMapCache,
|
networkMapCache,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package net.corda.node.services.statemachine
|
package net.corda.node.services.statemachine
|
||||||
|
|
||||||
import net.corda.core.internal.VisibleForTesting
|
|
||||||
import com.google.common.primitives.Primitives
|
import com.google.common.primitives.Primitives
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
|
import net.corda.core.internal.VisibleForTesting
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import java.lang.reflect.ParameterizedType
|
import java.lang.reflect.ParameterizedType
|
||||||
@ -32,7 +32,7 @@ data class FlowLogicRefImpl internal constructor(val flowLogicClassName: String,
|
|||||||
* in response to a potential malicious use or buggy update to an app etc.
|
* in response to a potential malicious use or buggy update to an app etc.
|
||||||
*/
|
*/
|
||||||
// TODO: Replace with a per app classloader/cordapp provider/cordapp loader - this will do for now
|
// TODO: Replace with a per app classloader/cordapp provider/cordapp loader - this will do for now
|
||||||
class FlowLogicRefFactoryImpl(private val classloader: ClassLoader) : SingletonSerializeAsToken(), FlowLogicRefFactory {
|
open class FlowLogicRefFactoryImpl(private val classloader: ClassLoader) : SingletonSerializeAsToken(), FlowLogicRefFactory {
|
||||||
override fun create(flowClass: Class<out FlowLogic<*>>, vararg args: Any?): FlowLogicRef {
|
override fun create(flowClass: Class<out FlowLogic<*>>, vararg args: Any?): FlowLogicRef {
|
||||||
if (!flowClass.isAnnotationPresent(SchedulableFlow::class.java)) {
|
if (!flowClass.isAnnotationPresent(SchedulableFlow::class.java)) {
|
||||||
throw IllegalFlowLogicException(flowClass, "because it's not a schedulable flow")
|
throw IllegalFlowLogicException(flowClass, "because it's not a schedulable flow")
|
||||||
@ -63,17 +63,7 @@ class FlowLogicRefFactoryImpl(private val classloader: ClassLoader) : SingletonS
|
|||||||
// to avoid requiring only a single constructor.
|
// to avoid requiring only a single constructor.
|
||||||
val argTypes = args.map { it?.javaClass }
|
val argTypes = args.map { it?.javaClass }
|
||||||
val constructor = try {
|
val constructor = try {
|
||||||
flowClass.kotlin.constructors.single { ctor ->
|
findConstructor(flowClass, argTypes)
|
||||||
// Get the types of the arguments, always boxed (as that's what we get in the invocation).
|
|
||||||
val ctorTypes = ctor.javaConstructor!!.parameterTypes.map { Primitives.wrap(it) }
|
|
||||||
if (argTypes.size != ctorTypes.size)
|
|
||||||
return@single false
|
|
||||||
for ((argType, ctorType) in argTypes.zip(ctorTypes)) {
|
|
||||||
if (argType == null) continue // Try and find a match based on the other arguments.
|
|
||||||
if (!ctorType.isAssignableFrom(argType)) return@single false
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
throw IllegalFlowLogicException(flowClass, "due to ambiguous match against the constructors: $argTypes")
|
throw IllegalFlowLogicException(flowClass, "due to ambiguous match against the constructors: $argTypes")
|
||||||
} catch (e: NoSuchElementException) {
|
} catch (e: NoSuchElementException) {
|
||||||
@ -85,6 +75,20 @@ class FlowLogicRefFactoryImpl(private val classloader: ClassLoader) : SingletonS
|
|||||||
return createKotlin(flowClass, argsMap)
|
return createKotlin(flowClass, argsMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun findConstructor(flowClass: Class<out FlowLogic<*>>, argTypes: List<Class<Any>?>): KFunction<FlowLogic<*>> {
|
||||||
|
return flowClass.kotlin.constructors.single { ctor ->
|
||||||
|
// Get the types of the arguments, always boxed (as that's what we get in the invocation).
|
||||||
|
val ctorTypes = ctor.javaConstructor!!.parameterTypes.map { Primitives.wrap(it) }
|
||||||
|
if (argTypes.size != ctorTypes.size)
|
||||||
|
return@single false
|
||||||
|
for ((argType, ctorType) in argTypes.zip(ctorTypes)) {
|
||||||
|
if (argType == null) continue // Try and find a match based on the other arguments.
|
||||||
|
if (!ctorType.isAssignableFrom(argType)) return@single false
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a [FlowLogicRef] by trying to find a Kotlin constructor that matches the given args.
|
* Create a [FlowLogicRef] by trying to find a Kotlin constructor that matches the given args.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user