purse deposit and the Cambio

Mark S. Miller markm@caplet.com
Sat, 19 Jun 1999 00:27:30 -0700


At 05:29 PM 6/18/99 , Ka-Ping Yee wrote:
>Precontext: this is a response to MarkM's ERTP, a wonderfully
>minimal and simple spec that he showed me last night; specifically
>it's about the Cambio example he uses to illustrate ERTP.

[#] The original example.
For those who haven't already looked at erights.updoc  
http://www.erights.org/smart-contracts/erights-updoc.txt here's the original 
Cambio example, minus the printing method that's also left out of Ping's 
responses:

  define CambioMaker(inPurse, outPurse, in2out) {
      define Cambio {
          to changeMoney(srcPurse) {
              define inAssay := inPurse depositAll(srcPurse)
              define outAssay := in2out(inAssay)
              define destPurse := outPurse getIssuer makePurse
              try {
                  outAssay transfer(outPurse, destPurse)
              } catch ex {
                  inAssay transfer(inPurse, srcPurse)
                  throw ex
              }
              destPurse
          }
      }
  }



>Postcontext: there is a comment about naming the deposit method
>here, but the rest of the message is really about a more general
>issue of transaction management and atomicity.  

[#] deposit* direction in this message, atomicity in the next.


>Date: Fri, 18 Jun 1999 03:30:11 -0700 (PDT)
>From: Ka-Ping Yee <ping@lfw.org>
>
>On the way home, i realized that it might be best to make
>the method name "depositInto" rather than "depositAll" or
>"depositFrom".  Motivations:
>
>    1.  People are used to source first, destination second.
>        In your Assay transfer method, you go along with this
>        convention.  It seems natural to use the same ordering
>        for transferring an entire purse's contents also.
>        So: sourcePurse depositInto(destPurse).
>
>    2.  When you talk about capabilities the "feel" i get is
>        that you are calling a method on the thing whose
>        rights you want to invoke.  I know that in this case,
>        the two purses are in cahoots and are simply agreeing
>        to do the transfer with each other, but it still feels
>        right to be calling the method on the thing that has
>        the rights i am invoking, i.e. the purse from which i
>        am *withdrawing* the rights.  It makes more sense to
>        me to say to the sourcePurse, "please give your rights
>        to this other purse here", rather than saying to the
>        destPurse, "please steal some rights from this purse".
>        (Or, in fewer words, Alice first.)

[-] "depositInto" gets the trust issues wrong.

First, I accept your earlier suggestion that "depositFrom" is a strict 
naming improvement over "depositAll" (same semantics, but makes the 
direction clear).  Now, contrast:

  define CambioMaker(inPurse, outPurse, in2out) {
      define Cambio {
          to changeMoney(srcPurse) {
              define inAssay := inPurse depositFrom(srcPurse)
with

  define CambioMaker(inPurse, outPurse, in2out) {
      define Cambio {
          to changeMoney(srcPurse) {
              define inAssay := srcPurse depositInto(inPurse)

In the first (the original with the renaming) the Cambio is trusting inPurse 
to do the transfer a payment and to report what transfer has been made.  In 
the second, the Cambio is trusting srcPurse to do this.  inPurse is provided 
by the instantiator of the Cambio (whom the Cambio implicitly trusts), 
whereas srcPurse is provided by the Cambio's untrusted customers.  A proper 
Purse indeed checks that the two Purses are in cahoots (ie, issued by the 
same Issuer), but the Cambio is depending on the receiver Purse to check 
this property about the argument Purse.

Given a Cambio for turning JoeBucks into BettyBucks that uses the second 
"depositInto" code block above, a dishonest customer, Darth, could make the 
following request:

  define MyJoeBucksPurse := JoeBucks makePurse

  define DarthPurse {
      to depositInto(dest) {
          # don't deposit anything into dest, but steal all its assets
          dest despositInto(MyJoeBucksPurse)
          # and claim we deposited 300 JoeBucks
          JoeBucks makeAssay(300)
      }
      ...
  }

  define MyBettyBucksPurse := JBCambio changeMoney(DarthPurse)

Not only does Darth get all the JoeBucks previous customers had paid to this 
Cambio, Darth also gets all the BettyBucks that this Cambio pays in exchange 
for 300 JoeBucks.  The contrast between these two blocks of code is probably 
a good example for explaining capability programming principles.

Since the next message is about atomicity and not deposit direction, in 
answering I will revise the quoted parts of your message to use depositFrom 
rather than depositInto.


	Cheers,
	--MarkM