Skip to content

Designing RPC for FSM CC

dimxy edited this page Nov 13, 2019 · 124 revisions

Designing RPC specification for FSM CC module

version 0.0.3

What's new in 0.0.3

  • introduced a new type of 'message events' as spend request transactions in mempool (therefore 'Validation Rules' are not used any more)
  • added payments example
  • added implementation suggestions section

Initial requirements

This is requirements to develop a FSM CC (Antara) module. 'FSM' states for Finite State Machine. The idea behind the FSM CC module is a belief that logics of many kinds of smart contracts might be implemented as state machines, so if we develop a FSM CC module which could run finite states machines defined by a configuration, we could create implementations for various smart contracts with a single FSM CC Module.

The FSM CC module should provide creation of FSM definitions with the fsmdefine rpc. Such definitions will serve as templates for FSM instances created with the fsmcreate rpc.
A FSM definition has state enumeration and state transition map defined in the opreturn data of the FSM definition initial transaction.
The state transitions are driven by events. FSM module support both internal and external events. Internal events occur when something happens inside the chain, external events are delivered into the chain by oracles dapps. The model of FSM CC module is partially derived from UML2 State Diagram specification.

Limitations

The first FSM CC Module version does not support state actions yet (defined by UML standard for the State Diagram). (Other limitations)

Extensions and changes to UML StateMachine specification

