[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