Fixing stuff

This commit is contained in:
Andras Slemmer 2017-12-18 15:39:00 +00:00
parent f3f06976d0
commit 107fcf82e3
45 changed files with 1060 additions and 283 deletions

View File

@ -162,33 +162,6 @@ allprojects {
tasks.withType(Test) {
// Prevent the project from creating temporary files outside of the build directory.
systemProperties['java.io.tmpdir'] = buildDir
// Ensures that "net.corda.testing.amqp.enable" is passed correctly from Gradle command line
// down to JVM executing unit test. It looks like we are running unit tests in the forked mode
// and all the "-D" parameters passed to Gradle not making it to unit test level
// TODO: Remove once we fully switched to AMQP
final AMQP_ENABLE_PROP_NAME = "net.corda.testing.amqp.enable"
systemProperty(AMQP_ENABLE_PROP_NAME, System.getProperty(AMQP_ENABLE_PROP_NAME))
// relational database provider to be used by node
final DATABASE_PROVIDER = "databaseProvider"
final DATASOURCE_URL = "dataSourceProperties.dataSource.url"
final DATASOURCE_CLASSNAME = "dataSourceProperties.dataSourceClassName"
final DATASOURCE_USER = "dataSourceProperties.dataSource.user"
final DATASOURCE_PASSWORD = "dataSourceProperties.dataSource.password"
// integration testing database configuration (to be used in conjunction with a DATABASE_PROVIDER)
final TEST_DB_ADMIN_USER = "test.db.admin.user"
final TEST_DB_ADMIN_PASSWORD = "test.db.admin.password"
final TEST_DB_SCRIPT_DIR = "test.db.script.dir"
[DATABASE_PROVIDER,DATASOURCE_URL, DATASOURCE_CLASSNAME, DATASOURCE_USER, DATASOURCE_PASSWORD,
TEST_DB_ADMIN_USER, TEST_DB_ADMIN_PASSWORD, TEST_DB_SCRIPT_DIR].forEach {
def property = System.getProperty(it)
if (property != null) {
systemProperty(it, property)
}
}
}
group 'com.r3.corda.enterprise'

View File

@ -63,8 +63,7 @@ public class CordaRPCJavaClientTest extends NodeBasedTest {
}
@Before
public void setUp() throws Exception {
super.setUp();
public void setUp() throws ExecutionException, InterruptedException {
node = startNode(ALICE_NAME, 1, singletonList(rpcUser));
client = new CordaRPCClient(requireNonNull(node.getInternals().getConfiguration().getRpcAddress()));
}

View File

@ -19,13 +19,11 @@ import net.corda.testing.node.MockNetwork
import net.corda.testing.node.startFlow
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
@Ignore
class IdentitySyncFlowTests {
private lateinit var mockNet: MockNetwork

View File

@ -6,11 +6,9 @@ import net.corda.testing.*
import net.corda.testing.node.MockNetwork
import org.junit.Before
import net.corda.testing.node.startFlow
import org.junit.Ignore
import org.junit.Test
import kotlin.test.*
@Ignore
class SwapIdentitiesFlowTests {
private lateinit var mockNet: MockNetwork

View File

@ -16,13 +16,21 @@ import java.security.PublicKey
abstract class NotaryService : SingletonSerializeAsToken() {
companion object {
const val ID_PREFIX = "corda.notary."
fun constructId(validating: Boolean, raft: Boolean = false, bft: Boolean = false, custom: Boolean = false): String {
require(Booleans.countTrue(raft, bft, custom) <= 1) { "At most one of raft, bft or custom may be true" }
@JvmOverloads
fun constructId(
validating: Boolean,
raft: Boolean = false,
bft: Boolean = false,
custom: Boolean = false,
mysql: Boolean = false
): String {
require(Booleans.countTrue(raft, bft, custom, mysql) <= 1) { "At most one of raft, bft, mysql or custom may be true" }
return StringBuffer(ID_PREFIX).apply {
append(if (validating) "validating" else "simple")
if (raft) append(".raft")
if (bft) append(".bft")
if (custom) append(".custom")
if (mysql) append(".mysql")
}.toString()
}
}

View File

@ -6,7 +6,6 @@ from the previous milestone release.
UNRELEASED
----------
* The network map service concept has been re-designed. More information can be found in :doc:`network-map`.
* The previous design was never intended to be final but was rather a quick implementation in the earliest days of the

View File

@ -15,7 +15,9 @@ import net.corda.core.utilities.days
import net.corda.core.utilities.seconds
import net.corda.finance.DOLLARS
import net.corda.finance.`issued by`
import net.corda.finance.contracts.asset.*
import net.corda.finance.contracts.asset.CASH
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.asset.STATE
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.testing.*
import net.corda.testing.dsl.EnforceVerifyOrFail

View File

@ -1,9 +1,15 @@
package net.corda.finance.contracts.asset
import com.nhaarman.mockito_kotlin.*
import com.nhaarman.mockito_kotlin.argThat
import com.nhaarman.mockito_kotlin.doNothing
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.*
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.queryBy
@ -20,10 +26,10 @@ import net.corda.node.services.vault.NodeVaultService
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.testing.*
import net.corda.testing.contracts.DummyState
import net.corda.testing.internal.LogHelper
import net.corda.testing.dsl.EnforceVerifyOrFail
import net.corda.testing.dsl.TransactionDSL
import net.corda.testing.dsl.TransactionDSLInterpreter
import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.vault.VaultFiller
import net.corda.testing.node.MockServices

View File

@ -1,5 +1,6 @@
package com.r3.corda.networkmanage.doorman
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import com.r3.corda.networkmanage.common.persistence.configureDatabase
import com.r3.corda.networkmanage.common.utils.buildCertPath
@ -8,22 +9,29 @@ import com.r3.corda.networkmanage.doorman.signer.LocalSigner
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SignedData
import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.cert
import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.minutes
import net.corda.core.utilities.seconds
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.network.NetworkMapClient
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
import net.corda.node.utilities.registration.NetworkRegistrationHelper
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.crypto.*
import net.corda.testing.ALICE_NAME
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.internal.rigorousMock
import org.bouncycastle.cert.X509CertificateHolder
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
@ -48,16 +56,11 @@ class DoormanIntegrationTest {
//Start doorman server
val doorman = startDoorman(intermediateCertAndKey, rootCertAndKey.certificate)
val doormanHostAndPort = doorman.hostAndPort
// Start Corda network registration.
val config = testNodeConfiguration(
baseDirectory = tempFolder.root.toPath(),
myLegalName = ALICE_NAME).also {
val doormanHostAndPort = doorman.hostAndPort
whenever(it.compatibilityZoneURL).thenReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}"))
whenever(it.emailAddress).thenReturn("iTest@R3.com")
val config = createConfig().also {
doReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}")).whenever(it).compatibilityZoneURL
}
config.trustStoreFile.parent.createDirectories()
loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword).also {
it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCertAndKey.certificate.cert)
@ -94,6 +97,7 @@ class DoormanIntegrationTest {
doorman.close()
}
@Ignore
@Test
fun `nodeInfo is published to the network map`() {
// Given
@ -105,13 +109,9 @@ class DoormanIntegrationTest {
val doormanHostAndPort = doorman.hostAndPort
// Start Corda network registration.
val config = testNodeConfiguration(
baseDirectory = tempFolder.root.toPath(),
myLegalName = ALICE_NAME).also {
whenever(it.compatibilityZoneURL).thenReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}"))
whenever(it.emailAddress).thenReturn("iTest@R3.com")
val config = createConfig().also {
doReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}")).whenever(it).compatibilityZoneURL
}
config.trustStoreFile.parent.createDirectories()
loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword).also {
it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCertAndKey.certificate.cert)
@ -128,7 +128,8 @@ class DoormanIntegrationTest {
val nodeInfoBytes = nodeInfo.serialize()
// When
networkMapClient.publish(SignedData(nodeInfoBytes, keyPair.sign(nodeInfoBytes)))
val signedNodeInfo = SignedNodeInfo(nodeInfoBytes, listOf(keyPair.sign(nodeInfoBytes)))
networkMapClient.publish(signedNodeInfo)
// Then
val networkMapNodeInfo = networkMapClient.getNodeInfo(nodeInfoBytes.hash)
@ -137,8 +138,24 @@ class DoormanIntegrationTest {
doorman.close()
}
fun createConfig(): NodeConfiguration {
return rigorousMock<NodeConfiguration>().also {
doReturn(tempFolder.root.toPath()).whenever(it).baseDirectory
doReturn(ALICE_NAME).whenever(it).myLegalName
doReturn(it.baseDirectory / "certificates").whenever(it).certificatesDirectory
doReturn(it.certificatesDirectory / "truststore.jks").whenever(it).trustStoreFile
doReturn(it.certificatesDirectory / "nodekeystore.jks").whenever(it).nodeKeystore
doReturn(it.certificatesDirectory / "sslkeystore.jks").whenever(it).sslKeystore
doReturn("trustpass").whenever(it).trustStorePassword
doReturn("cordacadevpass").whenever(it).keyStorePassword
// doReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}")).whenever(it).compatibilityZoneURL
doReturn("iTest@R3.com").whenever(it).emailAddress
}
}
}
fun createDoormanIntermediateCertificateAndKeyPair(rootCertificateAndKeyPair: CertificateAndKeyPair): CertificateAndKeyPair {
val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCertificateAndKeyPair.certificate, rootCertificateAndKeyPair.keyPair,

View File

@ -1,9 +1,6 @@
package com.r3.corda.networkmanage.hsm
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.whenever
import com.nhaarman.mockito_kotlin.*
import com.r3.corda.networkmanage.common.persistence.configureDatabase
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
@ -17,9 +14,11 @@ import net.corda.core.crypto.Crypto
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.cert
import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.internal.uncheckedCast
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.seconds
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
import net.corda.node.utilities.registration.NetworkRegistrationHelper
import net.corda.nodeapi.internal.crypto.*
@ -28,7 +27,7 @@ import net.corda.testing.ALICE_NAME
import net.corda.testing.BOB_NAME
import net.corda.testing.CHARLIE_NAME
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.node.testNodeConfiguration
import net.corda.testing.internal.rigorousMock
import org.bouncycastle.cert.X509CertificateHolder
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
import org.h2.tools.Server
@ -101,14 +100,12 @@ class SigningServiceIntegrationTest {
NetworkManagementServer().use { server ->
server.start(NetworkHostAndPort(HOST, 0), database, networkMapServiceParameter = null, doormanServiceParameter = DoormanConfig(approveAll = true, approveInterval = 2.seconds.toMillis(), jiraConfig = null), updateNetworkParameters = null)
val doormanHostAndPort = server.hostAndPort
// Start Corda network registration.
val config = testNodeConfiguration(
baseDirectory = tempFolder.root.toPath(),
myLegalName = ALICE_NAME).also {
val doormanHostAndPort = server.hostAndPort
whenever(it.compatibilityZoneURL).thenReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}"))
val config = createConfig().also {
doReturn(ALICE_NAME).whenever(it).myLegalName
doReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}")).whenever(it).compatibilityZoneURL
}
val signingServiceStorage = DBSignedCertificateRequestStorage(configureDatabase(makeTestDataSourceProperties()))
val hsmSigner = givenSignerSigningAllRequests(signingServiceStorage)
@ -149,6 +146,7 @@ class SigningServiceIntegrationTest {
* The split is done due to the limited console support while executing tests and inability to capture user's input there.
*
*/
@Ignore
@Test
fun `DEMO - Create CSR and poll`() {
//Start doorman server
@ -162,23 +160,41 @@ class SigningServiceIntegrationTest {
}
// Start Corda network registration.
(1..3).map {
(1..3).map { num ->
thread(start = true) {
val config = testNodeConfiguration(
baseDirectory = tempFolder.root.toPath(),
myLegalName = when (it) {
1 -> ALICE_NAME
2 -> BOB_NAME
3 -> CHARLIE_NAME
else -> throw IllegalArgumentException("Unrecognised option")
}).also {
whenever(it.compatibilityZoneURL).thenReturn(URL("http://$HOST:${server.hostAndPort.port}"))
// Start Corda network registration.
val config = createConfig().also {
doReturn(when (num) {
1 -> ALICE_NAME
2 -> BOB_NAME
3 -> CHARLIE_NAME
else -> throw IllegalArgumentException("Unrecognised option")
}).whenever(it).myLegalName
doReturn(URL("http://$HOST:${server.hostAndPort.port}")).whenever(it).compatibilityZoneURL
}
config.trustStoreFile.parent.createDirectories()
loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword).also {
it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCACert.cert)
it.save(config.trustStoreFile, config.trustStorePassword)
}
NetworkRegistrationHelper(config, HTTPNetworkRegistrationService(config.compatibilityZoneURL!!)).buildKeystore()
}
}.map { it.join() }
}
}
fun createConfig(): NodeConfiguration {
return rigorousMock<NodeConfiguration>().also {
doReturn(tempFolder.root.toPath()).whenever(it).baseDirectory
doReturn(it.baseDirectory / "certificates").whenever(it).certificatesDirectory
doReturn(it.certificatesDirectory / "truststore.jks").whenever(it).trustStoreFile
doReturn(it.certificatesDirectory / "nodekeystore.jks").whenever(it).nodeKeystore
doReturn(it.certificatesDirectory / "sslkeystore.jks").whenever(it).sslKeystore
doReturn("trustpass").whenever(it).trustStorePassword
doReturn("cordacadevpass").whenever(it).keyStorePassword
doReturn("iTest@R3.com").whenever(it).emailAddress
}
}
}
private fun makeTestDataSourceProperties(): Properties {

View File

@ -15,7 +15,7 @@ class NetworkMapSigner(private val networkMapStorage: NetworkMapStorage, private
val nodeInfoHashes = networkMapStorage.getNodeInfoHashes(CertificateStatus.VALID)
val networkParameters = networkMapStorage.getLatestNetworkParameters()
val networkMap = NetworkMap(nodeInfoHashes, networkParameters.serialize().hash)
if (networkMap != currentSignedNetworkMap?.verified()) {
if (networkMap != currentSignedNetworkMap?.verified(null)) {
val digitalSignature = signer.sign(networkMap.serialize().bytes)
val signedHashedNetworkMap = SignedNetworkMap(networkMap.serialize(), digitalSignature)
networkMapStorage.saveNetworkMap(signedHashedNetworkMap)

View File

@ -5,6 +5,7 @@ import com.typesafe.config.ConfigParseOptions
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.internal.exists
import net.corda.core.utilities.days
import net.corda.core.utilities.parsePublicKeyBase58
import net.corda.nodeapi.internal.config.parseAs
import net.corda.nodeapi.internal.network.NetworkParameters

View File

@ -17,7 +17,6 @@ class NetworkParametersConfigurationTest {
fun `reads an existing file`() {
val networkParameters = parseNetworkParametersFrom(validOverrideNetworkConfigPath)
assertThat(networkParameters.minimumPlatformVersion).isEqualTo(1)
assertThat(networkParameters.eventHorizon).isEqualTo(100.days)
val notaries = networkParameters.notaries
assertThat(notaries).hasSize(2)
assertThat(notaries[0].validating).isTrue()

View File

@ -7,8 +7,8 @@ import com.r3.corda.networkmanage.common.persistence.CertificateStatus
import com.r3.corda.networkmanage.common.persistence.RequestStatus
import net.corda.core.crypto.SecureHash
import net.corda.core.utilities.seconds
import net.corda.nodeapi.internal.NetworkParameters
import net.corda.nodeapi.internal.NotaryInfo
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.testing.SerializationEnvironmentRule
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.junit.Rule
@ -62,7 +62,6 @@ abstract class TestBase {
return NetworkParameters(
minimumPlatformVersion = minimumPlatformVersion,
notaries = notaries,
eventHorizon = eventHorizon,
maxMessageSize = maxMessageSize,
maxTransactionSize = maxTransactionSize,
modifiedTime = modifiedTime,

View File

@ -81,7 +81,7 @@ class DBNetworkMapStorageTest : TestBase() {
val persistedSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
assertEquals(signedNetworkMap.signature, persistedSignedNetworkMap?.signature)
assertEquals(signedNetworkMap.verified(), persistedSignedNetworkMap?.verified())
assertEquals(signedNetworkMap.verified(rootCACert.cert), persistedSignedNetworkMap?.verified(rootCACert.cert))
}
@Test

View File

@ -11,10 +11,10 @@ import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.cert
import net.corda.core.serialization.serialize
import net.corda.nodeapi.internal.NetworkMap
import net.corda.nodeapi.internal.SignedNetworkMap
import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.SignedNetworkMap
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
@ -58,7 +58,7 @@ class NetworkMapSignerTest : TestBase() {
verify(networkMapStorage).getLatestNetworkParameters()
argumentCaptor<SignedNetworkMap>().apply {
verify(networkMapStorage).saveNetworkMap(capture())
val networkMap = firstValue.verified()
val networkMap = firstValue.verified(rootCACert.cert)
assertEquals(networkMapParameters.serialize().hash, networkMap.networkParameterHash)
assertEquals(signedNodeInfoHashes.size, networkMap.nodeInfoHashes.size)
assertTrue(networkMap.nodeInfoHashes.containsAll(signedNodeInfoHashes))
@ -104,7 +104,7 @@ class NetworkMapSignerTest : TestBase() {
verify(networkMapStorage).getLatestNetworkParameters()
argumentCaptor<SignedNetworkMap>().apply {
verify(networkMapStorage).saveNetworkMap(capture())
val networkMap = firstValue.verified()
val networkMap = firstValue.verified(rootCACert.cert)
assertEquals(networkMapParameters.serialize().hash, networkMap.networkParameterHash)
}
}

View File

@ -19,10 +19,10 @@ import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.seconds
import net.corda.nodeapi.internal.NetworkMap
import net.corda.nodeapi.internal.SignedNetworkMap
import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.SignedNetworkMap
import net.corda.testing.SerializationEnvironmentRule
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Rule
@ -82,7 +82,7 @@ class NodeInfoWebServiceTest {
val conn = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}").openConnection() as HttpURLConnection
val signedNetworkMap = conn.inputStream.readBytes().deserialize<SignedNetworkMap>()
verify(networkMapStorage, times(1)).getCurrentNetworkMap()
assertEquals(signedNetworkMap.verified(), networkMap)
assertEquals(signedNetworkMap.verified(rootCACert.cert), networkMap)
}
}

View File

@ -68,10 +68,12 @@ class SignedNetworkMap(val raw: SerializedBytes<NetworkMap>, val signature: Digi
* @throws SignatureException if the signature is invalid.
*/
@Throws(SignatureException::class, CertPathValidatorException::class)
fun verified(trustedRoot: X509Certificate): NetworkMap {
fun verified(trustedRoot: X509Certificate?): NetworkMap {
signature.by.publicKey.verify(raw.bytes, signature)
// Assume network map cert is under the default trust root.
X509Utilities.validateCertificateChain(trustedRoot, signature.by, trustedRoot)
if (trustedRoot != null) {
X509Utilities.validateCertificateChain(trustedRoot, signature.by, trustedRoot)
}
return raw.deserialize()
}
}

View File

@ -6,8 +6,8 @@ import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.node.services.statemachine.DataSessionMessage
import net.corda.nodeapi.internal.serialization.kryo.KryoHeaderV0_1
import net.corda.testing.internal.kryoSpecific
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.internal.kryoSpecific
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Rule

View File

@ -127,6 +127,8 @@ dependencies {
compile "org.postgresql:postgresql:$postgresql_version"
//For Azure SQL and SQL Server support in persistence
compile 'com.microsoft.sqlserver:mssql-jdbc:6.2.1.jre8'
// For the MySQLUniquenessProvider
compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'
// SQL connection pooling library
compile "com.zaxxer:HikariCP:2.5.1"

View File

@ -24,9 +24,9 @@ import net.corda.testing.*
import net.corda.testing.driver.DriverDSL
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.withoutTestSerialization
import net.corda.testing.services.MockAttachmentStorage
import net.corda.testing.internal.rigorousMock
import org.junit.Assert.assertEquals
import org.junit.ClassRule
import org.junit.Rule

View File

@ -25,11 +25,9 @@ import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.transactions.minClusterSize
import net.corda.node.services.transactions.minCorrectReplicas
import net.corda.nodeapi.internal.ServiceIdentityGenerator
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.testing.chooseIdentity
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.testing.IntegrationTest
import net.corda.testing.IntegrationTestSchemas
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
@ -39,19 +37,12 @@ import net.corda.testing.node.MockNodeParameters
import net.corda.testing.node.startFlow
import org.junit.After
import org.junit.Before
import org.junit.ClassRule
import org.junit.Test
import java.nio.file.Paths
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class BFTNotaryServiceTests : IntegrationTest() {
companion object {
@ClassRule @JvmField
val databaseSchemas = IntegrationTestSchemas("node_0", "node_1", "node_2", "node_3", "node_4", "node_5",
"node_6", "node_7", "node_8", "node_9")
}
class BFTNotaryServiceTests {
private lateinit var mockNet: MockNetwork
private lateinit var notary: Party
private lateinit var node: StartedNode<MockNode>

View File

@ -0,0 +1,154 @@
package net.corda.node.services
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef
import net.corda.core.crypto.TransactionSignature
import net.corda.core.flows.NotaryError
import net.corda.core.flows.NotaryException
import net.corda.core.flows.NotaryFlow
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode
import net.corda.node.services.config.NotaryConfig
import net.corda.nodeapi.internal.ServiceIdentityGenerator
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.testing.*
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.contracts.DummyContract
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNodeParameters
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.startFlow
import org.junit.After
import org.junit.Before
import org.junit.ClassRule
import org.junit.Test
import java.math.BigInteger
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class MySQLNotaryServiceTests : IntegrationTest() {
companion object {
val notaryName = CordaX500Name("MySQL Notary Service", "Zurich", "CH")
@ClassRule
@JvmField
val databaseSchemas = IntegrationTestSchemas("node_0", DUMMY_NOTARY_NAME.toDatabaseSchemaName())
}
private lateinit var mockNet: MockNetwork
private lateinit var node: StartedNode<MockNetwork.MockNode>
private lateinit var notaryParty: Party
private lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
@Before
fun before() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
notaryParty = ServiceIdentityGenerator.generateToDisk(
listOf(mockNet.baseDirectory(mockNet.nextNodeId)),
notaryName,
"identity"
)
val networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(notaryParty, false))))
val notaryNodeUnstarted = createNotaryNode()
val nodeUnstarted = mockNet.createUnstartedNode()
val startedNodes = listOf(notaryNodeUnstarted, nodeUnstarted).map { n ->
networkParameters.install(mockNet.baseDirectory(n.id))
n.start()
}
notaryNode = startedNodes.first()
node = startedNodes.last()
}
@After
fun stopNodes() {
mockNet.stopNodes()
}
@Test
fun `detect double spend`() {
val inputState = issueState(node, notaryParty)
val firstTxBuilder = TransactionBuilder(notaryParty)
.addInputState(inputState)
.addCommand(dummyCommand(node.services.myInfo.chooseIdentity().owningKey))
val firstSpendTx = node.services.signInitialTransaction(firstTxBuilder)
val firstSpend = node.services.startFlow(NotaryFlow.Client(firstSpendTx))
mockNet.runNetwork()
firstSpend.resultFuture.getOrThrow()
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run {
val dummyState = DummyContract.SingleOwnerState(0, node.info.chooseIdentity())
addOutputState(dummyState, DummyContract.PROGRAM_ID)
addCommand(dummyCommand(node.services.myInfo.chooseIdentity().owningKey))
this
}
val secondSpendTx = node.services.signInitialTransaction(secondSpendBuilder)
val secondSpend = node.services.startFlow(NotaryFlow.Client(secondSpendTx))
mockNet.runNetwork()
val ex = assertFailsWith(NotaryException::class) { secondSpend.resultFuture.getOrThrow() }
val error = ex.error as NotaryError.Conflict
assertEquals(error.txId, secondSpendTx.id)
}
@Test
fun `notarisations are idempotent`() {
val inputState = issueState(node, notaryParty)
val txBuilder = TransactionBuilder(notaryParty)
.addInputState(inputState)
.addCommand(dummyCommand(node.services.myInfo.chooseIdentity().owningKey))
val spendTx = node.services.signInitialTransaction(txBuilder)
val notarise = node.services.startFlow(NotaryFlow.Client(spendTx))
mockNet.runNetwork()
val signature = notarise.resultFuture.get().single()
val notariseRetry = node.services.startFlow(NotaryFlow.Client(spendTx))
mockNet.runNetwork()
val signatureRetry = notariseRetry.resultFuture.get().single()
fun checkSignature(signature: TransactionSignature) {
signature.verify(spendTx.id)
assertEquals(notaryParty.owningKey, signature.by)
}
checkSignature(signature)
checkSignature(signatureRetry)
}
private fun createNotaryNode(): MockNetwork.MockNode {
val dataStoreProperties = makeTestDataSourceProperties().apply {
setProperty("autoCommit", "false")
}
return mockNet.createUnstartedNode(
MockNodeParameters(
legalName = notaryName,
entropyRoot = BigInteger.valueOf(60L),
configOverrides = {
val notaryConfig = NotaryConfig(validating = false, mysql = dataStoreProperties)
doReturn(notaryConfig).whenever(it).notary
}
)
)
}
private fun issueState(node: StartedNode<*>, notary: Party): StateAndRef<*> {
return node.database.transaction {
val builder = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
val stx = node.services.signInitialTransaction(builder)
node.services.recordTransactions(stx)
StateAndRef(builder.outputStates().first(), StateRef(stx.id, 0))
}
}
}

View File

@ -11,24 +11,21 @@ import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.testing.ALICE_NAME
import net.corda.testing.BOB_NAME
import net.corda.testing.*
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.PortAllocation
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.node.internal.internalDriver
import net.corda.testing.node.internal.network.NetworkMapServer
import org.assertj.core.api.Assertions.assertThat
import org.junit.*
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.net.URL
import kotlin.test.assertEquals
class NetworkMapTest : IntegrationTest() {
companion object {
@ClassRule
@JvmField
val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(),
DUMMY_NOTARY_NAME.toDatabaseSchemaName())
}
class NetworkMapTest {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule(true)

View File

@ -15,10 +15,9 @@ import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
import net.corda.testing.IntegrationTest
import net.corda.testing.IntegrationTestSchemas
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.driver.PortAllocation
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.node.internal.internalDriver
import net.corda.testing.node.internal.network.NetworkMapServer
import org.assertj.core.api.Assertions.assertThat
@ -27,7 +26,6 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
import org.junit.After
import org.junit.Before
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import java.io.ByteArrayOutputStream
@ -42,11 +40,7 @@ import javax.ws.rs.*
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
class NodeRegistrationTest : IntegrationTest() {
companion object {
@ClassRule @JvmField
val databaseSchemas = IntegrationTestSchemas("Alice")
}
class NodeRegistrationTest {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule(true)

View File

@ -697,14 +697,19 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
private fun makeCoreNotaryService(notaryConfig: NotaryConfig, database: CordaPersistence): NotaryService {
val notaryKey = myNotaryIdentity?.owningKey ?: throw IllegalArgumentException("No notary identity initialized when creating a notary service")
return notaryConfig.run {
if (raft != null) {
val uniquenessProvider = RaftUniquenessProvider(configuration, database, services.monitoringService.metrics, raft)
(if (validating) ::RaftValidatingNotaryService else ::RaftNonValidatingNotaryService)(services, notaryKey, uniquenessProvider)
} else if (bftSMaRt != null) {
if (validating) throw IllegalArgumentException("Validating BFTSMaRt notary not supported")
BFTNonValidatingNotaryService(services, notaryKey, bftSMaRt, makeBFTCluster(notaryKey, bftSMaRt))
} else {
(if (validating) ::ValidatingNotaryService else ::SimpleNotaryService)(services, notaryKey)
when {
raft != null -> {
val uniquenessProvider = RaftUniquenessProvider(configuration, database, services.monitoringService.metrics, raft)
(if (validating) ::RaftValidatingNotaryService else ::RaftNonValidatingNotaryService)(services, notaryKey, uniquenessProvider)
}
bftSMaRt != null -> {
if (validating) throw IllegalArgumentException("Validating BFTSMaRt notary not supported")
BFTNonValidatingNotaryService(services, notaryKey, bftSMaRt, makeBFTCluster(notaryKey, bftSMaRt))
}
mysql != null -> {
(if (validating) ::MySQLValidatingNotaryService else ::MySQLNonValidatingNotaryService)(services, notaryKey, mysql, configuration.devMode)
}
else -> (if (validating) ::ValidatingNotaryService else ::SimpleNotaryService)(services, notaryKey)
}
}
}
@ -754,7 +759,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
Pair("identity", myLegalName)
} else {
val notaryId = notaryConfig.run {
NotaryService.constructId(validating, raft != null, bftSMaRt != null, custom)
NotaryService.constructId(validating, raft != null, bftSMaRt != null, custom, mysql != null)
}
// The node is part of a distributed notary whose identity must already be generated beforehand.
Pair(notaryId, null)

View File

@ -56,11 +56,12 @@ fun NodeConfiguration.shouldCheckCheckpoints(): Boolean {
data class NotaryConfig(val validating: Boolean,
val raft: RaftConfig? = null,
val bftSMaRt: BFTSMaRtConfiguration? = null,
val custom: Boolean = false
val custom: Boolean = false,
val mysql: Properties? = null
) {
init {
require(raft == null || bftSMaRt == null || !custom) {
"raft, bftSMaRt, and custom configs cannot be specified together"
require(raft == null || bftSMaRt == null || !custom || mysql == null) {
"raft, bftSMaRt, custom, and mysql configs cannot be specified together"
}
}
val isClusterConfig: Boolean get() = raft != null || bftSMaRt != null

View File

@ -0,0 +1,52 @@
package net.corda.node.services.transactions
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession
import net.corda.core.node.services.TimeWindowChecker
import net.corda.core.node.services.TrustedAuthorityNotaryService
import net.corda.node.services.api.ServiceHubInternal
import java.security.PublicKey
import java.util.*
/** Notary service backed by a replicated MySQL database. */
abstract class MySQLNotaryService(
final override val services: ServiceHubInternal,
override val notaryIdentityKey: PublicKey,
dataSourceProperties: Properties,
/** Database table will be automatically created in dev mode */
val devMode: Boolean) : TrustedAuthorityNotaryService() {
override val timeWindowChecker = TimeWindowChecker(services.clock)
override val uniquenessProvider = MySQLUniquenessProvider(
services.monitoringService.metrics,
dataSourceProperties
)
override fun start() {
if (devMode) uniquenessProvider.createTable()
}
override fun stop() {
uniquenessProvider.stop()
}
}
class MySQLNonValidatingNotaryService(services: ServiceHubInternal,
notaryIdentityKey: PublicKey,
dataSourceProperties: Properties,
devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, dataSourceProperties, devMode) {
companion object {
val id = constructId(validating = false, mysql = true)
}
override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic<Void?> = NonValidatingNotaryFlow(otherPartySession, this)
}
class MySQLValidatingNotaryService(services: ServiceHubInternal,
notaryIdentityKey: PublicKey,
dataSourceProperties: Properties,
devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, dataSourceProperties, devMode) {
companion object {
val id = constructId(validating = true, mysql = true)
}
override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic<Void?> = ValidatingNotaryFlow(otherPartySession, this)
}

View File

@ -0,0 +1,162 @@
package net.corda.node.services.transactions
import com.codahale.metrics.MetricRegistry
import com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import net.corda.core.contracts.StateRef
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.node.services.UniquenessException
import net.corda.core.node.services.UniquenessProvider
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.loggerFor
import java.security.PublicKey
import java.sql.BatchUpdateException
import java.sql.Connection
import java.util.*
/**
* Uniqueness provider backed by a MySQL database. It is intended to be used with a multi-master synchronously replicated
* variant of MySQL, such as Percona XtraDB Cluster, or MariaDB Galera Cluster.
*
* Note that no ORM is used since we want to retain full control over table schema and be able to experiment with optimisations.
*/
class MySQLUniquenessProvider(
metrics: MetricRegistry,
dataSourceProperties: Properties
) : UniquenessProvider, SingletonSerializeAsToken() {
companion object {
private val log = loggerFor<MySQLUniquenessProvider>()
// TODO: optimize table schema for InnoDB
private val createTableStatement =
"CREATE TABLE IF NOT EXISTS committed_states (" +
"issue_tx_id BINARY(32) NOT NULL," +
"issue_tx_output_id INT NOT NULL," +
"consuming_tx_id BINARY(32) NOT NULL," +
"consuming_tx_input_id INT UNSIGNED NOT NULL," +
"consuming_party_name TEXT NOT NULL," +
// TODO: do we need to store the key? X500 name should be sufficient
"consuming_party_key BLOB NOT NULL," +
"commit_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP," +
"CONSTRAINT id PRIMARY KEY (issue_tx_id, issue_tx_output_id)" +
")"
private val insertStatement = "INSERT INTO committed_states (issue_tx_id, issue_tx_output_id, consuming_tx_id, consuming_tx_input_id, consuming_party_name, consuming_party_key) VALUES (?, ?, ?, ?, ?, ?)"
private val findStatement = "SELECT consuming_tx_id, consuming_tx_input_id, consuming_party_name, consuming_party_key FROM committed_states WHERE issue_tx_id = ? AND issue_tx_output_id = ?"
}
private val metricPrefix = MySQLUniquenessProvider::class.simpleName
/** Transaction commit duration and rate metric timer */
private val commitTimer = metrics.timer("$metricPrefix.Commit")
/**
* When writing to multiple masters with Galera, transaction rollbacks may happen due to high write contention.
* This is a useful heath metric.
*/
private val rollbackCounter = metrics.counter("$metricPrefix.Rollback")
/** Track double spend attempts. Note that this will also include notarisation retries. */
private val conflictCounter = metrics.counter("$metricPrefix.Conflicts")
val dataSource = HikariDataSource(HikariConfig(dataSourceProperties))
private val connection: Connection
get() = dataSource.connection
fun createTable() {
log.debug("Attempting to create DB table if it does not yet exist: $createTableStatement")
connection.use {
it.createStatement().execute(createTableStatement)
it.commit()
}
}
fun stop() {
dataSource.close()
}
override fun commit(states: List<StateRef>, txId: SecureHash, callerIdentity: Party) {
val timer = commitTimer.time()
try {
retryTransaction(CommitAll(states, txId, callerIdentity))
} catch (e: BatchUpdateException) {
log.info("Unable to commit input states, finding conflicts", e)
conflictCounter.inc()
retryTransaction(FindConflicts(states))
} finally {
timer.stop()
}
}
private fun retryTransaction(tx: RetryableTransaction) {
connection.use {
while (true) {
try {
tx.run(it)
} catch (e: Exception) {
it.rollback()
if (e is MySQLTransactionRollbackException) {
log.warn("Rollback exception occurred, retrying", e)
rollbackCounter.inc()
continue
} else {
throw e
}
}
break
}
it.commit()
}
}
interface RetryableTransaction {
fun run(conn: Connection)
}
private class CommitAll(val states: List<StateRef>, val txId: SecureHash, val callerIdentity: Party) : RetryableTransaction {
override fun run(conn: Connection) {
conn.prepareStatement(insertStatement).apply {
states.forEachIndexed { index, stateRef ->
// StateRef
setBytes(1, stateRef.txhash.bytes)
setInt(2, stateRef.index)
// Consuming transaction
setBytes(3, txId.bytes)
setInt(4, index)
setString(5, callerIdentity.name.toString())
setBytes(6, callerIdentity.owningKey.serialize().bytes)
addBatch()
clearParameters()
}
executeBatch()
close()
}
}
}
private class FindConflicts(val states: List<StateRef>) : RetryableTransaction {
override fun run(conn: Connection) {
val conflicts = mutableMapOf<StateRef, UniquenessProvider.ConsumingTx>()
states.forEach {
val st = conn.prepareStatement(findStatement).apply {
setBytes(1, it.txhash.bytes)
setInt(2, it.index)
}
val result = st.executeQuery()
if (result.next()) {
val consumingTxId = SecureHash.SHA256(result.getBytes(1))
val inputIndex = result.getInt(2)
val partyName = CordaX500Name.parse(result.getString(3))
val partyKey: PublicKey = result.getBytes(4).deserialize()
conflicts[it] = UniquenessProvider.ConsumingTx(consumingTxId, inputIndex, Party(partyName, partyKey))
}
}
conn.commit()
if (conflicts.isNotEmpty()) throw UniquenessException(UniquenessProvider.Conflict(conflicts))
}
}
}

View File

@ -33,5 +33,4 @@ enterpriseConfiguration = {
waitInterval = 40000
}
}
useAMQPBridges = true
useAMQPBridges = true

View File

@ -46,10 +46,8 @@ import java.util.stream.StreamSupport;
import static net.corda.core.node.services.vault.QueryCriteriaUtils.DEFAULT_PAGE_NUM;
import static net.corda.core.node.services.vault.QueryCriteriaUtils.MAX_PAGE_SIZE;
import static net.corda.core.utilities.ByteArrays.toHexString;
import static net.corda.testing.TestConstants.*;
import static net.corda.testing.internal.InternalTestUtilsKt.rigorousMock;
import static net.corda.testing.TestConstants.BOC_NAME;
import static net.corda.testing.TestConstants.CHARLIE_NAME;
import static net.corda.testing.TestConstants.DUMMY_NOTARY_NAME;
import static net.corda.testing.node.MockServices.makeTestDatabaseAndMockServices;
import static net.corda.testing.node.MockServicesKt.makeTestIdentityService;
import static org.assertj.core.api.Assertions.assertThat;
@ -74,7 +72,8 @@ public class VaultQueryJavaTests {
"net.corda.testing.internal.vault",
"net.corda.finance.contracts.asset",
CashSchemaV1.class.getPackage().getName(),
DummyLinearStateSchemaV1.class.getPackage().getName());
DummyLinearStateSchemaV1.class.getPackage().getName()
);
IdentityServiceInternal identitySvc = makeTestIdentityService(MEGA_CORP.getIdentity(), DUMMY_CASH_ISSUER_INFO.getIdentity(), DUMMY_NOTARY.getIdentity());
Pair<CordaPersistence, MockServices> databaseAndServices = makeTestDatabaseAndMockServices(
cordappPackages,

View File

@ -13,11 +13,12 @@ import net.corda.node.services.statemachine.FlowStart
import net.corda.node.services.transactions.PersistentUniquenessProvider
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.*
import net.corda.testing.internal.LogHelper
import net.corda.testing.ALICE_NAME
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.TestIdentity
import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before

View File

@ -24,26 +24,26 @@ import net.corda.finance.POUNDS
import net.corda.finance.SWISS_FRANCS
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.asset.DummyFungibleContract
import net.corda.finance.schemas.CashSchemaV1
import net.corda.finance.sampleschemas.SampleCashSchemaV2
import net.corda.finance.sampleschemas.SampleCashSchemaV3
import net.corda.finance.schemas.CashSchemaV1
import net.corda.finance.utils.sumCash
import net.corda.node.internal.configureDatabase
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.vault.VaultSchemaV1
import net.corda.node.internal.configureDatabase
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.nodeapi.internal.persistence.HibernateConfiguration
import net.corda.testing.*
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.vault.DummyDealStateSchemaV1
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
import net.corda.testing.internal.vault.DummyLinearStateSchemaV2
import net.corda.testing.internal.vault.VaultFiller
import net.corda.testing.node.MockServices
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
import net.corda.testing.internal.vault.DummyLinearStateSchemaV2
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.hibernate.SessionFactory

View File

@ -1,6 +1,9 @@
package net.corda.node.services.vault
import net.corda.core.contracts.*
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.InsufficientBalanceException
import net.corda.core.contracts.LinearState
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.CordaX500Name
@ -42,7 +45,7 @@ import kotlin.test.fail
class VaultWithCashTest {
private companion object {
private val cordappPackages = listOf(
"net.corda.testing.internal.vault", "net.corda.finance.contracts.asset", CashSchemaV1::class.packageName, DummyLinearStateSchemaV1::class.packageName)
"net.corda.testing.contracts", "net.corda.finance.contracts.asset", CashSchemaV1::class.packageName, DummyLinearStateSchemaV1::class.packageName)
val BOB = TestIdentity(BOB_NAME, 80).party
val dummyCashIssuer = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10)
val DUMMY_CASH_ISSUER = dummyCashIssuer.ref(1)

View File

@ -4,18 +4,17 @@ import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import com.r3.corda.enterprise.perftestcordapp.DOLLARS
import com.r3.corda.enterprise.perftestcordapp.`issued by`
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.*
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.CASH
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.DUMMY_CASH_ISSUER_KEY
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.STATE
import net.corda.core.contracts.*
import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.node.services.Vault
import net.corda.core.node.services.VaultService
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.days
import net.corda.core.utilities.seconds
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.testing.*
import net.corda.testing.dsl.EnforceVerifyOrFail
@ -24,16 +23,12 @@ import net.corda.testing.dsl.TransactionDSLInterpreter
import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockServices
import net.corda.testing.node.ledger
import net.corda.testing.node.makeTestIdentityService
import net.corda.testing.node.transaction
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.time.Instant
import java.util.*
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
// TODO: The generate functions aren't tested by these tests: add them.
@ -47,8 +42,7 @@ interface CommercialPaperTestTemplate {
private val megaCorp = TestIdentity(CordaX500Name("MegaCorp", "London", "GB"))
private val MEGA_CORP get() = megaCorp.party
private val MEGA_CORP_IDENTITY get() = megaCorp.identity
private val MEGA_CORP_PUBKEY get() = megaCorp.publicKey
private val MEGA_CORP_PUBKEY get() = megaCorp.keyPair.public
class KotlinCommercialPaperTest : CommercialPaperTestTemplate {
@ -85,21 +79,14 @@ class CommercialPaperTestsGeneric {
@Parameterized.Parameters @JvmStatic
fun data() = listOf(KotlinCommercialPaperTest(), KotlinCommercialPaperLegacyTest())
private val dummyCashIssuer = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10)
private val DUMMY_CASH_ISSUER_IDENTITY get() = dummyCashIssuer.identity
private val DUMMY_CASH_ISSUER = dummyCashIssuer.ref(1)
private val alice = TestIdentity(ALICE_NAME, 70)
private val BIG_CORP_KEY = generateKeyPair()
private val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20)
private val miniCorp = TestIdentity(CordaX500Name("MiniCorp", "London", "GB"))
private val ALICE get() = alice.party
private val ALICE_KEY get() = alice.keyPair
private val ALICE_PUBKEY get() = alice.publicKey
private val ALICE_PUBKEY get() = alice.keyPair.public
private val DUMMY_NOTARY get() = dummyNotary.party
private val DUMMY_NOTARY_IDENTITY get() = dummyNotary.identity
private val MINI_CORP get() = miniCorp.party
private val MINI_CORP_IDENTITY get() = miniCorp.identity
private val MINI_CORP_PUBKEY get() = miniCorp.publicKey
private val MINI_CORP_PUBKEY get() = miniCorp.keyPair.public
}
@ -159,8 +146,10 @@ class CommercialPaperTestsGeneric {
output(Cash.PROGRAM_ID, "Alice's profit", aliceGetsBack.STATE ownedBy ALICE)
output(Cash.PROGRAM_ID, "Change", (someProfits - aliceGetsBack).STATE ownedBy MEGA_CORP)
}
command(MEGA_CORP_PUBKEY, Cash.Commands.Move())
command(ALICE_PUBKEY, thisTest.getRedeemCommand(DUMMY_NOTARY))
tweak {
outputs(700.DOLLARS `issued by` issuer)
timeWindow(TEST_TX_TIME + 8.days)
@ -252,96 +241,7 @@ class CommercialPaperTestsGeneric {
private lateinit var alicesVault: Vault<ContractState>
private val notaryServices = MockServices(emptyList(), rigorousMock(), MEGA_CORP.name, dummyNotary.keyPair)
private val issuerServices = MockServices(listOf("net.corda.finance.contracts", "net.corda.finance.schemas"), rigorousMock(), MEGA_CORP.name, dummyCashIssuer.keyPair)
private val issuerServices = MockServices(emptyList(), rigorousMock(), MEGA_CORP.name, DUMMY_CASH_ISSUER_KEY)
private lateinit var moveTX: SignedTransaction
@Test
fun `issue move and then redeem`() {
val aliceDatabaseAndServices = MockServices.makeTestDatabaseAndMockServices(
listOf("net.corda.finance.contracts"),
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY),
TestIdentity(MEGA_CORP.name, ALICE_KEY))
val databaseAlice = aliceDatabaseAndServices.first
aliceServices = aliceDatabaseAndServices.second
aliceVaultService = aliceServices.vaultService
databaseAlice.transaction {
alicesVault = aliceServices.fillWithSomeTestCash(9000.DOLLARS, issuerServices, issuedBy = DUMMY_CASH_ISSUER, outputNotary = DUMMY_NOTARY)
aliceVaultService = aliceServices.vaultService
}
val bigCorpDatabaseAndServices = MockServices.makeTestDatabaseAndMockServices(
listOf("net.corda.finance.contracts"),
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY),
TestIdentity(MEGA_CORP.name, BIG_CORP_KEY))
val databaseBigCorp = bigCorpDatabaseAndServices.first
bigCorpServices = bigCorpDatabaseAndServices.second
bigCorpVaultService = bigCorpServices.vaultService
databaseBigCorp.transaction {
bigCorpVault = bigCorpServices.fillWithSomeTestCash(13000.DOLLARS, issuerServices, issuedBy = DUMMY_CASH_ISSUER, outputNotary = DUMMY_NOTARY)
bigCorpVaultService = bigCorpServices.vaultService
}
// Propagate the cash transactions to each side.
aliceServices.recordTransactions(bigCorpVault.states.map { bigCorpServices.validatedTransactions.getTransaction(it.ref.txhash)!! })
bigCorpServices.recordTransactions(alicesVault.states.map { aliceServices.validatedTransactions.getTransaction(it.ref.txhash)!! })
// BigCorp™ issues $10,000 of commercial paper, to mature in 30 days, owned initially by itself.
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
val issuance = bigCorpServices.myInfo.chooseIdentity().ref(1)
val issueBuilder = CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY)
issueBuilder.setTimeWindow(TEST_TX_TIME, 30.seconds)
val issuePtx = bigCorpServices.signInitialTransaction(issueBuilder)
val issueTx = notaryServices.addSignature(issuePtx)
databaseAlice.transaction {
// Alice pays $9000 to BigCorp to own some of their debt.
moveTX = run {
val builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(aliceServices, builder, 9000.DOLLARS, AnonymousParty(BIG_CORP_KEY.public))
CommercialPaper().generateMove(builder, issueTx.tx.outRef(0), AnonymousParty(ALICE_PUBKEY))
val ptx = aliceServices.signInitialTransaction(builder)
val ptx2 = bigCorpServices.addSignature(ptx)
val stx = notaryServices.addSignature(ptx2)
stx
}
}
databaseBigCorp.transaction {
// Verify the txns are valid and insert into both sides.
listOf(issueTx, moveTX).forEach {
it.toLedgerTransaction(aliceServices).verify()
aliceServices.recordTransactions(it)
bigCorpServices.recordTransactions(it)
}
}
databaseBigCorp.transaction {
fun makeRedeemTX(time: Instant): Pair<SignedTransaction, UUID> {
val builder = TransactionBuilder(DUMMY_NOTARY)
builder.setTimeWindow(time, 30.seconds)
CommercialPaper().generateRedeem(builder, moveTX.tx.outRef(1), bigCorpServices, bigCorpServices.myInfo.chooseIdentityAndCert())
val ptx = aliceServices.signInitialTransaction(builder)
val ptx2 = bigCorpServices.addSignature(ptx)
val stx = notaryServices.addSignature(ptx2)
return Pair(stx, builder.lockId)
}
val redeemTX = makeRedeemTX(TEST_TX_TIME + 10.days)
val tooEarlyRedemption = redeemTX.first
val tooEarlyRedemptionLockId = redeemTX.second
val e = assertFailsWith(TransactionVerificationException::class) {
tooEarlyRedemption.toLedgerTransaction(aliceServices).verify()
}
// manually release locks held by this failing transaction
aliceServices.vaultService.softLockRelease(tooEarlyRedemptionLockId)
assertTrue(e.cause!!.message!!.contains("paper must have matured"))
val validRedemption = makeRedeemTX(TEST_TX_TIME + 31.days).first
validRedemption.toLedgerTransaction(aliceServices).verify()
// soft lock not released after success either!!! (as transaction not recorded)
}
}
}

View File

@ -137,13 +137,19 @@ class CashTests {
@Before
fun setUp() {
LogHelper.setLevel(NodeVaultService::class)
megaCorpServices = MockServices(listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas"), rigorousMock(), MEGA_CORP.name, MEGA_CORP_KEY)
miniCorpServices = MockServices(listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas"), rigorousMock<IdentityServiceInternal>().also {
doNothing().whenever(it).justVerifyAndRegisterIdentity(argThat { name == MINI_CORP.name })
}, MINI_CORP.name, MINI_CORP_KEY)
val notaryServices = MockServices(listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas"), rigorousMock(), DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
val databaseAndServices = makeTestDatabaseAndMockServices(
megaCorpServices = MockServices(
listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas"),
rigorousMock(), MEGA_CORP.name, MEGA_CORP_KEY)
miniCorpServices = MockServices(
listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas"),
rigorousMock<IdentityServiceInternal>().also {
doNothing().whenever(it).justVerifyAndRegisterIdentity(argThat { name == MINI_CORP.name })
}, MINI_CORP.name, MINI_CORP_KEY)
val notaryServices = MockServices(
listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas"),
rigorousMock(), DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
val databaseAndServices = makeTestDatabaseAndMockServices(
listOf("net.corda.finance.contracts.asset", "net.corda.finance.schemas"),
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY),
TestIdentity(CordaX500Name("Me", "London", "GB")))
database = databaseAndServices.first
@ -879,7 +885,7 @@ class CashTests {
transaction {
attachment(Cash.PROGRAM_ID)
input("MEGA_CORP cash")
// We send it to another publicKey so that the transaction is not identical to the previous one
// We send it to another pubkey so that the transaction is not identical to the previous one
output(Cash.PROGRAM_ID, "MEGA_CORP cash 3", "MEGA_CORP cash".output<Cash.State>().copy(owner = ALICE))
command(MEGA_CORP_PUBKEY, Cash.Commands.Move())
this.verifies()

View File

@ -51,6 +51,9 @@ include 'samples:notary-demo'
include 'samples:bank-of-corda-demo'
include 'samples:business-network-demo'
include 'cordform-common'
include 'network-management'
include 'network-management:capsule'
include 'network-management:capsule-hsm'
include 'verify-enclave'
include 'hsm-tool'
project(':hsm-tool').with {

View File

@ -268,8 +268,7 @@ class InMemoryMessagingNetwork internal constructor(
private val peerHandle: PeerHandle,
private val executor: AffinityExecutor,
private val database: CordaPersistence) : SingletonSerializeAsToken(), MessagingService {
private inner class Handler(val topicSession: String,
val callback: MessageHandler) : MessageHandlerRegistration
inner class Handler(val topicSession: String, val callback: MessageHandler) : MessageHandlerRegistration
@Volatile
private var running = true

View File

@ -398,7 +398,7 @@ class MockNetwork(private val cordappPackages: List<String>,
val config = mockNodeConfiguration().also {
doReturn(baseDirectory(id).createDirectories()).whenever(it).baseDirectory
doReturn(parameters.legalName ?: CordaX500Name("Mock Company $id", "London", "GB")).whenever(it).myLegalName
doReturn(makeTestDataSourceProperties("node_$id", "net_$networkId")).whenever(it).dataSourceProperties
doReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")).whenever(it).dataSourceProperties
doReturn(makeTestDatabaseProperties("node_$id")).whenever(it).database
parameters.configOverrides(it)
}
@ -503,6 +503,5 @@ private fun mockNodeConfiguration(): NodeConfiguration {
doReturn(5.seconds.toMillis()).whenever(it).additionalNodeInfoPollingFrequencyMsec
doReturn(null).whenever(it).devModeOptions
doReturn(true).whenever(it).useAMQPBridges
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration
}
}

View File

@ -15,7 +15,9 @@ import net.corda.core.serialization.internal.effectiveSerializationEnv
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.node.services.api.StartedNodeServices
import net.corda.testing.*
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.TestIdentity
import net.corda.testing.chooseIdentity
import net.corda.testing.dsl.*
/**

View File

@ -39,6 +39,9 @@ dependencies {
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_config', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'jorphan', version: "$jmVersion"
//For Azure SQL and SQL Server support in persistence
runtime group: 'com.microsoft.sqlserver', name: 'mssql-jdbc', version: '6.2.1.jre8'
testCompile project(':test-utils')
testCompile project(':node-driver')

View File

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="3.2" jmeter="3.3 r1808647">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">40000</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">3</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<longProp name="ThreadGroup.start_time">1509455820000</longProp>
<longProp name="ThreadGroup.end_time">1509455820000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC Connection Configuration" enabled="true">
<boolProp name="autocommit">true</boolProp>
<stringProp name="checkQuery"></stringProp>
<stringProp name="connectionAge">5000</stringProp>
<stringProp name="dataSource">testpool</stringProp>
<stringProp name="dbUrl">jdbc:sqlserver://perfperformancetest.database.windows.net:1433;databaseName=perftesting</stringProp>
<stringProp name="driver">com.microsoft.sqlserver.jdbc.SQLServerDriver</stringProp>
<boolProp name="keepAlive">true</boolProp>
<stringProp name="password">yourStrong(!)Password</stringProp>
<stringProp name="poolMax">0</stringProp>
<stringProp name="timeout">10000</stringProp>
<stringProp name="transactionIsolation">TRANSACTION_REPEATABLE_READ</stringProp>
<stringProp name="trimInterval">60000</stringProp>
<stringProp name="username">perfnode1@perfperformancetest</stringProp>
</JDBCDataSource>
<hashTree/>
<JDBCSampler guiclass="TestBeanGUI" testclass="JDBCSampler" testname="JDBC Request" enabled="true">
<stringProp name="dataSource">testpool</stringProp>
<stringProp name="query">select dbtransact0_.tx_id as tx_id1_22_0_, dbtransact0_.transaction_value as transact2_22_0_ from perfnode1.node_transactions dbtransact0_ where dbtransact0_.tx_id=&apos;${__UUID()}&apos;</stringProp>
<stringProp name="queryArguments"></stringProp>
<stringProp name="queryArgumentsTypes"></stringProp>
<stringProp name="queryTimeout"></stringProp>
<stringProp name="queryType">Select Statement</stringProp>
<stringProp name="resultSetHandler">Store as String</stringProp>
<stringProp name="resultVariable"></stringProp>
<stringProp name="variableNames"></stringProp>
</JDBCSampler>
<hashTree/>
<ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
<ResultCollector guiclass="StatGraphVisualizer" testclass="ResultCollector" testname="Aggregate Graph" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="GraphVisualizer" testclass="ResultCollector" testname="Graph Results" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="TableVisualizer" testclass="ResultCollector" testname="View Results in Table" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
<WorkBench guiclass="WorkBenchGui" testclass="WorkBench" testname="WorkBench" enabled="true">
<boolProp name="WorkBench.save">true</boolProp>
</WorkBench>
<hashTree/>
</hashTree>
</jmeterTestPlan>

View File

@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="3.2" jmeter="3.3 r1808647">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC Connection Configuration" enabled="true">
<boolProp name="autocommit">true</boolProp>
<stringProp name="checkQuery"></stringProp>
<stringProp name="connectionAge">5000</stringProp>
<stringProp name="dataSource">testpool</stringProp>
<stringProp name="dbUrl">jdbc:sqlserver://perfperformancetest.database.windows.net:1433;databaseName=perftesting</stringProp>
<stringProp name="driver">com.microsoft.sqlserver.jdbc.SQLServerDriver</stringProp>
<boolProp name="keepAlive">true</boolProp>
<stringProp name="password">yourStrong(!)Password</stringProp>
<stringProp name="poolMax">0</stringProp>
<stringProp name="timeout">10000</stringProp>
<stringProp name="transactionIsolation">TRANSACTION_REPEATABLE_READ</stringProp>
<stringProp name="trimInterval">60000</stringProp>
<stringProp name="username">perfnode1@perfperformancetest</stringProp>
</JDBCDataSource>
<hashTree/>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">40000</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">3</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<longProp name="ThreadGroup.start_time">1509455820000</longProp>
<longProp name="ThreadGroup.end_time">1509455820000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<JDBCSampler guiclass="TestBeanGUI" testclass="JDBCSampler" testname="JDBC Request" enabled="true">
<stringProp name="dataSource">testpool</stringProp>
<stringProp name="query">declare @sql nvarchar(4000)
set @sql = N&apos;select dbtransact0_.tx_id as tx_id1_22_0_, dbtransact0_.transaction_value as transact2_22_0_ from perfnode1.node_transactions dbtransact0_ where dbtransact0_.tx_id=@P0&apos;
exec sp_executesql @sql, N&apos;@P0 nvarchar(4000)&apos;, &apos;${__UUID()}&apos;</stringProp>
<stringProp name="queryArguments"></stringProp>
<stringProp name="queryArgumentsTypes"></stringProp>
<stringProp name="queryTimeout"></stringProp>
<stringProp name="queryType">Select Statement</stringProp>
<stringProp name="resultSetHandler">Store as String</stringProp>
<stringProp name="resultVariable"></stringProp>
<stringProp name="variableNames"></stringProp>
</JDBCSampler>
<hashTree/>
<ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
<ResultCollector guiclass="StatGraphVisualizer" testclass="ResultCollector" testname="Aggregate Graph" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="GraphVisualizer" testclass="ResultCollector" testname="Graph Results" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="TableVisualizer" testclass="ResultCollector" testname="View Results in Table" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
<WorkBench guiclass="WorkBenchGui" testclass="WorkBench" testname="WorkBench" enabled="true">
<boolProp name="WorkBench.save">true</boolProp>
</WorkBench>
<hashTree/>
</hashTree>
</jmeterTestPlan>

View File

@ -34,14 +34,13 @@ class NativeSgxApiTest {
val DUMMY_CASH_ISSUER = DUMMY_CASH_ISSUER_IDENTITY.party.ref(1)
val megaCorp = TestIdentity(CordaX500Name("MegaCorp", "London", "GB"))
val MEGA_CORP get() = megaCorp.party
val MEGA_CORP_PUBKEY get() = megaCorp.publicKey
val MINI_CORP_PUBKEY = TestIdentity(CordaX500Name("MiniCorp", "London", "GB")).publicKey
val MEGA_CORP_PUBKEY get() = megaCorp.keyPair.public
val MINI_CORP_PUBKEY = TestIdentity(CordaX500Name("MiniCorp", "London", "GB")).keyPair.public
}
private val identityService = rigorousMock<IdentityServiceInternal>().also {
doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY)
}
private val ledgerServices = MockServices(emptyList(), identityService, MEGA_CORP.name)
private val ledgerServices = MockServices(emptyList(), rigorousMock<IdentityServiceInternal>().also {
doReturn(NativeSgxApiTest.MEGA_CORP).whenever(it).partyFromKey(NativeSgxApiTest.MEGA_CORP_PUBKEY)
}, NativeSgxApiTest.MEGA_CORP.name)
@Ignore("The SGX code is not part of the standard build yet")
@Test

View File

@ -32,17 +32,16 @@ class EnclaveletTest {
val DUMMY_CASH_ISSUER = DUMMY_CASH_ISSUER_IDENTITY.party.ref(1)
val megaCorp = TestIdentity(CordaX500Name("MegaCorp", "London", "GB"))
val MEGA_CORP get() = megaCorp.party
val MEGA_CORP_PUBKEY get() = megaCorp.publicKey
val MINI_CORP_PUBKEY = TestIdentity(CordaX500Name("MiniCorp", "London", "GB")).publicKey
val MEGA_CORP_PUBKEY get() = megaCorp.keyPair.public
val MINI_CORP_PUBKEY = TestIdentity(CordaX500Name("MiniCorp", "London", "GB")).keyPair.public
}
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
private val identityService = rigorousMock<IdentityServiceInternal>().also {
private val ledgerServices = MockServices(emptyList(), rigorousMock<IdentityServiceInternal>().also {
doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY)
}
private val ledgerServices = MockServices(emptyList(), identityService, MEGA_CORP.name)
}, MEGA_CORP.name)
@Ignore("Pending Gradle bug: https://github.com/gradle/gradle/issues/2657")
@Test