CORDA-2327 add attachments for missing dependencies (#4456)

* CORDA-2327 first draft - add attachments for missing dependencies

* CORDA-2327 draft - fix unit tests

* CORDA-2327 draft - some cleanup.

* CORDA-2327 fix test

* CORDA-2327 fix test

* CORDA-2327 fix test

* CORDA-2327 Address code review comments

* CORDA-2327 fix api

* Address code review comments

* CORDA-2327 Address code review comments

* CORDA-2327 Address code review comments

* Fix merge

* Address code review comments
This commit is contained in:
Tudor Malene
2019-01-02 16:16:53 +00:00
committed by GitHub
parent b1112dd264
commit ee9251bd25
33 changed files with 241 additions and 82 deletions

View File

@ -10,6 +10,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.convertValue import com.fasterxml.jackson.module.kotlin.convertValue
import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.client.jackson.internal.childrenAs import net.corda.client.jackson.internal.childrenAs
import net.corda.client.jackson.internal.valueAs import net.corda.client.jackson.internal.valueAs
@ -25,6 +26,7 @@ import net.corda.core.node.NodeInfo
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.services.AttachmentStorage import net.corda.core.node.services.AttachmentStorage
import net.corda.core.node.services.NetworkParametersStorage import net.corda.core.node.services.NetworkParametersStorage
import net.corda.core.node.services.TransactionStorage
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
@ -237,6 +239,7 @@ class JacksonSupportTest(@Suppress("unused") private val name: String, factory:
doReturn(attachmentId).whenever(cordappProvider).getContractAttachmentID(DummyContract.PROGRAM_ID) doReturn(attachmentId).whenever(cordappProvider).getContractAttachmentID(DummyContract.PROGRAM_ID)
val attachmentStorage = rigorousMock<AttachmentStorage>() val attachmentStorage = rigorousMock<AttachmentStorage>()
doReturn(attachmentStorage).whenever(services).attachments doReturn(attachmentStorage).whenever(services).attachments
doReturn(mock<TransactionStorage>()).whenever(services).validatedTransactions
val attachment = rigorousMock<ContractAttachment>() val attachment = rigorousMock<ContractAttachment>()
doReturn(attachment).whenever(attachmentStorage).openAttachment(attachmentId) doReturn(attachment).whenever(attachmentStorage).openAttachment(attachmentId)
doReturn(attachmentId).whenever(attachment).id doReturn(attachmentId).whenever(attachment).id

View File

@ -1,6 +1,7 @@
package net.corda.deterministic.data package net.corda.deterministic.data
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.crypto.entropyToKeyPair import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
@ -39,7 +40,7 @@ object TransactionGenerator {
private val MEGA_CORP_PUBKEY: PublicKey = megaCorp.keyPair.public private val MEGA_CORP_PUBKEY: PublicKey = megaCorp.keyPair.public
private val MINI_CORP_PUBKEY: PublicKey = TestIdentity(CordaX500Name("MiniCorp", "London", "GB")).keyPair.public private val MINI_CORP_PUBKEY: PublicKey = TestIdentity(CordaX500Name("MiniCorp", "London", "GB")).keyPair.public
private val ledgerServices = MockServices(emptyList(), MEGA_CORP.name, rigorousMock<IdentityServiceInternal>().also { private val ledgerServices = MockServices(emptyList(), MEGA_CORP.name, mock<IdentityServiceInternal>().also {
doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY) doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY)
doReturn(DUMMY_CASH_ISSUER.party).whenever(it).partyFromKey(DUMMY_CASH_ISSUER_KEY.public) doReturn(DUMMY_CASH_ISSUER.party).whenever(it).partyFromKey(DUMMY_CASH_ISSUER_KEY.public)
}) })

View File

@ -1,6 +1,7 @@
package net.corda.core.internal package net.corda.core.internal
import net.corda.core.DeleteForDJVM import net.corda.core.DeleteForDJVM
import net.corda.core.contracts.ContractAttachment
import net.corda.core.contracts.ContractClassName import net.corda.core.contracts.ContractClassName
import net.corda.core.cordapp.Cordapp import net.corda.core.cordapp.Cordapp
import net.corda.core.cordapp.CordappConfig import net.corda.core.cordapp.CordappConfig
@ -11,6 +12,11 @@ import net.corda.core.flows.FlowLogic
import net.corda.core.node.NetworkParameters import net.corda.core.node.NetworkParameters
import net.corda.core.node.ServicesForResolution import net.corda.core.node.ServicesForResolution
import net.corda.core.node.ZoneVersionTooLowException import net.corda.core.node.ZoneVersionTooLowException
import net.corda.core.node.services.AttachmentStorage
import net.corda.core.node.services.vault.AttachmentQueryCriteria
import net.corda.core.node.services.vault.AttachmentSort
import net.corda.core.node.services.vault.Builder
import net.corda.core.node.services.vault.Sort
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
@ -19,6 +25,7 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction import net.corda.core.transactions.WireTransaction
import org.slf4j.MDC import org.slf4j.MDC
import java.security.PublicKey import java.security.PublicKey
import java.util.jar.JarInputStream
// *Internal* Corda-specific utilities. // *Internal* Corda-specific utilities.
@ -116,3 +123,34 @@ internal fun NetworkParameters.getPackageOwnerOf(contractClassNames: Set<Contrac
fun noPackageOverlap(packages: Collection<String>): Boolean { fun noPackageOverlap(packages: Collection<String>): Boolean {
return packages.all { outer -> packages.none { inner -> inner != outer && inner.startsWith("$outer.") } } return packages.all { outer -> packages.none { inner -> inner != outer && inner.startsWith("$outer.") } }
} }
/**
* Scans trusted (installed locally) contract attachments to find all that contain the [className].
* This is required as a workaround until explicit cordapp dependencies are implemented.
* DO NOT USE IN CLIENT code.
*
* @return the contract attachments with the highest version.
*
* TODO: Should throw when the class is found in multiple contract attachments (not different versions).
*/
fun AttachmentStorage.internalFindTrustedAttachmentForClass(className: String): ContractAttachment?{
val allTrusted = queryAttachments(
AttachmentQueryCriteria.AttachmentsQueryCriteria().withUploader(Builder.`in`(TRUSTED_UPLOADERS)),
AttachmentSort(listOf(AttachmentSort.AttachmentSortColumn(AttachmentSort.AttachmentSortAttribute.VERSION, Sort.Direction.DESC))))
// TODO - add caching if performance is affected.
for (attId in allTrusted) {
val attch = openAttachment(attId)!!
if (attch is ContractAttachment && attch.openAsJAR().use { hasFile(it, "$className.class") }) return attch
}
return null
}
private fun hasFile(jarStream: JarInputStream, className: String): Boolean {
while (true) {
val e = jarStream.nextJarEntry ?: return false
if (e.name == className) {
return true
}
}
}

View File

@ -0,0 +1,20 @@
package net.corda.core.internal
import net.corda.core.DeleteForDJVM
import net.corda.core.concurrent.CordaFuture
import net.corda.core.contracts.Attachment
import net.corda.core.transactions.LedgerTransaction
@DeleteForDJVM
interface TransactionVerifierServiceInternal {
/**
* Verifies the [transaction] but adds some [extraAttachments] to the classpath.
* Required for transactions built with Corda 3.x that might miss some dependencies due to a bug in that version.
*/
fun verify(transaction: LedgerTransaction, extraAttachments: List<Attachment> ): CordaFuture<*>
}
/**
* Defined here for visibility reasons.
*/
fun LedgerTransaction.verify(extraAttachments: List<Attachment>) = this.verifyInternal(extraAttachments)

View File

@ -1,7 +1,9 @@
package net.corda.core.node.services package net.corda.core.node.services
import net.corda.core.CordaInternal
import net.corda.core.DoNotImplement import net.corda.core.DoNotImplement
import net.corda.core.contracts.Attachment import net.corda.core.contracts.Attachment
import net.corda.core.contracts.ContractAttachment
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.node.services.vault.AttachmentQueryCriteria import net.corda.core.node.services.vault.AttachmentQueryCriteria
import net.corda.core.node.services.vault.AttachmentSort import net.corda.core.node.services.vault.AttachmentSort

View File

@ -3,6 +3,7 @@ package net.corda.core.node.services
import net.corda.core.DeleteForDJVM import net.corda.core.DeleteForDJVM
import net.corda.core.DoNotImplement import net.corda.core.DoNotImplement
import net.corda.core.concurrent.CordaFuture import net.corda.core.concurrent.CordaFuture
import net.corda.core.contracts.Attachment
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
/** /**

View File

@ -118,14 +118,21 @@ private constructor(
* @throws TransactionVerificationException if anything goes wrong. * @throws TransactionVerificationException if anything goes wrong.
*/ */
@Throws(TransactionVerificationException::class) @Throws(TransactionVerificationException::class)
fun verify() { fun verify() = verifyInternal(emptyList())
/**
* Verifies the transaction but takes a list of [extraAttachments] which are used to form the classpath.
* Used to work around a Corda 3 bug as there might be transactions out there that don't contain all the necessary dependencies in the attachments list.
*/
@CordaInternal
internal fun verifyInternal(extraAttachments: List<Attachment>) {
if (networkParameters == null) { if (networkParameters == null) {
// For backwards compatibility only. // For backwards compatibility only.
logger.warn("Network parameters on the LedgerTransaction with id: $id are null. Please don't use deprecated constructors of the LedgerTransaction. " + logger.warn("Network parameters on the LedgerTransaction with id: $id are null. Please don't use deprecated constructors of the LedgerTransaction. " +
"Use WireTransaction.toLedgerTransaction instead. The result of the verify method might not be accurate.") "Use WireTransaction.toLedgerTransaction instead. The result of the verify method might not be accurate.")
} }
AttachmentsClassLoaderBuilder.withAttachmentsClassloaderContext(this.attachments) { transactionClassLoader -> AttachmentsClassLoaderBuilder.withAttachmentsClassloaderContext(this.attachments + extraAttachments) { transactionClassLoader ->
Verifier(createLtxForVerification(), transactionClassLoader).verify() Verifier(createLtxForVerification(), transactionClassLoader).verify()
} }
} }

View File

@ -7,13 +7,16 @@ import net.corda.core.KeepForDJVM
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.TransactionVerifierServiceInternal
import net.corda.core.internal.VisibleForTesting import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.internalFindTrustedAttachmentForClass
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.ServicesForResolution import net.corda.core.node.ServicesForResolution
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
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.utilities.contextLogger
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import java.security.KeyPair import java.security.KeyPair
import java.security.PublicKey import java.security.PublicKey
@ -200,8 +203,29 @@ data class SignedTransaction(val txBits: SerializedBytes<CoreTransaction>,
@DeleteForDJVM @DeleteForDJVM
private fun verifyRegularTransaction(services: ServiceHub, checkSufficientSignatures: Boolean) { private fun verifyRegularTransaction(services: ServiceHub, checkSufficientSignatures: Boolean) {
val ltx = toLedgerTransaction(services, checkSufficientSignatures) val ltx = toLedgerTransaction(services, checkSufficientSignatures)
// TODO: allow non-blocking verification. try {
services.transactionVerifierService.verify(ltx).getOrThrow() // TODO: allow non-blocking verification.
services.transactionVerifierService.verify(ltx).getOrThrow()
} catch (e: NoClassDefFoundError) {
// Transactions created before Corda 4 can be missing dependencies on other cordapps.
// This code attempts to find the missing dependency in the attachment storage among the trusted contract attachments.
// When it finds one, it instructs the verifier to use it to create the transaction classloader.
// TODO - add check that transaction was created before Corda 4.
// TODO - should this be a [TransactionVerificationException]?
val missingClass = requireNotNull(e.message) { "Transaction $ltx is incorrectly formed." }
val attachment = requireNotNull(services.attachments.internalFindTrustedAttachmentForClass(missingClass)) {
"Transaction $ltx is incorrectly formed. Could not find local dependency for class: $missingClass."
}
log.warn("""Detected that transaction ${this.id} does not contain all cordapp dependencies.
|This may be the result of a bug in a previous version of Corda.
|Attempting to verify using the additional dependency: $attachment.
|Please check with the originator that this is a valid transaction.""".trimMargin())
(services.transactionVerifierService as TransactionVerifierServiceInternal).verify(ltx, listOf(attachment)).getOrThrow()
}
} }
/** /**
@ -219,7 +243,6 @@ data class SignedTransaction(val txBits: SerializedBytes<CoreTransaction>,
} }
} }
/** /**
* Resolves the underlying transaction with signatures and then returns it, handling any special case transactions * Resolves the underlying transaction with signatures and then returns it, handling any special case transactions
* such as [NotaryChangeWireTransaction]. * such as [NotaryChangeWireTransaction].
@ -272,6 +295,8 @@ data class SignedTransaction(val txBits: SerializedBytes<CoreTransaction>,
"keys: ${missing.joinToString { it.toStringShort() }}, " + "keys: ${missing.joinToString { it.toStringShort() }}, " +
"by signers: ${descriptions.joinToString()} " "by signers: ${descriptions.joinToString()} "
} }
private val log = contextLogger()
} }
@KeepForDJVM @KeepForDJVM

View File

@ -146,7 +146,7 @@ open class TransactionBuilder @JvmOverloads constructor(
checkConstraintValidity(state) checkConstraintValidity(state)
} }
return SerializationFactory.defaultFactory.withCurrentContext(serializationContext) { val wireTx = SerializationFactory.defaultFactory.withCurrentContext(serializationContext) {
WireTransaction( WireTransaction(
createComponentGroups( createComponentGroups(
inputStates(), inputStates(),
@ -160,6 +160,47 @@ open class TransactionBuilder @JvmOverloads constructor(
privacySalt privacySalt
) )
} }
// Check the transaction for missing dependencies, and attempt to add them.
// This is a workaround as the current version of Corda does not support cordapp dependencies.
// It works by running transaction validation and then scan the attachment storage for missing classes.
// TODO - remove once proper support for cordapp dependencies is added.
val addedDependency = addMissingDependency(services, wireTx)
return if (addedDependency)
toWireTransactionWithContext(services, serializationContext)
else
wireTx
}
/**
* @return true if a new dependency was successfully added.
*/
private fun addMissingDependency(services: ServicesForResolution, wireTx: WireTransaction): Boolean {
try {
wireTx.toLedgerTransaction(services).verify()
} catch (e: NoClassDefFoundError) {
val missingClass = e.message
requireNotNull(missingClass) { "Transaction is incorrectly formed." }
val attachment = services.attachments.internalFindTrustedAttachmentForClass(missingClass!!)
?: throw IllegalArgumentException("Attempted to find dependent attachment for class $missingClass, but could not find a suitable candidate.")
log.warnOnce("""The transaction currently built is missing an attachment for class: $missingClass.
Automatically attaching contract dependency $attachment.
It is strongly recommended to check that this is the desired attachment, and to manually add it to the transaction builder.
""".trimIndent())
addAttachment(attachment.id)
return true
// Ignore these exceptions as they will break unit tests.
// The point here is only to detect missing dependencies. The other exceptions are irrelevant.
} catch (tve: TransactionVerificationException) {
} catch (tre: TransactionResolutionException) {
} catch (ise: IllegalStateException) {
} catch (ise: IllegalArgumentException) {
}
return false
} }
/** /**
@ -185,7 +226,8 @@ open class TransactionBuilder @JvmOverloads constructor(
val explicitAttachmentContractsMap: Map<ContractClassName, SecureHash> = explicitAttachmentContracts.toMap() val explicitAttachmentContractsMap: Map<ContractClassName, SecureHash> = explicitAttachmentContracts.toMap()
val inputContractGroups: Map<ContractClassName, List<TransactionState<ContractState>>> = inputsWithTransactionState.map {it.state}.groupBy { it.contract } val inputContractGroups: Map<ContractClassName, List<TransactionState<ContractState>>> = inputsWithTransactionState.map { it.state }
.groupBy { it.contract }
val outputContractGroups: Map<ContractClassName, List<TransactionState<ContractState>>> = outputs.groupBy { it.contract } val outputContractGroups: Map<ContractClassName, List<TransactionState<ContractState>>> = outputs.groupBy { it.contract }
val allContracts: Set<ContractClassName> = inputContractGroups.keys + outputContractGroups.keys val allContracts: Set<ContractClassName> = inputContractGroups.keys + outputContractGroups.keys
@ -199,7 +241,8 @@ open class TransactionBuilder @JvmOverloads constructor(
selectAttachmentThatSatisfiesConstraints(true, refStateEntry.key, refStateEntry.value, emptySet(), services) selectAttachmentThatSatisfiesConstraints(true, refStateEntry.key, refStateEntry.value, emptySet(), services)
} }
val contractClassNameToInputStateRef : Map<ContractClassName, Set<StateRef>> = inputsWithTransactionState.map { Pair(it.state.contract,it.ref) }.groupBy { it.first }.mapValues { it.value.map { e -> e.second }.toSet() } val contractClassNameToInputStateRef: Map<ContractClassName, Set<StateRef>> = inputsWithTransactionState.map { Pair(it.state.contract, it.ref) }
.groupBy { it.first }.mapValues { it.value.map { e -> e.second }.toSet() }
// For each contract, resolve the AutomaticPlaceholderConstraint, and select the attachment. // For each contract, resolve the AutomaticPlaceholderConstraint, and select the attachment.
val contractAttachmentsAndResolvedOutputStates: List<Pair<Set<AttachmentId>, List<TransactionState<ContractState>>?>> = allContracts.toSet() val contractAttachmentsAndResolvedOutputStates: List<Pair<Set<AttachmentId>, List<TransactionState<ContractState>>?>> = allContracts.toSet()
@ -255,20 +298,21 @@ open class TransactionBuilder @JvmOverloads constructor(
if (inputsHashConstraints.isNotEmpty() && (outputHashConstraints.isNotEmpty() || outputSignatureConstraints.isNotEmpty())) { if (inputsHashConstraints.isNotEmpty() && (outputHashConstraints.isNotEmpty() || outputSignatureConstraints.isNotEmpty())) {
val attachmentIds = services.attachments.getContractAttachments(contractClassName) val attachmentIds = services.attachments.getContractAttachments(contractClassName)
// only switchover if we have both signed and unsigned attachments for the given contract class name // only switchover if we have both signed and unsigned attachments for the given contract class name
if (attachmentIds.isNotEmpty() && attachmentIds.size == 2) { if (attachmentIds.isNotEmpty() && attachmentIds.size == 2) {
val attachmentsToUse = attachmentIds.map { val attachmentsToUse = attachmentIds.map {
services.attachments.openAttachment(it)?.let { it as ContractAttachment } services.attachments.openAttachment(it)?.let { it as ContractAttachment }
?: throw IllegalArgumentException("Contract attachment $it for $contractClassName is missing.") ?: throw IllegalArgumentException("Contract attachment $it for $contractClassName is missing.")
} }
val signedAttachment = attachmentsToUse.filter { it.isSigned }.firstOrNull() ?: throw IllegalArgumentException("Signed contract attachment for $contractClassName is missing.") val signedAttachment = attachmentsToUse.filter { it.isSigned }.firstOrNull()
?: throw IllegalArgumentException("Signed contract attachment for $contractClassName is missing.")
val outputConstraints = val outputConstraints =
if (outputHashConstraints.isNotEmpty()) { if (outputHashConstraints.isNotEmpty()) {
log.warn("Switching output states from hash to signed constraints using signers in signed contract attachment given by ${signedAttachment.id}") log.warn("Switching output states from hash to signed constraints using signers in signed contract attachment given by ${signedAttachment.id}")
val outputsSignatureConstraints = outputHashConstraints.map { it.copy(constraint = SignatureAttachmentConstraint(signedAttachment.signerKeys.first())) } val outputsSignatureConstraints = outputHashConstraints.map { it.copy(constraint = SignatureAttachmentConstraint(signedAttachment.signerKeys.first())) }
outputs.addAll(outputsSignatureConstraints) outputs.addAll(outputsSignatureConstraints)
outputs.removeAll(outputHashConstraints) outputs.removeAll(outputHashConstraints)
outputsSignatureConstraints outputsSignatureConstraints
} else outputSignatureConstraints } else outputSignatureConstraints
return Pair(attachmentIds.toSet(), outputConstraints) return Pair(attachmentIds.toSet(), outputConstraints)
} }
} }

View File

@ -83,7 +83,7 @@ class ConstraintsPropagationTests {
ledgerServices = object : MockServices( ledgerServices = object : MockServices(
cordappPackages = listOf("net.corda.finance.contracts.asset"), cordappPackages = listOf("net.corda.finance.contracts.asset"),
initialIdentity = ALICE, initialIdentity = ALICE,
identityService = rigorousMock<IdentityServiceInternal>().also { identityService = mock<IdentityServiceInternal>().also {
doReturn(ALICE_PARTY).whenever(it).partyFromKey(ALICE_PUBKEY) doReturn(ALICE_PARTY).whenever(it).partyFromKey(ALICE_PUBKEY)
doReturn(BOB_PARTY).whenever(it).partyFromKey(BOB_PUBKEY) doReturn(BOB_PARTY).whenever(it).partyFromKey(BOB_PUBKEY)
}, },

View File

@ -1,6 +1,7 @@
package net.corda.core.contracts package net.corda.core.contracts
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
@ -40,7 +41,7 @@ class PackageOwnershipVerificationTests {
private val ledgerServices = MockServices( private val ledgerServices = MockServices(
cordappPackages = listOf("net.corda.finance.contracts.asset"), cordappPackages = listOf("net.corda.finance.contracts.asset"),
initialIdentity = ALICE, initialIdentity = ALICE,
identityService = rigorousMock<IdentityServiceInternal>().also { identityService = mock<IdentityServiceInternal>().also {
doReturn(ALICE_PARTY).whenever(it).partyFromKey(ALICE_PUBKEY) doReturn(ALICE_PARTY).whenever(it).partyFromKey(ALICE_PUBKEY)
doReturn(BOB_PARTY).whenever(it).partyFromKey(BOB_PUBKEY) doReturn(BOB_PARTY).whenever(it).partyFromKey(BOB_PUBKEY)
}, },

View File

@ -1,6 +1,7 @@
package net.corda.core.crypto package net.corda.core.crypto
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
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.*
import net.corda.core.crypto.SecureHash.Companion.zeroHash import net.corda.core.crypto.SecureHash.Companion.zeroHash
@ -68,7 +69,7 @@ class PartialMerkleTreeTest {
testLedger = MockServices( testLedger = MockServices(
cordappPackages = emptyList(), cordappPackages = emptyList(),
initialIdentity = TestIdentity(MEGA_CORP.name), initialIdentity = TestIdentity(MEGA_CORP.name),
identityService = rigorousMock<IdentityServiceInternal>().also { identityService = mock<IdentityServiceInternal>().also {
doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY) doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY)
}, },
networkParameters = testNetworkParameters(minimumPlatformVersion = 4, notaries = listOf(NotaryInfo(DUMMY_NOTARY, true))) networkParameters = testNetworkParameters(minimumPlatformVersion = 4, notaries = listOf(NotaryInfo(DUMMY_NOTARY, true)))

View File

@ -1,5 +1,6 @@
package net.corda.core.serialization package net.corda.core.serialization
import com.nhaarman.mockito_kotlin.mock
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
@ -69,7 +70,7 @@ class TransactionSerializationTests {
val outputState = TransactionState(TestCash.State(depositRef, 600.POUNDS, MEGA_CORP), TEST_CASH_PROGRAM_ID, DUMMY_NOTARY) val outputState = TransactionState(TestCash.State(depositRef, 600.POUNDS, MEGA_CORP), TEST_CASH_PROGRAM_ID, DUMMY_NOTARY)
val changeState = TransactionState(TestCash.State(depositRef, 400.POUNDS, MEGA_CORP), TEST_CASH_PROGRAM_ID, DUMMY_NOTARY) val changeState = TransactionState(TestCash.State(depositRef, 400.POUNDS, MEGA_CORP), TEST_CASH_PROGRAM_ID, DUMMY_NOTARY)
val megaCorpServices = object : MockServices(listOf("net.corda.core.serialization"), MEGA_CORP.name, rigorousMock(), testNetworkParameters(notaries = listOf(NotaryInfo(DUMMY_NOTARY, true))), MEGA_CORP_KEY) { val megaCorpServices = object : MockServices(listOf("net.corda.core.serialization"), MEGA_CORP.name, mock(), testNetworkParameters(notaries = listOf(NotaryInfo(DUMMY_NOTARY, true))), MEGA_CORP_KEY) {
//override mock implementation with a real one //override mock implementation with a real one
override fun loadContractAttachment(stateRef: StateRef, forContractClassName: ContractClassName?): Attachment = servicesForResolution.loadContractAttachment(stateRef, forContractClassName) override fun loadContractAttachment(stateRef: StateRef, forContractClassName: ContractClassName?): Attachment = servicesForResolution.loadContractAttachment(stateRef, forContractClassName)
} }

View File

@ -1,6 +1,7 @@
package net.corda.core.transactions package net.corda.core.transactions
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
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.*
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
@ -34,7 +35,7 @@ class LedgerTransactionQueryTests {
private val services = MockServices( private val services = MockServices(
listOf("net.corda.testing.contracts"), listOf("net.corda.testing.contracts"),
TestIdentity(CordaX500Name("MegaCorp", "London", "GB"), keyPair), TestIdentity(CordaX500Name("MegaCorp", "London", "GB"), keyPair),
rigorousMock<IdentityServiceInternal>().also { mock<IdentityServiceInternal>().also {
doReturn(null).whenever(it).partyFromKey(keyPair.public) doReturn(null).whenever(it).partyFromKey(keyPair.public)
}, },
testNetworkParameters(notaries = listOf(NotaryInfo(DUMMY_NOTARY, true))), testNetworkParameters(notaries = listOf(NotaryInfo(DUMMY_NOTARY, true))),

View File

@ -1,6 +1,7 @@
package net.corda.core.transactions package net.corda.core.transactions
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
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.*
import net.corda.core.contracts.Requirements.using import net.corda.core.contracts.Requirements.using
@ -48,7 +49,7 @@ class ReferenceStateTests {
private val ledgerServices = MockServices( private val ledgerServices = MockServices(
cordappPackages = listOf("net.corda.core.transactions", "net.corda.finance.contracts.asset"), cordappPackages = listOf("net.corda.core.transactions", "net.corda.finance.contracts.asset"),
initialIdentity = ALICE, initialIdentity = ALICE,
identityService = rigorousMock<IdentityServiceInternal>().also { identityService = mock<IdentityServiceInternal>().also {
doReturn(ALICE_PARTY).whenever(it).partyFromKey(ALICE_PUBKEY) doReturn(ALICE_PARTY).whenever(it).partyFromKey(ALICE_PUBKEY)
doReturn(BOB_PARTY).whenever(it).partyFromKey(BOB_PUBKEY) doReturn(BOB_PARTY).whenever(it).partyFromKey(BOB_PUBKEY)
}, },

View File

@ -1,6 +1,7 @@
package net.corda.core.transactions package net.corda.core.transactions
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
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.*
import net.corda.core.cordapp.CordappProvider import net.corda.core.cordapp.CordappProvider
@ -39,7 +40,7 @@ class TransactionBuilderTest {
private val services = rigorousMock<ServicesForResolution>() private val services = rigorousMock<ServicesForResolution>()
private val contractAttachmentId = SecureHash.randomSHA256() private val contractAttachmentId = SecureHash.randomSHA256()
private val attachments = rigorousMock<AttachmentStorage>() private val attachments = rigorousMock<AttachmentStorage>()
private val networkParametersStorage = rigorousMock<NetworkParametersStorage>() private val networkParametersStorage = mock<NetworkParametersStorage>()
@Before @Before
fun setup() { fun setup() {
@ -109,6 +110,7 @@ class TransactionBuilderTest {
.hasMessageContaining("Reference states") .hasMessageContaining("Reference states")
doReturn(testNetworkParameters(minimumPlatformVersion = 4)).whenever(services).networkParameters doReturn(testNetworkParameters(minimumPlatformVersion = 4)).whenever(services).networkParameters
doReturn(referenceState).whenever(services).loadState(referenceStateRef)
val wtx = builder.toWireTransaction(services) val wtx = builder.toWireTransaction(services)
assertThat(wtx.references).containsOnly(referenceStateRef) assertThat(wtx.references).containsOnly(referenceStateRef)
} }

View File

@ -1,6 +1,7 @@
package net.corda.core.transactions package net.corda.core.transactions
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
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.*
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
@ -56,7 +57,7 @@ class TransactionEncumbranceTests {
val ledgerServices = MockServices( val ledgerServices = MockServices(
listOf("net.corda.core.transactions", "net.corda.finance.contracts.asset"), listOf("net.corda.core.transactions", "net.corda.finance.contracts.asset"),
MEGA_CORP.name, MEGA_CORP.name,
rigorousMock<IdentityServiceInternal>().also { mock<IdentityServiceInternal>().also {
doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY) doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY)
}, },
testNetworkParameters(notaries = listOf(NotaryInfo(DUMMY_NOTARY, true))) testNetworkParameters(notaries = listOf(NotaryInfo(DUMMY_NOTARY, true)))

View File

@ -3,6 +3,7 @@
package net.corda.docs.kotlin.tutorial.testdsl package net.corda.docs.kotlin.tutorial.testdsl
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.TransactionVerificationException import net.corda.core.contracts.TransactionVerificationException
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
@ -47,7 +48,7 @@ class TutorialTestDSL {
// You can also use the alternative parameter initialIdentityName which accepts a // You can also use the alternative parameter initialIdentityName which accepts a
// [CordaX500Name] // [CordaX500Name]
megaCorp, megaCorp,
rigorousMock<IdentityService>().also { mock<IdentityService>().also {
doReturn(megaCorp.party).whenever(it).partyFromKey(megaCorp.publicKey) doReturn(megaCorp.party).whenever(it).partyFromKey(megaCorp.publicKey)
doReturn(null).whenever(it).partyFromKey(bigCorp.publicKey) doReturn(null).whenever(it).partyFromKey(bigCorp.publicKey)
doReturn(null).whenever(it).partyFromKey(alice.publicKey) doReturn(null).whenever(it).partyFromKey(alice.publicKey)

View File

@ -1,6 +1,7 @@
package net.corda.finance.contracts.universal package net.corda.finance.contracts.universal
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.finance.contracts.BusinessCalendar import net.corda.finance.contracts.BusinessCalendar
@ -26,7 +27,7 @@ import java.time.LocalDate
internal val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party internal val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
fun transaction(script: TransactionDSL<TransactionDSLInterpreter>.() -> EnforceVerifyOrFail) = run { fun transaction(script: TransactionDSL<TransactionDSLInterpreter>.() -> EnforceVerifyOrFail) = run {
MockServices(listOf("net.corda.finance.contracts.universal"), CordaX500Name("MegaCorp", "London", "GB"), MockServices(listOf("net.corda.finance.contracts.universal"), CordaX500Name("MegaCorp", "London", "GB"),
rigorousMock<IdentityServiceInternal>().also { mock<IdentityServiceInternal>().also {
listOf(acmeCorp, highStreetBank, momAndPop).forEach { party -> listOf(acmeCorp, highStreetBank, momAndPop).forEach { party ->
doReturn(null).whenever(it).partyFromKey(party.owningKey) doReturn(null).whenever(it).partyFromKey(party.owningKey)
} }

View File

@ -11,6 +11,7 @@ import net.corda.testing.core.TestIdentity;
import net.corda.testing.node.MockServices; import net.corda.testing.node.MockServices;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static net.corda.finance.Currencies.DOLLARS; import static net.corda.finance.Currencies.DOLLARS;
@ -19,6 +20,7 @@ import static net.corda.testing.node.NodeTestUtils.transaction;
import static net.corda.testing.internal.RigorousMockKt.rigorousMock; import static net.corda.testing.internal.RigorousMockKt.rigorousMock;
import static net.corda.testing.core.TestConstants.DUMMY_NOTARY_NAME; import static net.corda.testing.core.TestConstants.DUMMY_NOTARY_NAME;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/** /**
* This is an incomplete Java replica of CashTests.kt to show how to use the Java test DSL * This is an incomplete Java replica of CashTests.kt to show how to use the Java test DSL
@ -35,7 +37,7 @@ public class CashTestsJava {
@Test @Test
public void trivial() { public void trivial() {
IdentityServiceInternal identityService = rigorousMock(IdentityServiceInternal.class); IdentityServiceInternal identityService = mock(IdentityServiceInternal.class);
doReturn(MEGA_CORP.getParty()).when(identityService).partyFromKey(MEGA_CORP.getPublicKey()); doReturn(MEGA_CORP.getParty()).when(identityService).partyFromKey(MEGA_CORP.getPublicKey());
doReturn(MINI_CORP.getParty()).when(identityService).partyFromKey(MINI_CORP.getPublicKey()); doReturn(MINI_CORP.getParty()).when(identityService).partyFromKey(MINI_CORP.getPublicKey());
transaction(new MockServices(emptyList(), MEGA_CORP.getName(), identityService), DUMMY_NOTARY, tx -> { transaction(new MockServices(emptyList(), MEGA_CORP.getName(), identityService), DUMMY_NOTARY, tx -> {

View File

@ -1,6 +1,7 @@
package net.corda.finance.contracts.asset package net.corda.finance.contracts.asset
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
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.*
import net.corda.core.crypto.NullKeys.NULL_PARTY import net.corda.core.crypto.NullKeys.NULL_PARTY
@ -25,7 +26,6 @@ import net.corda.testing.core.*
import net.corda.testing.dsl.* import net.corda.testing.dsl.*
import net.corda.testing.internal.TEST_TX_TIME import net.corda.testing.internal.TEST_TX_TIME
import net.corda.testing.internal.fakeAttachment import net.corda.testing.internal.fakeAttachment
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.vault.CommodityState import net.corda.testing.internal.vault.CommodityState
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.ledger import net.corda.testing.node.ledger
@ -81,12 +81,12 @@ class ObligationTests {
beneficiary = CHARLIE beneficiary = CHARLIE
) )
private val outState = inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) private val outState = inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY))
private val miniCorpServices = object : MockServices(listOf("net.corda.finance.contracts.asset"), miniCorp, rigorousMock<IdentityService>()) { private val miniCorpServices = object : MockServices(listOf("net.corda.finance.contracts.asset"), miniCorp, mock<IdentityService>()) {
override fun loadState(stateRef: StateRef): TransactionState<*> = TransactionState(inState, Cash.PROGRAM_ID, dummyNotary.party) // Simulates the sate is recorded in node service override fun loadState(stateRef: StateRef): TransactionState<*> = TransactionState(inState, Cash.PROGRAM_ID, dummyNotary.party) // Simulates the sate is recorded in node service
} }
private val notaryServices = MockServices(emptyList(), MEGA_CORP.name, rigorousMock(), dummyNotary.keyPair) private val notaryServices = MockServices(emptyList(), MEGA_CORP.name, mock(), dummyNotary.keyPair)
private val identityService = rigorousMock<IdentityServiceInternal>().also { private val identityService = mock<IdentityServiceInternal>().also {
doReturn(null).whenever(it).partyFromKey(ALICE_PUBKEY) doReturn(null).whenever(it).partyFromKey(ALICE_PUBKEY)
doReturn(null).whenever(it).partyFromKey(BOB_PUBKEY) doReturn(null).whenever(it).partyFromKey(BOB_PUBKEY)
doReturn(null).whenever(it).partyFromKey(CHARLIE.owningKey) doReturn(null).whenever(it).partyFromKey(CHARLIE.owningKey)

View File

@ -2,6 +2,7 @@ package net.corda.nodeapi.internal
import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
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.*
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
@ -70,7 +71,7 @@ class AttachmentsClassLoaderStaticContractTests {
private val networkParameters = testNetworkParameters() private val networkParameters = testNetworkParameters()
private val networkParametersStorage get() = rigorousMock<NetworkParametersStorage>().also { private val networkParametersStorage get() = mock<NetworkParametersStorage>().also {
doReturn(networkParameters.serialize().hash).whenever(it).currentHash doReturn(networkParameters.serialize().hash).whenever(it).currentHash
} }

View File

@ -63,6 +63,7 @@ import net.corda.node.services.network.NetworkMapUpdater
import net.corda.node.services.network.NodeInfoWatcher import net.corda.node.services.network.NodeInfoWatcher
import net.corda.node.services.network.PersistentNetworkMapCache import net.corda.node.services.network.PersistentNetworkMapCache
import net.corda.node.services.persistence.* import net.corda.node.services.persistence.*
import net.corda.node.services.persistence.AttachmentStorageInternal
import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.statemachine.* import net.corda.node.services.statemachine.*
import net.corda.node.services.transactions.InMemoryTransactionVerifierService import net.corda.node.services.transactions.InMemoryTransactionVerifierService

View File

@ -309,7 +309,7 @@ class NodeAttachmentService(
private fun import(jar: InputStream, uploader: String?, filename: String?): AttachmentId { private fun import(jar: InputStream, uploader: String?, filename: String?): AttachmentId {
return database.transaction { return database.transaction {
withContractsInJar(jar) { contractClassNames, inputStream -> withContractsInJar(jar) { contractClassNames, inputStream ->
require(inputStream !is JarInputStream){"Input stream must not be a JarInputStream"} require(inputStream !is JarInputStream) { "Input stream must not be a JarInputStream" }
// Read the file into RAM and then calculate its hash. The attachment must fit into memory. // Read the file into RAM and then calculate its hash. The attachment must fit into memory.
// TODO: Switch to a two-phase insert so we can handle attachments larger than RAM. // TODO: Switch to a two-phase insert so we can handle attachments larger than RAM.
@ -359,16 +359,16 @@ class NodeAttachmentService(
} }
private fun getSigners(attachmentBytes: ByteArray) = private fun getSigners(attachmentBytes: ByteArray) =
JarSignatureCollector.collectSigners(JarInputStream(attachmentBytes.inputStream())) JarSignatureCollector.collectSigners(JarInputStream(attachmentBytes.inputStream()))
private fun getVersion(attachmentBytes: ByteArray) = private fun getVersion(attachmentBytes: ByteArray) =
JarInputStream(attachmentBytes.inputStream()).use { JarInputStream(attachmentBytes.inputStream()).use {
try { try {
it.manifest?.mainAttributes?.getValue(CORDAPP_CONTRACT_VERSION)?.toInt() ?: DEFAULT_CORDAPP_VERSION it.manifest?.mainAttributes?.getValue(CORDAPP_CONTRACT_VERSION)?.toInt() ?: DEFAULT_CORDAPP_VERSION
} catch (e: NumberFormatException) { } catch (e: NumberFormatException) {
DEFAULT_CORDAPP_VERSION DEFAULT_CORDAPP_VERSION
}
} }
}
@Suppress("OverridingDeprecatedMember") @Suppress("OverridingDeprecatedMember")
override fun importOrGetAttachment(jar: InputStream): AttachmentId { override fun importOrGetAttachment(jar: InputStream): AttachmentId {
@ -409,8 +409,8 @@ class NodeAttachmentService(
} }
fun toList(): List<AttachmentId> = fun toList(): List<AttachmentId> =
if(signed != null) { if (signed != null) {
if(unsigned != null) { if (unsigned != null) {
listOf(signed, unsigned) listOf(signed, unsigned)
} else listOf(signed) } else listOf(signed)
} else listOf(unsigned!!) } else listOf(unsigned!!)
@ -464,5 +464,4 @@ class NodeAttachmentService(
val versions: NavigableMap<Version, AttachmentIds> = getContractAttachmentVersions(contractClassName) val versions: NavigableMap<Version, AttachmentIds> = getContractAttachmentVersions(contractClassName)
return versions.values.flatMap { it.toList() }.toSet() return versions.values.flatMap { it.toList() }.toSet()
} }
} }

View File

@ -1,13 +1,21 @@
package net.corda.node.services.transactions package net.corda.node.services.transactions
import net.corda.core.contracts.Attachment
import net.corda.core.internal.TransactionVerifierServiceInternal
import net.corda.core.internal.concurrent.fork import net.corda.core.internal.concurrent.fork
import net.corda.core.internal.verify
import net.corda.core.node.services.TransactionVerifierService import net.corda.core.node.services.TransactionVerifierService
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
import java.util.concurrent.Executors import java.util.concurrent.Executors
class InMemoryTransactionVerifierService(numberOfWorkers: Int) : SingletonSerializeAsToken(), TransactionVerifierService, AutoCloseable { class InMemoryTransactionVerifierService(numberOfWorkers: Int) : SingletonSerializeAsToken(), TransactionVerifierService, TransactionVerifierServiceInternal, AutoCloseable {
private val workerPool = Executors.newFixedThreadPool(numberOfWorkers) private val workerPool = Executors.newFixedThreadPool(numberOfWorkers)
override fun verify(transaction: LedgerTransaction) = workerPool.fork(transaction::verify) override fun verify(transaction: LedgerTransaction) = workerPool.fork(transaction::verify)
override fun verify(transaction: LedgerTransaction, extraAttachments: List<Attachment>) = workerPool.fork {
transaction.verify(extraAttachments)
}
override fun close() = workerPool.shutdown() override fun close() = workerPool.shutdown()
} }

View File

@ -40,6 +40,7 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -64,6 +65,7 @@ import static net.corda.testing.internal.RigorousMockKt.rigorousMock;
import static net.corda.testing.node.MockServices.makeTestDatabaseAndMockServices; import static net.corda.testing.node.MockServices.makeTestDatabaseAndMockServices;
import static net.corda.testing.node.MockServicesKt.makeTestIdentityService; import static net.corda.testing.node.MockServicesKt.makeTestIdentityService;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class VaultQueryJavaTests { public class VaultQueryJavaTests {
private static final TestIdentity BOC = new TestIdentity(BOC_NAME); private static final TestIdentity BOC = new TestIdentity(BOC_NAME);
@ -89,7 +91,7 @@ public class VaultQueryJavaTests {
identitySvc, identitySvc,
MEGA_CORP, MEGA_CORP,
DUMMY_NOTARY.getKeyPair()); DUMMY_NOTARY.getKeyPair());
issuerServices = new MockServices(cordappPackages, DUMMY_CASH_ISSUER_INFO, rigorousMock(IdentityServiceInternal.class), BOC.getKeyPair()); issuerServices = new MockServices(cordappPackages, DUMMY_CASH_ISSUER_INFO, mock(IdentityServiceInternal.class), BOC.getKeyPair());
database = databaseAndServices.getFirst(); database = databaseAndServices.getFirst();
MockServices services = databaseAndServices.getSecond(); MockServices services = databaseAndServices.getSecond();
vaultFiller = new VaultFiller(services, DUMMY_NOTARY); vaultFiller = new VaultFiller(services, DUMMY_NOTARY);

View File

@ -100,12 +100,12 @@ class HibernateConfigurationTest {
@Before @Before
fun setUp() { fun setUp() {
val cordappPackages = listOf("net.corda.testing.internal.vault", "net.corda.finance.contracts.asset", "net.corda.finance.schemas") val cordappPackages = listOf("net.corda.testing.internal.vault", "net.corda.finance.contracts.asset", "net.corda.finance.schemas")
bankServices = MockServices(cordappPackages, BOC.name, rigorousMock(), BOC_KEY) bankServices = MockServices(cordappPackages, BOC.name, mock(), BOC_KEY)
issuerServices = MockServices(cordappPackages, dummyCashIssuer, rigorousMock<IdentityService>()) issuerServices = MockServices(cordappPackages, dummyCashIssuer, mock<IdentityService>())
notaryServices = MockServices(cordappPackages, dummyNotary, rigorousMock<IdentityService>()) notaryServices = MockServices(cordappPackages, dummyNotary, mock<IdentityService>())
notary = notaryServices.myInfo.singleIdentity() notary = notaryServices.myInfo.singleIdentity()
val dataSourceProps = makeTestDataSourceProperties() val dataSourceProps = makeTestDataSourceProperties()
val identityService = rigorousMock<IdentityService>().also { mock -> val identityService = mock<IdentityService>().also { mock ->
doReturn(null).whenever(mock).wellKnownPartyFromAnonymous(any<AbstractParty>()) doReturn(null).whenever(mock).wellKnownPartyFromAnonymous(any<AbstractParty>())
listOf(dummyCashIssuer, dummyNotary).forEach { listOf(dummyCashIssuer, dummyNotary).forEach {
doReturn(it.party).whenever(mock).wellKnownPartyFromAnonymous(it.party) doReturn(it.party).whenever(mock).wellKnownPartyFromAnonymous(it.party)
@ -118,7 +118,7 @@ class HibernateConfigurationTest {
hibernateConfig = database.hibernateConfig hibernateConfig = database.hibernateConfig
// `consumeCash` expects we can self-notarise transactions // `consumeCash` expects we can self-notarise transactions
services = object : MockServices(cordappPackages, BOB_NAME, rigorousMock<IdentityServiceInternal>().also { services = object : MockServices(cordappPackages, BOB_NAME, mock<IdentityServiceInternal>().also {
doNothing().whenever(it).justVerifyAndRegisterIdentity(argThat { name == BOB_NAME }, any()) doNothing().whenever(it).justVerifyAndRegisterIdentity(argThat { name == BOB_NAME }, any())
}, generateKeyPair(), dummyNotary.keyPair) { }, generateKeyPair(), dummyNotary.keyPair) {
override val vaultService = NodeVaultService(Clock.systemUTC(), keyManagementService, servicesForResolution, database, schemaService).apply { start() } override val vaultService = NodeVaultService(Clock.systemUTC(), keyManagementService, servicesForResolution, database, schemaService).apply { start() }

View File

@ -1,6 +1,7 @@
package net.corda.node.services.vault package net.corda.node.services.vault
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
@ -46,7 +47,7 @@ class ExternalIdMappingTest {
fun setUp() { fun setUp() {
val (db, mockServices) = MockServices.makeTestDatabaseAndMockServices( val (db, mockServices) = MockServices.makeTestDatabaseAndMockServices(
cordappPackages = cordapps, cordappPackages = cordapps,
identityService = rigorousMock<IdentityServiceInternal>().also { identityService = mock<IdentityServiceInternal>().also {
doReturn(notary.party).whenever(it).partyFromKey(notary.publicKey) doReturn(notary.party).whenever(it).partyFromKey(notary.publicKey)
doReturn(notary.party).whenever(it).wellKnownPartyFromAnonymous(notary.party) doReturn(notary.party).whenever(it).wellKnownPartyFromAnonymous(notary.party)
doReturn(notary.party).whenever(it).wellKnownPartyFromX500Name(notary.name) doReturn(notary.party).whenever(it).wellKnownPartyFromX500Name(notary.name)

View File

@ -1,10 +1,7 @@
package net.corda.node.services.vault package net.corda.node.services.vault
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.*
import com.nhaarman.mockito_kotlin.argThat
import com.nhaarman.mockito_kotlin.doNothing
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.NullKeys import net.corda.core.crypto.NullKeys
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
@ -35,7 +32,6 @@ import net.corda.testing.contracts.DummyContract
import net.corda.testing.contracts.DummyState import net.corda.testing.contracts.DummyState
import net.corda.testing.core.* import net.corda.testing.core.*
import net.corda.testing.internal.LogHelper import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.vault.* import net.corda.testing.internal.vault.*
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestIdentityService import net.corda.testing.node.makeTestIdentityService
@ -103,8 +99,8 @@ class NodeVaultServiceTest {
vaultFiller = VaultFiller(services, dummyNotary) vaultFiller = VaultFiller(services, dummyNotary)
// This is safe because MockServices only ever have a single identity // This is safe because MockServices only ever have a single identity
identity = services.myInfo.singleIdentityAndCert() identity = services.myInfo.singleIdentityAndCert()
issuerServices = MockServices(cordappPackages, dummyCashIssuer, rigorousMock<IdentityService>(), parameters) issuerServices = MockServices(cordappPackages, dummyCashIssuer, mock<IdentityService>(), parameters)
bocServices = MockServices(cordappPackages, bankOfCorda, rigorousMock<IdentityService>(), parameters) bocServices = MockServices(cordappPackages, bankOfCorda, mock<IdentityService>(), parameters)
services.identityService.verifyAndRegisterIdentity(DUMMY_CASH_ISSUER_IDENTITY) services.identityService.verifyAndRegisterIdentity(DUMMY_CASH_ISSUER_IDENTITY)
services.identityService.verifyAndRegisterIdentity(BOC_IDENTITY) services.identityService.verifyAndRegisterIdentity(BOC_IDENTITY)
} }
@ -133,10 +129,10 @@ class NodeVaultServiceTest {
return tryLockFungibleStatesForSpending(lockId, baseCriteria, amount, Cash.State::class.java) return tryLockFungibleStatesForSpending(lockId, baseCriteria, amount, Cash.State::class.java)
} }
class FungibleFoo(override val amount: Amount<Currency>, override val participants: List<AbstractParty>) : FungibleState<Currency>
@Test @Test
fun `fungible state selection test`() { fun `fungible state selection test`() {
val issuerParty = services.myInfo.legalIdentities.first() val issuerParty = services.myInfo.legalIdentities.first()
class FungibleFoo(override val amount: Amount<Currency>, override val participants: List<AbstractParty>) : FungibleState<Currency>
val fungibleFoo = FungibleFoo(100.DOLLARS, listOf(issuerParty)) val fungibleFoo = FungibleFoo(100.DOLLARS, listOf(issuerParty))
services.apply { services.apply {
val tx = signInitialTransaction(TransactionBuilder(DUMMY_NOTARY).apply { val tx = signInitialTransaction(TransactionBuilder(DUMMY_NOTARY).apply {
@ -182,7 +178,7 @@ class NodeVaultServiceTest {
assertThat(w1).hasSize(3) assertThat(w1).hasSize(3)
val originalVault = vaultService val originalVault = vaultService
val services2 = object : MockServices(emptyList(), MEGA_CORP.name, rigorousMock()) { val services2 = object : MockServices(emptyList(), MEGA_CORP.name, mock()) {
override val vaultService: NodeVaultService get() = originalVault override val vaultService: NodeVaultService get() = originalVault
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) { override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) {
for (stx in txs) { for (stx in txs) {
@ -525,7 +521,7 @@ class NodeVaultServiceTest {
@Test @Test
fun addNoteToTransaction() { fun addNoteToTransaction() {
val megaCorpServices = MockServices(cordappPackages, MEGA_CORP.name, rigorousMock(), MEGA_CORP_KEY) val megaCorpServices = MockServices(cordappPackages, MEGA_CORP.name, mock(), MEGA_CORP_KEY)
database.transaction { database.transaction {
val freshKey = identity.owningKey val freshKey = identity.owningKey
@ -631,7 +627,7 @@ class NodeVaultServiceTest {
val identity = services.myInfo.singleIdentityAndCert() val identity = services.myInfo.singleIdentityAndCert()
assertEquals(services.identityService.partyFromKey(identity.owningKey), identity.party) assertEquals(services.identityService.partyFromKey(identity.owningKey), identity.party)
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(identity, false) val anonymousIdentity = services.keyManagementService.freshKeyAndCert(identity, false)
val thirdPartyServices = MockServices(emptyList(), MEGA_CORP.name, rigorousMock<IdentityServiceInternal>().also { val thirdPartyServices = MockServices(emptyList(), MEGA_CORP.name, mock<IdentityServiceInternal>().also {
doNothing().whenever(it).justVerifyAndRegisterIdentity(argThat { name == MEGA_CORP.name }, any()) doNothing().whenever(it).justVerifyAndRegisterIdentity(argThat { name == MEGA_CORP.name }, any())
}) })
val thirdPartyIdentity = thirdPartyServices.keyManagementService.freshKeyAndCert(thirdPartyServices.myInfo.singleIdentityAndCert(), false) val thirdPartyIdentity = thirdPartyServices.keyManagementService.freshKeyAndCert(thirdPartyServices.myInfo.singleIdentityAndCert(), false)

View File

@ -1,5 +1,6 @@
package net.corda.node.services.vault package net.corda.node.services.vault
import com.nhaarman.mockito_kotlin.mock
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
@ -141,7 +142,7 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
services = databaseAndServices.second services = databaseAndServices.second
vaultFiller = VaultFiller(services, dummyNotary) vaultFiller = VaultFiller(services, dummyNotary)
vaultFillerCashNotary = VaultFiller(services, dummyNotary, CASH_NOTARY) vaultFillerCashNotary = VaultFiller(services, dummyNotary, CASH_NOTARY)
notaryServices = MockServices(cordappPackages, dummyNotary, rigorousMock(), dummyCashIssuer.keyPair, BOC_KEY, MEGA_CORP_KEY) notaryServices = MockServices(cordappPackages, dummyNotary, mock(), dummyCashIssuer.keyPair, BOC_KEY, MEGA_CORP_KEY)
identitySvc = services.identityService identitySvc = services.identityService
// Register all of the identities we're going to use // Register all of the identities we're going to use
(notaryServices.myInfo.legalIdentitiesAndCerts + BOC_IDENTITY + CASH_NOTARY_IDENTITY + MINI_CORP_IDENTITY + MEGA_CORP_IDENTITY).forEach { identity -> (notaryServices.myInfo.legalIdentitiesAndCerts + BOC_IDENTITY + CASH_NOTARY_IDENTITY + MINI_CORP_IDENTITY + MEGA_CORP_IDENTITY).forEach { identity ->
@ -1907,15 +1908,15 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
fun `unconsumed fungible assets for selected issuer parties`() { fun `unconsumed fungible assets for selected issuer parties`() {
// GBP issuer // GBP issuer
val gbpCashIssuerName = CordaX500Name(organisation = "British Pounds Cash Issuer", locality = "London", country = "GB") val gbpCashIssuerName = CordaX500Name(organisation = "British Pounds Cash Issuer", locality = "London", country = "GB")
val gbpCashIssuerServices = MockServices(cordappPackages, gbpCashIssuerName, rigorousMock(), generateKeyPair()) val gbpCashIssuerServices = MockServices(cordappPackages, gbpCashIssuerName, mock(), generateKeyPair())
val gbpCashIssuer = gbpCashIssuerServices.myInfo.singleIdentityAndCert() val gbpCashIssuer = gbpCashIssuerServices.myInfo.singleIdentityAndCert()
// USD issuer // USD issuer
val usdCashIssuerName = CordaX500Name(organisation = "US Dollars Cash Issuer", locality = "New York", country = "US") val usdCashIssuerName = CordaX500Name(organisation = "US Dollars Cash Issuer", locality = "New York", country = "US")
val usdCashIssuerServices = MockServices(cordappPackages, usdCashIssuerName, rigorousMock(), generateKeyPair()) val usdCashIssuerServices = MockServices(cordappPackages, usdCashIssuerName, mock(), generateKeyPair())
val usdCashIssuer = usdCashIssuerServices.myInfo.singleIdentityAndCert() val usdCashIssuer = usdCashIssuerServices.myInfo.singleIdentityAndCert()
// CHF issuer // CHF issuer
val chfCashIssuerName = CordaX500Name(organisation = "Swiss Francs Cash Issuer", locality = "Zurich", country = "CH") val chfCashIssuerName = CordaX500Name(organisation = "Swiss Francs Cash Issuer", locality = "Zurich", country = "CH")
val chfCashIssuerServices = MockServices(cordappPackages, chfCashIssuerName, rigorousMock(), generateKeyPair()) val chfCashIssuerServices = MockServices(cordappPackages, chfCashIssuerName, mock(), generateKeyPair())
val chfCashIssuer = chfCashIssuerServices.myInfo.singleIdentityAndCert() val chfCashIssuer = chfCashIssuerServices.myInfo.singleIdentityAndCert()
listOf(gbpCashIssuer, usdCashIssuer, chfCashIssuer).forEach { identity -> listOf(gbpCashIssuer, usdCashIssuer, chfCashIssuer).forEach { identity ->
services.identityService.verifyAndRegisterIdentity(identity) services.identityService.verifyAndRegisterIdentity(identity)

View File

@ -1,5 +1,6 @@
package net.corda.node.services.vault package net.corda.node.services.vault
import com.nhaarman.mockito_kotlin.mock
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.contracts.InsufficientBalanceException import net.corda.core.contracts.InsufficientBalanceException
import net.corda.core.contracts.LinearState import net.corda.core.contracts.LinearState
@ -27,7 +28,6 @@ import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.common.internal.addNotary import net.corda.testing.common.internal.addNotary
import net.corda.testing.core.* import net.corda.testing.core.*
import net.corda.testing.internal.LogHelper import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.vault.* import net.corda.testing.internal.vault.*
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices
@ -88,8 +88,8 @@ class VaultWithCashTest {
vaultFiller = VaultFiller(services, dummyNotary) vaultFiller = VaultFiller(services, dummyNotary)
issuerServices = MockServices(cordappPackages, dummyCashIssuer, rigorousMock(), networkParameters, MEGA_CORP_KEY) issuerServices = MockServices(cordappPackages, dummyCashIssuer, mock(), networkParameters, MEGA_CORP_KEY)
notaryServices = MockServices(cordappPackages, dummyNotary, rigorousMock(), networkParameters) notaryServices = MockServices(cordappPackages, dummyNotary, mock(), networkParameters)
notary = notaryServices.myInfo.legalIdentitiesAndCerts.single().party notary = notaryServices.myInfo.legalIdentitiesAndCerts.single().party
} }
@ -119,7 +119,7 @@ class VaultWithCashTest {
@Test @Test
fun `issue and spend total correctly and irrelevant ignored`() { fun `issue and spend total correctly and irrelevant ignored`() {
val megaCorpServices = MockServices(cordappPackages, MEGA_CORP.name, rigorousMock(), MEGA_CORP_KEY) val megaCorpServices = MockServices(cordappPackages, MEGA_CORP.name, mock(), MEGA_CORP_KEY)
val freshKey = services.keyManagementService.freshKey() val freshKey = services.keyManagementService.freshKey()
val usefulTX = val usefulTX =

View File

@ -1,6 +1,7 @@
package net.corda.irs.contract package net.corda.irs.contract
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.UniqueIdentifier import net.corda.core.contracts.UniqueIdentifier
@ -20,7 +21,6 @@ import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.TestIdentity import net.corda.testing.core.TestIdentity
import net.corda.testing.dsl.* import net.corda.testing.dsl.*
import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.ledger import net.corda.testing.node.ledger
import net.corda.testing.node.transaction import net.corda.testing.node.transaction
@ -228,13 +228,13 @@ class IRSTests {
val testSerialization = SerializationEnvironmentRule() val testSerialization = SerializationEnvironmentRule()
private val cordappPackages = listOf("net.corda.irs.contract") private val cordappPackages = listOf("net.corda.irs.contract")
private val networkParameters = testNetworkParameters().addNotary(dummyNotary.party) private val networkParameters = testNetworkParameters().addNotary(dummyNotary.party)
private val megaCorpServices = MockServices(cordappPackages, megaCorp, rigorousMock(), networkParameters, megaCorp.keyPair) private val megaCorpServices = MockServices(cordappPackages, megaCorp, mock(), networkParameters, megaCorp.keyPair)
private val miniCorpServices = MockServices(cordappPackages, miniCorp, rigorousMock(), networkParameters, miniCorp.keyPair) private val miniCorpServices = MockServices(cordappPackages, miniCorp, mock(), networkParameters, miniCorp.keyPair)
private val notaryServices = MockServices(cordappPackages, dummyNotary, rigorousMock(), networkParameters, dummyNotary.keyPair) private val notaryServices = MockServices(cordappPackages, dummyNotary, mock(), networkParameters, dummyNotary.keyPair)
private val ledgerServices = MockServices( private val ledgerServices = MockServices(
emptyList(), emptyList(),
megaCorp, megaCorp,
rigorousMock<IdentityServiceInternal>().also { mock<IdentityServiceInternal>().also {
doReturn(megaCorp.party).whenever(it).partyFromKey(megaCorp.publicKey) doReturn(megaCorp.party).whenever(it).partyFromKey(megaCorp.publicKey)
doReturn(null).whenever(it).partyFromKey(ORACLE_PUBKEY) doReturn(null).whenever(it).partyFromKey(ORACLE_PUBKEY)
}, },
@ -336,7 +336,7 @@ class IRSTests {
@Test @Test
fun generateIRSandFixSome() { fun generateIRSandFixSome() {
val services = MockServices(listOf("net.corda.irs.contract"), MEGA_CORP.name, val services = MockServices(listOf("net.corda.irs.contract"), MEGA_CORP.name,
rigorousMock<IdentityServiceInternal>().also { mock<IdentityServiceInternal>().also {
listOf(MEGA_CORP, MINI_CORP).forEach { party -> listOf(MEGA_CORP, MINI_CORP).forEach { party ->
doReturn(party).whenever(it).partyFromKey(party.owningKey) doReturn(party).whenever(it).partyFromKey(party.owningKey)
} }

View File

@ -5,11 +5,8 @@ import net.corda.core.contracts.ContractAttachment
import net.corda.core.contracts.ContractClassName import net.corda.core.contracts.ContractClassName
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.internal.AbstractAttachment import net.corda.core.internal.*
import net.corda.core.internal.TRUSTED_UPLOADERS
import net.corda.core.internal.UNKNOWN_UPLOADER
import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION
import net.corda.core.internal.readFully
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.core.node.services.vault.AttachmentQueryCriteria import net.corda.core.node.services.vault.AttachmentQueryCriteria