Extensions to UML StateMachines:

  • FSM CC Module has own expression language and basic function set to allow to set guards, actions, event-expressions
  • Message events in UML are specialized as CallEvent, SignalEvent or AnyReceiveEvent. In FSM CC module message events are 'Call For Validation' events (identified by funcid symbol.

Concepts

The basic terms of FSM CC Module:

  • FSM, finite state machine - a system which in one moment can be only in one state. Transitions from a state to state are driven by events.
  • State - state in which FSM instance could be. In one moment FSM could be only in one state. A state has an id and a name. FSM can transition from one state to another state if some event occured.
  • Event - a external or internal event which, when occured, causes FSM transition from one state to another. One Event may occur in different moments of time (that is event instances )
  • Internal Event - a event that occurs inside the chain, an internal event has an attached event condition which, when fulfilled, indicates that the internal event has occured.
  • External Event - a event that occurs externally to the chain and delivered to the chain as oracle data
  • Transition - transition from one state to another
  • Transition map - a map which defines a transition for a event
  • Guard Condition - a condition associated with a state transition. A guard condition is a boolean expression that runs on blockchain artefacts. A transition is enabled if its guard evaluates to true.
  • Transition Action - an Expression performed on blockchain artefacts which is executed after state transition.

RPC descriptions

fsmdefine

fsmdefine - creates a finite state machine definition. A FSM defintion is a template based on which, with values for the defined parameters, a FSM instance could be created and run.

  • Call:
    • fsmdefine name 'fsm-json-definition'
  • Parameters:
    • name - name of FSM definition
    • 'fsm-json-definition' - a json object with the definition for FSM, more info see here
  • Returns:
    • a fsm definition transaction which txid will be the 'fsmdefinitionid' in the call to fsmcreate rpc

fsmcreate

fsmcreate - creates and run a fsm instance based on a fsm definition.

  • Call:
    • fsmcreate fsmdefinitionid singleton=yes|no 'json-parameters'
  • Parameters:
    • singleton=yes|no - to allow or not more than one instance creation
    • 'json-parameters' - a json object with parameters for the FSM instance (like {"fundsaddress":"RG2nTYFBPTJafxQ6en2dhUgaJcMDk4RWec"})
  • Returns:
    • fsminstance creation transaction which txid is a fsminstanceid

fsmcreatetransition

fsmcreatetransition - creates a state transition transaction (for a dapp evaluating the FSM instance). The fsmcreatetransition rpc determines the current FSM state and searches if a event has occured which should move the FSM to the next state.
(TODO: what to do, if several events have occured for this moment when fsmcreatetransition is called? set priority?)
If such a event has occured the method returns a state transition transaction. The FSM validation code will also validate the state transition transaction to allow the transaction to be added to the chain.

  • Call:
    • fsmcreatetransition fsminstanceid
  • Parameters:
    • fsminstanceid - txid of tx created by the fsmcreate rpc
  • Returns:
    • state transition tx

fsminstanceinfo

fsminstanceinfo - returns info about fsminstance (current state).

  • Call:
    • fsminstanceinfo fsminstanceid
  • Parameters:
    • fsminstanceid - txid of tx created by fsmcreate rpc
  • Returns:
    • returns info about FSM instance including current state and preceding events

Parameter 'fsm-json-definition' decomposition

fsm-json-definition is a json object which defines a FSM states, events and the transition map. fsm-json-definition structure:

{
   {"states": [{"id":"<state-id>", "name":"<name>"},...]},
   {"events": [
       {"id":"<event-id>", "name":"<name>", "time-event-expression(opt)":"<time-event-expression>", "change-event-expression(opt)":"<change-event-expression>", "message-event-funcid":"<funcid>"},
       ...
   ]},
   {"transitions": [
       {"event":"<event-id>", "source-state":"<state-id>", "next-state":"<state-id>", "guard(opt)":"<guard-expression>", "action":"<action-expression>" },
       ...
   ]}
}

Note: (opt) means 'optional'.

Internal Events description

Internal events are those that occur inside the chain.
According to UML2 standard there are following types of events possible:

  • Time Events - which occur at the specified moment or after a duration. To specify this Time-Event Expressions are used (see below)
  • Change Events - occur when some value inside the blockchain has been changed. A Change Event is defined with a logical expression. It is important that a change event are not reused again, for this a transaction which creates a event should have a marker that could be spent by FSM Dapp.
  • Message Events - in UML standard message events occur when a sender requests something from a receiver by sending a message. UML defines message event specializations as either 'Call For Operation' or 'Signal Receipt' cases. In FSM CC Module a message event is either a transaction requesting transfer of coins from some shared CC address (in this case a message event could be defined as a 'Transfer Request' event) or a transaction in mempool which should be validated (in this case a message event could be defined as a 'Spend Request' event). In case of 'Spend Request' transaction validation rules are specified by defining guard conditions.

UML requires that events should be consumed by the State Machine and become not available any more after this. For the FSM CC module this is actual for Change Events, so a transaction with a change event should have a spendable vout which is spent by the event processing dapp.

External Events description

TODO: External Events description

Expressions

Expression are used in following cases:

  • Guard Expression is a boolean Expression which, if evaluates to true, indicates that transition can be done.
  • Time-Event Expression is a boolean Expression which, if evaluates to true, indicates time event has occured.
  • Action Expression is defined for transition action and is executed while the FSM is in a transition from a state to state. An Action Expression allows to make actions on blockchain artefacts in response to the event which caused this transition.

Expressions support a set of operations on blockchain artefacts, variables, function return values and constants.

Supported operators (in priority order):

  • () grouping operator
  • +, -, /, * arithmetic operators on numeric operands
  • >, >=, <, <= comparison operators on numeric operands
  • ==, != equality operators on any operands
  • &, |, ! logical operators
  • if(expr, true-expr, false-expr) operator which, if 'expr' evaluates to true, runs 'true-expr', else runs 'false-expr'. Returns the value of the evaluated expression
  • = assignment operator allows to create and set value of a variable for its further reading in the same expression
  • ; expression separator in multi-expression.

Operands could be following:

  • variables in fsmdefine rpc which values are assigned with fsminstance parameters
  • preset variables which values obtained from the blockchain (like 'CurrentHeight')
  • variables defined in expressions
  • constants defined in expressions
  • return values of supported function calls
  • other expressions.

If any errors occur in a logical expression, the result of the expression should evaluate to false.

Blockchain Artefacts used in Expressions

Blockchain Artefacts are named concepts from the blockchain which can be used in Expressions. Each such concept represents a basic type in Expressions. The following Expression basic types, which derived from the blockchain artefacts, are supported:

  • 'string' - string value
  • 'amount' - amount (numeric)
  • 'address' - blockchain address type
  • 'height' - block height (numeric)
  • 'time' - unix time in seconds (numeric)
  • 'txid' - transaction id
  • 'tx' - transaction object
  • 'TxOut' - a pair of txid and vout number
  • 'Pubkey' - public key
  • 'PubKeySet' - a set of pubkeys (actually a signed json array) which is used to verify signatures in transactions or messages
  • 'JSON' - a json object which values are addressable with a JSON Pointer expression

Functions which can be used in Expressions

FSM CC functions which may be used in Expressions:

  • AddressLatestTxOut(address) - returns the latest txOut for the address
  • TransferCoins(sourceAddress, destAddress, amount) - transfers amount of coins on a source address to destination address
  • TxOutIsSpent(TxOut) - returns true if txOut is spent
  • TxOutAddress(TxOut) - returns address for txOut
  • TxOutTime(TxOut) - returns time in seconds for the block where txOut is mined
  • TxOutHeight(TxOut) - returns block height where txOut is mined
  • TxOutIsCC(TxOut) - returns true if txOut is a cryptocondition
  • TxCheckSignature(txid, PubKeySet, M) - checks multiple signatures on a transaction with txid, uses PubKeySet parameter for verification, returns true if at least M signatures are valid
  • TxFuncId(tx) returns funcid from the transaction opreturn
  • TxCCVinHasPubkey(tx, Pubkey) - returns true if one or more cc vin contains Pubkey
  • CCAddressAmount(address) - calculates amount on address taking into account cc transactions. The cc transactions must be valid to be accounted (that is, with ExactAmounts for cc inputs and cc outputs function evaluating to true)
  • NormalAddress(Pubkey) - returns normal address for pubkey
  • CCAddress(Pubkey) - cc address for pubkey
  • AmountForPubkey(address, Pubkey) - returns amount which was sent to this address by the transactions funded with this Pubkey (NOTE: it could be several source pubkeys in the same transaction)
  • ChangePubkeySet(PubkeySet, PubkeySetReplacing) - changes a pubkey set using the provided replacement pubkeys, the replacing PubKey set should be signed with majority of pubkeys in the actual PubkeySet
  • FindTransactionByFuncId(funcid) - finds a transaction by its marker and funcid symbol in the opreturn output. Used to find arbitary transactions, for example, with json messages inside the opreturn output

JSON Functions:

  • JSONFromTxOpReturn(tx) - extracts json message from transaction opreturn output
  • JSONCheckSignature(JSON) - checks signatures in a signed json object (according to RFC7515). A signed json is a json object which contains a signature or multisignature properties and a payload property (see RFC7515)
  • JSONPayload(JSON) - returns a json object stored inside a signed json object payload (as in RFC7515)
  • JSONValue(JSON, stringJsonPointer) - returns value from a json object denoted with json pointer (RFC6901)

Preset Variables

Variables with preset values which are available in Expressions:

  • CurrentState - current FSM state
  • CurrentHeight - chain's current height
  • CurrentTime - time of the latest block in seconds, since 1970-01-01 (unix time)
  • BlockTime - block generation interval in seconds
  • StateTimeout - time in seconds since the transition into the current state
  • FSMCCAddress - FSM global CC address
  • FSMInstanceId - txid of current fsminstance
  • EvalTx - currently validated transaction

How to use FSM CC Module

The FSM module allows to create new smart contracts which could be modelled as finite state machine. For developing a smart contract which is based on FSM, instead of implementing each time an ad-hoc state machine inside a new CC module, it is necessary to create an appropriate FSM definition with fsmdefine rpc call and then create FSM instances with fsmcreateinstance call.

Examples

Example 1: Heir FSM

The FSM definiton for a Heir FSM which allows for the heir to spend funds locked by the owner after the owner's inactivity time:

Parameters:

  • OwnerPK
  • HeirPK
  • Funds1of2Address
  • Timeout - OwnerPK inactivity on Funds1of2Address timeout value

States:

  • 'Funds Added'
  • 'Funds Allowed to Spend for HeirPK'

Events:

  • 'OwnerPK Inactive for Timeout'
    • event-type: time-event
    • time-event Expression:
      CurrentTime - TxOutTime( AddressLatestTxOut(Funds1of2Address) ) > Timeout
  • 'Spend Request Tx'
    • event-type: message event
    • message-event Funcid: 'C'

Transition map:

  • 'Funds Added' -> 'Fund Allowed to Spend for HeirPK'
    • event: 'OwnerPK Inactive for Timeout'
  • 'Funds Added' -> 'Fund Added'
    • event: 'Spend Request Tx'
    • guard:
      TxCCVinHasPubkey(EvalTx, HeirPK)
  • 'Funds Allowed to Spend for HeirPK' -> 'Funds Allowed to Spend for HeirPK'
    • event: 'Spend Request Tx'
    • description: spending funds by any PK (1of2 cryptocondition will also provide only either of both PK spends)
    • guard: none

Example 2: Cashier FSM

Cashier FSM allows a pubkey to make a deposit of coins into a pool address (where several pubkeys could make deposits) and then it allows to make cashout of coins within the limit of the attested balance. Balance is attested by at least M from N of attestors public keys. The attestors public keys are passed at the Cashier FSM instance creation and may be changed after.

Parameters:

  • 'Pubkey' - depositor pubkey
  • 'PoolAddress' - a chain address where deposits are sent from several Cashier FSM instances
  • M - min number of valid signatures for multi-signature transaction validation
  • N - attestors-pubkeys size
  • 'AttestorPubkeys' - PubKeySet with attestors' public keys which sign the json message with the cashout balance

States:

  • 'Initial State' - Pubkey is sending coins to its cc address
  • 'Deposit Done' - Pubkey transferred coins from its cc address to the PoolAddress
  • 'Pubkey Cashout Allowed' - withdraw from the PoolAddress is allowed for PubKey within the attested balance
  • 'Pubkey Refund Allowed' - withdraw from the PoolAddress of the previously deposited amount is allowed for the Pubkey

Events:

  • 'Timeout'
    • event-type: time-event
    • description: if time from the state 'Deposit Done' is more than specified Timeout then transition to 'Pubkey Refund Allowed'
    • time-event Expression: StateTimeout > Timeout
  • 'Pubkey Requests Refund'
    • event-type: message-event
    • description: Pubkey requests refund the deposited amount back to the Pubkey
  • 'Pubkey Requests Cashout'
    • event-type: message-event
    • description: if a message with the attested balance exists then transition to 'Pubkey Cashout Allowed'

Transition Map:

  • 'Deposit Done' -> 'Pubkey Refund Allowed'
    • event: 'Timeout'
  • 'Pubkey Refund Allowed' -> 'Pubkey Refund Done'
    • event: 'Pubkey Requests Refund'
    • guard: checks that 'Deposited Amount is more than 0'
    • guard expression:
      MyDeposit = AmountForPubkey(PoolAddress, Pubkey), if(MyDeposit > 0, 'true', 'false')
    • action: transfer coins of deposited amount back to Pubkey which deposited it
    • action expression:
      TransferCoins(Pubkey, MyDeposit)
  • 'Deposit Done' -> 'Pubkey Cashout Done'
    • event: 'Pubkey Requests Cashout'
    • guard: checks that 'Attested balance' is more than 0
    • guard expression:
      SignedMessage = JSONFromTxOpReturn(FindTransactionByFuncId('S')); SigValid = JSONCheckSignature(SignedMessage, AttestorPubkeys, M); MyAttestedBalance = JSONValue(JSONPayload(jsigned), '/balance')); if(SigValid & MyAttestedBalance > 0, 'true', 'false')
    • action: transfer to Pubkey the amount of 'Attested Balance' from PoolAddress
    • action expression:
      TransferCoins(PoolAddress, NormalAddress(Pubkey), MyAttestedBalance)

