[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Taler] statically typed wallet, wrapper functions

From: Florian Dold
Subject: [Taler] statically typed wallet, wrapper functions
Date: Mon, 14 Dec 2015 05:27:39 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.4.0

Hi all,

I got annoyed by all those little mistakes and typos that only show up
when you reload the wallet extension and do something, so I've moved the
WebExtensions wallet to TypeScript (www.typescriptlang.org/Handbook).

Unlike emscripten, the output of the TypeScript compiler is
human-readable Javascript, so there shouldn't be any issues with
in-browser debugging.  It's also possible to mix in Javascript code
freely.  The syntax is a superset of Javascript.

To generate the *.ts files, run the compiler ('tsc') in the extension
directory without any arguments.

When adding a new TypeScript source file, make sure to add it to the
tsconfig.json file.  An X.ts file will be compiled to an X.js file in
the same directory.

Type declarations for existing/external Javascript functions are placed
in the decl/ folder.  This includes stuff like the DOM or the chrome.*
extension APIs.

The wrappers for foreign objects from emscripten now look like this
(full, working code):

class EddsaPrivateKey extends PackedArenaObject {
  static create(a?: Arena): EddsaPrivateKey {
    let k = new EddsaPrivateKey(a);
    k.nativePtr = emscAlloc.eddsa_key_create();
    return k;

  get size() { return 32; }

  getPublicKey(): EddsaPublicKey {
    let pk = new EddsaPublicKey(this.arena);
    pk.nativePtr = emscAlloc.eddsa_public_key_from_private(this.nativePtr);
    return pk;

Note that by extending the PackedArenaObject, we'll inherit functions to
destroy the object and encode it in base32crockford.  If we forget stuff
like the 'size' property, the compiler will let us know.  The
PackedArenaObject conceptually corresponds to structs that have the "P"
suffix in Taler.  Plan ArenaObject-s can't be automatically converted to
a string, since we don't know their size or layout.

And blind signing now actually has a signature ;-)

function rsaBlind(hashCode: HashCode,
                  blindingKey: RsaBlindingKey,
                  pkey: RsaPublicKey,
                  arena?: Arena): ByteArray {

Note that the arena is optional, if we leave it out the object will be
allocated in the global default arena.  This still allows us to track leaks.

I'm actually not sure whether it's better to use the existing wrapper
functions like this one

struct TALER_WithdrawRequestPS *
TALER_WRALL_make_withdraw_bundle (
  const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub,
  const struct TALER_Amount *total,
  const struct TALER_Amount *fee,
  const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub,
  const void *coin_env,
  size_t coin_env_size);

or if we should just construct the signature object inside native

We could do something like this (not implemented):

class WithdrawRequestPS implements SignatureStruct {
  get fieldTypes () {
    return [
       ["reserve_pub", ReservePublicKey],
       ["amount_with_fee", Amount],
       ["withdraw_fee", Amount],
       ["h_denomination_pub", HashCode],
       ["h_coin_envelope", HashCode]];

which saves us from
1. Having the wrapper function
2. Type-errors when calling the wrapper function.  In the example above,
everything is typed and named.  We only have to get all fields and their
order right *once*.

You'd use it like this:

let x = new WithdrawRequestPS({reserve_pub: bla, ...});

We'd automatically have the binary representation when all members are
either PackedArenaObjects or some other type that provides us the
necessary info.

We'd also have an automatic JSON serialization of the withdraw request,
with is convenient for the database.


- Florian

reply via email to

[Prev in Thread] Current Thread [Next in Thread]