Newbie questions about persistence

View: New views
20 Messages — Rating Filter:   Alert me  

Newbie questions about persistence

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I didn't find any solution to the previous problem, but it hasn't been
causing too much trouble and I'm trying to learn about persistence
now.

If you visit "erights.org -> ELib -> Persistence" you just get a load
of pages marked "to be written", but there's actually quite a lot of
good documentation if you can find it. In particular, I found these
links useful:

* http://www.erights.org/data/serial/jhu-paper/deconstructing.html
* http://www.eros-os.org/pipermail/e-lang/2004-January/009483.html
* http://www.erights.org/elib/distrib/captp/index.html

There are a number of things which are probably obvious if you know
the system, but took me a while to realise. I'll summarise them here
for other beginners, and so people can correct the bits I get wrong.

The prototype I'm writing has a client/server architecture. A client
generally requests objects be created on a server, and the server
monitors them. Both the client and server are able to persist their
current state. There are multiple clients and servers and quite a lot
of sharing goes on between them.


Sturdy refs

My first mistake was assuming that, since a client can invoke methods
on a live ref and can pass the live ref to other clients, it must know
the remote object's Swiss number. I therefore assumed that the client
should call "makeSturdyRef(farRef)" to be able to reconnect or persist
the reference.

The CapTP documentation says this about what is sent to the client (in
DeliverOnlyOp):

  "The NewFarDesc encoding must have all the information needed to
  create such a new Far reference, which is the position the Far
  reference should be assigned in the Imports table (the same as the
  position at which Carol is Exported), and the SwissNumber that,
  together with VatA's VatID, represents Carol's sameness identity.

However, the JavaDoc shows that a NewFarDesc actually contains only
the Swiss hash (i.e. the identity of the object), not the Swiss number
(the ability to call it):

  http://www.erights.org/javadoc/net/captp/jcomm/NewFarDesc.html

I'm not sure whether we're using NewFarDesc or OldFarDesc in practice,
though I assume it doesn't make any difference here.

My understanding of the situation now is that:

* When a live ref is sent to the client, it is assigned a small
  integer ID (like a Unix file descriptor), which is only valid in the
  context of that TCP connection. There is a special mechanism for
  passing these live refs between clients, via the server.

* The client cannot get a Swiss number from a live ref.

* The server (hosting vat) must always call makeSturdyRef on an object
  before passing it to another vat if it wants the remote end to be
  able to persist it or reconnect after the TCP connection is closed.

* Calling makeSturdyRef creates a new Swiss base and, from that, a new
  Swiss number. It adds a mapping from this to the object, in a map it
  shares with the time machine. It then registers the object with the
  IdentityMgr (so that clients can connect to it) and creates the
  actual SturdyRef object with the Swiss number in it.

* Calling makeSturdyRef.temp is similar, except that it doesn't add
  anything to the map shared with the time machine.

* The time machine works by saving the object graph starting from the
  swiss-number-to-object mapping.

* Since makeSturdyRef(obj) makes a sturdy ref that lasts forever and
  is persisted, and throws away the SwissRetainer used to cancel it,
  refs made this way will accumulate forever.


Persistence

Starting with the mapping from SwissRetainers to objects (i.e. all
persistent exported objects), the time machine serialises the object
graph to a file, along with the vat's private key and network address.
The format of this serialisation is a subset of E called Data-E.

Internally, the time machine uses a "surgeon" to serialise and
unserialise object graphs. Objects which should not be serialised, but
which will be available when reloading, are called "exits" of the
graph, and must be registered with the surgeon first.

The system is designed to be able to serialise mutually-suspicious and
untrusted objects. No object should be able to revive with more
authority than it started with.

Some objects in E can be serialised automatically, including numbers,
strings, lists, maps, etc.

Some objects can be serialised if an appropriate "loader" or
"uncaller" is registered with the surgeon. These include files and
modules.

Many things cannot be serialised by default, including:

- facets (obj.method)
- caretakers
- promises
- near problems (bug in minimalUncaller?)


Persistence of sturdy refs

A sturdy ref can only be serialised if fully resolved (is this a bug?),
e.g.

        ? introducer.onTheAir()
        ? def surgeon := <elib:serial.makeSurgeon>.withSrcKit("de: ").diverge()
        ? surgeon.addLoader(introducer, "cap__uriGetter")
        ? def a
        ? def b := makeSturdyRef.temp(3)
        ? bind a := b

        ? surgeon.serialize(a)
        # problem: Can't uneval <SturdyRef to 3>

        ? a == b
        # value: true

        ? surgeon.serialize(b)
        # value: "de: <cap://*qvcmrxvqy66rest6gfzhhxwrjni6nrdq@...:59905/jo6sk4nehnrewzo7bvntfz7rl32f6q2g>"


I used this code to work around this:

        # Uncalls SturdyRefs to <cap:...>
        def sturdyLoader extends introducer {
                to optUncall(obj) {
                        return super.optUncall(Ref.resolution(obj))
                }
        }
        surgeon.addLoader(sturdyLoader, "cap__uriGetter")


Persistence of cycles

Some cyclic data structures can be persisted, while others can't (is
this a bug?). I haven't worked out what the rule is, but I do have
some examples:

        def surgeon := <elib:serial.makeSurgeon>.withSrcKit("de: ").diverge()

        def roundTrip(obj) {
                println(`Serializing $obj...`)
                def data := surgeon.serialize(obj)
                println(`Serialized as $data`)
                def obj2 := surgeon.unserialize(data)
                println(`Unserialized as $obj2`)
                println("")
        }

        def a := [a]
        roundTrip(a)

        def b := [a, a]
        roundTrip(b)

This prints:

        Serializing [<***CYCLE***>]...
        Serialized as de: def t__0 := [t__0]
        Unserialized as [<***CYCLE***>]

        Serializing [[<***CYCLE***>], [<***CYCLE***>]]...
        Serialized as de: [def t__0 := [t__0], t__0]
        # problem: <IndexOutOfBoundsException: not found: t__0>

This is quite annoying, because a SwissRetainer includes a pointer to
its object, in addition to the pointer in the table for which the
retainer is a key. Therefore, an object containing a single cycle ends
up with the broken double-cycle structure when saved.


Persistence of identity

Transparent objects can implement __optUncall to allow them to be
persisted. This method returns all of the object's authority, proving
to the surgeon that it is permitted to be revived with it. However,
this also allows anyone else to get an object's authority by calling
__optUncall themselves.

Therefore, most objects should use __optSealedDispatch to seal the
result. There don't seem to be many examples of this (e.g. FileGetter
uses "obj instanceof File" instead). I'm having trouble seeing how to
use this. Should I add a new loader/uncaller? How is identity handled?
e.g if I have a one-shot object, how can I ensure that an object
holding it will revive with only one copy of the one-shot object?
Similarly for a caretaker.