Example 3: Payments FSM

Payments FSM allows for a Pubkey to send some funds to a PaymentAddress. Spending from the address is locked until an external release event or timeout event has occurred.

Parameters:

  • Pubkey
  • PaymentAddress
  • Timeout - timeout for external 'Funds Released' events

States:

  • 'Funds Added'
  • 'Funds Released'
  • 'Funds Returned because of Timeout'

Events:

  • 'Pubkey deposited coins'
    • event-type: change-event
    • description: funds transferred with cc transaction from Pubkey to Payments Address
  • 'No events for Timeout'
    • event-type: time-event
    • event-expression:
      CurrentTime - TxOutTime( FSMLatestEvent(FMSInstance) ) > Timeout"
  • 'Permission to Withdraw'
    • event-type: external-event
    • description: event with the event-code of permission to withdraw
  • 'Spend Request Tx'
    • event-type: message-event
    • description: transaction to spend from PaymentAddress
    • event-funcid: 'C'

Transition map:

  • 'Funds Added' -> 'Funds Returned to PubKey'
    • event: 'No events for timeout'
    • action: 'Return funds to Pubkey from PaymentAddress'
    • action expression:
      TransferCoins(PaymentAddress, NormalAddress(Pubkey), CCAddressAmount(PaymentAddress))
  • 'Funds Added' -> 'Funds Released'
    • event: 'Permission to Withdraw'
  • 'Funds Released' -> 'Funds Empty'
    • event: 'Spend Request Tx'
    • guard: none

