mirror of
https://github.com/corda/corda.git
synced 2025-06-01 15:10:54 +00:00
CORDA-2576 Viral update propagation: select attachments from those loaded by node on startup. (#4745)
* Retrieve contract attachment(s) loaded by node. * Remove redundant integration test case (downgrade rule checking) * Address PR review comments. * Revert changes to classloading dependencies hack.
This commit is contained in:
parent
ce8fa99e59
commit
0bdc8b363a
@ -441,9 +441,8 @@ open class TransactionBuilder(
|
|||||||
require(constraints.none { it in automaticConstraints })
|
require(constraints.none { it in automaticConstraints })
|
||||||
require(isReference || constraints.none { it is HashAttachmentConstraint })
|
require(isReference || constraints.none { it is HashAttachmentConstraint })
|
||||||
|
|
||||||
val minimumRequiredContractClassVersion = stateRefs?.map { services.loadContractAttachment(it).contractVersion }?.max() ?: DEFAULT_CORDAPP_VERSION
|
return services.cordappProvider.getContractAttachmentID(contractClassName)
|
||||||
return services.attachments.getLatestContractAttachments(contractClassName, minimumRequiredContractClassVersion).firstOrNull()
|
?: throw MissingContractAttachments(states, contractClassName)
|
||||||
?: throw MissingContractAttachments(states, contractClassName, minimumRequiredContractClassVersion)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun useWhitelistedByZoneAttachmentConstraint(contractClassName: ContractClassName, networkParameters: NetworkParameters) = contractClassName in networkParameters.whitelistedContractImplementations.keys
|
private fun useWhitelistedByZoneAttachmentConstraint(contractClassName: ContractClassName, networkParameters: NetworkParameters) = contractClassName in networkParameters.whitelistedContractImplementations.keys
|
||||||
|
@ -11,7 +11,6 @@ import net.corda.core.internal.div
|
|||||||
import net.corda.core.internal.packageName
|
import net.corda.core.internal.packageName
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
import net.corda.core.transactions.MissingContractAttachments
|
|
||||||
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
|
||||||
@ -23,15 +22,12 @@ import net.corda.testMessage.MessageState
|
|||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.driver.NodeParameters
|
import net.corda.testing.driver.NodeParameters
|
||||||
import net.corda.testing.driver.internal.incrementalPortAllocation
|
|
||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
import net.corda.testing.node.internal.cordappWithPackages
|
import net.corda.testing.node.internal.cordappWithPackages
|
||||||
import net.corda.testing.node.internal.internalDriver
|
import net.corda.testing.node.internal.internalDriver
|
||||||
import org.junit.Assume.assumeFalse
|
import org.junit.Assume.assumeFalse
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.sql.DriverManager
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
|
|
||||||
class SignatureConstraintVersioningTests {
|
class SignatureConstraintVersioningTests {
|
||||||
@ -83,57 +79,6 @@ class SignatureConstraintVersioningTests {
|
|||||||
assertNotNull(stateAndRef)
|
assertNotNull(stateAndRef)
|
||||||
assertEquals(transformetMessage, stateAndRef!!.state.data.message)
|
assertEquals(transformetMessage, stateAndRef!!.state.data.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `cannot evolve from higher contract class version to lower one`() {
|
|
||||||
assumeFalse(System.getProperty("os.name").toLowerCase().startsWith("win")) // See NodeStatePersistenceTests.kt.
|
|
||||||
|
|
||||||
val port = incrementalPortAllocation(21_000).nextPort()
|
|
||||||
|
|
||||||
val stateAndRef: StateAndRef<MessageState>? = internalDriver(inMemoryDB = false,
|
|
||||||
startNodesInProcess = isQuasarAgentSpecified(),
|
|
||||||
networkParameters = testNetworkParameters(notaries = emptyList(), minimumPlatformVersion = 4)) {
|
|
||||||
val nodeName = {
|
|
||||||
val nodeHandle = startNode(NodeParameters(rpcUsers = listOf(user), additionalCordapps = listOf(newCordapp)),
|
|
||||||
customOverrides = mapOf("h2Settings.address" to "localhost:$port")).getOrThrow()
|
|
||||||
val nodeName = nodeHandle.nodeInfo.singleIdentity().name
|
|
||||||
CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
|
||||||
it.proxy.startFlow(::CreateMessage, message, defaultNotaryIdentity).returnValue.getOrThrow()
|
|
||||||
}
|
|
||||||
nodeHandle.stop()
|
|
||||||
nodeName
|
|
||||||
}()
|
|
||||||
val result = {
|
|
||||||
(baseDirectory(nodeName) / "cordapps").deleteRecursively()
|
|
||||||
val nodeHandle = startNode(NodeParameters(providedName = nodeName, rpcUsers = listOf(user), additionalCordapps = listOf(oldCordapp)),
|
|
||||||
customOverrides = mapOf("h2Settings.address" to "localhost:$port")).getOrThrow()
|
|
||||||
|
|
||||||
//set the attachment with newer version (3) as untrusted one so the node can use only the older attachment with version 2
|
|
||||||
DriverManager.getConnection("jdbc:h2:tcp://localhost:$port/node", "sa", "").use {
|
|
||||||
it.createStatement().execute("UPDATE NODE_ATTACHMENTS SET UPLOADER = 'p2p' WHERE VERSION = 3")
|
|
||||||
}
|
|
||||||
var result: StateAndRef<MessageState>? = CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
|
||||||
val page = it.proxy.vaultQuery(MessageState::class.java)
|
|
||||||
page.states.singleOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
|
||||||
assertFailsWith(MissingContractAttachments::class) {
|
|
||||||
it.proxy.startFlow(::ConsumeMessage, result!!, defaultNotaryIdentity).returnValue.getOrThrow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
|
||||||
val page = it.proxy.vaultQuery(MessageState::class.java)
|
|
||||||
page.states.singleOrNull()
|
|
||||||
}
|
|
||||||
nodeHandle.stop()
|
|
||||||
result
|
|
||||||
}()
|
|
||||||
result
|
|
||||||
}
|
|
||||||
assertNotNull(stateAndRef)
|
|
||||||
assertEquals(message, stateAndRef!!.state.data.message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@StartableByRPC
|
@StartableByRPC
|
||||||
|
Loading…
x
Reference in New Issue
Block a user