mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +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}"
|
||||
}
|
||||
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
|
||||
// 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
|
||||
@ -640,7 +640,7 @@ object Crypto {
|
||||
require(isSupportedSignatureScheme(signatureScheme)) {
|
||||
"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.update(clearData)
|
||||
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. */
|
||||
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)
|
||||
|
||||
|
@ -43,7 +43,7 @@ class StatePointerSearch(val state: ContractState) {
|
||||
val fieldsWithObjects = fields.mapNotNull { field ->
|
||||
// Ignore classes which have not been loaded.
|
||||
// Assumption: all required state classes are already loaded.
|
||||
val packageName = field.type.`package`?.name
|
||||
val packageName = field.type.packageNameOrNull
|
||||
if (packageName == null) {
|
||||
null
|
||||
} else {
|
||||
@ -72,7 +72,7 @@ class StatePointerSearch(val state: ContractState) {
|
||||
is StatePointer<*> -> statePointers.add(obj)
|
||||
is Iterable<*> -> handleIterable(obj)
|
||||
else -> {
|
||||
val packageName = obj.javaClass.`package`.name
|
||||
val packageName = obj.javaClass.packageNameOrNull ?: ""
|
||||
val isBlackListed = blackListedPackages.any { packageName.startsWith(it) }
|
||||
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.SignatureScheme
|
||||
import net.corda.core.crypto.internal.Instances
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
||||
import org.bouncycastle.operator.ContentSigner
|
||||
import java.io.OutputStream
|
||||
@ -17,7 +18,7 @@ import java.security.Signature
|
||||
object ContentSignerBuilder {
|
||||
fun build(signatureScheme: SignatureScheme, privateKey: PrivateKey, provider: Provider, random: SecureRandom? = null): ContentSigner {
|
||||
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.
|
||||
// It is fixed in BC 161b12, so consider updating the below if-statement after updating BouncyCastle.
|
||||
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.node.CordaClock
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
||||
import net.corda.node.internal.classloading.requireAnnotation
|
||||
import net.corda.node.internal.cordapp.*
|
||||
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.SignedNodeInfo
|
||||
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.X509Utilities
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||
@ -184,7 +184,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
@Suppress("LeakingThis")
|
||||
val vaultService = makeVaultService(keyManagementService, servicesForResolution, database, cordappLoader).tokenize()
|
||||
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?
|
||||
val networkMapUpdater = NetworkMapUpdater(
|
||||
networkMapCache,
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.corda.node.services.statemachine
|
||||
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import com.google.common.primitives.Primitives
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
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.
|
||||
*/
|
||||
// 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 {
|
||||
if (!flowClass.isAnnotationPresent(SchedulableFlow::class.java)) {
|
||||
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.
|
||||
val argTypes = args.map { it?.javaClass }
|
||||
val constructor = try {
|
||||
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
|
||||
}
|
||||
findConstructor(flowClass, argTypes)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw IllegalFlowLogicException(flowClass, "due to ambiguous match against the constructors: $argTypes")
|
||||
} catch (e: NoSuchElementException) {
|
||||
@ -85,6 +75,20 @@ class FlowLogicRefFactoryImpl(private val classloader: ClassLoader) : SingletonS
|
||||
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.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user