Can we make TokenScript libraries cross-platform?

A ToenScript might be used:

  1. In user-agent (Android)
  2. In user-agent (iOS)
  3. In user-agent (MetaMask plugin)
  4. In data processing service (Amber data's data engine)
  5. In IoT devices
  6. In a Token management console (token issuer's backend tool)
  7. In an IDE (IntelliJ or Microsoft based)

The first 3 are the most urgent. However, their preferred languages are Java, SWIFT, JavaScript.

  • There is some cross-section of the former two. e.g. Rust/C code can be ported between the two to a certain extent and can be used in IoT as well
  • but a Java-based approach works best on Android and in data Processing.
  • MetaMask plugin approach might strictly JavaScript based. Yet it might prepare the code to execute in WebAssembly.

There is quite a bit of pathfinding needed. Here are my thoughts, using the route of least resistance method.

Java JavaScript Rust C
Android OK OK OK
iOS OK OK
MetaMask OK
Data Processor OK
IoT ? OK OK
Token Console OK OK OK OK
IDE OK OK

Think Java

  • Java's Java Cryptography Architecture (JCA) is the easiest to use and produces the least amount of code. So a Java-based library might be produced anyway.
  • From there, a library suitable for data processing might be produced as well.
  • And to develop a plugin for IntelliJ.
  • It's also easy to build a Java desktop tool for Token Console.

Think JavaScript

xml-crypto is a JavaScript library for XMLDigital Signature. Unfortunately, it doesn't support Manifest (useful for getting resources off IPFS etc), and it doesn't support ECDSA†.

† we depend on web3.js so ECDSA validation of the Express-of-Trust isn't a problem. Here we talk about ECDSA signatures on the TokenScript. See the difference between these two concepts.

It's perhaps not a good idea to provide JavaScript-based TokenScript library for iOS and Android since they use the library not only in a WebView.

Think Rust/C

To run Rust/C code in iOS/Android, we need it to have a minimalist dependency. There already was a libxml2 wrapper for iOS, so we are left with these choices:

  • Build a basic XML security library in SWIFT thanks to the XPATH/C14N support in libxml2. This has the least reüse value.
  • Build a minimum RUST library for XMLDSIG and shoehorn it into iOS. This requires extending the current RUST wrapper for libxml2 to include support for c14n (libxml2 supports c14n but the wrapper doesn't).
  • Shoehorn a RUST wrapper for libxmlsec1 into iOS.

The 3rd choice is the safest since it doesn't start with the word Build. One should not create a security library on a whim. But the community work has just begun on wrapping libxmlsec.

It will be easy to write a Token Console in Rust/C, but it will be difficult to integrate libxmlsec, which uses openssl/gnutls/nss, with Android/iOS's security strong-bux. Luckily we can avoid that.†

† because

  • When used in Android/iOS, both validates XML security, not signing TokenScript files, so we don't have to integrate iOS/Android's security strongbox with that C library.
  • When (potentially) used in a Token Console (use-case 6) or in an IDE (use-case 7), signing would be actually needed. But the environment is likely not mobile, so again we don't have to integrate iOS/Android's security strongbox with that C library.

What about running the RUST/C library in Web Assembly

The advantage, clearly, is not having to provide a JavaScript-based TokenScript library.

For the security quarantine reason, I prefer to think WebAssmebly as the run time environment of Token Enclave code - the bit of code embedded in TokenScript files, and not where the TokenScripts are parsed and examined. Rather instead, the TokenScript library running outside of the web page (in plugin-space) prepares the code to run in a WebAssembly (on the web page). This way the website, if gained the ability to compromise a WebAssemly instance, will not be able to validate a falsely signed TokenScript.

We still can, if that turns out to be an easy path, have a special WebAssembly instance just for TokenScript file parsing and security functions, live inside a plugin. This is an atypical way of using WebAssembly, since a WebAssemly instance runs on a web page, not on a plugin, and are supposed to live within the life-span of a web-page. Going down that route we are likely to trigger bugs that others don't see important.

Conclusion?

At first, it seems all 3 of them has to be implemented. Not any 2-out-of-3 combination will serve all purposes.

We can get by with JavaScript + Rust/C combination if we ignore traditional data processing needs. The fact that Indy is built with JavaScript, not Java, shows that the community shuns Java even in the area it is mostly suited and its traditional stronghold (service-oriented backend data processing). I'll consult AmberData on which framework they use to collect data. If they also ditched Java we can ditch Java out of the picture.

But that means we ditch the easier route (Java) in round 1. Java is the easier rought thanks to JCA.

It's perhaps not a good idea to provide JavaScript-based TokenScript library for iOS and Android since they use the library not only in a WebView.

Regarding JavaScript support for our use cases, JavaScriptCore is built-in with iOS. We should be able to support JavaScript on Android by bundling JavaScriptCore. This is how React Native runs JavaScript code on iOS and Android. Node runs on the cli and there is some support on IoT devices though I'm not sure how convenient it is to be used in a data engine (and especially its performance).

If we disregard the libraries (or the lack of them) for our purposes, it's actually the most portable language for our purposes. It also has the benefit that it works as a transpilation target for several better languages like TypeScript and ClojureScript if we don't want to use JavaScript directly.

What about if we pick an implementation language and write as much of the logic as possible and let native code (or otherwise code callable directly from native code) handle what we can't [1]? Good examples are XML parsers, XML canonicalization and XMLDSig, i/o, UI etc. A significant part of the TokenScript client is the logic that implements the schema (and in the future multiple schemas) and its changes as well as data flow and having a single code base (and a single set of tests) for those helps to reduce bugs and reduce development time, whereas tasks like XML parsing, XMLDSig ought not to change as much and are library-heavy.

[1] Such "native" code might include calling web APIs if a certain platform lacks good libraries for tasks. E.g XML for iOS

Having solidified that, it's high time we start coding a JavaScript library based on the said xml-crypto JS library.

I'm inclined to agree with @hboon, we should implement the initial cross platform code in JS as a start to quickly understand the scope of the project.

Following this; we will know what it can't handle and if it would be better to implement in a lower language with all the advantages that brings. Following this the library can be replaced piecemeal, cyborg like until a final implementation in Rust or C++ is complete.

Implementing an XML core would be a big step forward; the XML support in Android is not so good. Are there any XML frameworks we can use?

Implementing everything in JS though would need large development teams with slow release cycles.

Bumping up the requirement for more and more compatibility libraries is slightly worrying; but if it allows rapid prototyping and a better way of assessing where we need to put in optimisation work then this is way to go.

A good start would be an XML parser framework that can handle references; this would be instantly useful on Android.