ocap money in scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** 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 | |
*/ | |
abstract class Purse { // should this go inside Mint somehow? | |
def getBalance(): Int // hmm... num type? typeclass trick? | |
def sprout(): Purse | |
def getDecr(): Object | |
def deposit(amount: Int, src: Purse) | |
} | |
class Mint(name: String) { | |
private val mint = this; | |
private val brand = new Brand[Function1[Int, Unit]](name) | |
override def toString(): String = "<#" + name + "'s mint>" | |
def makePurse(initialBalance: Int): Purse = { | |
assert(initialBalance >= 0) | |
var balance = initialBalance | |
val decr: Function1[Int, Unit] = { case (amount: Int) => | |
assert(0 < amount && amount < balance) | |
balance -= amount | |
} | |
val purse = new Purse { | |
override def toString() = "<has #{" + balance + "} #{" + name + "} bucks>" | |
def getBalance() = balance | |
def sprout() = mint.makePurse(0) | |
def getDecr() = brand.sealer.seal(decr) | |
def deposit(amount: Int, src: Purse) { | |
brand.unsealer.unseal(src.getDecr())(amount) | |
balance += amount | |
} | |
} | |
return purse | |
} | |
} | |
/** Rights amplification | |
cf. http://wiki.erights.org/wiki/Walnut/Secure_Distributed_Computing/Capability_Patterns | |
*/ | |
trait Sealer[T] { | |
def seal(it: T): Object | |
} | |
trait Unsealer[T] { | |
def unseal(x: Object): T | |
} | |
class Brand[T](hint: String) { | |
private var shared: Option[T] = None | |
override def toString() = "<brand: " + hint + ">" | |
class SealedBox(obj: T) { | |
def shareContent() { shared = Some(obj) } | |
override def toString() = "<sealed " + hint + " box>" | |
} | |
val sealer = new Object with Sealer[T] { | |
def seal(it: T) = new SealedBox(it) | |
override def toString() = "<sealer: " + hint + ">" | |
} | |
val unsealer = new Object with Unsealer[T] { | |
override def toString() = "<unsealer: " + hint + ">" | |
def unseal(x: Object): T = { | |
x match { | |
case box: SealedBox => { | |
shared = None | |
box.shareContent() | |
shared match { | |
case Some(content) => { | |
shared = None | |
content | |
} | |
case _ => throw new IllegalArgumentException("invalid box") | |
} | |
} | |
case _ => throw new IllegalArgumentException("ill-typed box") | |
} | |
} | |
} | |
} | |
object ocap_money extends Application { | |
// eyeball-test makeBrandPair | |
val b = new Brand[String]("bob") | |
val x = b.sealer.seal("abc") | |
println(x) | |
println(b.unsealer.unseal(x)) | |
// example from ode-capabilities.html | |
val carolMint = new Mint("Carol") | |
println(carolMint) // value: <Carol's mint> | |
//println(carolMint.name) // does this compile? no. good. | |
val aliceMainPurse = carolMint.makePurse(1000) | |
println("alice has: " + aliceMainPurse) // value: <has 1000 Carol bucks> | |
val bobMainPurse = carolMint.makePurse(0) | |
println("bob has: " + bobMainPurse) // value: <has 0 Carol bucks> | |
println("transfer 50 from alice to bob.") | |
bobMainPurse.deposit(50, aliceMainPurse) | |
println("alice has: " + aliceMainPurse) | |
println("bob has: " + bobMainPurse) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment