On anonymous objects

4 views
Skip to first unread message

David Given

unread,
Mar 25, 2013, 2:07:55 PM3/25/13
to MOO-...@googlegroups.com
So I want to add user scripting to thickishstring. For various reasons
I'd rather not expose raw MOOcode. Instead I'm thinking of compiling a
user script in a custom syntax into MOOcode.

My basic thought is that each script compiles into an anonymous object
which contains some methods for, e.g., returning the source code for the
script, and a verb which actually runs the script. I pass in the
script's context (its set of global variables) when I call the verb.
This allows me to share the script object among multiple users of the
script. This is important for me as scripts will tend to be attached to
a realm, and I'll have multiple instances of the realm all sharing the
same set of scripts.

Are anonymous objects suitable for this, or should I be trying to attach
all my compiled scripts to a real object as uniquely named verbs?
(Possible, but it makes for more housekeeping.)

Also: any comments on using maps vs anonymous objects as fast key/value
storage?

(Incidentally, thanks very much for the new documentation; I missed it
earlier. It'll be very useful. I'm also reading up on TDOP parsers with
great interest.)

--
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────

│ 𝕻𝖍'𝖓𝖌𝖑𝖚𝖎 𝖒𝖌𝖑𝖜'𝖓𝖆𝖋𝖍 𝕮𝖙𝖍𝖚𝖑𝖍𝖚 𝕽'𝖑𝖞𝖊𝖍
𝖜𝖌𝖆𝖍'𝖓𝖆𝖌𝖑 𝖋𝖍𝖙𝖆𝖌𝖓.


signature.asc

Michael Munson

unread,
Mar 25, 2013, 4:51:29 PM3/25/13
to David Given, MOO-...@googlegroups.com

To me it seems like an ideal solution to use anonymous objects.

Todd Sundsted

unread,
Mar 28, 2013, 9:28:04 PM3/28/13
to David Given, MOO-...@googlegroups.com
David,

Sorry for the delayed reply...  off the grid for a few days...

One advantage of anonymous objects is that programmers can't forge a reference to an anonymous object.  To access verbs on a permanent objects you just have to _name_ the object with the literal: #1234:verb().  This means that the verbs/scripts have to protect against unwanted access, which may or may not be an issue.

Why don't you want to allow them to program directly in MOOcode?

Todd

David Given

unread,
Apr 2, 2013, 11:21:41 AM4/2/13
to MOO-...@googlegroups.com
Todd Sundsted wrote:
[...]
> Why don't you want to allow them to program directly in MOOcode?

There are things that MOOcode allows which I don't want the users to be
able to do. One is:

while (1)
suspend(0);
endwhile

I haven't found a way to protect the system from this yet.

Another reason is it doesn't seem possible to generally prevent one
player from calling methods belonging to another object. AFAICT the
MOOcode security model means that it's the callee's responsibility to
check whether the caller has permission to make the call or not. This
seems very brittle to me --- random users simply aren't going to
remember to put the protection in, with the result that calling methods
on other people's objects is probably going to end up in them changing
state.

(I find myself wondering what would happen if I run something like this
on LambdaMOO, for example:

while (1)
o = find_random_object();
v = o:find_random_verb();
o:(v)();
suspend(0);
endwhile

It would probably get me banned...)

And I'm afraid there's bad news: I'm probably going to end up rewriting
thickishstring's server in Python. It's not my favourite language but I
need support for distributed databases like Google's AppEngine, and
Python appears to be the best choice for that. Also, unfortunately, the
guy I'm trying to sell this to (in a mind-share sense) likes Python...

Still, even if it's going to end up as just being a prototype, the Stunt
version will still be invaluable for helping me refactor the design and
figure out exactly what I want, so thank you for that.
signature.asc

Jay Carlson

unread,
Apr 2, 2013, 7:50:39 PM4/2/13
to David Given, MOO-...@googlegroups.com
On Apr 2, 2013, at 11:21 AM, David Given wrote:

> Todd Sundsted wrote:
> [...]
>> Why don't you want to allow them to program directly in MOOcode?
>
> There are things that MOOcode allows which I don't want the users to be
> able to do. One is:
>
> while (1)
> suspend(0);
> endwhile

You can set $server_options.protect_suspend. There's always programmer.queued_task_limit too.

I suspect what you're really looking for is the dynamic-wind version of that, the fictional:

reserving suspend, 1000 ticks, 100 milliseconds try
victim:notify_of_eject("Bye!")
except e1 (E_TICKOUT)
notify(victim, "You didn't think I'd give you my last tick, did you?")
except e2 (E_TIMEOUT)
notify(victim, "Good job with the O(n^2) ops; you pass CS 201, but...")
except e3 (E_SUSPEND)
notify(victim, "Sorry, but you can't just avoid a process server in this universe.")
finally
// still have 1000 ticks and a tenth of a second (both minus the notify) here
move(victim, $player_start)
endtry

