corda/docs/source/hello-world-state.rst
2017-06-16 14:05:52 +01:00

6.3 KiB

Writing the state

In Corda, shared facts on the ledger are represented as states. Our first task will be to define a new state type to represent an IOU.

The ContractState interface

In Corda, any JVM class that implements the ContractState interface is a valid state. ContractState is defined as follows:

interface ContractState {
    // The contract that imposes constraints on how this state can evolve over time.
    val contract: Contract

    // The list of entities considered to have a stake in this state.
    val participants: List<AbstractParty>
}

The first thing you'll probably notice about this interface declaration is that its not written in Java or another common language. The core Corda platform, including the interface declaration above, is entirely written in Kotlin.

Learning some Kotlin will be very useful for understanding how Corda works internally, and usually only takes an experienced Java developer a day or so to pick up. However, learning Kotlin isn't essential. Because Kotlin code compiles down to JVM bytecode, CorDapps written in other JVM languages can interoperate with Corda.

If you do want to dive into Kotlin, there's an official getting started guide, and a series of Kotlin Koans.

If not, here's a quick primer on the Kotlinisms in the declaration of ContractState:

  • val declares a read-only property, similar to Java's final keyword
  • The syntax varName: varType declares varName as being of type varType

We can see that the ContractState interface declares two properties:

  • contract: the contract controlling transactions involving this state
  • participants: the list of entities that have to approve state changes such as changing the state's notary or upgrading the state's contract

Beyond this, our state is free to define any properties, methods, helpers or inner classes it requires to accurately represent a given class of shared facts on the ledger.

ContractState also has several child interfaces that you may wish to implement depending on your state, such as LinearState and OwnableState.

Modelling IOUs

How should we define the IOUState representing IOUs on the ledger? Beyond implementing the ContractState interface, our IOUState will also need properties to track the relevant features of the IOU:

  • The sender of the IOU
  • The IOU's recipient
  • The value of the IOU

There are many more fields you could include, such as the IOU's currency. We'll abstract them away for now. If you wish to add them later, its as simple as adding an additional property to your class definition.

Defining IOUState

Let's open TemplateState.java (for Java) or TemplateState.kt (for Kotlin) and update TemplateState to define an IOUState:

package com.template

import net.corda.core.contracts.ContractState
import net.corda.core.identity.Party

class IOUState(val value: Int,
               val sender: Party,
               val recipient: Party,
               // TODO: Once we've defined IOUContract, come back and update this.
               override val contract: TemplateContract = TemplateContract()) : ContractState {

    override val participants get() = listOf(sender, recipient)
}
package com.template;

import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty;
import net.corda.core.identity.Party;

import java.util.List;

public class IOUState implements ContractState {
    private final int value;
    private final Party sender;
    private final Party recipient;
    // TODO: Once we've defined IOUContract, come back and update this.
    private final TemplateContract contract;

    public IOUState(int value, Party sender, Party recipient, IOUContract contract) {
        this.value = value;
        this.sender = sender;
        this.recipient = recipient;
        this.contract = contract;
    }

    public int getValue() {
        return value;
    }

    public Party getSender() {
        return sender;
    }

    public Party getRecipient() {
        return recipient;
    }

    @Override
    // TODO: Once we've defined IOUContract, come back and update this.
    public TemplateContract getContract() {
        return contract;
    }

    @Override
    public List<AbstractParty> getParticipants() {
        return ImmutableList.of(sender, recipient);
    }
}

We've made the following changes:

  • We've renamed TemplateState to IOUState
  • We've added properties for value, sender and recipient (along with any getters and setters in Java):
    • value is just a standard int (in Java)/Int (in Kotlin), but sender and recipient are of type Party. Party is a built-in Corda type that represents an entity on the network.
  • We've overridden participants to return a list of the sender and recipient
  • This means that actions such as changing the state's contract or its notary will require approval from both the sender and the recipient

We've left IOUState's contract as TemplateContract for now. We'll update this once we've defined the IOUContract.

Progress so far

We've defined an IOUState that can be used to represent IOUs as shared facts on the ledger. As we've seen, states in Corda are simply JVM classes that implement the ContractState interface. They can have any additional properties and methods you like.

Next, we'll be writing our IOUContract to control the evolution of these shared facts over time.