vircadia / vircadia-native-core

Vircadia open source agent-based metaverse ecosystem.
https://vircadia.com/
Other
531 stars 175 forks source link

Project: Script Engine Upgrade #1180

Open digisomni opened 3 years ago

digisomni commented 3 years ago

This issue should serve as the central discussion for notes / needs for the script engine upgrade.

Mandatory Requirements for the New Scripting Engine:

JulianGro commented 3 years ago

My understanding is that all the mandatory requirements you list wouldn't need to be part of the actual script engine.

Security Context: The scripting engine will not know what kind of contexts we would need and what api functions would be allowed in what context. If the scripting engine has no functionality for defining what is and what isn't allowed, we can just do that on the api side.

Security Sandboxing: I don't see why the scripting engine would need proper sandboxing functionality. My understanding is that we wouldn't allow anything to leave the script engine except api calls. Of course it would be useful if we can just disable functions that access stuff like the filesystem or the internet, but my understanding is that we can just not give its thread access to the internet or the filesystem. Even if that is not possible, my understanding is that it would be trivial to disable functions which access filesystem or networking inside the script engine source code.

Script Versioning: If the script engine had no way of getting a version like that, we have several alternatives like checking the version before giving the script to the script engine, or defining the version in a call to the api and have the api handle that.

That being said, if we don't want to go with QJSEngine it would probably make sense to use a scripting engine that allows better upstreaming of changes/fixes than Qt does. Alternatives I have found while looking around:

daleglass commented 3 years ago

I think the first step would be to refactor the current code to make sure more than one scripting engine can exist.

This is because no matter what, this will be a big project. There's no doubt problems will arise. And given that everything depends on a working scripting engine, we can't just rip it out and spend half a year trying to integrate a new one. Everything would grind to a screeching halt.

That already exists to some extent, so it shouldn't be a huge project. I suggest the following milestones:

  1. Cleanup and document. There's a fair amount of documentation in ScriptEngine already.
  2. Present the current state of the system. As in somebody actually makes a presentation explaining what is where, what the parts are, how they interact, what design issues exist.
  3. Discuss how to refactor
  4. Refactor. The old script engine should remain just as functional as before.
  5. Implement a minimal, proof of concept second engine. QJSEngine probably would be easiest. By minimal I mean it can run a "hello world" -- this is a quick demo of how multiple engines work.
  6. Complete implementation of QJSEngine. I think it's the easiest one we could possibly do, so it's probably worthwhile even if it turns out to suck. Out of this we can draw some conclusions -- is it good enough? Is it lacking something? Did we screw up the refactoring somewhere?
  7. If we're unhappy with something at this point, only now consider V8 and alternatives.

My current preliminary thoughts:

daleglass commented 3 years ago

Thoughts on script security:

It's complicated because we don't have proper user accounts like SL does, and there's a lot that needs doing to keep things safe but usable. But here's my rough idea on the model.

Every API function call should begin with a call to the security system that evaluates the situation and returns a result: do we proceed, or not.

Here's a list of things we can currently look at:

Based on this we formulate a base policy. What is the default set of things that's okay to do? For instance:

Anything not permitted fails immediately without any questions. The security API would come with a "request permission" function that could be called first, to obtain a permanent or temporary exemption. Perhaps there also may be implicit permission grants, where the user doing something may grant permission for it to be done to them, for user friendliness.

There should be some way for grouping up permission requests to present a bunch at once, including for a whole domain. Like if a domain creates a game, which needs to rearrange your menus and to control your camera, this could all be done upfront.

digisomni commented 3 years ago

My understanding is that all the mandatory requirements you list wouldn't need to be part of the actual script engine.

Essentially, they are considerations to keep in mind when implementing the new one. It may not necessarily be the case that the new scripting environment will have these features implemented from go, but it is a requirement that it should support their implementation right off the bat when we do get around to it. We want to make sure that whatever is chosen and however we implement it is considering the things that we've long missed with our current implementation.

ctrlaltdavid commented 3 years ago

A good first step could be to refactor the current scripting implementation in conjunction with adding Qt's new script engine as a (compile time?) alternative - so that the new script engine can be tested against the old script engine, and to provide the framework for inserting other scripting engines.