> StiI haven't found a way to protect the system from this yet.

In theory, bozos with queued tasks go to the end of the line with the scheduler too, but your load average will peg at 1.0. But that's in a world where a lag meter returns non-zero.

> Another reason is it doesn't seem possible to generally prevent one
> player from calling methods belonging to another object.

Life would be boring if other people couldn't talk to you people or you couldn't be moved. People climb into the Human Cannon and then have .sessile or some other refuse-to-:moveto set. It violates the consensus reality contract if the cannon is fired but people inside don't go out the barrel. So anybody left over gets :eject()ed; a $room owner can throw any object out because of the wiz perms on $room:eject().

> AFAICT the
> MOOcode security model means that it's the callee's responsibility to
> check whether the caller has permission to make the call or not. This
> seems very brittle to me --- random users simply aren't going to
> remember to put the protection in, with the result that calling methods
> on other people's objects is probably going to end up in them changing
> state.

This is really is a feature. It limits the scope of security failure to the permissions of the programmer. In Unix, the ongoing trend has been towards apps suid to the subsystem-specific user id.

On the other hand, this is partially history. Back in a world where most people are writing !x commands it doesn't matter. I personally thought the verb editor should default blank +x verbs to:

1: caller == this || lose;
2: _

to give people a good start on security.

Anyway, what would you do differently? There are not that many systems out there trying to cope with mutually-suspicious programmers, so this really is an open question. I've been trying to figure out the live-Wiki analog to MOO for years now and haven't quite gotten the model straight. My latest attempts have returned to the ability of programmers to add their own private properties/annotations to objects but still keeping the suid-by-default model.

> (I find myself wondering what would happen if I run something like this
> on LambdaMOO, for example:
>
> while (1)
> o = find_random_object();
> v = o:find_random_verb();
> o:(v)();
> suspend(0);
> endwhile
>
> It would probably get me banned...)

Yes, it would, although with varying levels of deprogrammer/newt/toad/IP-block severity. It'd be at least as rude as calling $player:tell() on everybody connected over and over again.

I don't see how you can build a shared universe, one with objects that richly interact, without civility and politics. MMO clients have some tiny amount of scriptable functionality and even then you end up with TOS violation and sandbox contraction (warhammer turning off script access to /target to keep teams from auto-selecting single victims and bursting them down).

> And I'm afraid there's bad news: I'm probably going to end up rewriting
> thickishstring's server in Python. It's not my favourite language but I
> need support for distributed databases like Google's AppEngine, and
> Python appears to be the best choice for that.

Have fun with the causality problems....[1]

Less sarcastically, everybody seems to zone and instance heavily so they can limit the amount of sync they have to do. MOO doesn't give you any help there, but judging from the state of what I've seen deployed you're going to see the technology intruding on your world design.

> Also, unfortunately, the
> guy I'm trying to sell this to (in a mind-share sense) likes Python...

Aw, can't you make the "it's a game! we should use Lua! Lua is for games!" argument?

Jay

[1]: "global causality violation" is one of those delicious bits of jargon you just know is going to understate the precise nature of the catastrophe.

Todd Sundsted

unread,
Apr 3, 2013, 7:49:58 AM4/3/13
to David Given, moo-talk
Security is probably my #1 design issue with the server right now.

Historically, there weren't +x verbs.  Everything was a command.  Eventually +x verbs were added, but library code was relatively small scale.  I may have the exact details incorrect, but the point is, there is room for some improvement here.  I added the helpers `$private()', `$protected()', `$permit()', etc. to make it easier for programmers to constrain usage, and easier for tools to analyze code for vulnerabilities.  Eventually, these may make it into the server, itself.  And the next release of Stunt will add a run-verb-with-no-perms flag, which will cause the code to immediately drop all perms.  I'm increasingly trying to take advantage of Stunt's/LambdaMOO's natural value immutability to write side-effect free library code.  Obviously, some code needs to modify server state, but quite a bit of it does not.

I appreciate your giving Stunt a try, and I really appreciate your sharing feedback on it.  Insight into how people use it, abuse it, and deal with the warts is the most valuable thing a designer can have, IMO.  If you have more questions or feedback as you work on the prototype, hit me up.

Todd




Todd Sundsted

unread,
Apr 3, 2013, 11:45:53 AM4/3/13
to moo-...@googlegroups.com, David Given
One more follow-up...  I'm going to start capturing overall metrics (ticks used per user...), etc. which I think will help shed light on user behavior.  Lots of low-hanging fruit, here.

