mirror of
https://github.com/corda/corda.git
synced 2024-12-21 13:57:54 +00:00
Merge pull request #7318 from corda/colljos/record_txns_signature_verification
ENT-9566 Additional Signature verification and validation: recordTransactions()
This commit is contained in:
commit
c8b871af65
@ -10,6 +10,7 @@ import net.corda.core.crypto.SecureHash.Companion.allOnesHash
|
|||||||
import net.corda.core.crypto.SecureHash.Companion.zeroHash
|
import net.corda.core.crypto.SecureHash.Companion.zeroHash
|
||||||
import net.corda.core.crypto.SignableData
|
import net.corda.core.crypto.SignableData
|
||||||
import net.corda.core.crypto.SignatureMetadata
|
import net.corda.core.crypto.SignatureMetadata
|
||||||
|
import net.corda.core.crypto.sign
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.canBeTransitionedFrom
|
import net.corda.core.internal.canBeTransitionedFrom
|
||||||
@ -49,6 +50,7 @@ class ConstraintsPropagationTests {
|
|||||||
val testSerialization = SerializationEnvironmentRule()
|
val testSerialization = SerializationEnvironmentRule()
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
val DUMMY_NOTARY_IDENTITY = TestIdentity(DUMMY_NOTARY_NAME, 20)
|
||||||
val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
|
val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
|
||||||
val ALICE = TestIdentity(CordaX500Name("ALICE", "London", "GB"))
|
val ALICE = TestIdentity(CordaX500Name("ALICE", "London", "GB"))
|
||||||
val ALICE_PARTY get() = ALICE.party
|
val ALICE_PARTY get() = ALICE.party
|
||||||
@ -376,7 +378,8 @@ class ConstraintsPropagationTests {
|
|||||||
requireSupportedHashType(wireTransaction)
|
requireSupportedHashType(wireTransaction)
|
||||||
val nodeKey = ALICE_PUBKEY
|
val nodeKey = ALICE_PUBKEY
|
||||||
val sigs = listOf(keyManagementService.sign(
|
val sigs = listOf(keyManagementService.sign(
|
||||||
SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
|
SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey),
|
||||||
|
DUMMY_NOTARY_IDENTITY.keyPair.sign(SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(DUMMY_NOTARY_IDENTITY.publicKey).schemeNumberID))))
|
||||||
recordTransactions(SignedTransaction(wireTransaction, sigs))
|
recordTransactions(SignedTransaction(wireTransaction, sigs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,12 +99,17 @@ class ResolveTransactionsFlowTest {
|
|||||||
// DOCEND 1
|
// DOCEND 1
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun `dependency with an error`() {
|
fun `dependency with an error fails fast upon prior attempt to record transaction with missing signature`() {
|
||||||
val stx = makeTransactions(signFirstTX = false).second
|
val exception = assertFailsWith(IllegalStateException::class) {
|
||||||
val p = TestFlow(setOf(stx.id), megaCorp)
|
val stx = makeTransactions(signFirstTX = false).second
|
||||||
val future = miniCorpNode.startFlow(p)
|
// fails fast in above operation
|
||||||
mockNet.runNetwork()
|
// prior to platform version 13, same failure would occur upon transaction resolution
|
||||||
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
|
val p = TestFlow(setOf(stx.id), megaCorp)
|
||||||
|
val future = miniCorpNode.startFlow(p)
|
||||||
|
mockNet.runNetwork()
|
||||||
|
future.getOrThrow()
|
||||||
|
}
|
||||||
|
assertTrue(exception.cause.toString().contains("SignaturesMissingException"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
|
@ -80,7 +80,7 @@ class LedgerTransactionQueryTests {
|
|||||||
.addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
.addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
||||||
.addCommand(dummyCommand())
|
.addCommand(dummyCommand())
|
||||||
)
|
)
|
||||||
services.recordTransactions(fakeIssueTx)
|
services.recordTransactions(fakeIssueTx, disableSignatureVerification = true)
|
||||||
val dummyStateRef = StateRef(fakeIssueTx.id, 0)
|
val dummyStateRef = StateRef(fakeIssueTx.id, 0)
|
||||||
return StateAndRef(TransactionState(dummyState, DummyContract.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint), dummyStateRef)
|
return StateAndRef(TransactionState(dummyState, DummyContract.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint), dummyStateRef)
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,10 @@ import net.corda.core.crypto.SignableData
|
|||||||
import net.corda.core.crypto.SignatureMetadata
|
import net.corda.core.crypto.SignatureMetadata
|
||||||
import net.corda.core.crypto.TransactionSignature
|
import net.corda.core.crypto.TransactionSignature
|
||||||
import net.corda.core.flows.ContractUpgradeFlow
|
import net.corda.core.flows.ContractUpgradeFlow
|
||||||
|
import net.corda.core.internal.PlatformVersionSwitches.TWO_PHASE_FINALITY
|
||||||
|
import net.corda.core.internal.telemetry.TelemetryComponent
|
||||||
import net.corda.core.node.services.*
|
import net.corda.core.node.services.*
|
||||||
import net.corda.core.node.services.diagnostics.DiagnosticsService
|
import net.corda.core.node.services.diagnostics.DiagnosticsService
|
||||||
import net.corda.core.internal.telemetry.TelemetryComponent
|
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import net.corda.core.transactions.FilteredTransaction
|
import net.corda.core.transactions.FilteredTransaction
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
@ -204,6 +205,12 @@ interface ServiceHub : ServicesForResolution {
|
|||||||
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
||||||
* further processing if [notifyVault] is true. This is expected to be run within a database transaction.
|
* further processing if [notifyVault] is true. This is expected to be run within a database transaction.
|
||||||
*
|
*
|
||||||
|
* As of platform version [TWO_PHASE_FINALITY] also performs signature verification and will throw an
|
||||||
|
* [IllegalStateException] with details of the cause of error upon failure.
|
||||||
|
* Of course, you should not be recording transactions to the ledger that are not fully signed.
|
||||||
|
* It is possible, but not recommended, to revert to non-signature verification behaviour by setting the system property
|
||||||
|
* "net.corda.recordtransaction.signature.verification.disabled" to true upon node start-up.
|
||||||
|
*
|
||||||
* @param txs The transactions to record.
|
* @param txs The transactions to record.
|
||||||
* @param notifyVault indicate if the vault should be notified for the update.
|
* @param notifyVault indicate if the vault should be notified for the update.
|
||||||
*/
|
*/
|
||||||
@ -214,6 +221,12 @@ interface ServiceHub : ServicesForResolution {
|
|||||||
/**
|
/**
|
||||||
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
||||||
* further processing if [notifyVault] is true. This is expected to be run within a database transaction.
|
* further processing if [notifyVault] is true. This is expected to be run within a database transaction.
|
||||||
|
*
|
||||||
|
* As of platform version [TWO_PHASE_FINALITY] also performs signature verification and will throw an
|
||||||
|
* [IllegalStateException] with details of the cause of error upon failure.
|
||||||
|
* Of course, you should not be recording transactions to the ledger that are not fully signed.
|
||||||
|
* It is possible, but not recommended, to revert to non-signature verification behaviour by setting the system property
|
||||||
|
* "net.corda.recordtransaction.signature.verification.disabled" to true upon node start-up.
|
||||||
*/
|
*/
|
||||||
fun recordTransactions(notifyVault: Boolean, first: SignedTransaction, vararg remaining: SignedTransaction) {
|
fun recordTransactions(notifyVault: Boolean, first: SignedTransaction, vararg remaining: SignedTransaction) {
|
||||||
recordTransactions(notifyVault, listOf(first, *remaining))
|
recordTransactions(notifyVault, listOf(first, *remaining))
|
||||||
@ -224,6 +237,12 @@ interface ServiceHub : ServicesForResolution {
|
|||||||
* further processing if [statesToRecord] is not [StatesToRecord.NONE].
|
* further processing if [statesToRecord] is not [StatesToRecord.NONE].
|
||||||
* This is expected to be run within a database transaction.
|
* This is expected to be run within a database transaction.
|
||||||
*
|
*
|
||||||
|
* As of platform version [TWO_PHASE_FINALITY] also performs signature verification and will throw an
|
||||||
|
* [IllegalStateException] with details of the cause of error upon failure.
|
||||||
|
* Of course, you should not be recording transactions to the ledger that are not fully signed.
|
||||||
|
* It is possible, but not recommended, to revert to non-signature verification behaviour by setting the system property
|
||||||
|
* "net.corda.recordtransaction.signature.verification.disabled" to true upon node start-up.
|
||||||
|
*
|
||||||
* @param txs The transactions to record.
|
* @param txs The transactions to record.
|
||||||
* @param statesToRecord how the vault should treat the output states of the transaction.
|
* @param statesToRecord how the vault should treat the output states of the transaction.
|
||||||
*/
|
*/
|
||||||
@ -232,6 +251,13 @@ interface ServiceHub : ServicesForResolution {
|
|||||||
/**
|
/**
|
||||||
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
||||||
* further processing. This is expected to be run within a database transaction.
|
* further processing. This is expected to be run within a database transaction.
|
||||||
|
*
|
||||||
|
* As of platform version [TWO_PHASE_FINALITY] also performs signature verification and will throw an
|
||||||
|
* [IllegalStateException] with details of the cause of error upon failure.
|
||||||
|
* Of course, you should not be recording transactions to the ledger that are not fully signed.
|
||||||
|
* It is possible, but not recommended, to revert to non-signature verification behaviour by setting the system property
|
||||||
|
* "net.corda.recordtransaction.signature.verification.disabled" to true upon node start-up.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
fun recordTransactions(first: SignedTransaction, vararg remaining: SignedTransaction) {
|
fun recordTransactions(first: SignedTransaction, vararg remaining: SignedTransaction) {
|
||||||
recordTransactions(listOf(first, *remaining))
|
recordTransactions(listOf(first, *remaining))
|
||||||
@ -240,6 +266,13 @@ interface ServiceHub : ServicesForResolution {
|
|||||||
/**
|
/**
|
||||||
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
* Stores the given [SignedTransaction]s in the local transaction storage and then sends them to the vault for
|
||||||
* further processing. This is expected to be run within a database transaction.
|
* further processing. This is expected to be run within a database transaction.
|
||||||
|
*
|
||||||
|
* As of platform version [TWO_PHASE_FINALITY] also performs signature verification and will throw an
|
||||||
|
* [IllegalStateException] with details of the cause of error upon failure.
|
||||||
|
* Of course, you should not be recording transactions to the ledger that are not fully signed.
|
||||||
|
* It is possible, but not recommended, to revert to non-signature verification behaviour by setting the system property
|
||||||
|
* "net.corda.recordtransaction.signature.verification.disabled" to true upon node start-up.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
fun recordTransactions(txs: Iterable<SignedTransaction>) {
|
fun recordTransactions(txs: Iterable<SignedTransaction>) {
|
||||||
recordTransactions(StatesToRecord.ONLY_RELEVANT, txs)
|
recordTransactions(StatesToRecord.ONLY_RELEVANT, txs)
|
||||||
|
@ -8,7 +8,6 @@ import net.corda.core.internal.deleteRecursively
|
|||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.flows.isQuasarAgentSpecified
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.driver.NodeParameters
|
import net.corda.testing.driver.NodeParameters
|
||||||
@ -28,8 +27,8 @@ open class SignatureConstraintMigrationFromHashConstraintsTests : SignatureConst
|
|||||||
|
|
||||||
val stateAndRef: StateAndRef<MessageState>? = internalDriver(
|
val stateAndRef: StateAndRef<MessageState>? = internalDriver(
|
||||||
inMemoryDB = false,
|
inMemoryDB = false,
|
||||||
startNodesInProcess = isQuasarAgentSpecified(),
|
networkParameters = testNetworkParameters(notaries = emptyList(), minimumPlatformVersion = 4),
|
||||||
networkParameters = testNetworkParameters(notaries = emptyList(), minimumPlatformVersion = 4)
|
systemProperties = mapOf("net.corda.recordtransaction.signature.verification.disabled" to true.toString())
|
||||||
) {
|
) {
|
||||||
val nodeName = {
|
val nodeName = {
|
||||||
val nodeHandle = startNode(NodeParameters(rpcUsers = listOf(user), additionalCordapps = listOf(oldCordapp))).getOrThrow()
|
val nodeHandle = startNode(NodeParameters(rpcUsers = listOf(user), additionalCordapps = listOf(oldCordapp))).getOrThrow()
|
||||||
|
@ -9,7 +9,6 @@ import net.corda.core.internal.deleteRecursively
|
|||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.flows.isQuasarAgentSpecified
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.driver.NodeParameters
|
import net.corda.testing.driver.NodeParameters
|
||||||
@ -30,8 +29,8 @@ open class SignatureConstraintMigrationFromWhitelistConstraintTests : Signature
|
|||||||
|
|
||||||
val stateAndRef: StateAndRef<MessageState>? = internalDriver(
|
val stateAndRef: StateAndRef<MessageState>? = internalDriver(
|
||||||
inMemoryDB = false,
|
inMemoryDB = false,
|
||||||
startNodesInProcess = isQuasarAgentSpecified(),
|
networkParameters = testNetworkParameters(notaries = emptyList(), minimumPlatformVersion = 4),
|
||||||
networkParameters = testNetworkParameters(notaries = emptyList(), minimumPlatformVersion = 4)
|
systemProperties = mapOf("net.corda.recordtransaction.signature.verification.disabled" to true.toString())
|
||||||
) {
|
) {
|
||||||
val nodeName = {
|
val nodeName = {
|
||||||
val nodeHandle = startNode(NodeParameters(rpcUsers = listOf(user), additionalCordapps = listOf(oldCordapp))).getOrThrow()
|
val nodeHandle = startNode(NodeParameters(rpcUsers = listOf(user), additionalCordapps = listOf(oldCordapp))).getOrThrow()
|
||||||
@ -142,7 +141,7 @@ open class SignatureConstraintMigrationFromWhitelistConstraintTests : Signature
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
systemProperties = emptyMap(),
|
systemProperties = emptyMap(),
|
||||||
startNodesInProcess = true,
|
startNodesInProcess = false,
|
||||||
specifyExistingConstraint = true,
|
specifyExistingConstraint = true,
|
||||||
addAnotherAutomaticConstraintState = true
|
addAnotherAutomaticConstraintState = true
|
||||||
)
|
)
|
||||||
|
@ -74,7 +74,8 @@ open class SignatureConstraintVersioningTests {
|
|||||||
minimumPlatformVersion = minimumPlatformVersion,
|
minimumPlatformVersion = minimumPlatformVersion,
|
||||||
whitelistedContractImplementations = whitelistedAttachmentHashes
|
whitelistedContractImplementations = whitelistedAttachmentHashes
|
||||||
),
|
),
|
||||||
systemProperties = systemProperties
|
systemProperties = systemProperties +
|
||||||
|
("net.corda.recordtransaction.signature.verification.disabled" to true.toString())
|
||||||
) {
|
) {
|
||||||
// create transaction using first Cordapp
|
// create transaction using first Cordapp
|
||||||
val (nodeName, baseDirectory, issuanceTransaction) = createIssuanceTransaction(cordapp)
|
val (nodeName, baseDirectory, issuanceTransaction) = createIssuanceTransaction(cordapp)
|
||||||
|
@ -13,9 +13,11 @@ import net.corda.core.internal.NamedCacheFactory
|
|||||||
import net.corda.core.internal.ResolveTransactionsFlow
|
import net.corda.core.internal.ResolveTransactionsFlow
|
||||||
import net.corda.core.internal.ServiceHubCoreInternal
|
import net.corda.core.internal.ServiceHubCoreInternal
|
||||||
import net.corda.core.internal.TransactionsResolver
|
import net.corda.core.internal.TransactionsResolver
|
||||||
|
import net.corda.core.internal.VisibleForTesting
|
||||||
import net.corda.core.internal.concurrent.OpenFuture
|
import net.corda.core.internal.concurrent.OpenFuture
|
||||||
import net.corda.core.internal.dependencies
|
import net.corda.core.internal.dependencies
|
||||||
import net.corda.core.internal.requireSupportedHashType
|
import net.corda.core.internal.requireSupportedHashType
|
||||||
|
import net.corda.core.internal.warnOnce
|
||||||
import net.corda.core.messaging.DataFeed
|
import net.corda.core.messaging.DataFeed
|
||||||
import net.corda.core.messaging.StateMachineTransactionMapping
|
import net.corda.core.messaging.StateMachineTransactionMapping
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
@ -36,7 +38,8 @@ import net.corda.node.services.persistence.AttachmentStorageInternal
|
|||||||
import net.corda.node.services.statemachine.ExternalEvent
|
import net.corda.node.services.statemachine.ExternalEvent
|
||||||
import net.corda.node.services.statemachine.FlowStateMachineImpl
|
import net.corda.node.services.statemachine.FlowStateMachineImpl
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import java.security.PublicKey
|
import java.lang.IllegalStateException
|
||||||
|
import java.security.SignatureException
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
@ -67,6 +70,7 @@ interface NetworkMapCacheInternal : NetworkMapCache, NetworkMapCacheBase {
|
|||||||
interface ServiceHubInternal : ServiceHubCoreInternal {
|
interface ServiceHubInternal : ServiceHubCoreInternal {
|
||||||
companion object {
|
companion object {
|
||||||
private val log = contextLogger()
|
private val log = contextLogger()
|
||||||
|
private val SIGNATURE_VERIFICATION_DISABLED = java.lang.Boolean.getBoolean("net.corda.recordtransaction.signature.verification.disabled")
|
||||||
|
|
||||||
private fun topologicalSort(transactions: Collection<SignedTransaction>): Collection<SignedTransaction> {
|
private fun topologicalSort(transactions: Collection<SignedTransaction>): Collection<SignedTransaction> {
|
||||||
if (transactions.size == 1) return transactions
|
if (transactions.size == 1) return transactions
|
||||||
@ -188,9 +192,28 @@ interface ServiceHubInternal : ServiceHubCoreInternal {
|
|||||||
fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>?
|
fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>?
|
||||||
val cacheFactory: NamedCacheFactory
|
val cacheFactory: NamedCacheFactory
|
||||||
|
|
||||||
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) {
|
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) =
|
||||||
|
recordTransactions(statesToRecord, txs, SIGNATURE_VERIFICATION_DISABLED)
|
||||||
|
|
||||||
|
@Suppress("NestedBlockDepth")
|
||||||
|
@VisibleForTesting
|
||||||
|
fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>, disableSignatureVerification: Boolean) {
|
||||||
txs.forEach {
|
txs.forEach {
|
||||||
requireSupportedHashType(it)
|
requireSupportedHashType(it)
|
||||||
|
if (it.coreTransaction is WireTransaction) {
|
||||||
|
if (disableSignatureVerification) {
|
||||||
|
log.warnOnce("The current usage of recordTransactions is unsafe." +
|
||||||
|
"Recording transactions without signature verification may lead to severe problems with ledger consistency.")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
it.verifyRequiredSignatures()
|
||||||
|
}
|
||||||
|
catch (e: SignatureException) {
|
||||||
|
throw IllegalStateException("Signature verification failed", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
recordTransactions(
|
recordTransactions(
|
||||||
statesToRecord,
|
statesToRecord,
|
||||||
|
@ -10,10 +10,12 @@ import net.corda.core.flows.StateReplacementException
|
|||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
|
import net.corda.core.node.StatesToRecord
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
|
import net.corda.node.services.api.ServiceHubInternal
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.BOB_NAME
|
import net.corda.testing.core.BOB_NAME
|
||||||
@ -224,6 +226,6 @@ fun issueInvalidState(services: ServiceHub, identity: Party, notary: Party): Sta
|
|||||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0))
|
val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0))
|
||||||
tx.setTimeWindow(Instant.now(), 30.seconds)
|
tx.setTimeWindow(Instant.now(), 30.seconds)
|
||||||
val stx = services.signInitialTransaction(tx)
|
val stx = services.signInitialTransaction(tx)
|
||||||
services.recordTransactions(stx)
|
(services as ServiceHubInternal).recordTransactions(StatesToRecord.ONLY_RELEVANT, listOf(stx), disableSignatureVerification = true)
|
||||||
return stx.tx.outRef(0)
|
return stx.tx.outRef(0)
|
||||||
}
|
}
|
@ -382,8 +382,10 @@ class VaultWithCashTest {
|
|||||||
linearStates.forEach { println(it.state.data.linearId) }
|
linearStates.forEach { println(it.state.data.linearId) }
|
||||||
|
|
||||||
//copy transactions to notary - simulates transaction resolution
|
//copy transactions to notary - simulates transaction resolution
|
||||||
services.validatedTransactions.getTransaction(deals.first().ref.txhash)?.apply { notaryServices.recordTransactions(this) }
|
services.validatedTransactions.getTransaction(deals.first().ref.txhash)?.apply {
|
||||||
services.validatedTransactions.getTransaction(linearStates.first().ref.txhash)?.apply { notaryServices.recordTransactions(this) }
|
notaryServices.recordTransactions(this, disableSignatureVerification = true) }
|
||||||
|
services.validatedTransactions.getTransaction(linearStates.first().ref.txhash)?.apply {
|
||||||
|
notaryServices.recordTransactions(this, disableSignatureVerification = true) }
|
||||||
|
|
||||||
// Create a txn consuming different contract types
|
// Create a txn consuming different contract types
|
||||||
val dummyMoveBuilder = TransactionBuilder(notary = notary).apply {
|
val dummyMoveBuilder = TransactionBuilder(notary = notary).apply {
|
||||||
|
@ -12,6 +12,7 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.PLATFORM_VERSION
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
|
import net.corda.core.internal.VisibleForTesting
|
||||||
import net.corda.core.internal.requireSupportedHashType
|
import net.corda.core.internal.requireSupportedHashType
|
||||||
import net.corda.core.internal.telemetry.TelemetryComponent
|
import net.corda.core.internal.telemetry.TelemetryComponent
|
||||||
import net.corda.core.internal.telemetry.TelemetryServiceImpl
|
import net.corda.core.internal.telemetry.TelemetryServiceImpl
|
||||||
@ -451,8 +452,18 @@ open class MockServices private constructor(
|
|||||||
val cordappClassloader: ClassLoader
|
val cordappClassloader: ClassLoader
|
||||||
get() = cordappLoader.appClassLoader
|
get() = cordappLoader.appClassLoader
|
||||||
|
|
||||||
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) {
|
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) =
|
||||||
|
recordTransactions(txs, false)
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
fun recordTransactions(txn: SignedTransaction, disableSignatureVerification: Boolean) =
|
||||||
|
recordTransactions(listOf(txn), disableSignatureVerification)
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
fun recordTransactions(txs: Iterable<SignedTransaction>, disableSignatureVerification: Boolean) {
|
||||||
txs.forEach {
|
txs.forEach {
|
||||||
|
if (!disableSignatureVerification)
|
||||||
|
it.verifyRequiredSignatures()
|
||||||
(validatedTransactions as WritableTransactionStorage).addTransaction(it)
|
(validatedTransactions as WritableTransactionStorage).addTransaction(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import net.corda.core.transactions.SignedTransaction
|
|||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.node.services.DbTransactionsResolver
|
import net.corda.node.services.DbTransactionsResolver
|
||||||
|
import net.corda.node.services.api.WritableTransactionStorage
|
||||||
import net.corda.node.services.attachments.NodeAttachmentTrustCalculator
|
import net.corda.node.services.attachments.NodeAttachmentTrustCalculator
|
||||||
import net.corda.node.services.persistence.AttachmentStorageInternal
|
import net.corda.node.services.persistence.AttachmentStorageInternal
|
||||||
import net.corda.testing.core.dummyCommand
|
import net.corda.testing.core.dummyCommand
|
||||||
@ -367,7 +368,10 @@ data class TestLedgerDSLInterpreter private constructor(
|
|||||||
override fun verifies(): EnforceVerifyOrFail {
|
override fun verifies(): EnforceVerifyOrFail {
|
||||||
try {
|
try {
|
||||||
val usedInputs = mutableSetOf<StateRef>()
|
val usedInputs = mutableSetOf<StateRef>()
|
||||||
services.recordTransactions(transactionsUnverified.map { SignedTransaction(it, listOf(NULL_SIGNATURE)) })
|
transactionsUnverified.map {
|
||||||
|
(services.validatedTransactions as WritableTransactionStorage).addTransaction(SignedTransaction(it, listOf(NULL_SIGNATURE)))
|
||||||
|
}
|
||||||
|
|
||||||
for ((_, value) in transactionWithLocations) {
|
for ((_, value) in transactionWithLocations) {
|
||||||
val wtx = value.transaction
|
val wtx = value.transaction
|
||||||
val ltx = wtx.toLedgerTransaction(services)
|
val ltx = wtx.toLedgerTransaction(services)
|
||||||
@ -380,7 +384,7 @@ data class TestLedgerDSLInterpreter private constructor(
|
|||||||
throw DoubleSpentInputs(txIds)
|
throw DoubleSpentInputs(txIds)
|
||||||
}
|
}
|
||||||
usedInputs.addAll(wtx.inputs)
|
usedInputs.addAll(wtx.inputs)
|
||||||
services.recordTransactions(SignedTransaction(wtx, listOf(NULL_SIGNATURE)))
|
(services.validatedTransactions as WritableTransactionStorage).addTransaction(SignedTransaction(wtx, listOf(NULL_SIGNATURE)))
|
||||||
}
|
}
|
||||||
return EnforceVerifyOrFail.Token
|
return EnforceVerifyOrFail.Token
|
||||||
} catch (exception: TransactionVerificationException) {
|
} catch (exception: TransactionVerificationException) {
|
||||||
|
Loading…
Reference in New Issue
Block a user