[cap-talk] where(), and a mobile-code JS-over-Python experiment

Brian Warner warner at lothar.com
Sun Apr 11 13:46:00 PDT 2010


Tom Van Cutsem wrote:
> 
> Purely coincindentally, MarkM and I discussed an alternative semantics
> of 'where' for Javascript yesterday. In a nutshell:
> 
> var promise = try (x = <exp1>, y = <exp2>, ...) in ( farCompute ) {
>   ... x ... y ...
>   => <exp3>
> }

I like it. The farCompute object's apply() method could have a guard
that asserts properties of the AST it receives (like loop-free, q.v. my
other response on this subject). I think I'd want a convenience shortcut
in the environment-record construction, though, to make:

 var promise = try(x,y) in (farCompute) {
   return x+y
 }

be equivalent to:

 var promise = try(x=x,y=y) in (farCompute) {
   return x+y
 }

> The body of the 'try-in' statement should not contain any free
> variables (apart from maybe a small set of primordials?), so in
> principle this code can only communicate with either its originating
> or its recipient vat through the references that were explicitly
> listed in the try-in statement's "head".

I think that's an important property (and benefit) of try-in() over
where(). The where() clause, by capturing references to its free
variables, makes it awfully easy to accidentally reveal secret or
sensitive values to the remote Vat. Putting a barrier in place (the
environment-map (x=exp1,y=exp2) clause) provides a clear visual
demarcation of what will and will not be revealed to external parties.

For example, imagine you wanted to send a bag of pennies along with your
DB query function, so it could pay for its access, and you wanted to
merge the remaining pennies back into your main purse when you're done.
Accidentally revealing the purse to the remote Vat would give that Vat
the ability to drain the purse (even if you don't give the purse to the
database reference directly). The try-in clause would protect the
author, but the where clause would not:

  def some_pennies := my_money.withdraw(LITTLEMONEY)
  where(dbref) {
    dbreq.run_expensive_query(query, some_pennies)
    ... # do complicated, round-trip-intensive stuff
    ... # commit the transaction
    my_money.reabsorb(some_pennies) # oops
  }

versus:

  def some_pennies := my_money.withdraw(LITTLEMONEY)
  try (dbref, some_pennies) in (dbref <- getComputeRef()) {
    dbreq.run_expensive_query(query, some_pennies)
    ... # do complicated, round-trip-intensive stuff
    ... # commit the transaction
    my_money.reabsorb(some_pennies) # saved by compile-time error
  }

The "right" way to do this, of course, would involve an extra when()
block to reabsorb the money locally:

  def some_pennies := my_money.withdraw(LITTLEMONEY)
  def done := try (dbref, some_pennies) in (dbref <- getComputeRef()) {
    dbreq.run_expensive_query(query, some_pennies)
    ... # do complicated, round-trip-intensive stuff
    ... # commit the transaction
  }
  when (done) {
    my_money.reabsorb(some_pennies) # saved by compile-time error
  }

As for the primordials, that's tricky. You want the far object to behave
predictably. There are a set of objects that all E programs have access
to (basic data types, etc). A very strict try-in implementation would
obligate the programmer to declare their intention to grant access to
even these built-in objects, by including them in the environment-map.
An easier-to-use one would say that everything available to all E
programs (say, the environment that exists on the first line of the
program) is also available to the remote code. The difference between
the local implementations of these objects and the remote host's
versions is probably important to keep track of.

I'd also compare when() and try-in() on the basis of how the
objects-revealed-to-remote-Vat are made visually obvious. A reviewer
needs to be able to tell what is kept locally and what is revealed to
others. The try-in clause looks a little too much like a normal
try-catch clause (you'd want your editor's syntax-highlighter to make
that "in" keyword really stand out), but at least all of the revealed
references are contained on a single line next to the critical "in"
keyword. The where() clause is more distinct (the "where" keyword is on
the left edge, whereas "in" is buried somewhere in the middle of the
line), but then it takes a lot of manual inspection to figure out which
references are being revealed.

(it would be nice to have an editor which either highlighted the entire
try-in environment map, or identified and highlighted the free variables
in the where() block, to bring them to the attention of the
developer/reviewer)

Perhaps "send-to" instead of "try-in" ? Nope, "to" is already claimed.
"run-on" ? nope. "run-at", "deliver-to", "execute-where".. can't think
of anything better.

cheers,
 -Brian


More information about the cap-talk mailing list