Todd

David Given

unread,
Apr 3, 2013, 12:20:59 PM4/3/13
to MOO-...@googlegroups.com
Jay Carlson wrote:
[...]
> Anyway, what would you do differently?

I think there may be some scope in tying object access rules to the
object scoping rules. That would limit the possible interactions to only
those objects which are physically present. It makes intuitive sense
that in order to be able to peel the banana, you have to be able to see
inside the fruit bowl. Remote peelings would hardly ever be useful.

Of course, for performance reasons this would probably require baking
the scoping model into the server...

If we're willing to contemplate a radical redesign, it might be worth
stealing ideas from the capability-based OS people: instead of having
object IDs have limited-access tokens that you have to petition other
objects for. The player gets given a token to the room they're in; they
can ask that room for the tokens of visible objects in that room; one of
them is the fruit bowl; the fruit bowl gives them the token of the
banana. If you put the fruit bowl in the glass cabinet, the cabinet
ensures that the tokens it hands out for its contents don't give you
permission to call any methods that require physical access to the
contents. That means the player's code can examine the banana but not
peel it, and the security model enforces this.

It's tough, though. Ensuring that token leakage doesn't happen is
expensive. And I've no idea how user friendly it would be to use.

[...]
> I don't see how you can build a shared universe, one with objects that richly interact, without civility and politics.

Luckily, I don't have to. thickishstring's physics model is totally
crippled compared to traditional MOO. Each area is owned by a player and
the scripts that drive the area cannot communicate with anything outside
that area. Their interactions with the player are limited to telling the
player stuff and moving the player from room to room within the area.
That's it.

[...]
> Have fun with the causality problems....[1]

I've been looking into Operational Transformation. It makes me sad.

(So far I believe that I can run realms in parallel; as the only
communication between realms happens when the player moves between
realms, which is very rare, that limits the amount of cross-domain
synchronisation needed. Now, whether I can run realm instances in
parallel is another matter. And I didn't realise that GAE was so *slow*.
One update to a single database entity a second!)

[...]
> Aw, can't you make the "it's a game! we should use Lua! Lua is for games!" argument?

Not being able to use Lua also makes me sad.
signature.asc

Todd Sundsted

unread,
Apr 4, 2013, 9:06:23 AM4/4/13
to David Given, moo-talk
On Wed, Apr 3, 2013 at 12:20 PM, David Given <d...@cowlark.com> wrote:
Jay Carlson wrote:
[...]
> Anyway, what would you do differently?

I think there may be some scope in tying object access rules to the
object scoping rules. That would limit the possible interactions to only
those objects which are physically present.

The problem with this is that the virtual concept of physical presence only makes sense for some interactions, even at the command level.  With that said, I'd be interested in more constraints.  While, for some virtual reality settings, the idea of more experienced programmers "taking advantage of" novice programmers might be interesting game play, it's not always ideal...
 
If we're willing to contemplate a radical redesign, it might be worth
stealing ideas from the capability-based OS people: instead of having
object IDs have limited-access tokens that you have to petition other
objects for. The player gets given a token to the room they're in; they
can ask that room for the tokens of visible objects in that room; one of
them is the fruit bowl; the fruit bowl gives them the token of the
banana. If you put the fruit bowl in the glass cabinet, the cabinet
ensures that the tokens it hands out for its contents don't give you
permission to call any methods that require physical access to the
contents. That means the player's code can examine the banana but not
peel it, and the security model enforces this.

Do-able, IMO.  This is actually how Stunt started.  I started trying to "build a better VR" in plain-old LambdaMOO/MOOcode, and added features to the server when either 1) there was no nice, clean way to do it with existing functionality, or 2) I had a good solution in MOOcode and wanted to improve it by adding server support ($private(), $protected() et al will probably go this route, eventually).  I spend a lot of time prototyping things in MOOcode to find the rough edges.

Todd

Todd Sundsted

unread,
Apr 4, 2013, 9:07:29 AM4/4/13
to David Given, moo-talk
...and unfortunately (but as is often the case) all the server/core hacking has left very little time for work on an actual VR...

Todd

Todd Sundsted

unread,
Apr 6, 2013, 2:57:17 PM4/6/13
to Jay Carlson, David Given, moo-talk
On Tue, Apr 2, 2013 at 7:50 PM, Jay Carlson <n...@nop.com> wrote:
On Apr 2, 2013, at 11:21 AM, David Given wrote:

> Todd Sundsted wrote:
> [...]
>> Why don't you want to allow them to program directly in MOOcode?
>
> There are things that MOOcode allows which I don't want the users to be
> able to do. One is:
>
> while (1)
>  suspend(0);
> endwhile

