Commits

Dan Connolly committed 682d06f

reproduced the E money example in coffeescript

  • Participants
  • Parent commits e2a4879

Comments (0)

Files changed (2)

File money.coffee

+# 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
+
+# ugh... in tracebacks, node.js gives .js line numbers, not .coffee
+
+
+# js doesn't have immutable function args, does it?
+# Guards can be translated to assert, but it's a little messy.
+
+assert = require('assert')
+
+makeMint = (name) ->
+  [sealer, unsealer] = makeBrandPair(name)
+  mint = {
+    __printOn: (out) ->
+      out.print("<#{name}'s mint>")
+
+    makePurse: (balance) ->
+      assert.ok(typeof balance == 'number' && balance >= 0)
+
+      decr = (amount) ->
+        assert.ok(0 < amount && amount < balance)
+        balance -= amount
+
+      purse = {
+        __printOn: (out) ->
+          out.print("<has #{balance} #{name} bucks>")
+        getBalance: () -> balance
+        sprout: () -> mint.makePurse(0)
+        getDecr: () -> sealer.seal(decr)
+
+        deposit: (amount, src) ->
+          assert.ok(typeof amount == 'number')
+          unsealer.unseal(src.getDecr())(amount)
+          balance += amount
+        }
+      return purse
+  }
+  return 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
+makeBrandPair = (hint) ->
+  noObject = new Object()
+  shared = noObject
+  content = null
+  makeSealedBox = (obj) -> { shareContent: () -> shared = obj }
+
+  sealer = {
+    seal: (it) -> makeSealedBox(it)
+  }
+  unsealer = {
+    unseal: (box) ->
+      shared = noObject
+      box.shareContent()
+      if (shared == noObject)
+        throw new Error('invalid box')
+      contents = shared
+      shared = noObject
+      contents
+  }
+  return [sealer, unsealer]
+
+
+# eyeball-test makeBrandPair
+[s, u] = makeBrandPair('bob')
+x = s.seal('abc')
+console.log(x)
+console.log(u.unseal(x))
+
+# connect the dots between node.js's console
+# and http://wiki.erights.org/wiki/TextWriter
+out = {
+  print: (s) -> console.log(s)
+}
+
+# example from ode-capabilities.html
+carolMint = makeMint("Carol")
+carolMint.__printOn(out)
+# value: <Carol's mint>
+
+aliceMainPurse = carolMint.makePurse(1000)
+aliceMainPurse.__printOn(out)
+# value: <has 1000 Carol bucks>
+
+bobMainPurse = carolMint.makePurse(0)
+bobMainPurse.__printOn(out)
+# value: <has 0 Carol bucks>
+
+
+# struggling to figure out node.js module conventions
+# I think module caching threw me off.
+exports.makeBrandPair = makeBrandPair
+exports.makeMint = makeMint
+(function() {
+  var aliceMainPurse, assert, bobMainPurse, carolMint, makeBrandPair, makeMint, out, s, u, x, _ref;
+  assert = require('assert');
+  makeMint = function(name) {
+    var mint, sealer, unsealer, _ref;
+    _ref = makeBrandPair(name), sealer = _ref[0], unsealer = _ref[1];
+    mint = {
+      __printOn: function(out) {
+        return out.print("<" + name + "'s mint>");
+      },
+      makePurse: function(balance) {
+        var decr, purse;
+        assert.ok(typeof balance === 'number' && balance >= 0);
+        decr = function(amount) {
+          assert.ok(0 < amount && amount < balance);
+          return balance -= amount;
+        };
+        purse = {
+          __printOn: function(out) {
+            return out.print("<has " + balance + " " + name + " bucks>");
+          },
+          getBalance: function() {
+            return balance;
+          },
+          sprout: function() {
+            return mint.makePurse(0);
+          },
+          getDecr: function() {
+            return sealer.seal(decr);
+          },
+          deposit: function(amount, src) {
+            assert.ok(typeof amount === 'number');
+            unsealer.unseal(src.getDecr())(amount);
+            return balance += amount;
+          }
+        };
+        return purse;
+      }
+    };
+    return mint;
+  };
+  makeBrandPair = function(hint) {
+    var content, makeSealedBox, noObject, sealer, shared, unsealer;
+    noObject = new Object();
+    shared = noObject;
+    content = null;
+    makeSealedBox = function(obj) {
+      return {
+        shareContent: function() {
+          return shared = obj;
+        }
+      };
+    };
+    sealer = {
+      seal: function(it) {
+        return makeSealedBox(it);
+      }
+    };
+    unsealer = {
+      unseal: function(box) {
+        var contents;
+        shared = noObject;
+        box.shareContent();
+        if (shared === noObject) {
+          throw new Error('invalid box');
+        }
+        contents = shared;
+        shared = noObject;
+        return contents;
+      }
+    };
+    return [sealer, unsealer];
+  };
+  _ref = makeBrandPair('bob'), s = _ref[0], u = _ref[1];
+  x = s.seal('abc');
+  console.log(x);
+  console.log(u.unseal(x));
+  out = {
+    print: function(s) {
+      return console.log(s);
+    }
+  };
+  carolMint = makeMint("Carol");
+  carolMint.__printOn(out);
+  aliceMainPurse = carolMint.makePurse(1000);
+  aliceMainPurse.__printOn(out);
+  bobMainPurse = carolMint.makePurse(0);
+  bobMainPurse.__printOn(out);
+  exports.makeBrandPair = makeBrandPair;
+  exports.makeMint = makeMint;
+}).call(this);