mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
FlowException can be thrown from within UntrustworthyData.unwrap for better Java interop, and more checked exception annotations relating to flows
This commit is contained in:
parent
c2f1e05dc0
commit
e44159504c
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,7 +11,6 @@ tags
|
||||
|
||||
.gradle
|
||||
local.properties
|
||||
/docs/build/doctrees
|
||||
|
||||
# General build files
|
||||
**/build/*
|
||||
@ -34,7 +33,6 @@ lib/dokka.jar
|
||||
.idea/libraries
|
||||
.idea/shelf
|
||||
.idea/dataSources
|
||||
.idea/modules.xml
|
||||
|
||||
# if you remove the above rule, at least ignore the following:
|
||||
|
||||
|
@ -17,6 +17,7 @@ sealed class TransactionType {
|
||||
*
|
||||
* Note: Presence of _signatures_ is not checked, only the public keys to be signed for.
|
||||
*/
|
||||
@Throws(TransactionVerificationException::class)
|
||||
fun verify(tx: LedgerTransaction) {
|
||||
require(tx.notary != null || tx.timestamp == null) { "Transactions with timestamps must be notarised." }
|
||||
val duplicates = detectDuplicateInputs(tx)
|
||||
|
@ -3,6 +3,7 @@ package net.corda.core.contracts
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import java.util.*
|
||||
|
||||
@ -85,30 +86,35 @@ data class TransactionForContract(val inputs: List<ContractState>,
|
||||
data class InOutGroup<out T : ContractState, out K : Any>(val inputs: List<T>, val outputs: List<T>, val groupingKey: K)
|
||||
}
|
||||
|
||||
class TransactionResolutionException(val hash: SecureHash) : Exception() {
|
||||
override fun toString() = "Transaction resolution failure for $hash"
|
||||
class TransactionResolutionException(val hash: SecureHash) : FlowException() {
|
||||
override fun toString(): String = "Transaction resolution failure for $hash"
|
||||
}
|
||||
|
||||
class AttachmentResolutionException(val hash : SecureHash) : FlowException() {
|
||||
override fun toString(): String = "Attachment resolution failure for $hash"
|
||||
}
|
||||
|
||||
class TransactionConflictException(val conflictRef: StateRef, val tx1: LedgerTransaction, val tx2: LedgerTransaction) : Exception()
|
||||
|
||||
sealed class TransactionVerificationException(val tx: LedgerTransaction, cause: Throwable?) : Exception(cause) {
|
||||
sealed class TransactionVerificationException(val tx: LedgerTransaction, cause: Throwable?) : FlowException(cause) {
|
||||
class ContractRejection(tx: LedgerTransaction, val contract: Contract, cause: Throwable?) : TransactionVerificationException(tx, cause)
|
||||
class MoreThanOneNotary(tx: LedgerTransaction) : TransactionVerificationException(tx, null)
|
||||
class SignersMissing(tx: LedgerTransaction, val missing: List<CompositeKey>) : TransactionVerificationException(tx, null) {
|
||||
override fun toString() = "Signers missing: ${missing.joinToString()}"
|
||||
override fun toString(): String = "Signers missing: ${missing.joinToString()}"
|
||||
}
|
||||
class DuplicateInputStates(tx: LedgerTransaction, val duplicates: Set<StateRef>) : TransactionVerificationException(tx, null) {
|
||||
override fun toString() = "Duplicate inputs: ${duplicates.joinToString()}"
|
||||
override fun toString(): String = "Duplicate inputs: ${duplicates.joinToString()}"
|
||||
}
|
||||
|
||||
class InvalidNotaryChange(tx: LedgerTransaction) : TransactionVerificationException(tx, null)
|
||||
class NotaryChangeInWrongTransactionType(tx: LedgerTransaction, val outputNotary: Party) : TransactionVerificationException(tx, null) {
|
||||
override fun toString(): String = "Found unexpected notary change in transaction. Tx notary: ${tx.notary}, found: ${outputNotary}"
|
||||
override fun toString(): String {
|
||||
return "Found unexpected notary change in transaction. Tx notary: ${tx.notary}, found: $outputNotary"
|
||||
}
|
||||
}
|
||||
|
||||
class TransactionMissingEncumbranceException(tx: LedgerTransaction, val missing: Int, val inOut: Direction) : TransactionVerificationException(tx, null) {
|
||||
override val message: String?
|
||||
get() = "Missing required encumbrance ${missing} in ${inOut}"
|
||||
override val message: String get() = "Missing required encumbrance $missing in $inOut"
|
||||
}
|
||||
enum class Direction {
|
||||
INPUT,
|
||||
|
@ -9,5 +9,8 @@ package net.corda.core.flows
|
||||
* [FlowException] (or a subclass) can be a valid expected response from a flow, particularly ones which act as a service.
|
||||
* It is recommended a [FlowLogic] document the [FlowException] types it can throw.
|
||||
*/
|
||||
open class FlowException @JvmOverloads constructor(message: String? = null, cause: Throwable? = null)
|
||||
: Exception(message, cause)
|
||||
open class FlowException(override val message: String?, override val cause: Throwable?) : Exception() {
|
||||
constructor(message: String?) : this(message, null)
|
||||
constructor(cause: Throwable?) : this(cause?.toString(), cause)
|
||||
constructor() : this(null, null)
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ class LedgerTransaction(
|
||||
*
|
||||
* @throws TransactionVerificationException if anything goes wrong.
|
||||
*/
|
||||
@Throws(TransactionVerificationException::class)
|
||||
fun verify() = type.verify(this)
|
||||
|
||||
// TODO: When we upgrade to Kotlin 1.1 we can make this a data class again and have the compiler generate these.
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.core.transactions
|
||||
|
||||
import net.corda.core.contracts.AttachmentResolutionException
|
||||
import net.corda.core.contracts.NamedByHash
|
||||
import net.corda.core.contracts.TransactionResolutionException
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
@ -8,7 +9,6 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.signWithECDSA
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import java.io.FileNotFoundException
|
||||
import java.security.KeyPair
|
||||
import java.security.SignatureException
|
||||
import java.util.*
|
||||
@ -127,12 +127,12 @@ data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>,
|
||||
* [WireTransaction.toLedgerTransaction] with the passed in [ServiceHub] to resolve the dependencies,
|
||||
* returning an unverified LedgerTransaction.
|
||||
*
|
||||
* @throws FileNotFoundException if a required attachment was not found in storage.
|
||||
* @throws AttachmentResolutionException if a required attachment was not found in storage.
|
||||
* @throws TransactionResolutionException if an input points to a transaction not found in storage.
|
||||
* @throws SignatureException if any signatures were invalid or unrecognised
|
||||
* @throws SignaturesMissingException if any signatures that should have been present are missing.
|
||||
*/
|
||||
@Throws(FileNotFoundException::class, TransactionResolutionException::class, SignaturesMissingException::class)
|
||||
@Throws(AttachmentResolutionException::class, TransactionResolutionException::class, SignatureException::class)
|
||||
fun toLedgerTransaction(services: ServiceHub) = verifySignatures().toLedgerTransaction(services)
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,6 @@ import net.corda.core.serialization.THREAD_LOCAL_KRYO
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.Emoji
|
||||
import java.io.FileNotFoundException
|
||||
import java.security.PublicKey
|
||||
|
||||
/**
|
||||
@ -66,10 +65,10 @@ class WireTransaction(
|
||||
* Looks up identities and attachments from storage to generate a [LedgerTransaction]. A transaction is expected to
|
||||
* have been fully resolved using the resolution flow by this point.
|
||||
*
|
||||
* @throws FileNotFoundException if a required attachment was not found in storage.
|
||||
* @throws AttachmentResolutionException if a required attachment was not found in storage.
|
||||
* @throws TransactionResolutionException if an input points to a transaction not found in storage.
|
||||
*/
|
||||
@Throws(FileNotFoundException::class, TransactionResolutionException::class)
|
||||
@Throws(AttachmentResolutionException::class, TransactionResolutionException::class)
|
||||
fun toLedgerTransaction(services: ServiceHub): LedgerTransaction {
|
||||
// Look up public keys to authenticated identities. This is just a stub placeholder and will all change in future.
|
||||
val authenticatedArgs = commands.map {
|
||||
@ -78,7 +77,7 @@ class WireTransaction(
|
||||
}
|
||||
// Open attachments specified in this transaction. If we haven't downloaded them, we fail.
|
||||
val attachments = attachments.map {
|
||||
services.storageService.attachments.openAttachment(it) ?: throw FileNotFoundException(it.toString())
|
||||
services.storageService.attachments.openAttachment(it) ?: throw AttachmentResolutionException(it)
|
||||
}
|
||||
val resolvedInputs = inputs.map { StateAndRef(services.loadState(it), it) }
|
||||
return LedgerTransaction(resolvedInputs, outputs, authenticatedArgs, attachments, id, notary, mustSign, timestamp, type)
|
||||
|
@ -18,11 +18,18 @@ class UntrustworthyData<out T>(private val fromUntrustedWorld: T) {
|
||||
@Deprecated("Accessing the untrustworthy data directly without validating it first is a bad idea")
|
||||
get() = fromUntrustedWorld
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Throws(FlowException::class)
|
||||
inline fun <R> unwrap(validator: (T) -> R) = validator(data)
|
||||
fun <R> unwrap(validator: Validator<T, R>) = validator.validate(fromUntrustedWorld)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("This old name was confusing, use unwrap instead", replaceWith = ReplaceWith("unwrap"))
|
||||
inline fun <R> validate(validator: (T) -> R) = validator(data)
|
||||
|
||||
interface Validator<in T, out R> {
|
||||
@Throws(FlowException::class)
|
||||
fun validate(data: T): R
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
inline fun <T, R> UntrustworthyData<T>.unwrap(validator: (T) -> R): R = validator(data)
|
||||
|
@ -15,6 +15,7 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.UntrustworthyData
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.AbstractStateReplacementFlow.Acceptor
|
||||
import net.corda.flows.AbstractStateReplacementFlow.Instigator
|
||||
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.utilities.UntrustworthyData
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.FetchDataFlow.DownloadedVsRequestedDataMismatch
|
||||
import net.corda.flows.FetchDataFlow.HashNotFound
|
||||
import java.util.*
|
||||
|
@ -5,8 +5,8 @@ import net.corda.core.crypto.DigitalSignature
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.SignedData
|
||||
import net.corda.core.crypto.signWithECDSA
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.node.services.TimestampChecker
|
||||
import net.corda.core.node.services.UniquenessException
|
||||
import net.corda.core.node.services.UniquenessProvider
|
||||
@ -14,6 +14,7 @@ import net.corda.core.serialization.serialize
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.unwrap
|
||||
|
||||
object NotaryFlow {
|
||||
/**
|
||||
|
@ -16,6 +16,7 @@ import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.UntrustworthyData
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.core.utilities.unwrap
|
||||
import java.security.KeyPair
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,7 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.FinalityFlow
|
||||
import net.corda.flows.ResolveTransactionsFlow
|
||||
import java.util.*
|
||||
|
@ -8,6 +8,7 @@ import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.linearHeadsOfType
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.FinalityFlow
|
||||
import java.security.PublicKey
|
||||
import java.time.Duration
|
||||
|
@ -9,6 +9,7 @@ import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.unwrap
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,7 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.core.utilities.unwrap
|
||||
import java.security.KeyPair
|
||||
import java.util.*
|
||||
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.getOrThrow
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.random63BitValue
|
||||
import net.corda.core.seconds
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.node.internal.Node
|
||||
import net.corda.node.services.User
|
||||
import net.corda.node.services.config.SSLConfiguration
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.node.recordTransactions
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.*
|
||||
import java.util.function.Function
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
|
@ -21,6 +21,7 @@ import net.corda.core.random63BitValue
|
||||
import net.corda.core.rootCause
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.flows.CashCommand
|
||||
|
@ -14,6 +14,7 @@ import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.core.transactions.FilteredTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.irs.flows.FixingFlow
|
||||
import net.corda.irs.flows.RatesFixFlow
|
||||
import net.corda.node.services.api.AcceptsFileUpload
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.node.CordaPluginRegistry
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.testing.node.MockNetworkMapCache
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.function.Function
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.transactions.FilteredTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.irs.flows.RatesFixFlow.FixOutOfRange
|
||||
import net.corda.irs.utilities.suggestInterestRateAnnouncementTimeWindow
|
||||
import java.math.BigDecimal
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.node.CordaPluginRegistry
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.node.utilities.TestClock
|
||||
import net.corda.testing.node.MockNetworkMapCache
|
||||
import java.time.LocalDate
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.crypto.Party
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.TwoPartyDealFlow
|
||||
import net.corda.vega.contracts.IRSState
|
||||
import net.corda.vega.contracts.OGTrade
|
||||
|
@ -18,6 +18,7 @@ import net.corda.core.messaging.Ack
|
||||
import net.corda.core.node.PluginServiceHub
|
||||
import net.corda.core.node.services.dealsWith
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.AbstractStateReplacementFlow.Proposal
|
||||
import net.corda.flows.StateReplacementException
|
||||
import net.corda.flows.TwoPartyDealFlow
|
||||
|
@ -12,6 +12,7 @@ import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.Emoji
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.flows.TwoPartyTradeFlow
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
import java.nio.file.Path
|
||||
|
Loading…
Reference in New Issue
Block a user