digisomni commented 3 years ago

Yes, I suppose getting another one "pulled in" to experiment against whilst trying to separate things out will probably be step 1. Unless it's QJSEngine, in which case I'm pretty sure we can just write that code outright since it comes with Qt.

Though, I don't think QJSEngine will cut it just from what I know about it (being slow) vs scripting in mainstream game engines like Unity3D. We expect speed and control.

So, if it's easier to develop a parallel structure using QJSEngine as the fill in first, then cool. If it's easier to import V8 (or something like it) at the base and then use that to start testing out a parallel structure, also cool.

I think that many core pieces will probably change (especially in the way security would be handled) so maybe not making the parallel structure with QJS makes sense. Why? Because the way QJSEngine works would be fundamentally different from how the real implementation would work, no?

JulianGro commented 3 years ago

The question to me would be: In what way would QJSEngine be too slow and in what way would there not be enough control. I mean all really heavy calculations should probably not be done inside the scripting engine, but realistically speaking why would there be any real speed differences compared to any other JavaScript engine. What would a game even do inside a scripting engine that would require extreme performance that a mortal scripting engine cannot do?

I mean of course the engine shouldn't be extremely slow, but we are talking about Qt not some random dude on the Internet who coded the thing as a university project.

daleglass commented 3 years ago

@JulianGro Regarding performance, I agree in that it's probably a very secondary concern for the time being. Given that we control the entire system, if we need something performance intensive we could just make an API for it, such as cryptographic functions.

Regarding "not enough control", for instance QJSEngine doesn't have the debugging and monitoring support that QScriptEngine does, so for instance, PR #1156 uses an API that's not available in QJSEngine.

We probably need control more than performance, for instance for monitoring execution and being able to deal with misbehaving ones. For example we'd definitely want to set some sort of resource usage limits, and QJSEngine doesn't seem to provide any way for doing so. That's not surprising, it's an engine definitely not planned for this use case.

I think QJSEngine still should be implemented, because it's almost certain to be the easiest thing to try by far. Then based on that we can see how much trouble we run into practice, and how important it would be to spend the time on something else. And most anything is going to be a good deal trickier because we're going to need some sort of Qt/JS translation mechanism. The ones included in Qt have the enormous advantage of already having one.

It also might make sense to consider other options. For instance perhaps WebAssembly would be an easier thing to deal with because I imagine that if compilation of code can be dealt with separately, it makes for a smaller and simpler library that may be less troublesome for us.

odysseus654 commented 3 years ago

Yes, with all the stuff I've abandoned i've been thinking about this (specifically V8, as I have the most experience with this engine)

Currently there is a single isolate generated for each domain and each interface. This means that all scripts are in the same namespace (and also makes it much more difficult for us to isolate and prevent memory leaks). Global variables set in one script will be available to any other script that the server/client is running at the time.

My thoughts are to make much more use of isolates, but hopefully in such a way that we don't blow memory requirements out of the water (especially if we have a script actively trying to crash the system). There is no obvious limit to the number of isolates that can exist although we should keep things down to a "sane" number ( https://stackoverflow.com/questions/65088028/v8-isolates-is-there-a-limit-to-the-number-of-instances-crashes-at-4-7k-insta )

My current thoughts are:

For "context" I'm thinking of the following, which also defines the APIs that scripts have access to:

stale[bot] commented 3 years ago

Hello! Is this still an issue?

daleglass commented 2 years ago

This will take a while, but still a thing

stale[bot] commented 2 years ago

Hello! Is this still an issue?

odysseus654 commented 2 years ago

I really hope so

On Tue, Jul 26, 2022 at 9:43 PM stale[bot] @.***> wrote:

Hello! Is this still an issue?

— Reply to this email directly, view it on GitHub https://github.com/vircadia/vircadia/issues/1180#issuecomment-1196259965, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAIQHMG4CNOPIZU4C5KN6BDVWC46LANCNFSM43ARCNPA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

digisomni commented 2 years ago

It is still indeed, an issue. 🙃

stale[bot] commented 1 year ago

Hello! Is this still an issue?