Persistence of functions

The result of uncalling an object is usually of the form [makeFoo,
"run", [...]], where makeFoo is a top-level function in some module.
Is there any way to get the time machine to handle these
automatically, without having to add them all as exists manually?

My current solution is that every module looks like this:

        def makeFooInternal(state) {
                return def foo {
                        to __optUncall() {
                                return [makeFooInternal, "run", [state]]
                        }
                }
        }

        def makeFoo() {
                def state := ...
                return makeFooInternal(state)
        }

        [ =>makeFoo, =>makeFooInternal ]

I then add an uncaller that recognises top-level functions by their
name:

        def modules := [].asMap().diverge()

        def loader(pkg, name) {
                if (!modules.maps(pkg)) {
                        modules[pkg] := <import>[pkg]
                }
                return modules[pkg][name]
        }

        def functionUncaller {
                to optUncall(obj) {
                        if (Ref.isNear(obj)) {
                                def type := obj.__getAllegedType()
                                def name := type.getFQName().split("$")

                                if (name.size() != 2) {
                                        return null
                                }

                                def [pkg, obj] := name

                                return [loader, "run", [pkg, obj]]
                        }
                }
        }

This seems a bit clumsy. Is there a better way? There are too many
functions to add them manually.


Thanks, and sorry for all the questions!


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by Kevin Reid-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Aug 28, 2009, at 10:27, Thomas Leonard wrote:

> There are a number of things which are probably obvious if you know
> the system, but took me a while to realise. I'll summarise them here
> for other beginners, and so people can correct the bits I get wrong.
...
> Sturdy refs
>
> My first mistake was assuming that, since a client can invoke methods
> on a live ref and can pass the live ref to other clients, it must know
> the remote object's Swiss number. I therefore assumed that the client
> should call "makeSturdyRef(farRef)" to be able to reconnect or persist
> the reference.

The second part is true: to be persistent across CapTP connections a  
reference must be a SturdyRef.

> The CapTP documentation says this about what is sent to the client (in
> DeliverOnlyOp):
>
>  "The NewFarDesc encoding must have all the information needed to
>  create such a new Far reference, which is the position the Far
>  reference should be assigned in the Imports table (the same as the
>  position at which Carol is Exported), and the SwissNumber that,
>  together with VatA's VatID, represents Carol's sameness identity.
>
> However, the JavaDoc shows that a NewFarDesc actually contains only
> the Swiss hash (i.e. the identity of the object), not the Swiss number
> (the ability to call it):

MarkM, could you comment on why this is so?

> * When a live ref is sent to the client, it is assigned a small
>  integer ID (like a Unix file descriptor), which is only valid in the
>  context of that TCP connection. There is a special mechanism for
>  passing these live refs between clients, via the server.

There is no client or server in CapTP; it is a symmetric protocol. 3-
party introductions happen in the same way always.

> * The client cannot get a Swiss number from a live ref.

Yes.

> * The server (hosting vat) must always call makeSturdyRef on an object
>  before passing it to another vat if it wants the remote end to be
>  able to persist it or reconnect after the TCP connection is closed.

Yes.

> * Calling makeSturdyRef creates a new Swiss base and, from that, a new
>  Swiss number. It adds a mapping from this to the object, in a map it
>  shares with the time machine. It then registers the object with the
>  IdentityMgr (so that clients can connect to it) and creates the
>  actual SturdyRef object with the Swiss number in it.

Yes.

> * Calling makeSturdyRef.temp is similar, except that it doesn't add
>  anything to the map shared with the time machine.

Yes.

> * The time machine works by saving the object graph starting from the
>  swiss-number-to-object mapping.

Yes.

> * Since makeSturdyRef(obj) makes a sturdy ref that lasts forever and
>  is persisted, and throws away the SwissRetainer used to cancel it,
>  refs made this way will accumulate forever.

Not forever, but for the lifetime of the vat. So if the system is such  
that each Foo has a particular vat it, and only it runs in, it's  
perfectly fine to do makeSturdyRef(theFoo) after setting up the vat.

> Many things cannot be serialised by default, including:
>
> - facets (obj.method)

This is a bug, IMO, and probably due to the lack of availability of  
the persistence sealer as discussed below.

> - caretakers

This is a little tricky because it would be in general possible to  
serialize the caretaker but not the component which decides to revoke  
it. However, there is an (probably outdated) version of this called  
makeFancyRevoker in the Den <http://wiki.erights.org/wiki/Den> source  
code.

> - promises

In general, this is necessary. A promise becomes something else on  
some unspecified future event; that event is running code/messages in  
flight and cannot be serialized.

If you have some activity that *can* be serialized (e.g. a promise for  
the result of a lengthy computation, which can be saved/restarted)  
then the proxy interface <http://wiki.erights.org/wiki/Proxy> can be  
used to create a promise which is also serializable (by  
handleOptSealedDispatch).

> - near problems (bug in minimalUncaller?)

Do you mean broken references? Could you provide details on this bug?

> Persistence of sturdy refs
>
> A sturdy ref can only be serialised if fully resolved (is this a  
> bug?),
> e.g.
>
> ? introducer.onTheAir()
> ? def surgeon := <elib:serial.makeSurgeon>.withSrcKit("de:  
> ").diverge()
> ? surgeon.addLoader(introducer, "cap__uriGetter")
> ? def a
> ? def b := makeSturdyRef.temp(3)
> ? bind a := b
>
> ? surgeon.serialize(a)
> # problem: Can't uneval <SturdyRef to 3>
>
> ? a == b
> # value: true
>
> ? surgeon.serialize(b)
> # value: "de: <cap://*qvcmrxvqy66rest6gfzhhxwrjni6nrdq@...:59905/jo6sk4nehnrewzo7bvntfz7rl32f6q2g
> >"

This is a bug; I have committed a fix.

If a == b then nothing whatsoever (except for unsafe imports) should  
behave differently on a and b. Ref.resolution/1 should always be a no-
op from the E user's perspective. The bug was that  
Introducer.optUncall performed an instanceof check without  
Ref.resolution first.

> Persistence of cycles
>
> Some cyclic data structures can be persisted, while others can't (is
> this a bug?). I haven't worked out what the rule is, but I do have
> some examples:
...
> Serializing [[<***CYCLE***>], [<***CYCLE***>]]...
> Serialized as de: [def t__0 := [t__0], t__0]
> # problem: <IndexOutOfBoundsException: not found: t__0>
>
> This is quite annoying, because a SwissRetainer includes a pointer to
> its object, in addition to the pointer in the table for which the
> retainer is a key. Therefore, an object containing a single cycle ends
> up with the broken double-cycle structure when saved.

This is a bug. Please send versions, test cases, patches, etc.

The relevant code would be in esrc/org/erights/e/elib/serial/,  
deSubgraphKit, deASTKit, and deSrcKit. Since it mentions "t__0" as  
opposed to 0, probably deSrcKit.

