Skip to content

Instantly share code, notes, and snippets.

@stackdump
Last active November 5, 2018 08:55
Show Gist options
  • Save stackdump/d1e8dcbb00f17dbb0320e1f792775056 to your computer and use it in GitHub Desktop.
Save stackdump/d1e8dcbb00f17dbb0320e1f792775056 to your computer and use it in GitHub Desktop.

TicTacToe contract

Contract Declaration

{
    "inputs": [
        {
            "address": "|DEPOSITOR|",
            "amount": 1
        }
    ],
    "outputs": [
        {
            "address": "|DEPOSITOR|",
            "amount": 1
        },
        {
            "address": "|PLAYERX|",
            "amount": 1
        },
        {
            "address": "|PLAYERO|",
            "amount": 1
        }
    ],
    "blockheight": 60221409,
    "salt": "|RANDOM|",
    "contractid": "|ContractID|",
    "schema": "octoe-v1",
    "state": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
    "actions": {
        "ENDO": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1 ],
        "ENDX": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1 ],
        "EXEC": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -1, -1 ],
        "O00": [ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0 ],
        "O01": [ 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0 ],
        "O02": [ 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0 ],
        "O10": [ 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0 ],
        "O11": [ 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 0 ],
        "O12": [ 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0 ],
        "O20": [ 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 1, 0, 0, 0 ],
        "O21": [ 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 1, 0, 0, 0 ],
        "O22": [ 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 1, 0, 0, 0 ],
        "WINO": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0 ],
        "WINX": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0 ],
        "X00": [ -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0 ],
        "X01": [ 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0 ],
        "X02": [ 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0 ],
        "X10": [ 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0 ],
        "X11": [ 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, -1, 0, 0, 0 ],
        "X12": [ 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, -1, 0, 0, 0 ],
        "X20": [ 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, 0, 0, 0 ],
        "X21": [ 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, -1, 0, 0, 0 ],
        "X22": [ 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, 0, 0, 0 ]
    },
    "guards": [
        [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
        [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0 ],
        [ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0 ],
    ],
    "conditions": [
        [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 ],
        [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0 ],
        [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0 ]
    ]
}

event0:

First event triggers the EXEC 'BEGIN' transaction and includes a json-serialized payload containging contract declaration

{
    "timestamp": 1541078199752125017,
    "schema": "octoe-v1",
    "action": "EXEC",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
    "output": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 ],
    "payload": "deadBeefewogICAgImlucHV0cyI6IFsKICAgICAgICB7CiAgICAgICAgICAgICJhZGRyZXNzIj="
}

event1:

{
    "timestamp": 1541078199752724107,
    "schema": "octoe-v1",
    "action": "X11",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 ],
    "output": [ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 ],
    "payload": "e30="
}

event2:

{
    "timestamp": 1541078199752826526,
    "schema": "octoe-v1",
    "action": "O01",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 ],
    "output": [ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0 ],
    "payload": "e30="
}

event3:

{
    "timestamp": 1541078199752920020,
    "schema": "octoe-v1",
    "action": "X00",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0 ],
    "output": [ 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 ],
    "payload": "e30="
}

event4:

{
    "timestamp": 1541078199753010166,
    "schema": "octoe-v1",
    "action": "O02",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 ],
    "output": [ 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0 ],
    "payload": "e30="
}

event5:

{
    "timestamp": 1541078199753095273,
    "schema": "octoe-v1",
    "action": "X22",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0 ],
    "output": [ 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0 ],
    "payload": "e30="
}

event6:

{
    "timestamp": 1541078199753199866,
    "schema": "octoe-v1",
    "action": "WINX",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0 ],
    "output": [ 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0 ],
    "payload": "e30="
}

Option Contract

Contract Declaration

{
    "inputs": [ { "address": "|DEPOSITOR|", "amount": 1 } ],
    "outputs": [
        {
            "address": "|DEPOSITOR|",
            "amount": 1
        },
        {
            "address": "|PUBKEY1|",
            "amount": 1
        },
        {
            "address": "|PUBKEY2|",
            "amount": 1
        }
    ],
    "blockheight": 60221409,
    "salt": "|RANDOM|",
    "contractid": "|ContractID|",
    "schema": "option-v1",
    "state": [ 1, 1, 1, 1, 1 ],
    "actions": {
        "EXEC": [ 0, -1, -1, 0, -1 ],
        "FAIL": [ -1, 0, 0, -1, 1 ],
        "HALT": [ 0, 0, 0, -1, 0 ],
        "OPT_0": [ -1, 1, 0, 0, 0 ],
        "OPT_1": [ -1, 0, 1, 0, 0 ]
    },
    "guards": [
        [ 0, 0, 0, -1, 0 ],
        [ 0, 0, 0, -1, 0 ],
        [ 0, 0, 0, -1, 0 ]
    ],
    "conditions": [
        [ 0, 0, 0, 0, -1 ],
        [ 0, -1, 0, 0, 0 ],
        [ 0, 0, -1, 0, 0 ]
    ]
}

