Skip to content

Instantly share code, notes, and snippets.

@dckc
Last active May 19, 2017 04:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dckc/a49b51bbe014f09ab8f762d377f71958 to your computer and use it in GitHub Desktop.
Save dckc/a49b51bbe014f09ab8f762d377f71958 to your computer and use it in GitHub Desktop.
// transcription of money example from "Smart Contracts"
// http://www.erights.org/smart-contracts/index.html
// http://www.erights.org/elib/capability/ode/ode-capabilities.html
// http://www.madmode.com/2011/11/capability-security-in-e-coffescript.html
// https://bitbucket.org/DanC/coffee-craft/src/682d06f02e99/money.coffee?fileviewer=file-view-default
// typealias not allowed inside class
typealias Decr = (Int) -> Unit
class Mint(val name: String) {
// destructuring assignment can only be used on local vars :-/
val sealer: Sealer<Decr>
val unsealer: Unsealer<Decr>
init {
val (s, u) = Brand<Decr>(name).run()
sealer = s
unsealer = u
}
inner class Purse(bal: Int) { // balance clashes with getBalance
override fun toString(): String = "<has $current $name bucks>"
var current: Int
init {
require(bal >= 0)
current = bal
}
val decr = { amount: Int ->
require(0 < amount && amount <= current)
current -= amount
}
fun getBalance(): Int = current
fun sprout() = Purse(0)
fun getDecr() = sealer.seal(decr)
fun deposit(amount: Int, src: Purse) {
unsealer.unseal(src.getDecr())(amount)
current += amount
}
}
override fun toString(): String ="<${name}'s mint>"
}
// let's see if I remember how to do this...
// nope. looked it up:
// http://wiki.erights.org/wiki/Walnut/Secure_Distributed_Computing/Capability_Patterns
// https://www.cypherpunks.com/erights/javadoc/org/erights/e/elib/sealing/Brand.html
interface SealedBox<T> {
fun shareContent()
}
interface Sealer<T> {
fun seal(obj: T): SealedBox<T>
}
interface Unsealer<T> {
fun unseal(box: SealedBox<T>): T
}
class Brand<T>(hint: String) {
private var shared: Option<T> = Option.None
private var contents: T? = null
inner class MySealedBox constructor(val it: T) : SealedBox<T> {
override fun toString(): String ="SealedBox()"
override fun shareContent() {
val s = Option.Some(it)
shared = s
}
}
inner class MySealer : Sealer<T> {
override fun seal(it: T): SealedBox<T> = MySealedBox(it)
}
inner class MyUnsealer : Unsealer<T> {
override fun unseal(box: SealedBox<T>): T {
shared = Option.None
box.shareContent()
// val s to avoid
// Error:(86, 35) Kotlin: Smart cast to 'Option.Some<T>' is impossible,
// because 'shared' is a mutable property that could have been changed by this time
val s = shared
contents = when (s) {
is Option.None -> throw IllegalStateException("invalid box")
is Option.Some -> s.value
}
shared = Option.None
return contents!!
}
}
fun run(): Pair<Sealer<T>, Unsealer<T>> {
return Pair(MySealer(), MyUnsealer())
}
}
// https://hackernoon.com/kotlin-functors-applicatives-and-monads-in-pictures-part-1-3-c47a1b1ce251
sealed class Option<out A> {
object None : Option<Nothing>()
data class Some<out A>(val value: A) : Option<A>()
inline fun <B> map(f: (A) -> B): Option<B> = when (this) {
is None -> this
is Some -> Some(f(value))
}
}
fun main(args: Array<String>) {
// eyeball-test makeBrandPair
val (s, u) = Brand<String>("bob").run()
val x = s.seal("abc")
println(x)
println(u.unseal(x))
// example from ode-capabilities.html
val carolMint = Mint("Carol")
println(carolMint)
// value: <Carol's mint>
val aliceMainPurse = carolMint.Purse(1000)
println(aliceMainPurse)
// value: <has 1000 Carol bucks>
val bobMainPurse = carolMint.Purse(0)
println(bobMainPurse)
// value: <has 0 Carol bucks>
val paymentForBob = aliceMainPurse.sprout()
// value: <has 0 Carol bucks>
paymentForBob.deposit(10, aliceMainPurse)
//Then, we send a foo request to Bob, providing the purse containing $10 as payment:
// bob.foo(..., paymentForBob, ...)
//What might Bob's foo method look like?
class Bob {
// ...
//fun foo(payment: Purse) ... {
// bobMainPurse.deposit(10, payment)
// # proceed only if we got $10
// ...
}
// So playing Bob, we perform
bobMainPurse.deposit(10, paymentForBob)
// Our new balances are
println(bobMainPurse.getBalance())
// value: 10
println(aliceMainPurse.getBalance())
// value: 990
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment