💬

Introduction to Corda contract

2020/10/30に公開

What is Contract

Contract is verification logic for change to state. Contract verify logic which is independent of related parties and deterministic. Flow verify logic which is independent of parties and can be non-deterministic.

How to define your contract.

You define your Contract class by inheriting Contract class and overriding verify function

class MyContract : Contract {
    override fun verify(tx: LedgerTransaction) {
   }
}

Verify function

If verify don't throw, contract is valid. If verify throw, contract is invalid. Verify doesn't return any value. Verify function can access to only tx: LedgerTransaction object.

class MyContract : Contract {
    override fun verify(tx: LedgerTransaction) {
				return 
   }
}

verify function can access below data

  • tx.inputs, which lists the inputs
  • tx.outputs, which lists the outputs
  • tx.commands, which lists the commands and their associated signers
  • tx.outputsOfType<T>, which lists state object of Type T

Code Example

class MyContract : Contract {
    override fun verify(tx: LedgerTransaction) {
				const inputs = tx.inputs
				const outputs = tx.outputs
				const commands = tx.commands
				val output = tx.outputsOfType<IOUState>().single()
    }
}

How to define command in Contract.

We can define command class inside your Contract Class. And your Command should inherit from CommandData class.

class MyContract : Contract {
		class Create : CommandData
}

Command constraint

Transaction can contain more than two commands.

In this case, we check that transaction has only one Create Command.

class MyContract : Contract {

		class Create : CommandData
    override fun verify(tx: LedgerTransaction) {
				val command = requireSingleCommand<Create>()
				
    }
}

Signer Constraints

You should verify that required signs are collected.

You use output.borrower.owningKey, and output.lender.owningKey, command.signers.

class MyContract : Contract {

		class Create : CommandData
    override fun verify(tx: LedgerTransaction) {
        val command = tx.commands.requireSingleCommand<Create>()

        requireThat {
            val output = tx.outputsOfType<IOUState>().single()
            // Constraints on the signers.
            val expectedSigners = listOf(output.borrower.owningKey, output.lender.owningKey)
            "There must be two signers." using (command.signers.toSet().size == 2)
            "The borrower and lender must be signers." using (command.signers.containsAll(expectedSigners))
        }
    }
}

Discussion