> Persistence of identity
>
> Transparent objects can implement __optUncall to allow them to be
> persisted. This method returns all of the object's authority, proving
> to the surgeon that it is permitted to be revived with it. However,
> this also allows anyone else to get an object's authority by calling
> __optUncall themselves.

Yes.

> Therefore, most objects should use __optSealedDispatch to seal the
> result. There don't seem to be many examples of this (e.g. FileGetter
> uses "obj instanceof File" instead). I'm having trouble seeing how to
> use this. Should I add a new loader/uncaller?

No, you should use the vat-wide persistence sealer, whose unsealer is  
closely held by the vat persistence system, in your  
__optSealedDispatch. If you seal your portrayal (what you would return  
from __optUncall) then you will get the behavior you want without any  
global definitions.

Unfortunately, IIRC, the persistence sealer is also closely held, but  
there is no good reason for this. (MarkM, could you confirm this?)

> How is identity handled?
> e.g if I have a one-shot object, how can I ensure that an object
> holding it will revive with only one copy of the one-shot object?
> Similarly for a caretaker.

If your object uncalls only by request of the vat persistence sealer,  
then you're guaranteed that its reincarnations will only be along with  
the rest of the vat state. So your one-shot might be rolled back to  
the not-yet-fired state, but everything else will be rolled back too  
and in sync.

> Persistence of functions
>
> The result of uncalling an object is usually of the form [makeFoo,
> "run", [...]], where makeFoo is a top-level function in some module.
> Is there any way to get the time machine to handle these
> automatically, without having to add them all as exists manually?

The proper way for this to happen is that makeFoo is DeepFrozen. If  
this happens, then the <import> loader will automatically serve as a  
loader for your maker.

Unfortunately, the guard-based auditing system has not yet been  
implemented in E-on-Java, so the DeepFrozen auditor to verify your  
maker as DeepFrozen cannot be used with E-on-Java, and only built-in  
objects can be DeepFrozen in E-on-Java.

If you want to experiment with DeepFrozen you can use my own E-on-CL <http://wiki.erights.org/wiki/E-on-CL 
 > which contains the DeepFrozen auditor.

The workaround way, which I have used in Den, is to give the maker an  
__optUncall:

--- begin makeFoo.emaker ---
def makeFoo {
   to __optUncall() { return [<import>, "get", ["my.fqn.goes.here"]] }
   to run() {
     def foo {
       to __optUncall() { return [makeFoo, "run", []] }
     }
     return foo
   }
}
--- end makeFoo.emaker ---

The fully-generic way to write that optUncall is:

to __optUncall() {
   return [<import>, "get", [meta.context().getFQNPrefix().split("$")
[0]]]
}


> My current solution is that every module looks like this:
>
> def makeFooInternal(state) { ... }
>
> def makeFoo() { ... }
>
> [ =>makeFoo, =>makeFooInternal ]


A few comments:

* This will not work if you use persistence in the conventional  
fashion: uncalls should typically correspond to calls, but here you  
have a map, which will uncall using the map constructor, rather than  
<import:makeFoo>.

* Why are you using two objects instead of two methods on one object?

* Particularly, "internal" is a bad concept: I can guess that you are  
using this for persistence of the state of an object, which you never  
expect to be constructed explicitly, but it is important to remember  
that the way in which you portray the objects for serialization is  
part of *THE PUBLIC INTERFACE* to your code, because other people's  
serialized data will contain it even when you publish a new version of  
your library/module/appplication.

--
Kevin Reid                                  <http://switchb.org/kpreid/>




_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 2009-08-28 at 19:15 -0400, Kevin Reid wrote:
> On Aug 28, 2009, at 10:27, Thomas Leonard wrote:
[...]
> > Many things cannot be serialised by default, including:
> >
> > - facets (obj.method)
>
> This is a bug, IMO, and probably due to the lack of availability of  
> the persistence sealer as discussed below.

Would be nice to have.

> > - near problems (bug in minimalUncaller?)
>
> Do you mean broken references? Could you provide details on this bug?

        def makeAtomicFile := <import:org.erights.e.extern.persist.makeAtomicFile>

        timeMachine.new()
        timeMachine.createAs(makeAtomicFile(<file:.>, "tmp"))
        introducer.onTheAir()
        makeSturdyRef(Ref.broken("foo"))
        timeMachine.save()

gives:

        # problem: Can't uneval problem: foo

But, oddly:

        def makeAnUncaller := <elib:serial.makeAnUncaller>
        def minimalUncaller := makeAnUncaller.getMinimalUncallers()[0]
        println(minimalUncaller.optUncall(Ref.broken("foo")))

gives:

        [<makeRef>, "broken", [problem: foo]]


> > Persistence of sturdy refs
> >
> > A sturdy ref can only be serialised if fully resolved (is this a  
> > bug?),

> This is a bug; I have committed a fix.

Thanks. There's a similar bug with files:

        def makeAtomicFile := <import:org.erights.e.extern.persist.makeAtomicFile>

        timeMachine.new()
        timeMachine.createAs(makeAtomicFile(<file:.>, "tmp"))
        introducer.onTheAir()
        def a
        bind a := <file:foo.txt>
        makeSturdyRef(a)
        timeMachine.save()

gives:

        # problem: Can't uneval <file:.../foo.txt>

> > Persistence of cycles
> >
> > Some cyclic data structures can be persisted, while others can't (is
> > this a bug?). I haven't worked out what the rule is, but I do have
> > some examples:
> ...
> > Serializing [[<***CYCLE***>], [<***CYCLE***>]]...
> > Serialized as de: [def t__0 := [t__0], t__0]
> > # problem: <IndexOutOfBoundsException: not found: t__0>
> >
> > This is quite annoying, because a SwissRetainer includes a pointer to
> > its object, in addition to the pointer in the table for which the
> > retainer is a key. Therefore, an object containing a single cycle ends
> > up with the broken double-cycle structure when saved.
>
> This is a bug. Please send versions, test cases, patches, etc.

A minimal test case is:

        def surgeon := <elib:serial.makeSurgeon>.withSrcKit("de: ")
        surgeon.unserialize("de: [def t__0 := [t__0], t__0]")

which gives:

        # problem: <IndexOutOfBoundsException: not found: t__0>

Happens with the current release (0.9.2a) and svn versions of E.

> > Persistence of identity
[...]

