mirror of
https://github.com/corda/corda.git
synced 2025-06-17 06:38:21 +00:00
CORDA-716 Make serialization init less static (#1996)
This commit is contained in:
@ -17,26 +17,21 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.internal.cordapp.CordappLoader
|
||||
import net.corda.node.internal.cordapp.CordappProviderImpl
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.SerializationEnvironmentRule
|
||||
import net.corda.testing.driver.DriverDSLExposedInterface
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Files
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class AttachmentLoadingTests {
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
|
||||
private class Services : MockServices() {
|
||||
private val provider = CordappProviderImpl(CordappLoader.createDevMode(listOf(isolatedJAR)), attachments)
|
||||
private val cordapp get() = provider.cordapps.first()
|
||||
@ -83,7 +78,7 @@ class AttachmentLoadingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test a wire transaction has loaded the correct attachment`() {
|
||||
fun `test a wire transaction has loaded the correct attachment`() = withTestSerialization {
|
||||
val appClassLoader = services.appContext.classLoader
|
||||
val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java)
|
||||
val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java)
|
||||
@ -101,7 +96,7 @@ class AttachmentLoadingTests {
|
||||
|
||||
@Test
|
||||
fun `test that attachments retrieved over the network are not used for code`() {
|
||||
driver(initialiseSerialization = false) {
|
||||
driver {
|
||||
installIsolatedCordappTo(bankAName)
|
||||
val (bankA, bankB) = createTwoNodes()
|
||||
assertFailsWith<UnexpectedFlowEndException>("Party C=CH,L=Zurich,O=BankB rejected session request: Don't know net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator") {
|
||||
@ -112,7 +107,7 @@ class AttachmentLoadingTests {
|
||||
|
||||
@Test
|
||||
fun `tests that if the attachment is loaded on both sides already that a flow can run`() {
|
||||
driver(initialiseSerialization = false) {
|
||||
driver {
|
||||
installIsolatedCordappTo(bankAName)
|
||||
installIsolatedCordappTo(bankBName)
|
||||
val (bankA, bankB) = createTwoNodes()
|
||||
|
@ -10,11 +10,13 @@ import net.corda.nodeapi.NodeInfoFilesCopier
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.ALICE_KEY
|
||||
import net.corda.testing.getTestPartyAndCertificate
|
||||
import net.corda.testing.internal.NodeBasedTest
|
||||
import net.corda.testing.*
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.contentOf
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import rx.observers.TestSubscriber
|
||||
import rx.schedulers.TestScheduler
|
||||
import java.nio.file.Path
|
||||
@ -22,11 +24,17 @@ import java.util.concurrent.TimeUnit
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class NodeInfoWatcherTest : NodeBasedTest() {
|
||||
class NodeInfoWatcherTest {
|
||||
companion object {
|
||||
val nodeInfo = NodeInfo(listOf(), listOf(getTestPartyAndCertificate(ALICE)), 0, 0)
|
||||
}
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
@Rule
|
||||
@JvmField
|
||||
val tempFolder = TemporaryFolder()
|
||||
private lateinit var nodeInfoPath: Path
|
||||
private val scheduler = TestScheduler()
|
||||
private val testSubscriber = TestSubscriber<NodeInfo>()
|
||||
|
@ -9,9 +9,10 @@ import net.corda.core.internal.concurrent.thenMatch
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.messaging.RPCOps
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
||||
import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.internal.cordapp.CordappLoader
|
||||
import net.corda.node.serialization.KryoServerSerializationScheme
|
||||
@ -25,7 +26,6 @@ import net.corda.node.services.messaging.NodeMessagingClient
|
||||
import net.corda.node.utilities.AddressUtils
|
||||
import net.corda.node.utilities.AffinityExecutor
|
||||
import net.corda.node.utilities.DemoClock
|
||||
import net.corda.nodeapi.ArtemisMessagingComponent
|
||||
import net.corda.nodeapi.internal.ShutdownHook
|
||||
import net.corda.nodeapi.internal.addShutdownHook
|
||||
import net.corda.nodeapi.internal.serialization.*
|
||||
@ -274,14 +274,15 @@ open class Node(configuration: NodeConfiguration,
|
||||
|
||||
private fun initialiseSerialization() {
|
||||
val classloader = cordappLoader.appClassLoader
|
||||
SerializationDefaults.SERIALIZATION_FACTORY = SerializationFactoryImpl().apply {
|
||||
registerScheme(KryoServerSerializationScheme())
|
||||
registerScheme(AMQPServerSerializationScheme())
|
||||
}
|
||||
SerializationDefaults.P2P_CONTEXT = KRYO_P2P_CONTEXT.withClassLoader(classloader)
|
||||
SerializationDefaults.RPC_SERVER_CONTEXT = KRYO_RPC_SERVER_CONTEXT.withClassLoader(classloader)
|
||||
SerializationDefaults.STORAGE_CONTEXT = KRYO_STORAGE_CONTEXT.withClassLoader(classloader)
|
||||
SerializationDefaults.CHECKPOINT_CONTEXT = KRYO_CHECKPOINT_CONTEXT.withClassLoader(classloader)
|
||||
nodeSerializationEnv = SerializationEnvironmentImpl(
|
||||
SerializationFactoryImpl().apply {
|
||||
registerScheme(KryoServerSerializationScheme())
|
||||
registerScheme(AMQPServerSerializationScheme())
|
||||
},
|
||||
KRYO_P2P_CONTEXT.withClassLoader(classloader),
|
||||
rpcServerContext = KRYO_RPC_SERVER_CONTEXT.withClassLoader(classloader),
|
||||
storageContext = KRYO_STORAGE_CONTEXT.withClassLoader(classloader),
|
||||
checkpointContext = KRYO_CHECKPOINT_CONTEXT.withClassLoader(classloader))
|
||||
}
|
||||
|
||||
/** Starts a blocking event loop for message dispatch. */
|
||||
|
@ -11,6 +11,7 @@ import net.corda.core.node.services.PartyInfo
|
||||
import net.corda.core.node.services.TransactionVerifierService
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
@ -217,6 +218,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
|
||||
locator.connectionTTL = -1
|
||||
locator.clientFailureCheckPeriod = -1
|
||||
locator.minLargeMessageSize = ArtemisMessagingServer.MAX_FILE_SIZE
|
||||
locator.isUseGlobalPools = nodeSerializationEnv != null
|
||||
sessionFactory = locator.createSessionFactory()
|
||||
|
||||
// Login using the node username. The broker will authentiate us as its node (as opposed to another peer)
|
||||
|
@ -60,7 +60,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
val testSerialization = SerializationEnvironmentRule(true)
|
||||
private val realClock: Clock = Clock.systemUTC()
|
||||
private val stoppedClock: Clock = Clock.fixed(realClock.instant(), realClock.zone)
|
||||
private val testClock = TestClock(stoppedClock)
|
||||
|
@ -41,7 +41,7 @@ import kotlin.test.assertEquals
|
||||
class HTTPNetworkMapClientTest {
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
val testSerialization = SerializationEnvironmentRule(true)
|
||||
private lateinit var server: Server
|
||||
|
||||
private lateinit var networkMapClient: NetworkMapClient
|
||||
|
@ -30,7 +30,7 @@ class DistributedImmutableMapTests {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
val testSerialization = SerializationEnvironmentRule(true)
|
||||
lateinit var cluster: List<Member>
|
||||
lateinit var transaction: DatabaseTransaction
|
||||
private val databases: MutableList<CordaPersistence> = mutableListOf()
|
||||
|
@ -1,9 +1,12 @@
|
||||
package net.corda.node.services.vault
|
||||
|
||||
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.identity.AnonymousParty
|
||||
import net.corda.core.internal.concurrent.fork
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.internal.packageName
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.node.services.VaultService
|
||||
@ -11,6 +14,7 @@ import net.corda.core.node.services.queryBy
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.*
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
|
||||
@ -29,9 +33,9 @@ import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.fail
|
||||
|
||||
// TODO: Move this to the cash contract tests once mock services are further split up.
|
||||
|
||||
@ -42,7 +46,7 @@ class VaultWithCashTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
val testSerialization = SerializationEnvironmentRule(true)
|
||||
lateinit var services: MockServices
|
||||
lateinit var issuerServices: MockServices
|
||||
val vaultService: VaultService get() = services.vaultService
|
||||
@ -150,82 +154,74 @@ class VaultWithCashTest {
|
||||
}
|
||||
|
||||
val backgroundExecutor = Executors.newFixedThreadPool(2)
|
||||
val countDown = CountDownLatch(2)
|
||||
|
||||
// 1st tx that spends our money.
|
||||
backgroundExecutor.submit {
|
||||
val first = backgroundExecutor.fork {
|
||||
database.transaction {
|
||||
try {
|
||||
val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
|
||||
Cash.generateSpend(services, txn1Builder, 60.DOLLARS, BOB)
|
||||
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
|
||||
val txn1 = services.addSignature(ptxn1, freshKey)
|
||||
println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}")
|
||||
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
|
||||
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn1 states:
|
||||
val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
|
||||
Cash.generateSpend(services, txn1Builder, 60.DOLLARS, BOB)
|
||||
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
|
||||
val txn1 = services.addSignature(ptxn1, freshKey)
|
||||
println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}")
|
||||
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
|
||||
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn1 states:
|
||||
UNCONSUMED: ${unconsumedStates1.totalStatesAvailable} : $unconsumedStates1,
|
||||
CONSUMED: ${consumedStates1.totalStatesAvailable} : $consumedStates1,
|
||||
LOCKED: ${lockedStates1.count()} : $lockedStates1
|
||||
""")
|
||||
services.recordTransactions(txn1)
|
||||
println("txn1: Cash balance: ${services.getCashBalance(USD)}")
|
||||
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates2 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
|
||||
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn1 states:
|
||||
services.recordTransactions(txn1)
|
||||
println("txn1: Cash balance: ${services.getCashBalance(USD)}")
|
||||
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates2 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
|
||||
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn1 states:
|
||||
UNCONSUMED: ${unconsumedStates2.totalStatesAvailable} : $unconsumedStates2,
|
||||
CONSUMED: ${consumedStates2.totalStatesAvailable} : $consumedStates2,
|
||||
LOCKED: ${lockedStates2.count()} : $lockedStates2
|
||||
""")
|
||||
txn1
|
||||
} catch (e: Exception) {
|
||||
println(e)
|
||||
}
|
||||
txn1
|
||||
}
|
||||
println("txn1 COMMITTED!")
|
||||
countDown.countDown()
|
||||
}
|
||||
|
||||
// 2nd tx that attempts to spend same money
|
||||
backgroundExecutor.submit {
|
||||
val second = backgroundExecutor.fork {
|
||||
database.transaction {
|
||||
try {
|
||||
val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
|
||||
Cash.generateSpend(services, txn2Builder, 80.DOLLARS, BOB)
|
||||
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
|
||||
val txn2 = services.addSignature(ptxn2, freshKey)
|
||||
println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}")
|
||||
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
|
||||
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn2 states:
|
||||
val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
|
||||
Cash.generateSpend(services, txn2Builder, 80.DOLLARS, BOB)
|
||||
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
|
||||
val txn2 = services.addSignature(ptxn2, freshKey)
|
||||
println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}")
|
||||
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
|
||||
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn2 states:
|
||||
UNCONSUMED: ${unconsumedStates1.totalStatesAvailable} : $unconsumedStates1,
|
||||
CONSUMED: ${consumedStates1.totalStatesAvailable} : $consumedStates1,
|
||||
LOCKED: ${lockedStates1.count()} : $lockedStates1
|
||||
""")
|
||||
services.recordTransactions(txn2)
|
||||
println("txn2: Cash balance: ${services.getCashBalance(USD)}")
|
||||
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates2 = vaultService.queryBy<Cash.State>()
|
||||
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn2 states:
|
||||
services.recordTransactions(txn2)
|
||||
println("txn2: Cash balance: ${services.getCashBalance(USD)}")
|
||||
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
|
||||
val consumedStates2 = vaultService.queryBy<Cash.State>()
|
||||
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
|
||||
println("""txn2 states:
|
||||
UNCONSUMED: ${unconsumedStates2.totalStatesAvailable} : $unconsumedStates2,
|
||||
CONSUMED: ${consumedStates2.totalStatesAvailable} : $consumedStates2,
|
||||
LOCKED: ${lockedStates2.count()} : $lockedStates2
|
||||
""")
|
||||
txn2
|
||||
} catch (e: Exception) {
|
||||
println(e)
|
||||
}
|
||||
txn2
|
||||
}
|
||||
println("txn2 COMMITTED!")
|
||||
|
||||
countDown.countDown()
|
||||
}
|
||||
|
||||
countDown.await()
|
||||
val both = listOf(first, second).transpose()
|
||||
try {
|
||||
both.getOrThrow()
|
||||
fail("Expected insufficient balance.")
|
||||
} catch (e: InsufficientBalanceException) {
|
||||
assertEquals(0, e.suppressed.size) // One should succeed.
|
||||
}
|
||||
database.transaction {
|
||||
println("Cash balance: ${services.getCashBalance(USD)}")
|
||||
assertThat(services.getCashBalance(USD)).isIn(DOLLARS(20), DOLLARS(40))
|
||||
|
Reference in New Issue
Block a user