package models smartcontracts import StandardTypesConvers ions todo ma

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package models.smartcontracts
import StandardTypesConversions._
//todo: make ClauseParams case of it
abstract class State {
val name: String
override def equals(obj: scala.Any): Boolean = obj match{
case s : State => s.name == name
case _ => false
}
override def toString: String = name
}
abstract class InitState extends State
abstract class FinishState extends State
sealed trait Value {
val value: Any
}
case class StringValue(override val value: String) extends Value
case class LongValue(override val value: Long) extends Value
case class DoubleValue(override val value: Double) extends Value
object StandardTypesConversions{
implicit def string2StringValue(value : String) = StringValue(value)
implicit def stringValue2String(value : StringValue) = value.value
}
//todo: scheduling? (in application.properties?)
sealed abstract class Query[K, V <: Value] (val key:K) {
def query(): V
}
abstract class DNSQuery[V <: Value](val domain:StringValue) extends Query[StringValue, V](domain)
case class RegistrantQuery (override val domain:StringValue) extends DNSQuery[StringValue](domain) {
override def query(): StringValue = " "
}
sealed trait Predicate[V <: Value] {
val pattern: V
def matchPattern(value: V): Boolean
}
trait StringPredicate extends Predicate[StringValue]
case class StringIncludesPredicate(override val pattern: StringValue) extends StringPredicate {
override def matchPattern(value: StringValue) = value.value contains pattern.value
}
trait LongPredicate extends Predicate[LongValue]
trait DoublePredicate extends Predicate[DoubleValue]
sealed trait Action{
def process()
}
class ReleaseBitcoins extends Action{
def process() = ???
}
case class SendNxt(sender: Long, receiver: Long, amountNqt: Long) extends Action {
def process() = println(s"Sending nxts from $sender to $receiver")
}
class SendBitcoins extends Action {
def process() = ???
}
case class QueryAndCheck[K <: Value, V <: Value](query: Query[K, V], predicate: Predicate[V]){
def process() = predicate.matchPattern(query.query())
}
/**
* Smart Contract is like Finite State Machine structurally switching from a state to another state if predicate
* returns true. From functional point of view SmartContract is mapping between [ss:State,p:Predicate]
* and [a:Action,sf:State] sets. The structure is immutable, the only way to get modified object is to call doStep()
* returning modified contract
*/
abstract class SmartEscrow {
type Clause = (State, QueryAndCheck[_, _])
type Out = (Action, State)
val initState: InitState
val finishStates: Seq[FinishState]
val currentState: State
val transitions: Map[Clause, Out]
def doStep(): Option[State] = if (finished) None else {
val pt = transitions.filterKeys(_._1 == currentState)
pt.find { case ((_, qc), _) => qc.process()} match {
case Some(((state, qc), (action, stateToGo))) =>
action.process()
onTransition(qc.predicate, action, stateToGo)
Some(stateToGo)
case None => None
}
}
val finished = currentState match{
case _:FinishState => true
case _ => false
}
protected def onTransition(p: Predicate[_], a: Action, s: State) = println(s"State changed to $s")
}
case class DomainTransfer(domain:String, newOwner: String, sender: Long,
receiver: Long, amount: Long) extends SmartEscrow {
override val initState = new InitState {
override val name: String = "Waiting"
}
override val currentState = initState
val done = new FinishState {
override val name: String = "Done"
}
override val finishStates = Seq(done)
override val transitions:Map[Clause, Out] = Map(
(initState, QueryAndCheck(RegistrantQuery(domain), StringIncludesPredicate(newOwner)))
->(SendNxt(sender, receiver, amount), done)
)
}