[e-lang] Updated erights.updoc

Kevin Reid e-lang@mail.eros-os.org
Fri, 2 Jan 2004 19:05:17 -0500


At <http://www.erights.org/smart-contracts/>:

> ERTP is a simple protocol involving only 4 types and 9 methods. 
> erights.updoc shows money re-implemented as a proper eright.

I note that erights.updoc:
   * does not fit modern E syntax
   * does not follow the ERTP protocol as javadoc'd

Here's an updated version. I have not particularly checked it for 
security, only that updoc runs it with no complaints.

(I did make one unnecessary change: due to a vague memory of some old 
e-lang discussion, I made it use separate brands for each type of 
object it seals, so that they don't appear somewhat polymorphic. 
(Perhaps the getSealed methods should become __optSealedDispatch?))


? def makeBrand := <elib:sealing.Brand>
# value: <import:org.erights.e.elib.sealing.Brand>

? def makeMint(name) :any {
 >     def [assaySealer, assayUnsealer] := makeBrand(`$name assay`)
 >     def [purseSealer, purseUnsealer] := makeBrand(`$name purse`)
 >     def [incrSealer, incrUnsealer] := makeBrand(`$name incr`)
 >     def sturdyRefDuration := 1000 * 60 * 60 * 24 * 7
 >
 >     def issuer {
 >         to __printOn(oo) { oo.print(`<$name bucks>`) }
 >
 >         /** ERTP method */
 >         to vouchForAssay(item) :any {
 >             assayUnsealer.unseal(item.getSealed())
 >         }
 >
 >         /** ERTP method */
 >         to vouchForPurse(item) :any {
 >             purseUnsealer.unseal(item.getSealed())
 >         }
 >
 >         /** ERTP method */
 >         to sturdyVouchForAssay(item) :any {
 >             makeSturdyRef(issuer.vouchForAssay(item), timer.now() + 
sturdyRefDuration)
 >         }
 >
 >         /** ERTP method */
 >         to sturdyVouchForPurse(item) :any {
 >             makeSturdyRef(issuer.vouchForPurse(item), timer.now() + 
sturdyRefDuration)
 >         }
 >
 >         /** ERTP method */
 >         to makeEmptyPurse() :any {
 >             # NOTE: original code had the guard : (_ >= 0) on 
'balance', which does not work in current E.
 >             var balance := 0
 >             def incr(delta :int ? delta >= -balance) {
 >                 balance += delta
 >             }
 >
 >             def purse {
 >                 to __printOn(oo)     { oo.print(`<holds $balance 
$name bucks>`) }
 >                 /** ERTP method */
 >                 to getIssuer() :any  { issuer }
 >                 /** implementation detail */
 >                 to getSealed() :any  { purseSealer.seal(purse) }
 >
 >                 /** implementation detail */
 >                 to getIncr() :any    { incrSealer.seal(incr) }
 >                 /** ERTP method */
 >                 to getAssay() :any   { issuer.makeAssay(balance) }
 >                 to getBalance() :any { balance }
 >
 >                 /** ERTP method */
 >                 to depositAll(src) :any {
 >                     def assay := issuer.vouchForAssay(src.getAssay())
 >                     assay.transfer(src, purse)
 >                     assay
 >                 }
 >             }
 >         }
 >
 >         to makeAssay(amount :int ? (amount >= 0)) :any {
 >             def assay {
 >                 to __printOn(oo)    { oo.print(`<assays $amount $name 
bucks>`) }
 >                 /** ERTP method */
 >                 to getIssuer() :any { issuer }
 >                 /** implementation detail */
 >                 to getSealed() :any { assaySealer.seal(assay) }
 >
 >                 /** ERTP method */
 >                 to transfer(src, dest) :void {
 >                     def srcIncr := incrUnsealer.unseal(src.getIncr())
 >                     def destIncr := 
incrUnsealer.unseal(dest.getIncr())
 >                     srcIncr(-amount)
 >                     destIncr(amount)
 >                 }
 >                 /** ERTP method */
 >                 to compareTo(otherAssay) :any {
 >                     def vouchedOtherAssay := 
issuer.vouchForAssay(otherAssay)
 >                     amount.compareTo(vouchedOtherAssay.getAmount())
 >                 }
 >                 to getAmount() :any { amount }
 >             }
 >         }
 >     }
 >     def mint {
 >         to __printOn(oo) { oo.print(`<$name's Mint>`) }
 >         to getIssuer() :any { issuer }
 >
 >         to inflate(dest, amount) {
 >             def destIncr := incrUnsealer.unseal(dest.getIncr())
 >             destIncr(amount)
 >         }
 >     }
 > }
