Namecoin SPA

From Organic Design wiki
Revision as of 23:01, 27 August 2012 by Nad (talk | contribs) (the old NR.c code)

I'm making a Single Page Application which exists entirely inside the Namecoin network's name:value storage system. Values can only be a maximum size of one kilobyte, so the boot-strapping has to be very modular. In fact it turns out that the current version has a bug that prevents values from being updated if the current value is greater than 520 bytes! There's discussion about raising the limit at some point to around 9KB, but incurring steeper transaction costs for updates greater than 1KB.

od_init is the first node which declares two functions, the first called "v" takes a namecoin domain name and returns the content of its value field, or "404" if no such name was found. The second function called "d" extends the first function by taking one or more namecoin domain names and treating their values as the content of functions thats it declares. After the two functions are declared, it then calls "d" with "od_http" as the parameter to declare the contents of that domain as a function, and then calls that function.

{{{1}}}


od_http is a small server loop which listens for HTTP requests on port 2012, it declares functions from two other domains, "od_send" and "od_recv" which are called within the loop. The od_recv function is called when the server loop detects that input needs to be processed, the result will always be a domain name which is then passed through the "v" function to get its value, and this value is sent back to the client as an HTTP response message by od_send.

{{{1}}}


od_send composes the passed content into an HTTP message and sends it to the client.

<perl>select$c;$


od_recv reads in the GET request text and extracts just the valid domain part of it if any. If no domain is requested, then an HTML page is constructed from three other domains, "od_html" (an HTML DOCTYPE definition and opening element), "od_head" (meta tags, CSS and useful JS frameworks) abd "od_js" which is the next stage of the applications execution.

{{{1}}}


od_html is a standard DOCTYPE definition and opening HTML element for our applications page.

<xml><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr"></xml>


od_head is the HTML head element for our page including jQuery and jQueryUI which are practically prerequisites for any kind of web application these days.

{{{1}}}


od_json is the initial script that gives us the ability to declare new functionality from other namecoin domain values, it defines $v and $d functions which perform the same role as the initial Perl stage. In this case the $v function is passed a domain name and a function references, it retrieves the value of the name from the Perl server via Ajax, and then executes the passed function when the value is returned. Since all the names from here on are preceded by "od_", that part will be ommitted from here on and added by $v when requested the name from the Perl server.

The $d is also passed a name and a function reference, the name is passed to $v along with a function that declares a new function of the same name as the domain with its content being the value of the name. The new function is declared inside the $d function-object so it can be accessed from any scope.

The $j (JSON) function is more high-level, like the previous two, its accepts a domain name and a callback function to deal with the resulting value (obtained via $v), but the result is treated as JSON data and stored as an object inside $j. The $j function looks in a property called "map" for the properties it will store for the node, the reason being that the JSON is then compatible with the namecoin network's method of encoding relationships between domains. If the JSON was not valid or there was no "map" property, an empty object will be stored. The resulting object is then passed to the processing function to handle.

This level of functionality now gives us the ability to define an Ontology, i.e. a triple-space of nodes with a reasonable number of relationships to other nodes (remember the JSON description must currently stay under 520 bytes).

It then uses $d to declare a new function from the "od_loop" domain which defines some fundamental functionality for a small group of domains that will be treated as nodes.

<js>function $v(n,f){$.ajax({type:"GET",url:"/od_"+n,success:function(v){f(v)

)}

function $d(n,f){$v(n,function(v){eval("$d."+n+"=function(){"+v+"}");f()})} function $j(n,f){v=$v(n,function(v){$j[n]={};try{j=$.parseJSON(v)}catch(e){j={}}if('map'in j){for(i in j.map)$j[n][i]=j.map[i]};f($j[n])})} $d('loop',function(){$d.loop()})</js>}}


od_loop makes sure that the number of current JSON objects inside $j is kept to a maximum by disposing of the ones that haven't been accessed for longest. This is done by declaring another function called $l by which the objects are accessed rather than directly accessing them via $j. This allows the objects in $j to be organised and "lazy loaded" on demand if necessray.

The easiest way to do this is by adding some properties to the objects in $j forming a closed linked-list, or loop, that has one position considered to be the start (and the previous, to be the end). All newly created nodes (which are created simply by requesting items that aren't yet loaded or have been previously deleted) are inserted into the start point, becoming the new start, and if the total number becomes more than the maximum number allowed, then the one in the last position is deleted.

The $l accessor function moves the $j object being accessed to the head of the list to ensure that only the objects with the least activity are ever deleted. Note that there is not really a list of items making up $l, i.e. there is no array like there is within $j, the loop accessed via $l exists entirely in the form of next and prev relationships between the $j items.


od_node

After od_node is executed, all further program execution will be controlled by the relationships between nodes. It does this by treating a node as a reducable recursive queue, itself being the default starting point for this process if there is no node specified in the hash-fragment of the current URL. It declares another function from the od_hash domain, which allows this focal point to be connected to another node at any time by changing the hash-fragment, either directly, or by clicking on a link in the page that has a hash address.

If some executing code requests an object using $n and the object is already loaded, the reference is returned and the function execution continues on. However, if the object is not loaded, then the function returns null and execution should stop and any calling function will return null upon receivng a null - these nulls propagate all the way back to ensure a clean halt to the entire executing reduction structure. The same thread will continue again when the missing function has loaded because the the $n will ensure that the context from which it exceuted will be reestablished when the requested node has been loaded.

So in addition to defining $n, od_node's job is also to define the program-flow mechanism using relationships between nodes. Each node that gets focus may have an associated function to execute which will then be called with this set to that node entry within the $j structure. Functions must not rely on local scope across calls to $n because execution can be broken at that point by the requested object needing to be loaded.

The main purpose of od_node is basically to create a jQuery event-based version of the nodal reduction recursive toroidal execution algorithm developed in 2005. Here's the main reduction function written in C that od_node will be replicating.

// Moves "this" to node's focus if exists then rotates loop and executes/reduces the focus item
void nodeReduce() {
    if(this = nodeLoopRotate(parent = this)) {        // Move "this" to the focus in the node's loop and rotate
        nodeSetValue(this, nodePARENT, parent);       // Update the parent association
        if(code = *nodeState(this, nodeCODE)) code(); // nodeCODE value is a pointer-index, execute as function-reference if non-zero
    }
}


od_hash

When the URL hash-fragment changes, it should behave similarly to a page reload except without needing to reload anything. The result is that the focus (of nodal reduction) moves to the new node specified in the fragment, effectely putting the prior context "on ice" until it regains focus at a later time. Remember that the od_node function treats any passed node name as a reducable queue to execute if one is passed, and only does its function declaration followed by default-node reduction if no node-name was passed.

<js>$(window).bind("hashchange",$d.od_node(window.location.hash.substr(1)));</js>


See also