diff --git a/core/build.gradle b/core/build.gradle index 889476111a..ea991614f7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -133,6 +133,9 @@ dependencies { // required to use @Type annotation compile "org.hibernate:hibernate-core:$hibernate_version" + + // FastThreadLocal + compile "io.netty:netty-common:$netty_version" } // TODO Consider moving it to quasar-utils in the future (introduced with PR-1388) diff --git a/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt b/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt index 3fe8acdce3..c804fb63f8 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt @@ -10,6 +10,7 @@ package net.corda.core.crypto +import io.netty.util.concurrent.FastThreadLocal import net.corda.core.serialization.CordaSerializable import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.parseAsHex @@ -63,12 +64,16 @@ sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) { } } + private val threadLocalSha256MessageDigest = object : FastThreadLocal() { + override fun initialValue() = MessageDigest.getInstance("SHA-256") + } + /** * Computes the SHA-256 hash value of the [ByteArray]. * @param bytes The [ByteArray] to hash. */ @JvmStatic - fun sha256(bytes: ByteArray) = SHA256(MessageDigest.getInstance("SHA-256").digest(bytes)) + fun sha256(bytes: ByteArray) = SHA256(threadLocalSha256MessageDigest.get().digest(bytes)) /** * Computes the SHA-256 hash of the [ByteArray], and then computes the SHA-256 hash of the hash. diff --git a/core/src/test/kotlin/net/corda/core/crypto/SecureHashTest.kt b/core/src/test/kotlin/net/corda/core/crypto/SecureHashTest.kt new file mode 100644 index 0000000000..492bf1af20 --- /dev/null +++ b/core/src/test/kotlin/net/corda/core/crypto/SecureHashTest.kt @@ -0,0 +1,11 @@ +package net.corda.core.crypto + +import org.junit.Test +import kotlin.test.assertEquals + +class SecureHashTest { + @Test + fun `sha256 does not retain state between same-thread invocations`() { + assertEquals(SecureHash.sha256("abc"), SecureHash.sha256("abc")) + } +} diff --git a/node/build.gradle b/node/build.gradle index c37012442e..f8f45931c5 100644 --- a/node/build.gradle +++ b/node/build.gradle @@ -33,6 +33,7 @@ configurations { // We don't need these because we already include netty-all. exclude group: 'io.netty', module: 'netty-transport' exclude group: 'io.netty', module: 'netty-handler' + exclude group: 'io.netty', module: 'netty-common' } integrationTestCompile.extendsFrom testCompile