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:
Tudor Malene
2018-08-15 18:38:35 +01:00
committed by tudor.malene@gmail.com
parent 7902d758bd
commit f96a59932c
28 changed files with 925 additions and 195 deletions

View File

@ -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(

View File

@ -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) }
}

View File

@ -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)
}
}
}

View File

@ -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)
}