From 7aafcf8c57e6f8bc9e4068d071d0d8a514ae0a67 Mon Sep 17 00:00:00 2001 From: Andrius Dagys Date: Fri, 14 Jul 2017 20:40:21 +0100 Subject: [PATCH] Prevent exception causes showing up as null in logs (#1018) * Passing exception messages via constructor instead of overriding toString --- .../core/contracts/TransactionVerification.kt | 45 +++++++++---------- .../kotlin/net/corda/core/flows/NotaryFlow.kt | 10 ++--- .../core/flows/ResolveTransactionsFlowTest.kt | 2 +- .../net/corda/docs/CustomNotaryTutorial.kt | 8 ++-- .../transactions/ValidatingNotaryFlow.kt | 8 ++-- .../ValidatingNotaryServiceTests.kt | 9 ++-- 6 files changed, 39 insertions(+), 43 deletions(-) diff --git a/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt b/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt index 6ce17e267a..0b48cae298 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt @@ -93,35 +93,32 @@ data class TransactionForContract(val inputs: List, // DOCEND 3 } -class TransactionResolutionException(val hash: SecureHash) : FlowException() { - override fun toString(): String = "Transaction resolution failure for $hash" -} +class TransactionResolutionException(val hash: SecureHash) : FlowException("Transaction resolution failure for $hash") +class AttachmentResolutionException(val hash: SecureHash) : FlowException("Attachment resolution failure for $hash") -class AttachmentResolutionException(val hash: SecureHash) : FlowException() { - override fun toString(): String = "Attachment resolution failure for $hash" -} +sealed class TransactionVerificationException(val txId: SecureHash, message: String, cause: Throwable?) + : FlowException("$message, transaction: $txId", cause) { -sealed class TransactionVerificationException(val txId: SecureHash, cause: Throwable?) : FlowException(cause) { - class ContractRejection(txId: SecureHash, val contract: Contract, cause: Throwable?) : TransactionVerificationException(txId, cause) - class MoreThanOneNotary(txId: SecureHash) : TransactionVerificationException(txId, null) - class SignersMissing(txId: SecureHash, val missing: List) : TransactionVerificationException(txId, null) { - override fun toString(): String = "Signers missing: ${missing.joinToString()}" - } + class ContractRejection(txId: SecureHash, contract: Contract, cause: Throwable) + : TransactionVerificationException(txId, "Contract verification failed: ${cause.message}, contract: $contract", cause) - class DuplicateInputStates(txId: SecureHash, val duplicates: NonEmptySet) : TransactionVerificationException(txId, null) { - override fun toString(): String = "Duplicate inputs: ${duplicates.joinToString()}" - } + class MoreThanOneNotary(txId: SecureHash) + : TransactionVerificationException(txId, "More than one notary", null) - class InvalidNotaryChange(txId: SecureHash) : TransactionVerificationException(txId, null) - class NotaryChangeInWrongTransactionType(txId: SecureHash, val txNotary: Party, val outputNotary: Party) : TransactionVerificationException(txId, null) { - override fun toString(): String { - return "Found unexpected notary change in transaction. Tx notary: $txNotary, found: $outputNotary" - } - } + class SignersMissing(txId: SecureHash, missing: List) + : TransactionVerificationException(txId, "Signers missing: ${missing.joinToString()}", null) - class TransactionMissingEncumbranceException(txId: SecureHash, val missing: Int, val inOut: Direction) : TransactionVerificationException(txId, null) { - override val message: String get() = "Missing required encumbrance $missing in $inOut" - } + class DuplicateInputStates(txId: SecureHash, val duplicates: NonEmptySet) + : TransactionVerificationException(txId, "Duplicate inputs: ${duplicates.joinToString()}", null) + + class InvalidNotaryChange(txId: SecureHash) + : TransactionVerificationException(txId, "Detected a notary change. Outputs must use the same notary as inputs", null) + + class NotaryChangeInWrongTransactionType(txId: SecureHash, txNotary: Party, outputNotary: Party) + : TransactionVerificationException(txId, "Found unexpected notary change in transaction. Tx notary: $txNotary, found: $outputNotary", null) + + class TransactionMissingEncumbranceException(txId: SecureHash, missing: Int, inOut: Direction) + : TransactionVerificationException(txId, "Missing required encumbrance $missing in $inOut", null) @CordaSerializable enum class Direction { diff --git a/core/src/main/kotlin/net/corda/core/flows/NotaryFlow.kt b/core/src/main/kotlin/net/corda/core/flows/NotaryFlow.kt index a13c3ad650..e452ebc560 100644 --- a/core/src/main/kotlin/net/corda/core/flows/NotaryFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/NotaryFlow.kt @@ -13,6 +13,7 @@ import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.unwrap +import java.security.SignatureException import java.util.function.Predicate object NotaryFlow { @@ -51,8 +52,8 @@ object NotaryFlow { } try { stx.verifySignatures(notaryParty.owningKey) - } catch (ex: SignedTransaction.SignaturesMissingException) { - throw NotaryException(NotaryError.SignaturesMissing(ex)) + } catch (ex: SignatureException) { + throw NotaryException(NotaryError.TransactionInvalid(ex)) } val payload: Any = if (serviceHub.networkMapCache.isValidatingNotary(notaryParty)) { @@ -134,10 +135,7 @@ sealed class NotaryError { /** Thrown if the time specified in the [TimeWindow] command is outside the allowed tolerance. */ object TimeWindowInvalid : NotaryError() - data class TransactionInvalid(val msg: String) : NotaryError() - data class SignaturesInvalid(val msg: String) : NotaryError() - - data class SignaturesMissing(val cause: SignedTransaction.SignaturesMissingException) : NotaryError() { + data class TransactionInvalid(val cause: Throwable) : NotaryError() { override fun toString() = cause.toString() } } diff --git a/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt b/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt index 1e0f222f10..b11d93564f 100644 --- a/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt @@ -70,7 +70,7 @@ class ResolveTransactionsFlowTest { val p = ResolveTransactionsFlow(setOf(stx.id), a.info.legalIdentity) val future = b.services.startFlow(p).resultFuture mockNet.runNetwork() - assertFailsWith(SignatureException::class) { future.getOrThrow() } + assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() } } @Test diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomNotaryTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomNotaryTutorial.kt index eacbfe96ff..8a4b528d28 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomNotaryTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomNotaryTutorial.kt @@ -61,8 +61,8 @@ class MyValidatingNotaryFlow(otherSide: Party, service: MyCustomValidatingNotary private fun checkSignatures(stx: SignedTransaction) { try { stx.verifySignatures(serviceHub.myInfo.notaryIdentity.owningKey) - } catch(e: SignedTransaction.SignaturesMissingException) { - throw NotaryException(NotaryError.SignaturesMissing(e)) + } catch(e: SignatureException) { + throw NotaryException(NotaryError.TransactionInvalid(e)) } } @@ -75,8 +75,8 @@ class MyValidatingNotaryFlow(otherSide: Party, service: MyCustomValidatingNotary return ltx } catch (e: Exception) { throw when (e) { - is TransactionVerificationException -> NotaryException(NotaryError.TransactionInvalid(e.toString())) - is SignatureException -> NotaryException(NotaryError.SignaturesInvalid(e.toString())) + is TransactionVerificationException, + is SignatureException -> NotaryException(NotaryError.TransactionInvalid(e)) else -> e } } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryFlow.kt b/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryFlow.kt index afe9a81d99..daf70b1b24 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryFlow.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryFlow.kt @@ -34,8 +34,8 @@ class ValidatingNotaryFlow(otherSide: Party, service: TrustedAuthorityNotaryServ private fun checkSignatures(stx: SignedTransaction) { try { stx.verifySignatures(serviceHub.myInfo.notaryIdentity.owningKey) - } catch(e: SignedTransaction.SignaturesMissingException) { - throw NotaryException(NotaryError.SignaturesMissing(e)) + } catch(e: SignatureException) { + throw NotaryException(NotaryError.TransactionInvalid(e)) } } @@ -46,8 +46,8 @@ class ValidatingNotaryFlow(otherSide: Party, service: TrustedAuthorityNotaryServ wtx.toLedgerTransaction(serviceHub).verify() } catch (e: Exception) { throw when (e) { - is TransactionVerificationException -> NotaryException(NotaryError.TransactionInvalid(e.toString())) - is SignatureException -> NotaryException(NotaryError.SignaturesInvalid(e.toString())) + is TransactionVerificationException, + is SignatureException -> NotaryException(NotaryError.TransactionInvalid(e)) else -> e } } diff --git a/node/src/test/kotlin/net/corda/node/services/transactions/ValidatingNotaryServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/transactions/ValidatingNotaryServiceTests.kt index f1ca383d4e..ef24dc12b2 100644 --- a/node/src/test/kotlin/net/corda/node/services/transactions/ValidatingNotaryServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/transactions/ValidatingNotaryServiceTests.kt @@ -59,7 +59,8 @@ class ValidatingNotaryServiceTests { val future = runClient(stx) val ex = assertFailsWith(NotaryException::class) { future.getOrThrow() } - assertThat(ex.error).isInstanceOf(NotaryError.SignaturesInvalid::class.java) + val notaryError = ex.error as NotaryError.TransactionInvalid + assertThat(notaryError.cause).isInstanceOf(SignedTransaction.SignaturesMissingException::class.java) } @Test @@ -77,10 +78,10 @@ class ValidatingNotaryServiceTests { val future = runClient(stx) future.getOrThrow() } - val notaryError = ex.error - assertThat(notaryError).isInstanceOf(NotaryError.SignaturesMissing::class.java) + val notaryError = ex.error as NotaryError.TransactionInvalid + assertThat(notaryError.cause).isInstanceOf(SignedTransaction.SignaturesMissingException::class.java) - val missingKeys = (notaryError as NotaryError.SignaturesMissing).cause.missing + val missingKeys = (notaryError.cause as SignedTransaction.SignaturesMissingException).missing assertEquals(setOf(expectedMissingKey), missingKeys) }