See DAGSync: Graph-aware Zcash wallets by str4d.
TLDR: as we're syncing the wallet, we normally scan forwards prioritizing both sends and receives the same. Instead we can optimize this for immediate spendability (despite not having full received balance). Assume we have the entire blockchain state but haven't yet trial decrypted all notes.
Additionally:
Knitting is where periodically wallets will gather all unspent coins and construct a new one. It will use the memo field to indicate to wallet sync that it doesn't need to go back any further than this point.
However since wallets keep track of their own coins (assuming a wallet isn't shared between 2 devices) which is the majority usecase, then this technique is less relevant since you know which coins you've spent.
The current standard model for smart contract cryptocurrencies is to abuse the web browser's plugin architecture. This has several undesirable effects:
Benefits of hackable software are:
help(foo) on objects.Addons are sandboxed WASM code which has tightly controlled permissions. They are untrusted third party 'apps'.
Most functionality are the client code for wallets. For example we want to use the DAO contract so we download an addon. An addon may provide this functionality:
Addons should be sandboxed. By default access to all host functions is blacklisted, and they must be explicitly whitelisted to call any function other addons.
We can run addons in separate threads so that if one of them crashes, the host application can simply kill the process. Addons can then run alongside each other without any effect on each other. However this leads to increased memory usage from the overhead of having every addon spawning a new thread, so we may wish to use WASM functionality to interpret addon functions that take too long.
There is a special function inside the WASM which is called on startup
called requested_permissions(). This is used to request the
permissions from the user who then adds it to the whitelist for this
addon. While the requested permissions will be a list of namespaced
functions, the UI will simply display these as something simple to the
user like "manage a database" or "use event graph" (see below).
Addons are loaded dynamically and can be downloaded from a source such as the DHT network.
Blender's addon browser looks much better than Firefox's.
When creating addon UIs, there should be a way to allow live reloading of the UI for convenient design, and possibly the impl too which makes live debugging possible.
Overtime there will be a tension between upgrading the core API and maintaining a large ecosystem of addons. Therefore there should be a centralized git repo for all addons listed in the wallet. Addon authors can tag releases and request their addon be updated downstream by the wallet maintainers.
This way when large breaking API changes are needed, we have the ability to:
This is similar to how Linux distributions maintain packages.
Addons must also have contact details so darkfi core and the wallet team are able to contact them.
These are dynamic objects which are trusted and provide full access to the host system.
An example of such a module could be an event_graph module.
This enables addons to request a specific event graph instance. For
example the users of a DAO may wish to coordinate through the p2p
network. They would therefore use the event_graph module to create an
event graph instance for that usecase, and the p2p network would create
a swarm for this event graph. All of this would be handled by the
module which simply provides a convenient interface to the addon.
This enables using the full power of the system, but safely segregating this functionality from untrusted addons through a firewall. It solves the issue of relying on hosted/centralized gateways since user wallets will just spin up p2p nodes locally.
Modules can only be installed manually from file and require restarting the wallet.
This is a popular gamedev design pattern where the entire program state is represented as an introspectable tree. It's similar to the UNIX pattern of "everything is a file", and maybe plan9's idea.
The scenegraph is a world where the children are objects, and the objects have attributes that can be read and operated on. These can all be composed together through generic node interfaces.
example of a scenegraph from a game engine
scenegraph in blender
Application
SettingsRegistry
Window #1
TabBar
Tab #1
Panel #1
WasmSandbox
...
Panel #2
...
Tab #2
...
...
Window #2
...
Module #1
event() method and update() method.
Update is called per frame, while event can be used for timer events
such as periodic updates or wakeups, as well as input events.draw() method. Drawing outside the boundary is
disallowed.Laundry list of required features:
See also the Blender Human Interface Guidelines: Paradigms.
drk CLI tool with basic core apps working. We want to ship
so this is the only core prerequisite to start.Steps 3 and 4 can be done in parallel.
Multi-platform main view with splitting and these editors:
The story goes like this. There's a node running of some kind. This could be darkfid or darkirc.
In the case of darkfid, there's additional per wallet processing that's done such as scanning transactions. Currently this is the role played by drk scan.
Regardless of whether there's one node with functionality existing as pluggable modules, we assume now there are nodes running which the wallet/UI must communicate with.
Inside the user wallet, there are multiple plugins. A plugin might need to query the blockchain, spawn a p2p network (to exchange data for OTC or coordinate DAO activity as examples). They do this by connecting to the nodes.
We now give an overview of the current iteration of the scene graph:
bin/darkwallet/pydrk/api.py:5 for the fields in a property.mouse_clicked. Multiple slots can be
registered for a signal. Think of this like notifications.create_foo() which is like request-reply.Each app has a separate plugin. Plugins have their own private internal data. Any data they wish to expose can be done by providing properties or methods in their node in the scene graph.
The scene graph then applies access restrictions depending on the ownership semantics of properties and methods (think like UNIX users and groups).
Plugins provide init() and update(event) functions. init() is
called when a new plugin instance is created. Plugins can have
multiple instances.
Using the scene graph, this is scriptable from any language, introspectable and with permissions - using a data structure inspised by UNIX and plan9.
When a plugin is opened, the UI creates
/plugin/dao/instance1
and gives it a layer to draw in, which is simultaneously linked into both
/window/dao_instance1_layer
/plugin/dao/instance1/dao_instance1_layer
The plugin can then speak with modules by calling methods or
subscribing to signals on /mod/darkfid. Methods and signals are
automatically proxied from the node.
Lets say we wish to do OTC swaps and utilize the event graph. Are users then required to run a new node per app?
At least in this case, there should be a way to spin up an event graph.
For scanning transactions, is this done at startup incurring an initialization cost when opening the wallet? I guess so to maintain independence of keys from the darkfid node.
Another example is the task manager and darkirc chat. Do these remain separate daemons? When we add swarming support to p2p, it might be possible to merge all p2p functionality across apps into a unified subsystem, reducing complexity. In which case there should be a simple way to utilize this subsystem.
The more nodes users are required to run, the more difficult it will become to have a decentralized network, so we should find a way to reduce the burden for users to setup our infra.
Wallets are clients talking to the node (remote).