# value: <makeMint>

? def JoeMint := makeMint("Joe")
# value: <Joe's Mint>

? def JoeCurrency := JoeMint.getIssuer()
# value: <Joe bucks>

? def ThreeBucks := JoeCurrency.makeAssay(3)
# value: <assays 3 Joe bucks>

? def PurseA := JoeCurrency.makeEmptyPurse()
# value: <holds 0 Joe bucks>

? def PurseB := JoeCurrency.makeEmptyPurse()
# value: <holds 0 Joe bucks>

? ThreeBucks.transfer(PurseA, PurseB)
# problem: such-that expression was false

? [PurseA, PurseB]
# value: [<holds 0 Joe bucks>, <holds 0 Joe bucks>]

? JoeMint.inflate(PurseA, 100)
? JoeMint.inflate(PurseB, 200)
? [PurseA, PurseB]
# value: [<holds 100 Joe bucks>, <holds 200 Joe bucks>]

? ThreeBucks.transfer(PurseA, PurseB)
? [PurseA, PurseB]
# value: [<holds 97 Joe bucks>, <holds 203 Joe bucks>]

? def TwoBucks := JoeCurrency.makeAssay(2)
# value: <assays 2 Joe bucks>

? TwoBucks < ThreeBucks
# value: true

? PurseA.depositAll(PurseB)
# value: <assays 203 Joe bucks>

? [PurseA, PurseB]
# value: [<holds 300 Joe bucks>, <holds 0 Joe bucks>]

? def makeCambio(inPurse, outPurse, in2out) :any {
 >
 >     def cambio {
 >         to __printOn(oo) {
 >             oo.print(`<turning ${inPurse.getIssuer()} into 
${outPurse.getIssuer()}>`)
 >         }
 >         to changeMoney(srcPurse) :any {
 >             def inAssay := inPurse.depositAll(srcPurse)
 >             def outAssay := in2out(inAssay)
 >             def destPurse := outPurse.getIssuer().makeEmptyPurse()
 >             try {
 >                 outAssay.transfer(outPurse, destPurse)
 >             } catch ex {
 >                 inAssay.transfer(inPurse, srcPurse)
 >                 throw(ex)
 >             }
 >             destPurse
 >         }
 >     }
 > }
# value: <makeCambio>

? def BettyMint := makeMint("Betty")
# value: <Betty's Mint>

? def BettyBucks := BettyMint.getIssuer()
# value: <Betty bucks>

? def BettyPurseA := BettyBucks.makeEmptyPurse()
# value: <holds 0 Betty bucks>

? BettyMint.inflate(BettyPurseA, 250)
? BettyPurseA
# value: <holds 250 Betty bucks>

? def in2out(inAssay) :any {
 >     BettyBucks.makeAssay((0.5 * inAssay.getAmount()).round())
 > }
# value: <in2out>

? def JBCambio := makeCambio(PurseA, BettyPurseA, in2out)
# value: <turning <Joe bucks> into <Betty bucks>>

? [PurseA, BettyPurseA]
# value: [<holds 300 Joe bucks>, <holds 250 Betty bucks>]

? JoeMint.inflate(PurseB, 23)
? def BettyPurseB := JBCambio.changeMoney(PurseB)
# value: <holds 12 Betty bucks>

? [PurseA, BettyPurseA]
# value: [<holds 323 Joe bucks>, <holds 238 Betty bucks>]

?















-- 
Kevin Reid