> > Therefore, most objects should use __optSealedDispatch to seal the
> > result. There don't seem to be many examples of this (e.g. FileGetter
> > uses "obj instanceof File" instead). I'm having trouble seeing how to
> > use this. Should I add a new loader/uncaller?
>
> No, you should use the vat-wide persistence sealer, whose unsealer is  
> closely held by the vat persistence system, in your  
> __optSealedDispatch. If you seal your portrayal (what you would return  
> from __optUncall) then you will get the behavior you want without any  
> global definitions.
>
> Unfortunately, IIRC, the persistence sealer is also closely held, but  
> there is no good reason for this. (MarkM, could you confirm this?)
>
> > How is identity handled?
> > e.g if I have a one-shot object, how can I ensure that an object
> > holding it will revive with only one copy of the one-shot object?
> > Similarly for a caretaker.
>
> If your object uncalls only by request of the vat persistence sealer,  
> then you're guaranteed that its reincarnations will only be along with  
> the rest of the vat state. So your one-shot might be rolled back to  
> the not-yet-fired state, but everything else will be rolled back too  
> and in sync.

I think I still need more help here. A naive attempt would be:

        def makeOneShot(var used) {
                return def oneShot {
                        to __optSealedDispatch(brand) {
                                if (keyHolder.getTHE_BRAND() == brand) {
                                        def uncall := [makeOneShot, "run", [used]]
                                        return keyHolder.getTHE_SEALER().seal(uncall)
                                }
                                return null
                        }
                        to invoke() {
                                if (used) {
                                        throw("Used up")
                                }
                                used := true
                                println("Invoking!")
                        }
                }
        }

The idea here is that a oneShot can be used to print "Invoking!" only
once, e.g.

        def myOneShot := makeOneShot(false)
        myOneShot.invoke()
        myOneShot.invoke()

gives:

        Invoking!
        # problem: Used up

But, since anyone can call __optSealedDispatch, an attacker can
obviously make copies of my oneShot. e.g.

        def makeMimic(obj) {
                return def mimic {
                        to __optSealedDispatch(brand) {
                                return obj.__optSealedDispatch(brand)
                        }
                }
        }

        def makeAttacker {
                to run(oneShot) {
                        return def larva {
                                to __optUncall() {
                                        return [makeAttacker, "revive", [oneShot, makeMimic(oneShot)]]
                                }
                        }
                }

                to revive(oneShotA, oneShotB) {
                        oneShotA<-invoke()
                        oneShotB<-invoke()

                        return def obj { }
                }
        }

My attacker gets persisted with a single oneShot, but revives with two
(and can therefore print "Invoking!" twice).

I suppose I could create a simple proxy to the oneShot and give that to
the attacker. The attacker could make copies of the proxy, but they'd
still all forward to a single oneShot. It seems clumsy and error-prone,
though, and I'm not sure I've thought through all the implications. A
simple example to copy from would be good.

Thanks,


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, 2009-09-01 at 16:08 +0100, Thomas Leonard wrote:
> On Fri, 2009-08-28 at 19:15 -0400, Kevin Reid wrote:
> > On Aug 28, 2009, at 10:27, Thomas Leonard wrote:

[ snip persistence of facets, broken promises, files, cycles ]

> > > Persistence of identity
> [...]
> > > Therefore, most objects should use __optSealedDispatch to seal the
> > > result. There don't seem to be many examples of this (e.g. FileGetter
> > > uses "obj instanceof File" instead). I'm having trouble seeing how to
> > > use this. Should I add a new loader/uncaller?
> >
> > No, you should use the vat-wide persistence sealer, whose unsealer is  
> > closely held by the vat persistence system, in your  
> > __optSealedDispatch. If you seal your portrayal (what you would return  
> > from __optUncall) then you will get the behavior you want without any  
> > global definitions.
> >
> > Unfortunately, IIRC, the persistence sealer is also closely held, but  
> > there is no good reason for this. (MarkM, could you confirm this?)

