CORDA-3584: Now cope with 2 contract jars with same hash but different name (#5952)

* CORDA-3484: Now cope with 2 contract jars with same hash but different name, we just select one and use that.

* ENT-3584: Contract jars are now generated on the fly.

* CORDA-3584: Reverted changes to CordappProviderImpl. Exception is raised if node started with multiple jars with same hash.

* ENT-3584: Fixing test failure.

* CORDA-3584: Switch to test extension method instead of reflection to access internal member.

* ENT-3584: Address review comment. Dont fully qualify exception.

* CORDA-3584: Address review comment and converted lazy to a resettable one.

* CORDA-3584: Removed unused logger.

* CORDA-3584: Fixed visibility.

* CORDA-3584: Removed synchronized

* CORDA-3584: Removed CordappResolver

* CORDA-3584: Reverted change in gradle file and fixed test.

* CORDA-3584: Removed V3 from test description as it wasn't actually V3 specific.

* CORDA-3584: Address review comment. Let classes be garbage collected.
This commit is contained in:
Adel El-Beik
2020-02-25 11:18:02 +00:00
committed by GitHub
parent 2c9c2985c0
commit fe625d0f37
9 changed files with 81 additions and 263 deletions

View File

@ -13,7 +13,6 @@ import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.VisibleForTesting import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.cordapp.CordappResolver
import net.corda.core.internal.warnOnce import net.corda.core.internal.warnOnce
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
@ -95,7 +94,7 @@ private constructor(private val otherSideSession: FlowSession?,
override fun call(): LinkedHashMap<Party, AnonymousParty> { override fun call(): LinkedHashMap<Party, AnonymousParty> {
val session = if (otherParty != null && otherParty != otherSideSession?.counterparty) { val session = if (otherParty != null && otherParty != otherSideSession?.counterparty) {
logger.warnOnce("The current usage of SwapIdentitiesFlow is unsafe. Please consider upgrading your CorDapp to use " + logger.warnOnce("The current usage of SwapIdentitiesFlow is unsafe. Please consider upgrading your CorDapp to use " +
"SwapIdentitiesFlow with FlowSessions. (${CordappResolver.currentCordapp?.info})") "SwapIdentitiesFlow with FlowSessions. (${serviceHub.getAppContext().cordapp.info})")
initiateFlow(otherParty) initiateFlow(otherParty)
} else { } else {
otherSideSession!! otherSideSession!!

View File

@ -4,7 +4,6 @@ import com.natpryce.hamkrest.and
import com.natpryce.hamkrest.assertion.assertThat import com.natpryce.hamkrest.assertion.assertThat
import net.corda.core.flows.FinalityFlow import net.corda.core.flows.FinalityFlow
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.cordapp.CordappResolver
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
@ -25,7 +24,8 @@ class FinalityFlowTests : WithFinality {
private val CHARLIE = TestIdentity(CHARLIE_NAME, 90).party private val CHARLIE = TestIdentity(CHARLIE_NAME, 90).party
} }
override val mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, enclosedCordapp())) override val mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, enclosedCordapp(),
CustomCordapp(targetPlatformVersion = 3, classes = setOf(FinalityFlow::class.java))))
private val aliceNode = makeNode(ALICE_NAME) private val aliceNode = makeNode(ALICE_NAME)
@ -60,11 +60,8 @@ class FinalityFlowTests : WithFinality {
fun `allow use of the old API if the CorDapp target version is 3`() { fun `allow use of the old API if the CorDapp target version is 3`() {
val oldBob = createBob(cordapps = listOf(tokenOldCordapp())) val oldBob = createBob(cordapps = listOf(tokenOldCordapp()))
val stx = aliceNode.issuesCashTo(oldBob) val stx = aliceNode.issuesCashTo(oldBob)
val resultFuture = CordappResolver.withTestCordapp(targetPlatformVersion = 3) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture.getOrThrow()
}
resultFuture.getOrThrow()
assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull() assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull()
} }

View File

@ -5,7 +5,6 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.isFulfilledBy import net.corda.core.crypto.isFulfilledBy
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.groupAbstractPartyByWellKnownParty import net.corda.core.identity.groupAbstractPartyByWellKnownParty
import net.corda.core.internal.cordapp.CordappResolver
import net.corda.core.internal.pushToLoggingContext import net.corda.core.internal.pushToLoggingContext
import net.corda.core.internal.warnOnce import net.corda.core.internal.warnOnce
import net.corda.core.node.StatesToRecord import net.corda.core.node.StatesToRecord
@ -136,7 +135,7 @@ class FinalityFlow private constructor(val transaction: SignedTransaction,
override fun call(): SignedTransaction { override fun call(): SignedTransaction {
if (!newApi) { if (!newApi) {
logger.warnOnce("The current usage of FinalityFlow is unsafe. Please consider upgrading your CorDapp to use " + logger.warnOnce("The current usage of FinalityFlow is unsafe. Please consider upgrading your CorDapp to use " +
"FinalityFlow with FlowSessions. (${CordappResolver.currentCordapp?.info})") "FinalityFlow with FlowSessions. (${serviceHub.getAppContext().cordapp.info})")
} else { } else {
require(sessions.none { serviceHub.myInfo.isLegalIdentity(it.counterparty) }) { require(sessions.none { serviceHub.myInfo.isLegalIdentity(it.counterparty) }) {
"Do not provide flow sessions for the local node. FinalityFlow will record the notarised transaction locally." "Do not provide flow sessions for the local node. FinalityFlow will record the notarised transaction locally."

View File

@ -1,133 +0,0 @@
package net.corda.core.internal.cordapp
import net.corda.core.cordapp.Cordapp
import net.corda.core.internal.PLATFORM_VERSION
import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.warnOnce
import net.corda.core.utilities.loggerFor
import java.util.concurrent.ConcurrentHashMap
/**
* Provides a way to acquire information about the calling CorDapp.
*/
object CordappResolver {
private val logger = loggerFor<CordappResolver>()
private val cordappClasses: ConcurrentHashMap<String, Set<Cordapp>> = ConcurrentHashMap()
private val insideInMemoryTest: Boolean by lazy { insideInMemoryTest() }
// TODO Use the StackWalker API once we migrate to Java 9+
private var cordappResolver: () -> Cordapp? = {
Exception().stackTrace
.mapNotNull { cordappClasses[it.className] }
// in case there are multiple classes matched, we select the first one having a single CorDapp registered against it.
.firstOrNull { it.size == 1 }
// otherwise we return null, signalling we cannot reliably determine the current CorDapp.
?.single()
}
/**
* Associates class names with CorDapps or logs a warning when a CorDapp is already registered for a given class.
* This could happen when trying to run different versions of the same CorDapp on the same node.
*
* @throws IllegalStateException when multiple CorDapps are registered for the same contract class,
* since this can lead to undefined behaviour.
*/
@Synchronized
fun register(cordapp: Cordapp) {
val contractClasses = cordapp.contractClassNames.toSet()
val existingClasses = cordappClasses.keys
val classesToRegister = cordapp.cordappClasses.toSet()
val notAlreadyRegisteredClasses = classesToRegister - existingClasses
val alreadyRegistered= HashMap(cordappClasses).apply { keys.retainAll(classesToRegister) }
notAlreadyRegisteredClasses.forEach { cordappClasses[it] = setOf(cordapp) }
for ((registeredClassName, registeredCordapps) in alreadyRegistered) {
val duplicateCordapps = registeredCordapps.filter { it.jarHash == cordapp.jarHash }.toSet()
if (duplicateCordapps.isNotEmpty()) {
logger.warnOnce("The CorDapp (name: ${cordapp.info.shortName}, file: ${cordapp.name}) " +
"is installed multiple times on the node. The following files correspond to the exact same content: " +
"${duplicateCordapps.map { it.name }}")
continue
}
// During in-memory tests, the spawned nodes share the same CordappResolver, so detected conflicts can be spurious.
if (registeredClassName in contractClasses && !insideInMemoryTest) {
throw IllegalStateException("More than one CorDapp installed on the node for contract $registeredClassName. " +
"Please remove the previous version when upgrading to a new version.")
}
cordappClasses[registeredClassName] = registeredCordapps + cordapp
}
}
private fun insideInMemoryTest(): Boolean {
return Exception().stackTrace.any {
it.className.startsWith("net.corda.testing.node.internal.InternalMockNetwork") ||
it.className.startsWith("net.corda.testing.node.internal.InProcessNode") ||
it.className.startsWith("net.corda.testing.node.MockServices")
}
}
/*
* This should only be used when making a change that would break compatibility with existing CorDapps. The change
* can then be version-gated, meaning the old behaviour is used if the calling CorDapp's target version is lower
* than the platform version that introduces the new behaviour.
* In situations where a `[CordappProvider]` is available the CorDapp context should be obtained from there.
*
* @return Information about the CorDapp from which the invoker is called, null if called outside a CorDapp or the
* calling CorDapp cannot be reliably determined.
*/
val currentCordapp: Cordapp? get() = cordappResolver()
/**
* Returns the target version of the current calling CorDapp. Defaults to platform version 1 if there isn't one,
* assuming only basic platform capabilities.
*/
val currentTargetVersion: Int get() = currentCordapp?.targetPlatformVersion ?: 1
// A list of extra CorDapps added to the current CorDapps list for testing purposes.
private var extraCordappsForTesting = listOf<Cordapp>()
/**
* Return all the CorDapps that were involved in the call stack at the point the provided exception was generated.
*
* This is provided to allow splitting the cost of generating the exception and retrieving the CorDapps involved.
*/
fun cordappsFromException(exception: Exception): List<Cordapp> {
val apps = exception.stackTrace
.mapNotNull { cordappClasses[it.className] }
.flatten()
.distinct()
return (apps + extraCordappsForTesting)
}
/**
* Temporarily apply a fake CorDapp with the given parameters. For use in testing.
*/
@Synchronized
@VisibleForTesting
fun <T> withTestCordapp(minimumPlatformVersion: Int = 1,
targetPlatformVersion: Int = PLATFORM_VERSION,
extraApps: List<CordappImpl> = listOf(),
block: () -> T): T {
val currentResolver = cordappResolver
cordappResolver = {
CordappImpl.TEST_INSTANCE.copy(minimumPlatformVersion = minimumPlatformVersion, targetPlatformVersion = targetPlatformVersion)
}
extraCordappsForTesting = listOf(cordappResolver()!!) + extraApps
try {
return block()
} finally {
cordappResolver = currentResolver
extraCordappsForTesting = listOf()
}
}
@VisibleForTesting
internal fun clear() {
cordappClasses.clear()
}
}

View File

@ -1,92 +0,0 @@
package net.corda.core.internal.cordapp
import net.corda.core.crypto.SecureHash
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.lang.IllegalStateException
import kotlin.test.assertEquals
class CordappResolverTest {
@Before
@After
fun clearCordappInfoResolver() {
CordappResolver.clear()
}
@Test(timeout=300_000)
fun `the correct cordapp resolver is used after calling withCordappInfo`() {
val defaultTargetVersion = 222
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
contractClassNames = listOf(javaClass.name),
minimumPlatformVersion = 3,
targetPlatformVersion = defaultTargetVersion
))
assertEquals(defaultTargetVersion, CordappResolver.currentTargetVersion)
val expectedTargetVersion = 555
CordappResolver.withTestCordapp(targetPlatformVersion = expectedTargetVersion) {
val actualTargetVersion = CordappResolver.currentTargetVersion
assertEquals(expectedTargetVersion, actualTargetVersion)
}
assertEquals(defaultTargetVersion, CordappResolver.currentTargetVersion)
}
@Test(timeout=300_000)
fun `when the same cordapp is registered for the same class multiple times, the resolver deduplicates and returns it as the current one`() {
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
contractClassNames = listOf(javaClass.name),
minimumPlatformVersion = 3,
targetPlatformVersion = 222
))
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
contractClassNames = listOf(javaClass.name),
minimumPlatformVersion = 2,
targetPlatformVersion = 456
))
assertThat(CordappResolver.currentCordapp).isNotNull()
}
@Test(timeout=300_000)
fun `when different cordapps are registered for the same (non-contract) class, the resolver returns null`() {
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
contractClassNames = listOf("ContractClass1"),
minimumPlatformVersion = 3,
targetPlatformVersion = 222,
jarHash = SecureHash.randomSHA256()
))
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
contractClassNames = listOf("ContractClass2"),
minimumPlatformVersion = 2,
targetPlatformVersion = 456,
jarHash = SecureHash.randomSHA256()
))
assertThat(CordappResolver.currentCordapp).isNull()
}
@Test(timeout=300_000)
fun `when different cordapps are registered for the same (contract) class, the resolver throws an exception`() {
val firstCordapp = CordappImpl.TEST_INSTANCE.copy(
contractClassNames = listOf(javaClass.name),
minimumPlatformVersion = 3,
targetPlatformVersion = 222,
jarHash = SecureHash.randomSHA256()
)
val secondCordapp = CordappImpl.TEST_INSTANCE.copy(
contractClassNames = listOf(javaClass.name),
minimumPlatformVersion = 2,
targetPlatformVersion = 456,
jarHash = SecureHash.randomSHA256()
)
CordappResolver.register(firstCordapp)
assertThatThrownBy { CordappResolver.register(secondCordapp) }
.isInstanceOf(IllegalStateException::class.java)
.hasMessageContaining("More than one CorDapp installed on the node for contract ${javaClass.name}. " +
"Please remove the previous version when upgrading to a new version.")
}
}