You can set $server_options.protect_suspend. There's always programmer.queued_task_limit too.

I'm not happy with LambdaMOO's implementation of cooperative multitasking, but it's simple enough.  I'm mostly unhappy with the fact that it's hard to write code that's guaranteed to have enough ticks to complete.  Rather than explicitly worrying about ticks and seconds, I'd like code that suspends whenever it's appropriate, and transactional memory + language support that takes care of managing atomic sets of reads/writes.

> StiI haven't found a way to protect the system from this yet.

In theory, bozos with queued tasks go to the end of the line with the scheduler too, but your load average will peg at 1.0. But that's in a world where a lag meter returns non-zero.

For maintaining programming discipline, I _am_ implementing journaling of ticks/seconds used information so that I can report on it offline.  I don't care so much if a programmer writes (intentionally) poor code, if the resulting resource usage is can be used for management.
 
> Another reason is it doesn't seem possible to generally prevent one
> player from calling methods belonging to another object.

Life would be boring if other people couldn't talk to you people or you couldn't be moved. People climb into the Human Cannon and then have .sessile or some other refuse-to-:moveto set. It violates the consensus reality contract if the cannon is fired but people inside don't go out the barrel. So anybody left over gets :eject()ed; a $room owner can throw any object out because of the wiz perms on $room:eject().

Yes!  There is always going to be some effort involved in building objects that work well in a cooperatively programmed environment.  Understanding the environment is part of the learning challenge.
 
Anyway, what would you do differently? There are not that many systems out there trying to cope with mutually-suspicious programmers, so this really is an open question. I've been trying to figure out the live-Wiki analog to MOO for years now and haven't quite gotten the model straight. My latest attempts have returned to the ability of programmers to add their own private properties/annotations to objects but still keeping the suid-by-default model.

Yes, again!  LambdaMOO is 23+ years old, but parts of the problem set are still fertile ground for innovation/research.  LambdaMOO is not as popular as it once way, but I think of that as a benefit of sorts.  Even ten years ago there was strong resistance to doing anything ground-breaking with the server because of concern over incompatibility with the installed base.  That's pretty much a moot concern now.  Yet, at the same time there is a small base of interested users, so that I can have conversations like this, for example.
 
> Also, unfortunately, the
> guy I'm trying to sell this to (in a mind-share sense) likes Python...

Aw, can't you make the "it's a game! we should use Lua! Lua is for games!" argument?


Surprisingly (or perhaps not) I spend a lot of time studying other languages for features that might make sense in MOOcode.  Lua is one of them.  I'm waiting for the day when someone points out that I'm making MOOcode look too much like language XYZ.  Coffeescript, anyone?

 
Jay

Jay Carlson

unread,
Apr 8, 2013, 1:42:42 PM4/8/13
to David Given, MOO-...@googlegroups.com


On Apr 3, 2013 12:21 PM, "David Given" <d...@cowlark.com> wrote:
>
> Jay Carlson wrote:
> [...]
> > Anyway, what would you do differently?
>
> I think there may be some scope in tying object access rules to the
> object scoping rules. That would limit the possible interactions to only
> those objects which are physically present. It makes intuitive sense
> that in order to be able to peel the banana, you have to be able to see
> inside the fruit bowl. Remote peelings would hardly ever be useful.
>
> Of course, for performance reasons this would probably require baking
> the scoping model into the server...
>
> If we're willing to contemplate a radical redesign, it might be worth
> stealing ideas from the capability-based OS people: instead of having
> object IDs have limited-access tokens that you have to petition other
> objects for. The player gets given a token to the room they're in; they
> can ask that room for the tokens of visible objects in that room; one of
> them is the fruit bowl; the fruit bowl gives them the token of the
> banana. If you put the fruit bowl in the glass cabinet, the cabinet
> ensures that the tokens it hands out for its contents don't give you
> permission to call any methods that require physical access to the
> contents. That means the player's code can examine the banana but not
> peel it, and the security model enforces this.
>
> It's tough, though. Ensuring that token leakage doesn't happen is
> expensive. And I've no idea how user friendly it would be to use.

Consider a new class of objnums which are indirect and resolve dynamically.

#-10 could be "my location". Calling #-10:contents() would turn into a call on #1234:contents(), except with some analog of "caller" or "player" set to #-10 still. The location would know it was being accessed through a local name.

Setting up the dynamic environment is a bit tricky. I think suspend() and fork should tear down any existing bindings.

This might also clarify some long-standing niggles in how !x verbs work; a #-20 resolving to dobj and #-21 resolving to iobj could get those symbols out of the verb local variable environment.

Hell, player could go.

Reply all
Reply to author
Forward
0 new messages