mirror of
https://github.com/corda/corda.git
synced 2025-06-24 10:18:27 +00:00
ENT-2222 Constraints propagation
ENT-2222 Fix tests ENT-2222 Fix tests ENT-2222 Add ledger transaction verification logic ENT-2222 Fixed IRS test ENT-2222 Fixed IRS test ENT-2222 Fixed unit test ENT-2222 Better kdocs ENT-2222 Support for reference states ENT-2222 Fix support for reference states ENT-2222 Revert wrong change ENT-2222 Fix Kdoc ENT-2222 Fix Kdoc ENT-2222 Better docs ENT-2222 Address code review comments ENT-2222 Fix test ENT-2222 Fix rebase ENT-2222 Add documentation around constraint propagation ENT-2222 Add tests for contract propagation ENT-2222 Add Signature Constraints propagation - first draft ENT-2222 fix tests ENT-2222 more tests ENT-2222 unseal the TransactionVerificationException ENT-2222 unseal the TransactionVerificationException ENT-2222 more docs ENT-2222 address code review comments ENT-2222 address code review comments ENT-2222 re-implement transition logic ENT-2222 better comments and checks ENT-2222 Fix tests ENT-2222 merge fixes
This commit is contained in:
committed by
tudor.malene@gmail.com
parent
7902d758bd
commit
f96a59932c
@ -11,6 +11,7 @@ import net.corda.core.internal.UNKNOWN_UPLOADER
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.ServicesForResolution
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
@ -147,8 +148,13 @@ data class TestTransactionDSLInterpreter private constructor(
|
||||
override fun _tweak(dsl: TransactionDSLInterpreter.() -> EnforceVerifyOrFail) = copy().dsl()
|
||||
|
||||
override fun _attachment(contractClassName: ContractClassName) {
|
||||
(services.cordappProvider as MockCordappProvider).addMockCordapp(contractClassName, services.attachments as MockAttachmentStorage)
|
||||
attachment((services.cordappProvider as MockCordappProvider).addMockCordapp(contractClassName, services.attachments as MockAttachmentStorage))
|
||||
}
|
||||
|
||||
override fun _attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List<PublicKey>){
|
||||
attachment((services.cordappProvider as MockCordappProvider).addMockCordapp(contractClassName, services.attachments as MockAttachmentStorage, attachmentId, signers))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class TestLedgerDSLInterpreter private constructor(
|
||||
|
@ -1,9 +1,19 @@
|
||||
package net.corda.testing.dsl
|
||||
|
||||
import net.corda.core.DoNotImplement
|
||||
import net.corda.core.contracts.AlwaysAcceptAttachmentConstraint
|
||||
import net.corda.core.contracts.Attachment
|
||||
import net.corda.core.contracts.AttachmentConstraint
|
||||
import net.corda.core.contracts.AutomaticPlaceholderConstraint
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.contracts.TimeWindow
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.seconds
|
||||
import java.security.PublicKey
|
||||
@ -80,6 +90,13 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup {
|
||||
* @param contractClassName The contract class to attach
|
||||
*/
|
||||
fun _attachment(contractClassName: ContractClassName)
|
||||
|
||||
/**
|
||||
* Attaches an attachment containing the named contract to the transaction
|
||||
* @param contractClassName The contract class to attach
|
||||
* @param attachmentId The attachment
|
||||
*/
|
||||
fun _attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List<PublicKey>)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,37 +148,37 @@ class TransactionDSL<out T : TransactionDSLInterpreter>(interpreter: T, private
|
||||
* Adds a labelled output to the transaction.
|
||||
*/
|
||||
fun output(contractClassName: ContractClassName, label: String, notary: Party, contractState: ContractState) =
|
||||
output(contractClassName, label, notary, null, AutomaticHashConstraint, contractState)
|
||||
output(contractClassName, label, notary, null, AutomaticPlaceholderConstraint, contractState)
|
||||
|
||||
/**
|
||||
* Adds a labelled output to the transaction.
|
||||
*/
|
||||
fun output(contractClassName: ContractClassName, label: String, encumbrance: Int, contractState: ContractState) =
|
||||
output(contractClassName, label, notary, encumbrance, AutomaticHashConstraint, contractState)
|
||||
output(contractClassName, label, notary, encumbrance, AutomaticPlaceholderConstraint, contractState)
|
||||
|
||||
/**
|
||||
* Adds a labelled output to the transaction.
|
||||
*/
|
||||
fun output(contractClassName: ContractClassName, label: String, contractState: ContractState) =
|
||||
output(contractClassName, label, notary, null, AutomaticHashConstraint, contractState)
|
||||
output(contractClassName, label, notary, null, AutomaticPlaceholderConstraint, contractState)
|
||||
|
||||
/**
|
||||
* Adds an output to the transaction.
|
||||
*/
|
||||
fun output(contractClassName: ContractClassName, notary: Party, contractState: ContractState) =
|
||||
output(contractClassName, null, notary, null, AutomaticHashConstraint, contractState)
|
||||
output(contractClassName, null, notary, null, AutomaticPlaceholderConstraint, contractState)
|
||||
|
||||
/**
|
||||
* Adds an output to the transaction.
|
||||
*/
|
||||
fun output(contractClassName: ContractClassName, encumbrance: Int, contractState: ContractState) =
|
||||
output(contractClassName, null, notary, encumbrance, AutomaticHashConstraint, contractState)
|
||||
output(contractClassName, null, notary, encumbrance, AutomaticPlaceholderConstraint, contractState)
|
||||
|
||||
/**
|
||||
* Adds an output to the transaction.
|
||||
*/
|
||||
fun output(contractClassName: ContractClassName, contractState: ContractState) =
|
||||
output(contractClassName, null, notary, null, AutomaticHashConstraint, contractState)
|
||||
output(contractClassName, null, notary, null, AutomaticPlaceholderConstraint, contractState)
|
||||
|
||||
/**
|
||||
* Adds a command to the transaction.
|
||||
@ -186,5 +203,8 @@ class TransactionDSL<out T : TransactionDSLInterpreter>(interpreter: T, private
|
||||
*/
|
||||
fun attachment(contractClassName: ContractClassName) = _attachment(contractClassName)
|
||||
|
||||
fun attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List<PublicKey>) = _attachment(contractClassName, attachmentId, signers)
|
||||
fun attachment(contractClassName: ContractClassName, attachmentId: AttachmentId) = _attachment(contractClassName, attachmentId, emptyList())
|
||||
|
||||
fun attachments(vararg contractClassNames: ContractClassName) = contractClassNames.forEach { attachment(it) }
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package net.corda.testing.internal
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.cordapp.Cordapp
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER
|
||||
import net.corda.core.internal.cordapp.CordappImpl
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
@ -11,6 +12,7 @@ import net.corda.node.cordapp.CordappLoader
|
||||
import net.corda.node.internal.cordapp.CordappProviderImpl
|
||||
import net.corda.testing.services.MockAttachmentStorage
|
||||
import java.nio.file.Paths
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
|
||||
class MockCordappProvider(
|
||||
@ -21,7 +23,7 @@ class MockCordappProvider(
|
||||
|
||||
private val cordappRegistry = mutableListOf<Pair<Cordapp, AttachmentId>>()
|
||||
|
||||
fun addMockCordapp(contractClassName: ContractClassName, attachments: MockAttachmentStorage) {
|
||||
fun addMockCordapp(contractClassName: ContractClassName, attachments: MockAttachmentStorage, contractHash: AttachmentId? = null, signers: List<PublicKey> = emptyList()): AttachmentId {
|
||||
val cordapp = CordappImpl(
|
||||
contractClassNames = listOf(contractClassName),
|
||||
initiatedFlows = emptyList(),
|
||||
@ -35,21 +37,23 @@ class MockCordappProvider(
|
||||
jarPath = Paths.get("").toUri().toURL(),
|
||||
allFlows = emptyList(),
|
||||
jarHash = SecureHash.allOnesHash)
|
||||
if (cordappRegistry.none { it.first.contractClassNames.contains(contractClassName) }) {
|
||||
cordappRegistry.add(Pair(cordapp, findOrImportAttachment(listOf(contractClassName), contractClassName.toByteArray(), attachments)))
|
||||
if (cordappRegistry.none { it.first.contractClassNames.contains(contractClassName) && it.second == contractHash }) {
|
||||
cordappRegistry.add(Pair(cordapp, findOrImportAttachment(listOf(contractClassName), contractClassName.toByteArray(), attachments, contractHash, signers)))
|
||||
}
|
||||
return cordappRegistry.findLast { contractClassName in it.first.contractClassNames }?.second!!
|
||||
}
|
||||
|
||||
override fun getContractAttachmentID(contractClassName: ContractClassName): AttachmentId? = cordappRegistry.find { it.first.contractClassNames.contains(contractClassName) }?.second ?: super.getContractAttachmentID(contractClassName)
|
||||
override fun getContractAttachmentID(contractClassName: ContractClassName): AttachmentId? = cordappRegistry.find { it.first.contractClassNames.contains(contractClassName) }?.second
|
||||
?: super.getContractAttachmentID(contractClassName)
|
||||
|
||||
private fun findOrImportAttachment(contractClassNames: List<ContractClassName>, data: ByteArray, attachments: MockAttachmentStorage): AttachmentId {
|
||||
val existingAttachment = attachments.files.filter {
|
||||
Arrays.equals(it.value.second, data)
|
||||
private fun findOrImportAttachment(contractClassNames: List<ContractClassName>, data: ByteArray, attachments: MockAttachmentStorage, contractHash: AttachmentId?, signers: List<PublicKey>): AttachmentId {
|
||||
val existingAttachment = attachments.files.filter { (attachmentId, content) ->
|
||||
contractHash == attachmentId
|
||||
}
|
||||
return if (!existingAttachment.isEmpty()) {
|
||||
existingAttachment.keys.first()
|
||||
} else {
|
||||
attachments.importContractAttachment(contractClassNames, DEPLOYED_CORDAPP_UPLOADER, data.inputStream())
|
||||
attachments.importContractAttachment(contractClassNames, DEPLOYED_CORDAPP_UPLOADER, data.inputStream(), contractHash, signers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.contracts.ContractAttachment
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.sha256
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.AbstractAttachment
|
||||
import net.corda.core.internal.UNKNOWN_UPLOADER
|
||||
import net.corda.core.internal.readFully
|
||||
@ -15,6 +16,7 @@ import net.corda.core.node.services.vault.AttachmentSort
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.nodeapi.internal.withContractsInJar
|
||||
import java.io.InputStream
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
import java.util.jar.JarInputStream
|
||||
|
||||
@ -53,21 +55,22 @@ class MockAttachmentStorage : AttachmentStorage, SingletonSerializeAsToken() {
|
||||
}
|
||||
}
|
||||
|
||||
fun importContractAttachment(contractClassNames: List<ContractClassName>, uploader: String, jar: InputStream): AttachmentId = importAttachmentInternal(jar, uploader, contractClassNames)
|
||||
@JvmOverloads
|
||||
fun importContractAttachment(contractClassNames: List<ContractClassName>, uploader: String, jar: InputStream, attachmentId: AttachmentId? = null, signers: List<PublicKey> = emptyList()): AttachmentId = importAttachmentInternal(jar, uploader, contractClassNames, attachmentId, signers)
|
||||
|
||||
fun getAttachmentIdAndBytes(jar: InputStream): Pair<AttachmentId, ByteArray> = jar.readFully().let { bytes -> Pair(bytes.sha256(), bytes) }
|
||||
|
||||
private class MockAttachment(dataLoader: () -> ByteArray, override val id: SecureHash) : AbstractAttachment(dataLoader)
|
||||
private class MockAttachment(dataLoader: () -> ByteArray, override val id: SecureHash, override val signers: List<PublicKey>) : AbstractAttachment(dataLoader)
|
||||
|
||||
private fun importAttachmentInternal(jar: InputStream, uploader: String, contractClassNames: List<ContractClassName>? = null): AttachmentId {
|
||||
private fun importAttachmentInternal(jar: InputStream, uploader: String, contractClassNames: List<ContractClassName>? = null, attachmentId: AttachmentId? = null, signers: List<PublicKey> = emptyList()): AttachmentId {
|
||||
// JIS makes read()/readBytes() return bytes of the current file, but we want to hash the entire container here.
|
||||
require(jar !is JarInputStream)
|
||||
|
||||
val bytes = jar.readFully()
|
||||
|
||||
val sha256 = bytes.sha256()
|
||||
val sha256 = attachmentId ?: bytes.sha256()
|
||||
if (sha256 !in files.keys) {
|
||||
val baseAttachment = MockAttachment({ bytes }, sha256)
|
||||
val baseAttachment = MockAttachment({ bytes }, sha256, signers)
|
||||
val attachment = if (contractClassNames == null || contractClassNames.isEmpty()) baseAttachment else ContractAttachment(baseAttachment, contractClassNames.first(), contractClassNames.toSet(), uploader)
|
||||
_files[sha256] = Pair(attachment, bytes)
|
||||
}
|
||||
|
Reference in New Issue
Block a user