User:Kevin Reid/Offline delegation

From Erights

< User:Kevin Reid
Revision as of 21:44, 22 November 2010 by Kevin Reid (Talk)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search

Mailing list post of this: [1]

# Copyright 2008 Kevin Reid, under the terms of the MIT X license
# found at http://www.opensource.org/licenses/mit-license.html ................

pragma.syntax("0.9")

# --- Utilities ---

def makeProxy := <elib:ref.makeProxy>
def makeBrand := <elib:sealing.makeBrand>

def everything {
  to contains(_) { return true }
}

# --- Signing ---

interface ::"Signed" guards SignedStamp {}

def makeSigner(label) {
  def who {
    to __printOn(out) {
      out.print("<", label, ">")
    }
  }
  def signer {
    to __printOn(out) {
      out.print("<signing as ", label, ">")
    }
    to who() { return who }
    to run(what) {
      def ::"signed" implements SignedStamp {
        to _who() { return who }
        to _get() { return what }
      }
      return ::"signed"
    }
  }
  return signer
}

def verifyAndGet(::"signed" : ::"Signed") {
  return [::"signed"._get(), ::"signed"._who()]
}

# --- Operations ---

def ::"delegate"(scap, filter, note) {
  def [cert, signer, host] := scap
  def newSigner := makeSigner(note)
  return [signer(["delegate", cert, newSigner.who(), filter]), newSigner, host]
}

/** Turn an object whose methods take an extra argument for the delegation chain into a scap. */
def exportOD(handler) {
  def rootSigner := makeSigner("export root")

  def handleMessage(delegators, verb :String, args :List, cert) {
    def [[=="delegate", prevCert, whoTo, filter], whoBy] := verifyAndGet(cert)
    if (!filter.contains(verb)) {
      throw(`$verb not permitted by $whoBy`)
    }
    
    def delegators1 := delegators.with(whoTo)
    return if (whoBy != rootSigner.who()) {
      handleMessage(delegators1, verb, args, prevCert)
    } else {
      E.call(handler, verb, [delegators1] + args)
    }
  }
  
  def host(verb, args, cert) {
    handleMessage([], verb, args, cert)
  }
  
  return [rootSigner(["delegate", Ref.broken("n/a"), rootSigner.who(), everything]), rootSigner, host]
}

/** Turn a scap into a normal invokable reference. */
def importOD(scap) {
  def [cert, signer, host] := scap
  return makeProxy(def handler {
    to handleSend(verb, args) {
      return host <- (verb, args, cert)
    }
    to handleSendOnly(verb, args) {
      return host <- (verb, args, cert)
    }
    to handleOptSealedDispatch(_) {}
  }, Ref.whenBroken(host, fn _ {Ref.optProblem(host)}), true)
}

# --- Example ---

def carol(x) {
  def xr := importOD(x)
  xr <- hello("world")
}

def bob(x) {
  def xr := importOD(x)
  when ( carol <- (::"delegate"(x, ["hello"].asSet(), "Carol")) ) -> {
    xr <- goodbye()
  }
}

def alice(x) {
  bob <- (::"delegate"(x, ["hello", "goodbye"].asSet(), "Bob"))
}


def root := exportOD(def root0 {
  to hello(chain, greeted) {
    println(chain, " greeted ", greeted)
  }
  to goodbye(chain) {
    println(chain, " said goodbye")
  }
})
alice(::"delegate"(root, ["hello", "goodbye"].asSet(), "Alice"))
Personal tools
more tools