View File

@ -9,7 +9,6 @@ import net.corda.core.flows.*
import net.corda.core.internal.* import net.corda.core.internal.*
import net.corda.core.internal.cordapp.CordappImpl import net.corda.core.internal.cordapp.CordappImpl
import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN_INFO import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN_INFO
import net.corda.core.internal.cordapp.CordappResolver
import net.corda.core.internal.cordapp.get import net.corda.core.internal.cordapp.get
import net.corda.core.internal.notary.NotaryService import net.corda.core.internal.notary.NotaryService
import net.corda.core.internal.notary.SinglePartyNotaryService import net.corda.core.internal.notary.SinglePartyNotaryService
@ -30,6 +29,7 @@ import java.net.URL
import java.net.URLClassLoader import java.net.URLClassLoader
import java.nio.file.Path import java.nio.file.Path
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import java.util.jar.Manifest import java.util.jar.Manifest
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
@ -52,7 +52,7 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
logger.info("Loading CorDapps from ${cordappJarPaths.joinToString()}") logger.info("Loading CorDapps from ${cordappJarPaths.joinToString()}")
} }
} }
private val cordappClasses: ConcurrentHashMap<String, Set<Cordapp>> = ConcurrentHashMap()
override val cordapps: List<CordappImpl> by lazy { loadCordapps() + extraCordapps } override val cordapps: List<CordappImpl> by lazy { loadCordapps() + extraCordapps }
override val appClassLoader: URLClassLoader = URLClassLoader(cordappJarPaths.stream().map { it.url }.toTypedArray(), javaClass.classLoader) override val appClassLoader: URLClassLoader = URLClassLoader(cordappJarPaths.stream().map { it.url }.toTypedArray(), javaClass.classLoader)
@ -128,10 +128,35 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
} }
} }
} }
cordapps.forEach(CordappResolver::register) cordapps.forEach(::register)
return cordapps return cordapps
} }
private fun register(cordapp: Cordapp) {
val contractClasses = cordapp.contractClassNames.toSet()
val existingClasses = cordappClasses.keys
val classesToRegister = cordapp.cordappClasses.toSet()
val notAlreadyRegisteredClasses = classesToRegister - existingClasses
val alreadyRegistered= HashMap(cordappClasses).apply { keys.retainAll(classesToRegister) }
notAlreadyRegisteredClasses.forEach { cordappClasses[it] = setOf(cordapp) }
for ((registeredClassName, registeredCordapps) in alreadyRegistered) {
val duplicateCordapps = registeredCordapps.filter { it.jarHash == cordapp.jarHash }.toSet()
if (duplicateCordapps.isNotEmpty()) {
throw IllegalStateException("The CorDapp (name: ${cordapp.info.shortName}, file: ${cordapp.name}) " +
"is installed multiple times on the node. The following files correspond to the exact same content: " +
"${duplicateCordapps.map { it.name }}")
}
if (registeredClassName in contractClasses) {
throw IllegalStateException("More than one CorDapp installed on the node for contract $registeredClassName. " +
"Please remove the previous version when upgrading to a new version.")
}
cordappClasses[registeredClassName] = registeredCordapps + cordapp
}
}
private fun RestrictedScanResult.toCordapp(url: RestrictedURL): CordappImpl { private fun RestrictedScanResult.toCordapp(url: RestrictedURL): CordappImpl {
val manifest: Manifest? = url.url.openStream().use { JarInputStream(it).manifest } val manifest: Manifest? = url.url.openStream().use { JarInputStream(it).manifest }
val info = parseCordappInfo(manifest, CordappImpl.jarName(url.url)) val info = parseCordappInfo(manifest, CordappImpl.jarName(url.url))

View File

@ -5,7 +5,8 @@ import com.typesafe.config.ConfigFactory
import net.corda.core.node.services.AttachmentId import net.corda.core.node.services.AttachmentId
import net.corda.core.node.services.AttachmentStorage import net.corda.core.node.services.AttachmentStorage
import net.corda.node.VersionInfo import net.corda.node.VersionInfo
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.core.internal.ContractJarTestUtils
import net.corda.testing.core.internal.SelfCleaningDir
import net.corda.testing.internal.MockCordappConfigProvider import net.corda.testing.internal.MockCordappConfigProvider
import net.corda.testing.services.MockAttachmentStorage import net.corda.testing.services.MockAttachmentStorage
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
@ -14,7 +15,9 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.lang.IllegalStateException
import java.net.URL import java.net.URL
import java.nio.file.Files
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
import java.util.zip.Deflater.NO_COMPRESSION import java.util.zip.Deflater.NO_COMPRESSION
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
@ -56,7 +59,6 @@ class CordappProviderImplTests {
} }
private lateinit var attachmentStore: AttachmentStorage private lateinit var attachmentStore: AttachmentStorage
private val whitelistedContractImplementations = testNetworkParameters().whitelistedContractImplementations
@Before @Before
fun setup() { fun setup() {
@ -189,6 +191,33 @@ class CordappProviderImplTests {
assertThat(fixedIDs).containsExactlyInAnyOrder(ID2, ID4) assertThat(fixedIDs).containsExactlyInAnyOrder(ID2, ID4)
} }
@Test(timeout=300_000)
fun `test an exception is raised when we have two jars with the same hash`() {
SelfCleaningDir().use { file ->
val jarAndSigner = ContractJarTestUtils.makeTestSignedContractJar(file.path, "com.example.MyContract")
val signedJarPath = jarAndSigner.first
val duplicateJarPath = signedJarPath.parent.resolve("duplicate-" + signedJarPath.fileName)
Files.copy(signedJarPath, duplicateJarPath)
assertFailsWith<IllegalStateException> {
newCordappProvider(signedJarPath.toUri().toURL(), duplicateJarPath.toUri().toURL())
}
}
}
@Test(timeout=300_000)
fun `test an exception is raised when two jars share a contract`() {
SelfCleaningDir().use { file ->
val jarA = ContractJarTestUtils.makeTestContractJar(file.path, listOf("com.example.MyContract", "com.example.AnotherContractForA"), generateManifest = false, jarFileName = "sampleA.jar")
val jarB = ContractJarTestUtils.makeTestContractJar(file.path, listOf("com.example.MyContract", "com.example.AnotherContractForB"), generateManifest = false, jarFileName = "sampleB.jar")
assertFailsWith<IllegalStateException> {
newCordappProvider(jarA.toUri().toURL(), jarB.toUri().toURL())
}
}
}
private fun File.writeFixupRules(vararg lines: String): File { private fun File.writeFixupRules(vararg lines: String): File {
JarOutputStream(FileOutputStream(this)).use { jar -> JarOutputStream(FileOutputStream(this)).use { jar ->
jar.setMethod(DEFLATED) jar.setMethod(DEFLATED)

View File

@ -5,7 +5,6 @@ import net.corda.core.contracts.TransactionVerificationException
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FinalityFlow import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.StateMachineRunId import net.corda.core.flows.StateMachineRunId
import net.corda.core.internal.cordapp.CordappResolver
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
@ -35,7 +34,8 @@ class FinalityHandlerTest {
fun `sent to flow hospital on error and attempted retry on node restart`() { fun `sent to flow hospital on error and attempted retry on node restart`() {
// Setup a network where only Alice has the finance CorDapp and it sends a cash tx to Bob who doesn't have the // Setup a network where only Alice has the finance CorDapp and it sends a cash tx to Bob who doesn't have the
// CorDapp. Bob's FinalityHandler will error when validating the tx. // CorDapp. Bob's FinalityHandler will error when validating the tx.
val alice = mockNet.createNode(InternalMockNodeParameters(legalName = ALICE_NAME, additionalCordapps = FINANCE_CORDAPPS)) val alice = mockNet.createNode(InternalMockNodeParameters(legalName = ALICE_NAME,
additionalCordapps = FINANCE_CORDAPPS + CustomCordapp(targetPlatformVersion = 3, classes = setOf(FinalityFlow::class.java))))
var bob = mockNet.createNode(InternalMockNodeParameters( var bob = mockNet.createNode(InternalMockNodeParameters(
legalName = BOB_NAME, legalName = BOB_NAME,
@ -82,13 +82,11 @@ class FinalityHandlerTest {
} }
private fun TestStartedNode.finaliseWithOldApi(stx: SignedTransaction): CordaFuture<SignedTransaction> { private fun TestStartedNode.finaliseWithOldApi(stx: SignedTransaction): CordaFuture<SignedTransaction> {
return CordappResolver.withTestCordapp(targetPlatformVersion = 3) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
services.startFlow(FinalityFlow(stx)).resultFuture.apply { return services.startFlow(FinalityFlow(stx)).resultFuture.apply {
mockNet.runNetwork() mockNet.runNetwork()
} }
} }
}
private inline fun <reified R : MedicalRecord> TestStartedNode.medicalRecordsOfType(): Observable<R> { private inline fun <reified R : MedicalRecord> TestStartedNode.medicalRecordsOfType(): Observable<R> {
return smm return smm

View File

@ -2,7 +2,6 @@ package net.corda.node.services.vault
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.nhaarman.mockito_kotlin.argThat import com.nhaarman.mockito_kotlin.argThat
import com.nhaarman.mockito_kotlin.doNothing
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.* import net.corda.core.contracts.*
@ -11,7 +10,6 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.* import net.corda.core.identity.*
import net.corda.core.internal.NotaryChangeTransactionBuilder import net.corda.core.internal.NotaryChangeTransactionBuilder
import net.corda.core.internal.cordapp.CordappResolver
import net.corda.core.internal.packageName import net.corda.core.internal.packageName
import net.corda.core.node.NotaryInfo import net.corda.core.node.NotaryInfo
import net.corda.core.node.StatesToRecord import net.corda.core.node.StatesToRecord
@ -887,7 +885,7 @@ class NodeVaultServiceTest {
} }
@Test(timeout=300_000) @Test(timeout=300_000)
fun `V3 vault queries return all states by default`() { fun `Vault queries return all states by default`() {
fun createTx(number: Int, vararg participants: Party): SignedTransaction { fun createTx(number: Int, vararg participants: Party): SignedTransaction {
return services.signInitialTransaction(TransactionBuilder(DUMMY_NOTARY).apply { return services.signInitialTransaction(TransactionBuilder(DUMMY_NOTARY).apply {
addOutputState(DummyState(number, participants.toList()), DummyContract.PROGRAM_ID) addOutputState(DummyState(number, participants.toList()), DummyContract.PROGRAM_ID)
@ -897,7 +895,6 @@ class NodeVaultServiceTest {
fun List<StateAndRef<DummyState>>.getNumbers() = map { it.state.data.magicNumber }.toSet() fun List<StateAndRef<DummyState>>.getNumbers() = map { it.state.data.magicNumber }.toSet()
CordappResolver.withTestCordapp(targetPlatformVersion = 3) {
services.recordTransactions(StatesToRecord.ONLY_RELEVANT, listOf(createTx(1, megaCorp.party))) services.recordTransactions(StatesToRecord.ONLY_RELEVANT, listOf(createTx(1, megaCorp.party)))
services.recordTransactions(StatesToRecord.ONLY_RELEVANT, listOf(createTx(2, miniCorp.party))) services.recordTransactions(StatesToRecord.ONLY_RELEVANT, listOf(createTx(2, miniCorp.party)))
services.recordTransactions(StatesToRecord.ONLY_RELEVANT, listOf(createTx(3, miniCorp.party, megaCorp.party))) services.recordTransactions(StatesToRecord.ONLY_RELEVANT, listOf(createTx(3, miniCorp.party, megaCorp.party)))
@ -910,7 +907,6 @@ class NodeVaultServiceTest {
// RelevancyStatus is ALL by default. This should return five states. // RelevancyStatus is ALL by default. This should return five states.
val resultOne = vaultService.queryBy<DummyState>().states.getNumbers() val resultOne = vaultService.queryBy<DummyState>().states.getNumbers()
assertEquals(setOf(1, 3, 4, 5, 6), resultOne) assertEquals(setOf(1, 3, 4, 5, 6), resultOne)
}
// We should never see 2 or 7. // We should never see 2 or 7.
} }