public class SignTransactionFlow extends FlowLogic<T>
The class SignTransactionFlow
should be called in response to the class CollectSignaturesFlow
. It automates the signing of
a transaction providing the transaction:
Should actually be signed by the class Party
invoking this flow
Is valid as per the contracts referenced in the transaction
Has been, at least, signed by the counterparty which created it
Conforms to custom checking provided in the checkTransaction
method of the class SignTransactionFlow
Usage:
Subclass class SignTransactionFlow
- this can be done inside an existing flow (as shown below)
Override the checkTransaction
method to add some custom verification logic
Call the flow via FlowLogic.subFlow
The flow returns the transaction signed with the additional signature.
Example - checking and signing a transaction involving a net.corda.core.contracts.DummyContract, see CollectSignaturesFlowTests.kt for further examples:
class Responder(val otherPartySession: FlowSession): FlowLogic() {
@Suspendable override fun call(): SignedTransaction {
// [SignTransactionFlow] sub-classed as a singleton object.
val flow = object : SignTransactionFlow(otherPartySession) {
@Suspendable override fun checkTransaction(stx: SignedTransaction) = requireThat {
val tx = stx.tx
val magicNumberState = tx.outputs.single().data as DummyContract.MultiOwnerState
"Must be 1337 or greater" using (magicNumberState.magicNumber >= 1337)
}
}
// Invoke the subFlow, in response to the counterparty calling [CollectSignaturesFlow].
val expectedTxId = subFlow(flow).id
return subFlow(ReceiveFinalityFlow(otherPartySession, expectedTxId))
}
}
@JvmOverloads public SignTransactionFlow(@NotNull FlowSession otherSideSession, @NotNull ProgressTracker progressTracker)
The class SignTransactionFlow
should be called in response to the class CollectSignaturesFlow
. It automates the signing of
a transaction providing the transaction:
Should actually be signed by the class Party
invoking this flow
Is valid as per the contracts referenced in the transaction
Has been, at least, signed by the counterparty which created it
Conforms to custom checking provided in the checkTransaction
method of the class SignTransactionFlow
Usage:
Subclass class SignTransactionFlow
- this can be done inside an existing flow (as shown below)
Override the checkTransaction
method to add some custom verification logic
Call the flow via FlowLogic.subFlow
The flow returns the transaction signed with the additional signature.
Example - checking and signing a transaction involving a net.corda.core.contracts.DummyContract, see CollectSignaturesFlowTests.kt for further examples:
class Responder(val otherPartySession: FlowSession): FlowLogic() {
@Suspendable override fun call(): SignedTransaction {
// [SignTransactionFlow] sub-classed as a singleton object.
val flow = object : SignTransactionFlow(otherPartySession) {
@Suspendable override fun checkTransaction(stx: SignedTransaction) = requireThat {
val tx = stx.tx
val magicNumberState = tx.outputs.single().data as DummyContract.MultiOwnerState
"Must be 1337 or greater" using (magicNumberState.magicNumber >= 1337)
}
}
// Invoke the subFlow, in response to the counterparty calling [CollectSignaturesFlow].
val expectedTxId = subFlow(flow).id
return subFlow(ReceiveFinalityFlow(otherPartySession, expectedTxId))
}
}
otherSideSession
- The session which is providing you a transaction to sign.progressTracker
- Override this to provide a class ProgressTracker
. If one is provided and stepped, the framework will do something
helpful with the progress reports e.g record to the audit service. If this flow is invoked as a subflow of another,
then the tracker will be made a child of the current step in the parent. If it's null, this flow doesn't track
progress.
Note that this has to return a tracker before the flow is invoked. You can't change your mind half way through.
class SignTransactionFlow
,
class CollectSignaturesFlow
,
class Party
,
checkTransaction
,
class SignTransactionFlow
,
class SignTransactionFlow
,
checkTransaction
,
FlowLogic.subFlow
,
net.corda.core.contracts.DummyContract@JvmOverloads public SignTransactionFlow(@NotNull FlowSession otherSideSession)
The class SignTransactionFlow
should be called in response to the class CollectSignaturesFlow
. It automates the signing of
a transaction providing the transaction:
Should actually be signed by the class Party
invoking this flow
Is valid as per the contracts referenced in the transaction
Has been, at least, signed by the counterparty which created it
Conforms to custom checking provided in the checkTransaction
method of the class SignTransactionFlow
Usage:
Subclass class SignTransactionFlow
- this can be done inside an existing flow (as shown below)
Override the checkTransaction
method to add some custom verification logic
Call the flow via FlowLogic.subFlow
The flow returns the transaction signed with the additional signature.
Example - checking and signing a transaction involving a net.corda.core.contracts.DummyContract, see CollectSignaturesFlowTests.kt for further examples:
class Responder(val otherPartySession: FlowSession): FlowLogic() {
@Suspendable override fun call(): SignedTransaction {
// [SignTransactionFlow] sub-classed as a singleton object.
val flow = object : SignTransactionFlow(otherPartySession) {
@Suspendable override fun checkTransaction(stx: SignedTransaction) = requireThat {
val tx = stx.tx
val magicNumberState = tx.outputs.single().data as DummyContract.MultiOwnerState
"Must be 1337 or greater" using (magicNumberState.magicNumber >= 1337)
}
}
// Invoke the subFlow, in response to the counterparty calling [CollectSignaturesFlow].
val expectedTxId = subFlow(flow).id
return subFlow(ReceiveFinalityFlow(otherPartySession, expectedTxId))
}
}
otherSideSession
- The session which is providing you a transaction to sign.class SignTransactionFlow
,
class CollectSignaturesFlow
,
class Party
,
checkTransaction
,
class SignTransactionFlow
,
class SignTransactionFlow
,
checkTransaction
,
FlowLogic.subFlow
,
net.corda.core.contracts.DummyContract@Suspendable @NotNull public SignedTransaction call()
This is where you fill out your business logic.
@Suspendable protected void checkTransaction(@NotNull SignedTransaction stx)
The checkTransaction
method allows the caller of this flow to provide some additional checks over the proposed
transaction received from the counterparty. For example:
Ensuring that the transaction you are receiving is the transaction you EXPECT to receive. I.e. is has the expected type and number of inputs and outputs
Checking that the properties of the outputs are as you would expect. Linking into any reference data sources might be appropriate here
Checking that the transaction is not incorrectly spending (perhaps maliciously) one of your asset states, as potentially the transaction creator has access to some of your state references
WARNING: If appropriate checks, such as the ones listed above, are not defined then it is likely that your node will sign any transaction if it conforms to the contract code in the transaction's referenced contracts.
IllegalArgumentException, IllegalStateException and AssertionError will be caught and rethrown as flow exceptions i.e. the other side will be given information about what exact check failed.
stx
- a partially signed transaction received from your counterparty.FlowException
- if the proposed transaction fails the checks.checkTransaction
,
IllegalArgumentException,
IllegalStateException,
AssertionError@NotNull public FlowSession getOtherSideSession()
The session which is providing you a transaction to sign.
@NotNull public ProgressTracker getProgressTracker()
Override this to provide a class ProgressTracker
. If one is provided and stepped, the framework will do something
helpful with the progress reports e.g record to the audit service. If this flow is invoked as a subflow of another,
then the tracker will be made a child of the current step in the parent. If it's null, this flow doesn't track
progress.
Note that this has to return a tracker before the flow is invoked. You can't change your mind half way through.
class ProgressTracker
@JvmStatic @NotNull public static ProgressTracker tracker()