FSM CC Module Implementation Suggestions

Architecture

There are following architecture components that form the FSM CC module:

  • Dapp - an application external to blockchain which scans chain and detects change amd time internal events and external events
  • 'Spend Request' message events are transactions in mempool ('Spend Request' events), their processing is performed inside FSM CC validation code. As any events in UML StateMachine specification, such message events will cause state transitions. Treating transactions in mempool as events allows to use transition guard conditions as tx validation rules (see the examples above)
  • To evaluate guard, time-event, change-event and action Expressions an expression parsing and evaluating module should be developed as a component of the FSM CC Module. Also basic functions should be developed to support Expressions.

The FSM CC Module architecture is depicted on the diagram:

As it is shonw on the architecture diagram, the event processing in FSM CC is done both in the FSM Dapp and FSM CC validation code. The FSM CC validation code is responsible for processing of message events ('Spend Request' transactions in mempool). If guard condition evaluates to true, the FSM CC validation code should create a state transition transaction.

FSM CC Module basic features:

  • The state processing code should check by default for each transition if FSM is in allowed state for this transition and evaluate the guard and/or action (if any set)
  • The FSM Module should by default distinguish FSM instances (so no need to add such expressions into FSM definitions). For this each transaction should contain fsm-instance-id in the opreturn
  • The FSM Module should by default identify and find message event tx by funcid
  • The FSM Module validation code should check all state transitions validity.

'Spend Requests' Message Events

'Spend Requests' events are transactions in mempool waiting for validation. They are often transition from a current state to self with spending some value. The FSM validation code would use the Guard condition to check if the tx is valid. 'Spend Requests' in UML State Machine terms could be named as 'Call For Validation' events (similar to 'CallEvent' subclass of the 'Message Event' classifier). To identify a transaction inside the FSM CC validation code as a 'Spend Request' the funcid in the tx opreturn is used.

FSM CC Module Expressions Development Suggestions

The expression parser could be implemented with the use of 'Shunting Yard' algorithm or 'Recursive Descent' algorithm. In case of Recursive Descent a formal grammar should be defined for expression language. A variant object type should be used internally to represent basic types which are allowed in expressions.

There is a nice and very advanced library for creating new languages - cparse. Its MIT license allows to extend it and use in open source projects. It has Shunting Yard algorithm-implemented parser and expression calculator and provides adding new basic and compound types, operations and functions. It has all features for implementation of FSM Module Expressions.

Clone this wiki locally