event0:

{
    "timestamp": 1541078199753397543,
    "schema": "option-v1",
    "action": "EXEC",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 1, 1, 1, 1, 1 ],
    "output": [ 1, 0, 0, 1, 0 ],
    "payload": "deadBeefewogICAgImlucHV0cyI6IFsKICAgICAgICB7CiAgICAgICAgICAgICJhZGRyZXNzIj="
}

event1:

{
    "timestamp": 1541078199753569309,
    "schema": "option-v1",
    "action": "OPT_0",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 1, 0, 0, 1, 0 ],
    "output": [ 0, 1, 0, 1, 0 ],
    "payload": "e30="
}

event2:

This action is called HALT (and also happens to halt the contract)

{
    "timestamp": 1541078199753664258,
    "schema": "option-v1",
    "action": "HALT",
    "oid": "|ContractID|",
    "value": 1,
    "input": [ 0, 1, 0, 1, 0 ],
    "output": [ 0, 1, 0, 0, 0 ],
    "payload": "e30="
}
@stackdump
Copy link
Author

stackdump commented Nov 1, 2018

Intro

Here's some sample data showing 2 petri-net smart contracts - one is a game of tic-tac-toe and the other is a simple 'option' contract where an offer is made to 2 addresses and can only be redeemed by 1 or sent back to depositor

Redeem With State

the general idea is that a transaction is completed w/ normal key /RCD validation Plus an additional restriction that the 'conditions' specified in the contract are met

State Conditions

(like an Access Control List) guards & conditions prevent input actions & release of tokens respectively
unless the given state is deemed valid

'Valid'

in this model - valid means state vector can be added to condition w/o resulting in any values < 1

Halting State

The contract is complete when it is 'halted' - when there are no valid moves left
contract expires if it does not halt before the specified blockheight

Related

bisimulation - is a concept I've been trying to integrate - https://en.wikipedia.org/wiki/Bisimulation - I think it's a great way to think about what is going on with this model

Bisimulation
In theoretical computer science a bisimulation is a binary relation between state transition systems, associating systems that behave in the same way in the sense that one system simulates the other and vice versa.
Intuitively two systems are bisimilar if they match each othe...

The general approach for aggregating events to calculate state is widely known as https://martinfowler.com/eaaDev/EventSourcing.html

@stackdump
Copy link
Author

  1. Q: In the tic-tac-toe how do you identity each players?
    A: There is a 'role' place that indicates whose turn it is - the Guard conditions relate the key ordering to state TODO: add explicit examples

  2. Q: Any particular reason you encode base64 the payload?
    A: mostly because Golang marshalled the json-encoded string that way in my demo code - could change to just be json (though I like the idea that it could be encryped bytes also)

  3. Q: Do you have tool that convert those matrix/vector to graphical representation?
    A: I've sortof been going the other way - designing graphical and then converting using: https://www.blahchain.com/PetriNetEditor/ and http://sarahtattersall.github.io/PIPE/

  4. Q: Why do you need to put input and output as part of the entry? As you said, it is Event sourcing so the state should be calculated by the program reading the chain, why is there a need to store the calculated state?
    A: you are correct these values can be recomputed (I could be convinced to leave this out)- I added this data to the payload because makes auditing trivial

  5. Q: Why value is always = 1 in the tic tac toe
    A: this is a 'multiplier' - each of the transform vectors in the state machine can be executed 'N' times by including a value > 1
    this is added to allow contracts where we need to specify an 'amount' - basically the actions can be thought of as 'Unit Vectors' in that case

  6. Q: Why does an explicit WINX event needs to be submitted? Isn't it just the consequence of all previous moves? Which party is supposed to emit this WIN event?
    A: WINX isn't really required - the evidence for the winner is in the chain by the time this event is added - I added this mechanism as sort of an illustration whereby the original depositor is the Judge of the game.

  7. Q: How to apply the "conditions"? I mean how do I know if a state satisfy the conditions? Kind of the same question for guards?
    A: conditions are applied by adding vectors - if the sum contains any negative values - the condition is False/Invalid (I will release code soon)

  8. Q: I see there are as many guards as there are outputs, is that a coincidence? Or maybe I haven't understood what guards are, could you re explain me please?
    A: not a coincidence - guards restrict who is 'allowed' to interact w/ the state machine at a givn state - the order of Outputs corresponds to the 'Role' being asserted by a Guard clause

  9. Q:the "conditions" allow to describe the conditions that need to be met for the token to be released right? But how did you encode to WHO it should be , is it just the ordering of conditions that match ordering of outputs?
    A: yes - the ordering of outputs corresponds to the 'Who' has unlocked the funds

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment