Skip to content

Obsidian Tutorial

celestebarnaby edited this page Jul 10, 2017 · 7 revisions

Obsidian is a blockchain-based language that allows users to write programs comprised of contracts and transactions. If you are familiar with Java, you may think of contracts as being similar to classes and transactions as similar to methods.

A program may contain any number of contracts, and exactly one of these must be a "main" contract. Each contract may contain fields of type int, string, or bool; constructors; transactions; and states. A transaction takes any number of parameters and optionally return a value. This is an example of what a simple contract may look like:

main contract Example {
   int x;
   string s;
   bool b;

   //Constructor with default values for the contract's fields
   Example() {
       x = 1;
       s = "hi";
       b = true;
   }
   
   //Sets the field x to newX and returns the old value of x
   transaction setX(int newX) returns int {
      int oldX = x;
      x = newX;
      return oldX;
   }
}

Once a contract has been written, the client writes a separate program wherein they can make a new instance of a contract and execute its transactions.

main contract ExampleClient {
   transaction main(remote ExampleClient ex) {
      int oldX = ex.setX(42);
      ex.setX(2);
   }
}

A state is a block of code with the distinction that the client can only access whatever is in that block if they are in the corresponding state. You enter a state using a state transition. Take this contract, for instance:

main contract StateExample {
    int x;
    string s;
    bool b;

    StateExample() {
        x = 2;
        s = "abc";
        b = true;
    }

    transaction setX(int newX) returns int {
        int oldX = x;
        x = newX;
        -> S1;
        return oldX;
    }
    state S1{
        transaction setS(int newS) returns string {
           string oldS = s;
           s = newS
           return oldS;
        }
    }
}

Note that you can only execute the setS transaction if you are in state S1, and the only way to enter S1 is to execute the setX transaction, as it contains the state transition "->S1;". If you attempt to execute setS when you are not in S1, you will get an error.

States can also have their own fields, and you can initialize the fields of a state using a state transition, e.g.:

transaction toS1(string newS) {
        ->S1({s1Str = news});
    }

state S1 {
    string s1Str;
    transaction setS() returns string {
       string oldS = s;
       s = s1Str;
       return oldS;
    }
}