CORDA-654 Various MockServices refactorings (#2167)

* Remove MockServices.stateMachineRecordedTransactionMapping which does nothing
* Inline StateLoaderImpl
* Remove unused MockServices
* MockServices well-known identities not needed in a place
* A few things don't need a full-blown ServiceHub
This commit is contained in:
Andrzej Cichocki 2017-12-05 16:22:53 +00:00 committed by GitHub
parent e4d76204c1
commit b0ebf3d7e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 91 additions and 208 deletions

View File

@ -1873,7 +1873,7 @@ public final class net.corda.core.node.services.TimeWindowChecker extends java.l
@org.jetbrains.annotations.NotNull public final java.time.Clock getClock() @org.jetbrains.annotations.NotNull public final java.time.Clock getClock()
public final boolean isValid(net.corda.core.contracts.TimeWindow) public final boolean isValid(net.corda.core.contracts.TimeWindow)
## ##
@net.corda.core.DoNotImplement public interface net.corda.core.node.services.TransactionStorage @net.corda.core.DoNotImplement public interface net.corda.core.node.services.TransactionStorage extends net.corda.core.node.StateLoader
@org.jetbrains.annotations.Nullable public abstract net.corda.core.transactions.SignedTransaction getTransaction(net.corda.core.crypto.SecureHash) @org.jetbrains.annotations.Nullable public abstract net.corda.core.transactions.SignedTransaction getTransaction(net.corda.core.crypto.SecureHash)
@org.jetbrains.annotations.NotNull public abstract rx.Observable getUpdates() @org.jetbrains.annotations.NotNull public abstract rx.Observable getUpdates()
@org.jetbrains.annotations.NotNull public abstract net.corda.core.messaging.DataFeed track() @org.jetbrains.annotations.NotNull public abstract net.corda.core.messaging.DataFeed track()

View File

@ -2,9 +2,9 @@
package net.corda.core.internal package net.corda.core.internal
import net.corda.core.cordapp.CordappProvider
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256 import net.corda.core.crypto.sha256
import net.corda.core.node.ServiceHub
import net.corda.core.node.ServicesForResolution import net.corda.core.node.ServicesForResolution
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
@ -295,15 +295,15 @@ fun <K, V> Iterable<Pair<K, V>>.toMultiMap(): Map<K, List<V>> = this.groupBy({ i
* Provide access to internal method for AttachmentClassLoaderTests * Provide access to internal method for AttachmentClassLoaderTests
* @suppress * @suppress
*/ */
fun TransactionBuilder.toWireTransaction(services: ServicesForResolution, serializationContext: SerializationContext): WireTransaction { fun TransactionBuilder.toWireTransaction(cordappProvider: CordappProvider, serializationContext: SerializationContext): WireTransaction {
return toWireTransactionWithContext(services, serializationContext) return toWireTransactionWithContext(cordappProvider, serializationContext)
} }
/** /**
* Provide access to internal method for AttachmentClassLoaderTests * Provide access to internal method for AttachmentClassLoaderTests
* @suppress * @suppress
*/ */
fun TransactionBuilder.toLedgerTransaction(services: ServiceHub, serializationContext: SerializationContext) = toLedgerTransactionWithContext(services, serializationContext) fun TransactionBuilder.toLedgerTransaction(services: ServicesForResolution, serializationContext: SerializationContext) = toLedgerTransactionWithContext(services, serializationContext)
/** Convenience method to get the package name of a class literal. */ /** Convenience method to get the package name of a class literal. */
val KClass<*>.packageName: String get() = java.`package`.name val KClass<*>.packageName: String get() = java.`package`.name

View File

@ -38,7 +38,9 @@ interface StateLoader {
// TODO: future implementation to use a Vault state ref -> contract state BLOB table and perform single query bulk load // TODO: future implementation to use a Vault state ref -> contract state BLOB table and perform single query bulk load
// as the existing transaction store will become encrypted at some point // as the existing transaction store will become encrypted at some point
@Throws(TransactionResolutionException::class) @Throws(TransactionResolutionException::class)
fun loadStates(stateRefs: Set<StateRef>): Set<StateAndRef<ContractState>> fun loadStates(stateRefs: Set<StateRef>): Set<StateAndRef<ContractState>> {
return stateRefs.map { StateAndRef(loadState(it), it) }.toSet()
}
} }
/** /**

View File

@ -1,8 +1,12 @@
package net.corda.core.node.services package net.corda.core.node.services
import net.corda.core.DoNotImplement import net.corda.core.DoNotImplement
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionResolutionException
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.node.StateLoader
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import rx.Observable import rx.Observable
@ -10,12 +14,18 @@ import rx.Observable
* Thread-safe storage of transactions. * Thread-safe storage of transactions.
*/ */
@DoNotImplement @DoNotImplement
interface TransactionStorage { interface TransactionStorage : StateLoader {
/** /**
* Return the transaction with the given [id], or null if no such transaction exists. * Return the transaction with the given [id], or null if no such transaction exists.
*/ */
fun getTransaction(id: SecureHash): SignedTransaction? fun getTransaction(id: SecureHash): SignedTransaction?
@Throws(TransactionResolutionException::class)
override fun loadState(stateRef: StateRef): TransactionState<*> {
val stx = getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash)
return stx.resolveBaseTransaction(this).outputs[stateRef.index]
}
/** /**
* Get a synchronous Observable of updates. When observations are pushed to the Observer, the vault will already * Get a synchronous Observable of updates. When observations are pushed to the Observer, the vault will already
* incorporate the update. * incorporate the update.

View File

@ -2,6 +2,7 @@ package net.corda.core.transactions
import co.paralleluniverse.strands.Strand import co.paralleluniverse.strands.Strand
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.cordapp.CordappProvider
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SignableData import net.corda.core.crypto.SignableData
import net.corda.core.crypto.SignatureMetadata import net.corda.core.crypto.SignatureMetadata
@ -82,16 +83,16 @@ open class TransactionBuilder(
* @returns A new [WireTransaction] that will be unaffected by further changes to this [TransactionBuilder]. * @returns A new [WireTransaction] that will be unaffected by further changes to this [TransactionBuilder].
*/ */
@Throws(MissingContractAttachments::class) @Throws(MissingContractAttachments::class)
fun toWireTransaction(services: ServicesForResolution): WireTransaction = toWireTransactionWithContext(services) fun toWireTransaction(services: ServicesForResolution): WireTransaction = toWireTransactionWithContext(services.cordappProvider)
internal fun toWireTransactionWithContext(services: ServicesForResolution, serializationContext: SerializationContext? = null): WireTransaction { internal fun toWireTransactionWithContext(cordappProvider: CordappProvider, serializationContext: SerializationContext? = null): WireTransaction {
// Resolves the AutomaticHashConstraints to HashAttachmentConstraints for convenience. The AutomaticHashConstraint // Resolves the AutomaticHashConstraints to HashAttachmentConstraints for convenience. The AutomaticHashConstraint
// allows for less boiler plate when constructing transactions since for the typical case the named contract // allows for less boiler plate when constructing transactions since for the typical case the named contract
// will be available when building the transaction. In exceptional cases the TransactionStates must be created // will be available when building the transaction. In exceptional cases the TransactionStates must be created
// with an explicit [AttachmentConstraint] // with an explicit [AttachmentConstraint]
val resolvedOutputs = outputs.map { state -> val resolvedOutputs = outputs.map { state ->
if (state.constraint is AutomaticHashConstraint) { if (state.constraint is AutomaticHashConstraint) {
services.cordappProvider.getContractAttachmentID(state.contract)?.let { cordappProvider.getContractAttachmentID(state.contract)?.let {
state.copy(constraint = HashAttachmentConstraint(it)) state.copy(constraint = HashAttachmentConstraint(it))
} ?: throw MissingContractAttachments(listOf(state)) } ?: throw MissingContractAttachments(listOf(state))
} else { } else {
@ -106,8 +107,7 @@ open class TransactionBuilder(
@Throws(AttachmentResolutionException::class, TransactionResolutionException::class) @Throws(AttachmentResolutionException::class, TransactionResolutionException::class)
fun toLedgerTransaction(services: ServiceHub) = toWireTransaction(services).toLedgerTransaction(services) fun toLedgerTransaction(services: ServiceHub) = toWireTransaction(services).toLedgerTransaction(services)
internal fun toLedgerTransactionWithContext(services: ServiceHub, serializationContext: SerializationContext) = toWireTransactionWithContext(services, serializationContext).toLedgerTransaction(services) internal fun toLedgerTransactionWithContext(services: ServicesForResolution, serializationContext: SerializationContext) = toWireTransactionWithContext(services.cordappProvider, serializationContext).toLedgerTransaction(services)
@Throws(AttachmentResolutionException::class, TransactionResolutionException::class, TransactionVerificationException::class) @Throws(AttachmentResolutionException::class, TransactionResolutionException::class, TransactionVerificationException::class)
fun verify(services: ServiceHub) { fun verify(services: ServiceHub) {
toLedgerTransaction(services).verify() toLedgerTransaction(services).verify()

View File

@ -1,16 +1,20 @@
package net.corda.nodeapi.internal package net.corda.nodeapi.internal
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.ServicesForResolution
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.node.MockServices import net.corda.testing.node.MockAttachmentStorage
import org.junit.Assert.* import org.junit.Assert.*
import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -44,11 +48,8 @@ class AttachmentsClassLoaderStaticContractTests {
} }
} }
private lateinit var serviceHub: MockServices private val serviceHub = rigorousMock<ServicesForResolution>().also {
doReturn(CordappProviderImpl(CordappLoader.createWithTestPackages(listOf("net.corda.nodeapi.internal")), MockAttachmentStorage())).whenever(it).cordappProvider
@Before
fun `create service hub`() {
serviceHub = MockServices(cordappPackages = listOf("net.corda.nodeapi.internal"))
} }
@Test @Test

View File

@ -19,10 +19,8 @@ import net.corda.nodeapi.internal.serialization.attachmentsClassLoaderEnabledPro
import net.corda.nodeapi.internal.serialization.withTokenContext import net.corda.nodeapi.internal.serialization.withTokenContext
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.node.MockAttachmentStorage import net.corda.testing.node.MockAttachmentStorage
import net.corda.testing.node.MockServices
import org.apache.commons.io.IOUtils import org.apache.commons.io.IOUtils
import org.junit.Assert.* import org.junit.Assert.*
import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
@ -52,14 +50,13 @@ class AttachmentsClassLoaderTests {
@Rule @Rule
@JvmField @JvmField
val testSerialization = SerializationEnvironmentRule() val testSerialization = SerializationEnvironmentRule()
private lateinit var serviceHub: DummyServiceHub private val attachments = MockAttachmentStorage()
private val cordappProvider = CordappProviderImpl(CordappLoader.createDevMode(listOf(ISOLATED_CONTRACTS_JAR_PATH)), attachments)
class DummyServiceHub : MockServices() { private val cordapp get() = cordappProvider.cordapps.first()
override val cordappProvider: CordappProviderImpl private val attachmentId get() = cordappProvider.getCordappAttachmentId(cordapp)!!
= CordappProviderImpl(CordappLoader.createDevMode(listOf(ISOLATED_CONTRACTS_JAR_PATH)), attachments) private val appContext get() = cordappProvider.getAppContext(cordapp)
private val cordapp get() = cordappProvider.cordapps.first() private val serviceHub = rigorousMock<ServiceHub>().also {
val attachmentId get() = cordappProvider.getCordappAttachmentId(cordapp)!! doReturn(attachments).whenever(it).attachments
val appContext get() = cordappProvider.getAppContext(cordapp)
} }
// These ClassLoaders work together to load 'AnotherDummyContract' in a disposable way, such that even though // These ClassLoaders work together to load 'AnotherDummyContract' in a disposable way, such that even though
@ -77,12 +74,6 @@ class AttachmentsClassLoaderTests {
} }
class ClassLoaderForTests : URLClassLoader(arrayOf(ISOLATED_CONTRACTS_JAR_PATH), FilteringClassLoader) class ClassLoaderForTests : URLClassLoader(arrayOf(ISOLATED_CONTRACTS_JAR_PATH), FilteringClassLoader)
@Before
fun `create service hub`() {
serviceHub = DummyServiceHub()
}
@Test @Test
fun `dynamically load AnotherDummyContract from isolated contracts jar`() { fun `dynamically load AnotherDummyContract from isolated contracts jar`() {
ClassLoaderForTests().use { child -> ClassLoaderForTests().use { child ->
@ -112,8 +103,8 @@ class AttachmentsClassLoaderTests {
@Test @Test
fun `test MockAttachmentStorage open as jar`() { fun `test MockAttachmentStorage open as jar`() {
val storage = serviceHub.attachments val storage = attachments
val key = serviceHub.attachmentId val key = attachmentId
val attachment = storage.openAttachment(key)!! val attachment = storage.openAttachment(key)!!
val jar = attachment.openAsJAR() val jar = attachment.openAsJAR()
@ -123,9 +114,8 @@ class AttachmentsClassLoaderTests {
@Test @Test
fun `test overlapping file exception`() { fun `test overlapping file exception`() {
val storage = serviceHub.attachments val storage = attachments
val att0 = attachmentId
val att0 = serviceHub.attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some data"))) val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some other data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some other data")))
@ -136,9 +126,8 @@ class AttachmentsClassLoaderTests {
@Test @Test
fun `basic`() { fun `basic`() {
val storage = serviceHub.attachments val storage = attachments
val att0 = attachmentId
val att0 = serviceHub.attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
@ -169,9 +158,8 @@ class AttachmentsClassLoaderTests {
@Test @Test
fun `loading class AnotherDummyContract`() { fun `loading class AnotherDummyContract`() {
val storage = serviceHub.attachments val storage = attachments
val att0 = attachmentId
val att0 = serviceHub.attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
@ -194,10 +182,8 @@ class AttachmentsClassLoaderTests {
val contract = createContract2Cash() val contract = createContract2Cash()
val bytes = contract.serialize() val bytes = contract.serialize()
val storage = attachments
val storage = serviceHub.attachments val att0 = attachmentId
val att0 = serviceHub.attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
@ -222,10 +208,8 @@ class AttachmentsClassLoaderTests {
val context2 = SerializationFactory.defaultFactory.defaultContext.withWhitelisted(data.contract.javaClass) val context2 = SerializationFactory.defaultFactory.defaultContext.withWhitelisted(data.contract.javaClass)
val bytes = data.serialize(context = context2) val bytes = data.serialize(context = context2)
val storage = attachments
val storage = serviceHub.attachments val att0 = attachmentId
val att0 = serviceHub.attachmentId
val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data")))
val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data")))
@ -276,7 +260,7 @@ class AttachmentsClassLoaderTests {
@Test @Test
fun `test serialization of WireTransaction with dynamically loaded contract`() { fun `test serialization of WireTransaction with dynamically loaded contract`() {
val child = serviceHub.appContext.classLoader val child = appContext.classLoader
val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child) val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child)
val contract = contractClass.newInstance() as DummyContractBackdoor val contract = contractClass.newInstance() as DummyContractBackdoor
val tx = contract.generateInitial(MEGA_CORP.ref(0), 42, DUMMY_NOTARY) val tx = contract.generateInitial(MEGA_CORP.ref(0), 42, DUMMY_NOTARY)
@ -288,7 +272,7 @@ class AttachmentsClassLoaderTests {
.withClassLoader(child) .withClassLoader(child)
val bytes = run { val bytes = run {
val wireTransaction = tx.toWireTransaction(serviceHub, context) val wireTransaction = tx.toWireTransaction(cordappProvider, context)
wireTransaction.serialize(context = context) wireTransaction.serialize(context = context)
} }
val copiedWireTransaction = bytes.deserialize(context = context) val copiedWireTransaction = bytes.deserialize(context = context)
@ -307,13 +291,12 @@ class AttachmentsClassLoaderTests {
val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child) val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child)
val contract = contractClass.newInstance() as DummyContractBackdoor val contract = contractClass.newInstance() as DummyContractBackdoor
val tx = contract.generateInitial(MEGA_CORP.ref(0), 42, DUMMY_NOTARY) val tx = contract.generateInitial(MEGA_CORP.ref(0), 42, DUMMY_NOTARY)
val attachmentRef = attachmentId
val attachmentRef = serviceHub.attachmentId
val bytes = run { val bytes = run {
val outboundContext = SerializationFactory.defaultFactory.defaultContext val outboundContext = SerializationFactory.defaultFactory.defaultContext
.withServiceHub(serviceHub) .withServiceHub(serviceHub)
.withClassLoader(child) .withClassLoader(child)
val wireTransaction = tx.toWireTransaction(serviceHub, outboundContext) val wireTransaction = tx.toWireTransaction(cordappProvider, outboundContext)
wireTransaction.serialize(context = outboundContext) wireTransaction.serialize(context = outboundContext)
} }
// use empty attachmentStorage // use empty attachmentStorage
@ -340,7 +323,7 @@ class AttachmentsClassLoaderTests {
val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child) val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child)
val contract = contractClass.newInstance() as DummyContractBackdoor val contract = contractClass.newInstance() as DummyContractBackdoor
val outboundContext = SerializationFactory.defaultFactory.defaultContext.withClassLoader(child) val outboundContext = SerializationFactory.defaultFactory.defaultContext.withClassLoader(child)
val attachmentRef = serviceHub.attachmentId val attachmentRef = attachmentId
// We currently ignore annotations in attachments, so manually whitelist. // We currently ignore annotations in attachments, so manually whitelist.
val inboundContext = SerializationFactory val inboundContext = SerializationFactory
.defaultFactory .defaultFactory

View File

@ -1,8 +1,9 @@
package net.corda.node.services package net.corda.node.services
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.Contract import net.corda.core.contracts.Contract
import net.corda.core.contracts.PartyAndReference import net.corda.core.contracts.PartyAndReference
import net.corda.core.cordapp.CordappProvider
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.UnexpectedFlowEndException import net.corda.core.flows.UnexpectedFlowEndException
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
@ -11,6 +12,8 @@ import net.corda.core.internal.concurrent.transpose
import net.corda.core.internal.createDirectories import net.corda.core.internal.createDirectories
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.toLedgerTransaction import net.corda.core.internal.toLedgerTransaction
import net.corda.core.node.ServicesForResolution
import net.corda.core.node.services.IdentityService
import net.corda.core.serialization.SerializationFactory import net.corda.core.serialization.SerializationFactory
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
@ -23,22 +26,19 @@ import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.DriverDSLExposedInterface import net.corda.testing.driver.DriverDSLExposedInterface
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.node.MockServices import net.corda.testing.node.MockAttachmentStorage
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test import org.junit.Test
import java.net.URLClassLoader import java.net.URLClassLoader
import java.nio.file.Files import java.nio.file.Files
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
class AttachmentLoadingTests { class AttachmentLoadingTests {
private class Services : MockServices() { private val attachments = MockAttachmentStorage()
private val provider = CordappProviderImpl(CordappLoader.createDevMode(listOf(isolatedJAR)), attachments) private val provider = CordappProviderImpl(CordappLoader.createDevMode(listOf(isolatedJAR)), attachments)
private val cordapp get() = provider.cordapps.first() private val cordapp get() = provider.cordapps.first()
val attachmentId get() = provider.getCordappAttachmentId(cordapp)!! private val attachmentId get() = provider.getCordappAttachmentId(cordapp)!!
val appContext get() = provider.getAppContext(cordapp) private val appContext get() = provider.getAppContext(cordapp)
override val cordappProvider: CordappProvider = provider
}
private companion object { private companion object {
private val logger = contextLogger() private val logger = contextLogger()
@ -70,16 +70,17 @@ class AttachmentLoadingTests {
} }
} }
private lateinit var services: Services private val services = rigorousMock<ServicesForResolution>().also {
doReturn(attachments).whenever(it).attachments
@Before doReturn(provider).whenever(it).cordappProvider
fun setup() { doReturn(rigorousMock<IdentityService>().also {
services = Services() doReturn(null).whenever(it).partyFromKey(DUMMY_BANK_A.owningKey)
}).whenever(it).identityService
} }
@Test @Test
fun `test a wire transaction has loaded the correct attachment`() = withTestSerialization { fun `test a wire transaction has loaded the correct attachment`() = withTestSerialization {
val appClassLoader = services.appContext.classLoader val appClassLoader = appContext.classLoader
val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java) val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java)
val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java) val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java)
val contract = contractClass.newInstance() val contract = contractClass.newInstance()
@ -89,8 +90,7 @@ class AttachmentLoadingTests {
contract.verify(ledgerTx) contract.verify(ledgerTx)
val actual = ledgerTx.attachments.first() val actual = ledgerTx.attachments.first()
val expected = services.attachments.openAttachment(services.attachmentId)!! val expected = attachments.openAttachment(attachmentId)!!
assertEquals(expected, actual) assertEquals(expected, actual)
} }

View File

@ -192,8 +192,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
val (startedImpl, schedulerService) = initialiseDatabasePersistence(schemaService, identityService) { database -> val (startedImpl, schedulerService) = initialiseDatabasePersistence(schemaService, identityService) { database ->
identityService.loadIdentities(info.legalIdentitiesAndCerts) identityService.loadIdentities(info.legalIdentitiesAndCerts)
val transactionStorage = makeTransactionStorage(database) val transactionStorage = makeTransactionStorage(database)
val stateLoader = StateLoaderImpl(transactionStorage) val nodeServices = makeServices(keyPairs, schemaService, transactionStorage, database, info, identityService)
val nodeServices = makeServices(keyPairs, schemaService, transactionStorage, stateLoader, database, info, identityService)
val notaryService = makeNotaryService(nodeServices, database) val notaryService = makeNotaryService(nodeServices, database)
val smm = makeStateMachineManager(database) val smm = makeStateMachineManager(database)
val flowStarter = FlowStarterImpl(serverThread, smm) val flowStarter = FlowStarterImpl(serverThread, smm)
@ -201,7 +200,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
platformClock, platformClock,
database, database,
flowStarter, flowStarter,
stateLoader, transactionStorage,
unfinishedSchedules = busyNodeLatch, unfinishedSchedules = busyNodeLatch,
serverThread = serverThread) serverThread = serverThread)
if (serverThread is ExecutorService) { if (serverThread is ExecutorService) {
@ -498,7 +497,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
* Builds node internal, advertised, and plugin services. * Builds node internal, advertised, and plugin services.
* Returns a list of tokenizable services to be added to the serialisation context. * Returns a list of tokenizable services to be added to the serialisation context.
*/ */
private fun makeServices(keyPairs: Set<KeyPair>, schemaService: SchemaService, transactionStorage: WritableTransactionStorage, stateLoader: StateLoader, database: CordaPersistence, info: NodeInfo, identityService: IdentityService): MutableList<Any> { private fun makeServices(keyPairs: Set<KeyPair>, schemaService: SchemaService, transactionStorage: WritableTransactionStorage, database: CordaPersistence, info: NodeInfo, identityService: IdentityService): MutableList<Any> {
checkpointStorage = DBCheckpointStorage() checkpointStorage = DBCheckpointStorage()
val metrics = MetricRegistry() val metrics = MetricRegistry()
attachments = NodeAttachmentService(metrics) attachments = NodeAttachmentService(metrics)
@ -509,7 +508,6 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
keyManagementService, keyManagementService,
schemaService, schemaService,
transactionStorage, transactionStorage,
stateLoader,
MonitoringService(metrics), MonitoringService(metrics),
cordappProvider, cordappProvider,
database, database,
@ -722,18 +720,17 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
override val keyManagementService: KeyManagementService, override val keyManagementService: KeyManagementService,
override val schemaService: SchemaService, override val schemaService: SchemaService,
override val validatedTransactions: WritableTransactionStorage, override val validatedTransactions: WritableTransactionStorage,
private val stateLoader: StateLoader,
override val monitoringService: MonitoringService, override val monitoringService: MonitoringService,
override val cordappProvider: CordappProviderInternal, override val cordappProvider: CordappProviderInternal,
override val database: CordaPersistence, override val database: CordaPersistence,
override val myInfo: NodeInfo override val myInfo: NodeInfo
) : SingletonSerializeAsToken(), ServiceHubInternal, StateLoader by stateLoader { ) : SingletonSerializeAsToken(), ServiceHubInternal, StateLoader by validatedTransactions {
override val rpcFlows = ArrayList<Class<out FlowLogic<*>>>() override val rpcFlows = ArrayList<Class<out FlowLogic<*>>>()
override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage() override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage()
override val auditService = DummyAuditService() override val auditService = DummyAuditService()
override val transactionVerifierService by lazy { makeTransactionVerifierService() } override val transactionVerifierService by lazy { makeTransactionVerifierService() }
override val networkMapCache by lazy { NetworkMapCacheImpl(PersistentNetworkMapCache(database), identityService) } override val networkMapCache by lazy { NetworkMapCacheImpl(PersistentNetworkMapCache(database), identityService) }
override val vaultService by lazy { makeVaultService(keyManagementService, stateLoader, database.hibernateConfig) } override val vaultService by lazy { makeVaultService(keyManagementService, validatedTransactions, database.hibernateConfig) }
override val contractUpgradeService by lazy { ContractUpgradeServiceImpl() } override val contractUpgradeService by lazy { ContractUpgradeServiceImpl() }
override val attachments: AttachmentStorage get() = this@AbstractNode.attachments override val attachments: AttachmentStorage get() = this@AbstractNode.attachments
override val networkService: MessagingService get() = network override val networkService: MessagingService get() = network

View File

@ -1,14 +1,11 @@
package net.corda.node.internal package net.corda.node.internal
import net.corda.core.contracts.*
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatedBy import net.corda.core.flows.InitiatedBy
import net.corda.core.internal.VisibleForTesting import net.corda.core.internal.VisibleForTesting
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.StateLoader
import net.corda.core.node.services.NotaryService import net.corda.core.node.services.NotaryService
import net.corda.core.node.services.TransactionStorage
import net.corda.node.services.api.CheckpointStorage import net.corda.node.services.api.CheckpointStorage
import net.corda.node.services.api.StartedNodeServices import net.corda.node.services.api.StartedNodeServices
import net.corda.node.services.messaging.MessagingService import net.corda.node.services.messaging.MessagingService
@ -44,17 +41,3 @@ interface StartedNode<out N : AbstractNode> {
return internals.internalRegisterFlowFactory(smm, initiatingFlowClass, flowFactory, initiatedFlowClass, track) return internals.internalRegisterFlowFactory(smm, initiatingFlowClass, flowFactory, initiatedFlowClass, track)
} }
} }
class StateLoaderImpl(private val validatedTransactions: TransactionStorage) : StateLoader {
@Throws(TransactionResolutionException::class)
override fun loadState(stateRef: StateRef): TransactionState<*> {
val stx = validatedTransactions.getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash)
return stx.resolveBaseTransaction(this).outputs[stateRef.index]
}
@Throws(TransactionResolutionException::class)
// TODO: future implementation to retrieve contract states from a Vault BLOB store
override fun loadStates(stateRefs: Set<StateRef>): Set<StateAndRef<ContractState>> {
return (stateRefs.map { StateAndRef(loadState(it), it) }).toSet()
}
}

View File

@ -1,48 +0,0 @@
package net.corda.node.services.persistence
import net.corda.core.internal.ThreadBox
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.StateMachineRunId
import net.corda.core.messaging.DataFeed
import net.corda.core.messaging.StateMachineTransactionMapping
import net.corda.node.services.api.StateMachineRecordedTransactionMappingStorage
import rx.subjects.PublishSubject
import java.util.*
import javax.annotation.concurrent.ThreadSafe
/**
* This is a temporary in-memory storage of a state machine id -> txhash mapping
*
* TODO persist this instead
*/
@ThreadSafe
class InMemoryStateMachineRecordedTransactionMappingStorage : StateMachineRecordedTransactionMappingStorage {
private class InnerState {
val stateMachineTransactionMap = HashMap<StateMachineRunId, HashSet<SecureHash>>()
val updates = PublishSubject.create<StateMachineTransactionMapping>()!!
}
private val mutex = ThreadBox(InnerState())
override fun addMapping(stateMachineRunId: StateMachineRunId, transactionId: SecureHash) {
mutex.locked {
stateMachineTransactionMap.getOrPut(stateMachineRunId) { HashSet() }.add(transactionId)
updates.onNext(StateMachineTransactionMapping(stateMachineRunId, transactionId))
}
}
override fun track():
DataFeed<List<StateMachineTransactionMapping>, StateMachineTransactionMapping> {
mutex.locked {
return DataFeed(
stateMachineTransactionMap.flatMap { entry ->
entry.value.map {
StateMachineTransactionMapping(entry.key, it)
}
},
updates.bufferUntilSubscribed()
)
}
}
}

View File

@ -16,7 +16,6 @@ import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.days import net.corda.core.utilities.days
import net.corda.node.internal.FlowStarterImpl import net.corda.node.internal.FlowStarterImpl
import net.corda.node.internal.StateLoaderImpl
import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.cordapp.CordappProviderImpl import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.node.services.api.MonitoringService import net.corda.node.services.api.MonitoringService
@ -95,7 +94,6 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
kms = MockKeyManagementService(identityService, ALICE_KEY) kms = MockKeyManagementService(identityService, ALICE_KEY)
val configuration = testNodeConfiguration(Paths.get("."), CordaX500Name("Alice", "London", "GB")) val configuration = testNodeConfiguration(Paths.get("."), CordaX500Name("Alice", "London", "GB"))
val validatedTransactions = MockTransactionStorage() val validatedTransactions = MockTransactionStorage()
val stateLoader = StateLoaderImpl(validatedTransactions)
database.transaction { database.transaction {
services = rigorousMock<Services>().also { services = rigorousMock<Services>().also {
doReturn(configuration).whenever(it).configuration doReturn(configuration).whenever(it).configuration
@ -105,13 +103,13 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
doReturn(myInfo).whenever(it).myInfo doReturn(myInfo).whenever(it).myInfo
doReturn(kms).whenever(it).keyManagementService doReturn(kms).whenever(it).keyManagementService
doReturn(CordappProviderImpl(CordappLoader.createWithTestPackages(listOf("net.corda.testing.contracts")), MockAttachmentStorage())).whenever(it).cordappProvider doReturn(CordappProviderImpl(CordappLoader.createWithTestPackages(listOf("net.corda.testing.contracts")), MockAttachmentStorage())).whenever(it).cordappProvider
doReturn(NodeVaultService(testClock, kms, stateLoader, database.hibernateConfig)).whenever(it).vaultService doReturn(NodeVaultService(testClock, kms, validatedTransactions, database.hibernateConfig)).whenever(it).vaultService
doReturn(this@NodeSchedulerServiceTest).whenever(it).testReference doReturn(this@NodeSchedulerServiceTest).whenever(it).testReference
} }
smmExecutor = AffinityExecutor.ServiceAffinityExecutor("test", 1) smmExecutor = AffinityExecutor.ServiceAffinityExecutor("test", 1)
mockSMM = StateMachineManagerImpl(services, DBCheckpointStorage(), smmExecutor, database) mockSMM = StateMachineManagerImpl(services, DBCheckpointStorage(), smmExecutor, database)
scheduler = NodeSchedulerService(testClock, database, FlowStarterImpl(smmExecutor, mockSMM), stateLoader, schedulerGatedExecutor, serverThread = smmExecutor) scheduler = NodeSchedulerService(testClock, database, FlowStarterImpl(smmExecutor, mockSMM), validatedTransactions, schedulerGatedExecutor, serverThread = smmExecutor)
mockSMM.changes.subscribe { change -> mockSMM.changes.subscribe { change ->
if (change is StateMachineManager.Change.Removed && mockSMM.allStateMachines.isEmpty()) { if (change is StateMachineManager.Change.Removed && mockSMM.allStateMachines.isEmpty()) {
smmHasRemovedAllFlows.countDown() smmHasRemovedAllFlows.countDown()

View File

@ -10,13 +10,15 @@ import net.corda.core.internal.cert
import net.corda.core.internal.toX509CertHolder import net.corda.core.internal.toX509CertHolder
import net.corda.core.node.services.IdentityService import net.corda.core.node.services.IdentityService
import net.corda.core.node.services.UnknownAnonymousPartyException import net.corda.core.node.services.UnknownAnonymousPartyException
import net.corda.node.internal.configureDatabase
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509CertificateFactory import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.makeTestIdentityService import net.corda.testing.node.makeTestIdentityService
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -30,15 +32,12 @@ import kotlin.test.assertNull
*/ */
class PersistentIdentityServiceTests { class PersistentIdentityServiceTests {
private lateinit var database: CordaPersistence private lateinit var database: CordaPersistence
private lateinit var services: MockServices
private lateinit var identityService: IdentityService private lateinit var identityService: IdentityService
@Before @Before
fun setup() { fun setup() {
val databaseAndServices = MockServices.makeTestDatabaseAndMockServices(emptyList(), PersistentIdentityService(DEV_TRUST_ROOT), initialIdentityName = MEGA_CORP.name) identityService = PersistentIdentityService(DEV_TRUST_ROOT)
database = databaseAndServices.first database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(), identityService)
services = databaseAndServices.second
identityService = services.identityService
} }
@After @After

View File

@ -5,20 +5,14 @@ import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SignatureMetadata import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.TransactionSignature import net.corda.core.crypto.TransactionSignature
import net.corda.core.node.StatesToRecord
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.WireTransaction import net.corda.core.transactions.WireTransaction
import net.corda.node.services.api.VaultServiceInternal
import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.transactions.PersistentUniquenessProvider import net.corda.node.services.transactions.PersistentUniquenessProvider
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.internal.configureDatabase import net.corda.node.internal.configureDatabase
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.node.MockServices
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -35,32 +29,11 @@ class DBTransactionStorageTests {
private lateinit var database: CordaPersistence private lateinit var database: CordaPersistence
private lateinit var transactionStorage: DBTransactionStorage private lateinit var transactionStorage: DBTransactionStorage
private lateinit var services: MockServices
@Before @Before
fun setUp() { fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class) LogHelper.setLevel(PersistentUniquenessProvider::class)
val dataSourceProps = makeTestDataSourceProperties() val dataSourceProps = makeTestDataSourceProperties()
val schemaService = NodeSchemaService() database = configureDatabase(dataSourceProps, DatabaseConfig(), rigorousMock())
database = configureDatabase(dataSourceProps, DatabaseConfig(), rigorousMock(), schemaService)
database.transaction {
services = object : MockServices(BOB_KEY) {
override val vaultService: VaultServiceInternal
get() {
val vaultService = NodeVaultService(clock, keyManagementService, stateLoader, database.hibernateConfig)
hibernatePersister = HibernateObserver.install(vaultService.rawUpdates, database.hibernateConfig, schemaService)
return vaultService
}
override fun recordTransactions(txs: Iterable<SignedTransaction>) {
for (stx in txs) {
validatedTransactions.addTransaction(stx)
}
// Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions.
vaultService.notifyAll(StatesToRecord.ONLY_RELEVANT, txs.map { it.tx })
}
}
}
newTransactionStorage() newTransactionStorage()
} }

View File

@ -4,7 +4,6 @@ import com.google.common.collect.MutableClassToInstanceMap
import net.corda.core.cordapp.CordappProvider import net.corda.core.cordapp.CordappProvider
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StateMachineRunId
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
@ -16,16 +15,13 @@ import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.node.VersionInfo import net.corda.node.VersionInfo
import net.corda.node.internal.StateLoaderImpl
import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.services.api.SchemaService import net.corda.node.services.api.SchemaService
import net.corda.node.services.api.StateMachineRecordedTransactionMappingStorage
import net.corda.node.services.api.VaultServiceInternal import net.corda.node.services.api.VaultServiceInternal
import net.corda.node.services.api.WritableTransactionStorage import net.corda.node.services.api.WritableTransactionStorage
import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.services.keys.freshCertificate import net.corda.node.services.keys.freshCertificate
import net.corda.node.services.keys.getSigner import net.corda.node.services.keys.getSigner
import net.corda.node.services.persistence.InMemoryStateMachineRecordedTransactionMappingStorage
import net.corda.node.services.schema.HibernateObserver import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.transactions.InMemoryTransactionVerifierService import net.corda.node.services.transactions.InMemoryTransactionVerifierService
@ -53,10 +49,9 @@ fun makeTestIdentityService(identities: Iterable<PartyAndCertificate> = emptySet
open class MockServices( open class MockServices(
cordappLoader: CordappLoader, cordappLoader: CordappLoader,
override val validatedTransactions: WritableTransactionStorage, override val validatedTransactions: WritableTransactionStorage,
protected val stateLoader: StateLoaderImpl = StateLoaderImpl(validatedTransactions),
private val initialIdentityName: CordaX500Name = MEGA_CORP.name, private val initialIdentityName: CordaX500Name = MEGA_CORP.name,
vararg val keys: KeyPair vararg val keys: KeyPair
) : ServiceHub, StateLoader by stateLoader { ) : ServiceHub, StateLoader by validatedTransactions {
companion object { companion object {
@JvmStatic @JvmStatic
val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor") val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor")
@ -99,9 +94,7 @@ open class MockServices(
override val vaultService: VaultServiceInternal = makeVaultService(database.hibernateConfig, schemaService) override val vaultService: VaultServiceInternal = makeVaultService(database.hibernateConfig, schemaService)
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) { override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) {
for (stx in txs) { super.recordTransactions(statesToRecord, txs)
validatedTransactions.addTransaction(stx)
}
// Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions. // Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions.
vaultService.notifyAll(statesToRecord, txs.map { it.tx }) vaultService.notifyAll(statesToRecord, txs.map { it.tx })
} }
@ -122,15 +115,11 @@ open class MockServices(
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) { override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) {
txs.forEach { txs.forEach {
stateMachineRecordedTransactionMapping.addMapping(StateMachineRunId.createRandom(), it.id) validatedTransactions.addTransaction(it)
}
for (stx in txs) {
validatedTransactions.addTransaction(stx)
} }
} }
final override val attachments = MockAttachmentStorage() final override val attachments = MockAttachmentStorage()
val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage = MockStateMachineRecordedTransactionMappingStorage()
override val identityService: IdentityService = makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)) override val identityService: IdentityService = makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY))
override val keyManagementService: KeyManagementService by lazy { MockKeyManagementService(identityService, *keys) } override val keyManagementService: KeyManagementService by lazy { MockKeyManagementService(identityService, *keys) }
@ -149,7 +138,7 @@ open class MockServices(
lateinit var hibernatePersister: HibernateObserver lateinit var hibernatePersister: HibernateObserver
fun makeVaultService(hibernateConfig: HibernateConfiguration, schemaService: SchemaService): VaultServiceInternal { fun makeVaultService(hibernateConfig: HibernateConfiguration, schemaService: SchemaService): VaultServiceInternal {
val vaultService = NodeVaultService(Clock.systemUTC(), keyManagementService, stateLoader, hibernateConfig) val vaultService = NodeVaultService(Clock.systemUTC(), keyManagementService, validatedTransactions, hibernateConfig)
hibernatePersister = HibernateObserver.install(vaultService.rawUpdates, hibernateConfig, schemaService) hibernatePersister = HibernateObserver.install(vaultService.rawUpdates, hibernateConfig, schemaService)
return vaultService return vaultService
} }
@ -201,10 +190,6 @@ class MockKeyManagementService(val identityService: IdentityService,
} }
} }
class MockStateMachineRecordedTransactionMappingStorage(
val storage: StateMachineRecordedTransactionMappingStorage = InMemoryStateMachineRecordedTransactionMappingStorage()
) : StateMachineRecordedTransactionMappingStorage by storage
open class MockTransactionStorage : WritableTransactionStorage, SingletonSerializeAsToken() { open class MockTransactionStorage : WritableTransactionStorage, SingletonSerializeAsToken() {
override fun track(): DataFeed<List<SignedTransaction>, SignedTransaction> { override fun track(): DataFeed<List<SignedTransaction>, SignedTransaction> {
return DataFeed(txns.values.toList(), _updatesPublisher) return DataFeed(txns.values.toList(), _updatesPublisher)