OK, I modified ScopeSetup to put a "persistence" object in safeScope (I
couldn't see a way to do this from E). The main program binds this to an
object with the brand and sealer, using a resolver in privScope. Is this
sensible (at least as a work-around)?

There are 48 separate objects in my program that need it, so I'm
reluctant to start passing it around everywhere. I want to make it as
easy as possible to serialise objects in a safe way; otherwise people
will be tempted to __optUncall instead, I think.

> > > How is identity handled?
> > > e.g if I have a one-shot object, how can I ensure that an object
> > > holding it will revive with only one copy of the one-shot object?
> > > Similarly for a caretaker.
> >
> > If your object uncalls only by request of the vat persistence sealer,  
> > then you're guaranteed that its reincarnations will only be along with  
> > the rest of the vat state. So your one-shot might be rolled back to  
> > the not-yet-fired state, but everything else will be rolled back too  
> > and in sync.
>
> I think I still need more help here. A naive attempt would be:
[...]
> My attacker gets persisted with a single oneShot, but revives with two
> (and can therefore print "Invoking!" twice).
>
> I suppose I could create a simple proxy to the oneShot and give that to
> the attacker. The attacker could make copies of the proxy, but they'd
> still all forward to a single oneShot.

Can someone confirm whether this is the correct approach?

Thanks!


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by David-Sarah Hopwood-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thomas Leonard wrote:
> OK, I modified ScopeSetup to put a "persistence" object in safeScope (I
> couldn't see a way to do this from E). The main program binds this to an
> object with the brand and sealer, using a resolver in privScope. Is this
> sensible (at least as a work-around)?
>
> There are 48 separate objects in my program that need it, so I'm
> reluctant to start passing it around everywhere.

Why can't you just define it in an outer scope of your program, so that
it is accessible to all nested scopes?

--
David-Sarah Hopwood  ⚥  http://davidsarah.livejournal.com

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Kevin Reid-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sep 14, 2009, at 11:08, Thomas Leonard wrote:

> On Tue, 2009-09-01 at 16:08 +0100, Thomas Leonard wrote:
>> On Fri, 2009-08-28 at 19:15 -0400, Kevin Reid wrote:
>>> No, you should use the vat-wide persistence sealer, whose unsealer  
>>> is
>>> closely held by the vat persistence system, in your
>>> __optSealedDispatch. If you seal your portrayal (what you would  
>>> return
>>> from __optUncall) then you will get the behavior you want without  
>>> any
>>> global definitions.
>>>
>>> Unfortunately, IIRC, the persistence sealer is also closely held,  
>>> but
>>> there is no good reason for this. (MarkM, could you confirm this?)
>
> OK, I modified ScopeSetup to put a "persistence" object in safeScope  
> (I
> couldn't see a way to do this from E). The main program binds this  
> to an
> object with the brand and sealer, using a resolver in privScope. Is  
> this
> sensible (at least as a work-around)?

IMO, ScopeSetup should directly get the sealer from the  
PersistentKeyHolder, rather than having E-level code do it. There may  
be a reason to have more configurability than that though.

MarkM, is there any reason the persistence sealer should not be widely  
available?

> There are 48 separate objects in my program that need it, so I'm
> reluctant to start passing it around everywhere. I want to make it as
> easy as possible to serialise objects in a safe way; otherwise people
> will be tempted to __optUncall instead, I think.

__optUncall is appropriate for any 'data structure'-like (Transparent)  
object with no private state.

>> I think I still need more help here. A naive attempt would be:
> [...]
>> My attacker gets persisted with a single oneShot, but revives with  
>> two
>> (and can therefore print "Invoking!" twice).
>>
>> I suppose I could create a simple proxy to the oneShot and give  
>> that to
>> the attacker. The attacker could make copies of the proxy, but they'd
>> still all forward to a single oneShot.
>
> Can someone confirm whether this is the correct approach?

I missed this point before. You're right - the persistence sealer  
protocol does not ensure uniqueness. This could be fixed in the  
protocol by including the object's own traversal key.

But as a workaround, you can define the proxy as you describe. I would  
recommend making it part of the implementation of the oneShot, and not  
exposing its existence to the user. (One way to do it would be to have  
your oneShot serialize, not as its current state, but rather the slot  
of the used flag: def uncall := [makeOneShot, "withFlagSlot",  
[&used]]. Then the 'used' slot object serves as the un-duplicatable  
object.

But this seems like a kludge, and I think we should fix the  
persistence protocol. Thanks for spotting this.

MarkM, do you agree this is an excessively surprising problem?

--
Kevin Reid                                  <http://switchb.org/kpreid/>




_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, 2009-09-14 at 19:18 +0100, David-Sarah Hopwood wrote:

> Thomas Leonard wrote:
> > OK, I modified ScopeSetup to put a "persistence" object in safeScope (I
> > couldn't see a way to do this from E). The main program binds this to an
> > object with the brand and sealer, using a resolver in privScope. Is this
> > sensible (at least as a work-around)?
> >
> > There are 48 separate objects in my program that need it, so I'm
> > reluctant to start passing it around everywhere.
>
> Why can't you just define it in an outer scope of your program, so that
> it is accessible to all nested scopes?

Can I do that while keeping the objects in separate files?


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, 2009-09-14 at 15:43 -0400, Kevin Reid wrote:
> On Sep 14, 2009, at 11:08, Thomas Leonard wrote:
> > On Tue, 2009-09-01 at 16:08 +0100, Thomas Leonard wrote:
[...]
> > There are 48 separate objects in my program that need it, so I'm
> > reluctant to start passing it around everywhere. I want to make it as
> > easy as possible to serialise objects in a safe way; otherwise people
> > will be tempted to __optUncall instead, I think.
>
> __optUncall is appropriate for any 'data structure'-like (Transparent)  
> object with no private state.

Unfortunately, few of my classes are like that, and even a class which
currently provides free access to all of its state might be extended
later, and it would be easy to forget to switch to the secure version.

Also, people are going to cut-and-paste my code when extending it, and
they probably won't think about these things much while they're doing
it, so I'd like to make it as hard as possible to get it wrong.

> >> I think I still need more help here. A naive attempt would be:
> > [...]
> >> My attacker gets persisted with a single oneShot, but revives with  
> >> two
> >> (and can therefore print "Invoking!" twice).
> >>
> >> I suppose I could create a simple proxy to the oneShot and give  
> >> that to
> >> the attacker. The attacker could make copies of the proxy, but they'd
> >> still all forward to a single oneShot.
> >
> > Can someone confirm whether this is the correct approach?
>
> I missed this point before. You're right - the persistence sealer  
> protocol does not ensure uniqueness. This could be fixed in the  
> protocol by including the object's own traversal key.
>
> But as a workaround, you can define the proxy as you describe. I would  
> recommend making it part of the implementation of the oneShot, and not  
> exposing its existence to the user. (One way to do it would be to have  
> your oneShot serialize, not as its current state, but rather the slot  
> of the used flag: def uncall := [makeOneShot, "withFlagSlot",  
> [&used]]. Then the 'used' slot object serves as the un-duplicatable  
> object.

That's clever - thanks!

> But this seems like a kludge, and I think we should fix the  
> persistence protocol. Thanks for spotting this.
>
> MarkM, do you agree this is an excessively surprising problem?


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, 2009-09-17 at 10:21 +0100, Thomas Leonard wrote:
> On Mon, 2009-09-14 at 15:43 -0400, Kevin Reid wrote:
[...]
> > But as a workaround, you can define the proxy as you describe. I would  
> > recommend making it part of the implementation of the oneShot, and not  
> > exposing its existence to the user. (One way to do it would be to have  
> > your oneShot serialize, not as its current state, but rather the slot  
> > of the used flag: def uncall := [makeOneShot, "withFlagSlot",  
> > [&used]]. Then the 'used' slot object serves as the un-duplicatable  
> > object.
>
> That's clever - thanks!

Oops. I spoke too soon. Looks like only final slots can be persisted:

#   . <makeRef>.fulfillment(<ref broken by problem: Can't uneval <var false>>)


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by Kevin Reid-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sep 17, 2009, at 8:23, Thomas Leonard wrote:

> On Thu, 2009-09-17 at 10:21 +0100, Thomas Leonard wrote:
>> On Mon, 2009-09-14 at 15:43 -0400, Kevin Reid wrote:
> [...]
>>> exposing its existence to the user. (One way to do it would be to  
>>> have
>>> your oneShot serialize, not as its current state, but rather the  
>>> slot
>>> of the used flag: def uncall := [makeOneShot, "withFlagSlot",
>>> [&used]]. Then the 'used' slot object serves as the un-duplicatable
>>> object.
>>
>> That's clever - thanks!
>
> Oops. I spoke too soon. Looks like only final slots can be persisted:
>
> #   . <makeRef>.fulfillment(<ref broken by problem: Can't uneval  
> <var false>>)

Gah. Sometimes I forget what's my own invention.

MarkM, is there any reason not to add __optUncall to (unguarded) var  
slots?

--
Kevin Reid                                  <http://switchb.org/kpreid/>




_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Mark Miller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Catching up now. Sorry for the long delay. I'd like to say it won't
happen again, but I'm likely to continue to be too busy for the
foreseeable future (at least seven months). But I'll try to catch up
again as I have the chance.

On Mon, Sep 14, 2009 at 3:43 PM, Kevin Reid <kpreid@...> wrote:

> On Sep 14, 2009, at 11:08, Thomas Leonard wrote:
>> OK, I modified ScopeSetup to put a "persistence" object in safeScope
>> (I couldn't see a way to do this from E). The main program binds this
>> to an object with the brand and sealer, using a resolver in privScope. Is
>> this sensible (at least as a work-around)?
>
> IMO, ScopeSetup should directly get the sealer from the
> PersistentKeyHolder, rather than having E-level code do it. There may
> be a reason to have more configurability than that though.
>
> MarkM, is there any reason the persistence sealer should not be widely
> available?

An oversight. This is a good plan. Thomas, feel free to submit a
patch. Kevin, feel free to make a commitment along the lines you
explain above.


>> There are 48 separate objects in my program that need it, so I'm
>> reluctant to start passing it around everywhere. I want to make it as
>> easy as possible to serialise objects in a safe way; otherwise people
>> will be tempted to __optUncall instead, I think.
>
> __optUncall is appropriate for any 'data structure'-like (Transparent)
> object with no private state.
>
>>> I think I still need more help here. A naive attempt would be:
>> [...]
>>> My attacker gets persisted with a single oneShot, but revives with
>>> two
>>> (and can therefore print "Invoking!" twice).
>>>
>>> I suppose I could create a simple proxy to the oneShot and give
>>> that to
>>> the attacker. The attacker could make copies of the proxy, but they'd
>>> still all forward to a single oneShot.
>>
>> Can someone confirm whether this is the correct approach?
>
> I missed this point before. You're right - the persistence sealer
> protocol does not ensure uniqueness. This could be fixed in the
> protocol by including the object's own traversal key.
>
> But as a workaround, you can define the proxy as you describe. I would
> recommend making it part of the implementation of the oneShot, and not
> exposing its existence to the user. (One way to do it would be to have
> your oneShot serialize, not as its current state, but rather the slot
> of the used flag: def uncall := [makeOneShot, "withFlagSlot",
> [&used]]. Then the 'used' slot object serves as the un-duplicatable
> object.
>
> But this seems like a kludge, and I think we should fix the
> persistence protocol. Thanks for spotting this.
>
> MarkM, do you agree this is an excessively surprising problem?

This is indeed excessively surprising. I'm not sure whether or not the
slot solution is a kludge. The persistence of var-slots needs to be
fixed regardless.


--
Text by me above is hereby placed in the public domain

    Cheers,
    --MarkM
_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Fixing the sealed persistence protocol (was Newbie questions about persistence)

by Kevin Reid-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sep 19, 2009, at 11:42, Mark Miller wrote:

> On Mon, Sep 14, 2009 at 3:43 PM, Kevin Reid <kpreid@...> wrote:
>> IMO, ScopeSetup should directly get the sealer from the
>> PersistentKeyHolder, rather than having E-level code do it. There may
>> be a reason to have more configurability than that though.
>>
>> MarkM, is there any reason the persistence sealer should not be  
>> widely
>> available?
>
> An oversight. This is a good plan. Thomas, feel free to submit a
> patch. Kevin, feel free to make a commitment along the lines you
> explain above.

Commitment? Do you mean commit? I'm not sure what exactly you mean --  
that I should revise and commit Thomas's patch, or ...?

>> But as a workaround, you can define the proxy as you describe. I  
>> would
>> recommend making it part of the implementation of the oneShot, and  
>> not
>> exposing its existence to the user. (One way to do it would be to  
>> have
>> your oneShot serialize, not as its current state, but rather the slot
>> of the used flag: def uncall := [makeOneShot, "withFlagSlot",
>> [&used]]. Then the 'used' slot object serves as the un-duplicatable
>> object.
>>
>> But this seems like a kludge, and I think we should fix the
>> persistence protocol. Thanks for spotting this.
>>
>> MarkM, do you agree this is an excessively surprising problem?
>
> This is indeed excessively surprising. I'm not sure whether or not the
> slot solution is a kludge. The persistence of var-slots needs to be
> fixed regardless.

The slot solution is a kludge because:

- nontrivial objects may have state which is not naturally expressed  
*across upgrades* as one or more var slots.

- it means the object may be constructed with its internal shared with  
other parties: this could violate invariants.

- it is not a natural style to program in and creates additional  
visual noise in the program.

- the maker provides degrees of freedom which are unrelated to the  
actual application.

- the need for it IS unnecessarily surprising -- programmers will  
write accidentally insecure programs by not doing it.


Let's think about how to fix the persistence protocol.

What we want to achieve is that an object (henceforth referred to as  
the oneShot, even though this is general) may reveal a portrayal to  
the persistence subsystem, and thus be persistent, but with the  
guarantee that it will only be instantiated at most once in any given  
future vat incarnation.

The problem with just returning a portrayal in a sealed box from  
__optSealedDispatch is that any other object can proxy its  
__optSealedDispatch to the oneShot and thus revive as a duplicate of it.

So one fix would be to stuff the identity in the box and check it:

# from org.erights.e.extern.persist.initTimeMachine
def persistUncaller {
     to optUncall(obj) :nullOk[__Portrayal] {
         if (Ref.isNear(obj) &&
               pUnsealer.amplify(obj) =~ \
                 [[==(makeTraversalKey(obj)), portrayal]]) {
             return portrayal
         } else {
             return null
         }
     }
}

def oneShot {
     to __optSealedDispatch(brand) { switch (brand) {
         match ==persistBrand {
             return persistSealer.seal(makeTraversalKey(oneShot),
                                       [makeOneShot, ...])
         }
     }}
}

An oddball variation of this would be to put the object in the box and  
use it instead if the identities don't match: this would permit  
proxying __optSealedDispatch but change the behavior such that the  
proxying object is revived as the lone oneShot rather than a duplicate  
of it.

def persistUncaller {
     to optUncall(obj) :nullOk[__Portrayal] {
         if (Ref.isNear(obj) &&
               pUnsealer.amplify(obj) =~ [[objForIdentity,  
portrayal]]) {
             if (obj == objForIdentity) {
                 return portrayal
             } else {
                 return [__identityFunc, "run", objForIdentity]
             }
         } else {
             return null
         }
     }
}

def oneShot {
     to __optSealedDispatch(brand) { switch (brand) {
         match ==persistBrand {
             return persistSealer.seal(oneShot, [makeOneShot, ...])
         }
     }}
}


Also, I note that org.erights.e.extern.persist.initTimeMachine's  
persistUncaller is currently equivalent to makeAmplifier in  
org.erights.e.elib.serial.makeAnUncaller except for requiring nearness.

- Should all amplifying uncallers work in this same way? I have not  
considered the matter, but I would think this issue is likely to crop  
up similarly in other applications.

- The nearness restriction should be dropped and the uncall made  
through Ref.optSealedDispatch. If a Proxy-ref wants to be persistent,  
let it.

Given both of these changes, the persistUncaller is just  
makeAnUncaller.makeAmplifier(pUnsealer).

--
Kevin Reid                                  <http://switchb.org/kpreid/>




_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Fixing the sealed persistence protocol (was Newbie questions about persistence)

by Mark Miller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, Sep 19, 2009 at 12:32 PM, Kevin Reid <kpreid@...> wrote:
> On Sep 19, 2009, at 11:42, Mark Miller wrote:
>> An oversight. This is a good plan. Thomas, feel free to submit a
>> patch. Kevin, feel free to make a commitment along the lines you
>> explain above.
>
> Commitment? Do you mean commit? I'm not sure what exactly you mean --
> that I should revise and commit Thomas's patch, or ...?

I meant "commit". Whether this is a revision made directly by you or a
revision of a patch submitted by Thomas I leave to the two of you.

I am still chewing on the rest of your note. You make good points
about the slot solution being a kludge.

--
Text by me above is hereby placed in the public domain

    Cheers,
    --MarkM
_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence

by Mark Miller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Sep 17, 2009 at 3:06 PM, Kevin Reid <kpreid@...> wrote:

> On Sep 17, 2009, at 8:23, Thomas Leonard wrote:
>> On Thu, 2009-09-17 at 10:21 +0100, Thomas Leonard wrote:
>>> On Mon, 2009-09-14 at 15:43 -0400, Kevin Reid wrote:
>> [...]
>>>> exposing its existence to the user. (One way to do it would be to
>>>> have
>>>> your oneShot serialize, not as its current state, but rather the
>>>> slot
>>>> of the used flag: def uncall := [makeOneShot, "withFlagSlot",
>>>> [&used]]. Then the 'used' slot object serves as the un-duplicatable
>>>> object.
>>>
>>> That's clever - thanks!
>>
>> Oops. I spoke too soon. Looks like only final slots can be persisted:
>>
>> #   . <makeRef>.fulfillment(<ref broken by problem: Can't uneval
>> <var false>>)
>
> Gah. Sometimes I forget what's my own invention.
>
> MarkM, is there any reason not to add __optUncall to (unguarded) var
> slots?

I don't believe so. This seems like a good idea to me.


--
Text by me above is hereby placed in the public domain

    Cheers,
    --MarkM
_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, 2009-09-19 at 11:42 -0400, Mark Miller wrote:
> On Mon, Sep 14, 2009 at 3:43 PM, Kevin Reid <kpreid@...> wrote:
[...]

> > IMO, ScopeSetup should directly get the sealer from the
> > PersistentKeyHolder, rather than having E-level code do it. There may
> > be a reason to have more configurability than that though.
> >
> > MarkM, is there any reason the persistence sealer should not be widely
> > available?
>
> An oversight. This is a good plan. Thomas, feel free to submit a
> patch. Kevin, feel free to make a commitment along the lines you
> explain above.
OK, here's an attempt at a patch. I didn't find any documentation on the
safej syntax, so I'm just guessing here. I didn't see any way to make
just the getTHE_BRAND() and getTHE_SEALER() methods safe, whilst still
allowing getTHE_UNSEALER() to be accessible using <unsafe>, so I made a
new class.

I named the class PersistentSealer (rather than PersistenceSealer) to
match PersistentKeyHolder.

The seal function takes an extra "self" parameter, currently ignored, in
anticipation of Kevin's changes to the persistence protocol.

Thanks,


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

[0001-Make-the-persistence-brand-and-sealer-widely-availab.patch]

>From 6b8526ba8c459fbfee036969a5c45fa81a67f425 Mon Sep 17 00:00:00 2001
From: Thomas Leonard <tal@...>
Date: Thu, 24 Sep 2009 13:39:19 +0100
Subject: [PATCH] Make the persistence brand and sealer widely available

See: http://www.eros-os.org/pipermail/e-lang/2009-September/013255.html
("Newbie questions about persistence")

Patch provided by the University of Southampton IT Innovation Centre.
---
 .../erights/e/elib/serial/PersistentSealer.java    |   56 ++++++++++++++++++++
 .../erights/e/elib/serial/PersistentSealer.safej   |    8 +++
 2 files changed, 64 insertions(+), 0 deletions(-)
 create mode 100644 src/jsrc/org/erights/e/elib/serial/PersistentSealer.java
 create mode 100644 src/safej/org/erights/e/elib/serial/PersistentSealer.safej

diff --git a/src/jsrc/org/erights/e/elib/serial/PersistentSealer.java b/src/jsrc/org/erights/e/elib/serial/PersistentSealer.java
new file mode 100644
index 0000000..6eb05e6
--- /dev/null
+++ b/src/jsrc/org/erights/e/elib/serial/PersistentSealer.java
@@ -0,0 +1,56 @@
+/////////////////////////////////////////////////////////////////////////
+//
+// © University of Southampton IT Innovation Centre, 2009
+//
+// Copyright in this file belongs to the University of Southampton
+// University Road, Highfield, Southampton, UK, SO17 1BJ
+//
+// This software may not be used, sold, licensed, transferred, copied
+// or reproduced in whole or in part in any manner or form or in or
+// on any media by any person other than in accordance with the terms
+// of the Licence Agreement supplied with the software, or otherwise
+// without the prior written consent of the copyright owners.
+//
+// This software is distributed WITHOUT ANY WARRANTY, without even the
+// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE, except where stated in the Licence Agreement supplied with
+// the software.
+//
+// Created By : Thomas Leonard
+// Created Date : 2009-09-24
+// Created for Project : SERSCIS
+//
+/////////////////////////////////////////////////////////////////////////
+
+// Released under the terms of the MIT X license
+// found at http://www.opensource.org/licenses/mit-license.html ...............
+
+package org.erights.e.elib.serial;
+
+import org.erights.e.elib.sealing.SealedBox;
+import org.erights.e.elib.sealing.Brand;
+
+/** The public facet of the persistence sealer.
+ * Objects which are persistent but not transparent should seal their portrayal
+ * using this class to prevent other objects from getting hold of their authority.
+ * @author Thomas Leonard
+ */
+public class PersistentSealer {
+    private PersistentSealer() {
+    }
+
+    static public Brand getBrand() {
+        return PersistentKeyHolder.THE_BRAND;
+    }
+
+    /** Seal a portrayal using the persistence sealer.
+     * @param self the object being persisted
+     * @param contents the object's portrayal
+     * "self" is provided to prevent a man-in-the-middle attack, where one object
+     * forwards to another's __optSealedDispatch in order to revive with a new
+     * copy of the object. Currently, this parameter is ignored.
+     */
+    static public SealedBox seal(Object self, Object contents) {
+        return PersistentKeyHolder.THE_SEALER.seal(contents);
+    }
+}
diff --git a/src/safej/org/erights/e/elib/serial/PersistentSealer.safej b/src/safej/org/erights/e/elib/serial/PersistentSealer.safej
new file mode 100644
index 0000000..d43fe59
--- /dev/null
+++ b/src/safej/org/erights/e/elib/serial/PersistentSealer.safej
@@ -0,0 +1,8 @@
+# © University of Southampton IT Innovation Centre, 2009,
+# under the terms of the MIT X license found at
+# http://www.opensource.org/licenses/mit-license.html ................
+
+class(safe,
+      "org.erights.e.elib.serial.PersistentSealer",
+      statics(method("getBrand()"),
+              method("seal(Object, Object)")))
--
1.6.0.4



_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Kevin Reid-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sep 24, 2009, at 11:11, Thomas Leonard wrote:

> On Sat, 2009-09-19 at 11:42 -0400, Mark Miller wrote:
>> On Mon, Sep 14, 2009 at 3:43 PM, Kevin Reid <kpreid@...> wrote:
> [...]
>>> IMO, ScopeSetup should directly get the sealer from the
>>> PersistentKeyHolder, rather than having E-level code do it. There  
>>> may
>>> be a reason to have more configurability than that though.
>>>
>>> MarkM, is there any reason the persistence sealer should not be  
>>> widely
>>> available?
>>
>> An oversight. This is a good plan. Thomas, feel free to submit a
>> patch. Kevin, feel free to make a commitment along the lines you
>> explain above.
>
> OK, here's an attempt at a patch.

Your PersistentSealer.java has a copyright statement contains specific  
language which is not the MIT license. I would prefer that this be  
removed and there only be two-line header as in other E files, to  
avoid any future problems.

> I didn't find any documentation on the
> safej syntax, so I'm just guessing here. I didn't see any way to make
> just the getTHE_BRAND() and getTHE_SEALER() methods safe, whilst still
> allowing getTHE_UNSEALER() to be accessible using <unsafe>, so I  
> made a
> new class.

This is unnecessary complexity. Just have ScopeSetup put the sealer in  
the safeScope. Though I'm not sure what the name of the object should  
be. MarkM?

> I named the class PersistentSealer (rather than PersistenceSealer) to
> match PersistentKeyHolder.

I haven't liked the name of PersistentKeyHolder. It's not a holder of  
persistent keys, and so on. I'd rather see a consistent renaming to  
'Persistence'. MarkM?

> The seal function takes an extra "self" parameter, currently  
> ignored, in
> anticipation of Kevin's changes to the persistence protocol.


This doesn't feel appropriate to me; I can't quite say what the  
problem with it is though. It feels like something that ought to be  
'utility' not 'primitive', in particular that the unrestricted sealing  
authority should be available. but I can't quite justify that.

If nothing else, we should wait to invent such things until MarkM has  
finished chewing on the problem:
   <http://www.eros-os.org/pipermail/e-lang/2009-September/013261.html>

I also don't like that you're using a StaticMaker to be the sealer  
object, but I don't have a justification for that either.

--
Kevin Reid                                  <http://switchb.org/kpreid/>




_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Mark Miller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Sep 24, 2009 at 9:20 AM, Kevin Reid <kpreid@...> wrote:

[out of order]
>> I named the class PersistentSealer (rather than PersistenceSealer) to
>> match PersistentKeyHolder.
>
> I haven't liked the name of PersistentKeyHolder. It's not a holder of
> persistent keys, and so on. I'd rather see a consistent renaming to
> 'Persistence'. MarkM?

Yes, 'Persistence'.

> This is unnecessary complexity. Just have ScopeSetup put the sealer in
> the safeScope. Though I'm not sure what the name of the object should
> be. MarkM?

'PersistenceSealer'?


>> The seal function takes an extra "self" parameter, currently
>> ignored, in
>> anticipation of Kevin's changes to the persistence protocol.
>
>
> This doesn't feel appropriate to me; I can't quite say what the
> problem with it is though. It feels like something that ought to be
> 'utility' not 'primitive', in particular that the unrestricted sealing
> authority should be available. but I can't quite justify that.
>
> If nothing else, we should wait to invent such things until MarkM has
> finished chewing on the problem:
>   <http://www.eros-os.org/pipermail/e-lang/2009-September/013261.html>
>
> I also don't like that you're using a StaticMaker to be the sealer
> object, but I don't have a justification for that either.

Please don't wait for me. I'm not sure when I'll have the bandwidth again.


--
Text by me above is hereby placed in the public domain

    Cheers,
    --MarkM
_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Kevin Reid-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sep 24, 2009, at 20:28, Mark Miller wrote:

>> This is unnecessary complexity. Just have ScopeSetup put the sealer  
>> in
>> the safeScope. Though I'm not sure what the name of the object should
>> be. MarkM?
>
> 'PersistenceSealer'?

It's not a guard/type object, so 'persistenceSealer'.

--
Kevin Reid                                  <http://switchb.org/kpreid/>




_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Mark Miller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Sep 24, 2009 at 6:04 PM, Kevin Reid <kpreid@...> wrote:

> On Sep 24, 2009, at 20:28, Mark Miller wrote:
>
>>> This is unnecessary complexity. Just have ScopeSetup put the sealer
>>> in
>>> the safeScope. Though I'm not sure what the name of the object should
>>> be. MarkM?
>>
>> 'PersistenceSealer'?
>
> It's not a guard/type object, so 'persistenceSealer'.

+1


> --
> Kevin Reid                                  <http://switchb.org/kpreid/>
>
>
>
>
> _______________________________________________
> e-lang mailing list
> e-lang@...
> http://www.eros-os.org/mailman/listinfo/e-lang
>



--
Text by me above is hereby placed in the public domain

    Cheers,
    --MarkM
_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang

Re: Newbie questions about persistence (Attn MarkM: Possible surprise-vulnerability in persistence protocol)

by Thomas Leonard :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, 2009-09-24 at 12:20 -0400, Kevin Reid wrote:

> On Sep 24, 2009, at 11:11, Thomas Leonard wrote:
> > On Sat, 2009-09-19 at 11:42 -0400, Mark Miller wrote:
> >> On Mon, Sep 14, 2009 at 3:43 PM, Kevin Reid <kpreid@...> wrote:
> > [...]
> >>> IMO, ScopeSetup should directly get the sealer from the
> >>> PersistentKeyHolder, rather than having E-level code do it. There  
> >>> may
> >>> be a reason to have more configurability than that though.
> >>>
> >>> MarkM, is there any reason the persistence sealer should not be  
> >>> widely
> >>> available?
> >>
> >> An oversight. This is a good plan. Thomas, feel free to submit a
> >> patch. Kevin, feel free to make a commitment along the lines you
> >> explain above.
> >
> > OK, here's an attempt at a patch.
>
> Your PersistentSealer.java has a copyright statement contains specific  
> language which is not the MIT license. I would prefer that this be  
> removed and there only be two-line header as in other E files, to  
> avoid any future problems.

So would I, but it's company policy, and changing it may take months or
years. Is there anything actually incompatible about the terms? Mainly
it just states the obvious: that copyright law applies by default, with
extra rights permitted by the license, and that we provide no warranty.

[...]

I'd be perfectly happy if you want to make a different patch along the
lines you suggest, with your own header. I added the extra "self"
parameter to make it easy to switch to the new persistence protocol
later (i.e. slowly move things over to using the new API, then change
the protocol). I don't much mind either way, though.


--
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal@...
http://www.it-innovation.soton.ac.uk 

_______________________________________________
e-lang mailing list
e-lang@...
http://www.eros-os.org/mailman/listinfo/e-lang