Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to check contract constraints

From release-M13 of Corda, in the CordApp-Tutorial example, there are some constraints checks made within the flow itself (ExampleFlow.Acceptor). My question is, what constraints may I check on the flow, and what constraints in the Contract? Or it's just an organization issue?

like image 527
Maka Avatar asked Jul 12 '17 19:07

Maka


People also ask

What are the Constraint of contract?

Contract constraints define the versions of a CorDapp can be used to provide the contract to a transaction. The constraints property is stored in each state.

What is the default contract constraints that TransactionBuilder uses of the Corda was signed when built?

By default, the TransactionBuilder uses Signature Constraints for any issuance transactions if the CorDapp attached to it is signed. To manually define the contract constraint of an output state, see the example below: java.

What does Corda contract verify?

In the context of a CorDapp, contracts define rules for verifying transaction inputs and outputs. A CorDapp can have more than one contract, and each contract defines the rules for one or more states.


1 Answers

This is a great question. I believe you are referring to:

    @InitiatedBy(Initiator::class)
    class Acceptor(val otherParty: Party) : FlowLogic<SignedTransaction>() {
        @Suspendable
        override fun call(): SignedTransaction {
            val signTransactionFlow = object : SignTransactionFlow(otherParty) {
                override fun checkTransaction(stx: SignedTransaction) = requireThat {
                    val output = stx.tx.outputs.single().data
                    "This must be an IOU transaction." using (output is IOUState)
                    val iou = output as IOUState
                    "The IOU's value can't be too high." using (iou.iou.value < 100)
                }
            }

            return subFlow(signTransactionFlow)
        }
    }

The CollectSignaturesFlow and its counterpart, the SignTransactionFlow automates the collection of signatures for any type of transaction. This automation is super useful because developers don't have to manually write flows for signature collection anymore! However, developers have to be aware that given any valid transaction - as per the referenced contract code in the transaction - the counter-party will always sign! This is because transactions are validated in isolation, not relative to some expected external values.

Let me provide two examples:

  • If I have access to one of your unspent cash states from a previous transaction, then perhaps I could create a cash spend transaction (from you to me) and ask you to sign it via the CollectSignaturesFlow. If the transaction is valid then, without any additional checking, you'll sign it which will result in you sending me the cash. Clearly you don't want this!
  • The contract code can only go part of the way to verifying a transaction. If you want to check that the transaction represents a deal you want to enter into e.g. price < some amount then you'll have to do some additional checking. The contract code cannot opine on what constitutes a commercially viable deal for you. This checking has to be done as part of the SignTransactionFlow by overriding signTransaction

In a production CorDapp, one may wish to defer to human judgement on whether to sign a transaction and enter into a deal. Or alternatively, this process could be automated by reaching out to some external reference data system via HTTP API or MQ to determine if the deal is one that should be entered into.

In the code example above, we added two simple constraints:

  • One which prevents a borrower from creating an overly large (greater than 100) IOU state
  • One which ensures the transaction does indeed contain an IOU state and not some other state we are not expecting

Note that these two constraints cannot be placed inside the contract code. Contract code is more appropriate for defining the constraints that govern how an asset or agreement should evolve over time. For example, with regards to an IOU:

  • Issuances must be signed by lender and borrower
  • Issuances must be for a value greater than zero
  • Redemptions must involve a cash payment of the correct currency
  • The IOU must be redeemed before the expiry date
  • More examples available here: https://github.com/roger3cev/iou-cordapp-v2/blob/master/src/main/kotlin/net/corda/iou/contract/IOUContract.kt

Remember, Corda is designed for potentially mutually distrusting parties to enter into consensus about shared facts. As such, nodes cannot implicitly trust what they receive over the wire from their counter-parties, therefore we always have to check what we receive is what we expect to receive.

Hope that makes sense!

like image 58
Roger Willis Avatar answered Oct 03 '22 23:10

Roger Willis