diff --git a/.gitattributes b/.gitattributes
index e4062a2..3605b01 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,4 @@
+*keys* filter=git-crypt diff=git-crypt
*.eml filter=git-crypt diff=git-crypt
*.mbox filter=git-crypt diff=git-crypt
*.sec* filter=git-crypt diff=git-crypt
diff --git a/CAStore/genesis.yml b/CAStore/genesis.yml
deleted file mode 100644
index 781ba46..0000000
--- a/CAStore/genesis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
---- # genesis block
-ver: 0
-data:
- seq: 0
- payload: /ipfs/QmWM48KvyK9YyPjJt69erxVPN3nbXVMgZWrncRJhAVkGAv
- comment: "This is the genesis block"
-meta:
- seed: 0xb3560762
- salt: ~ # used in address computation
- txroot: ~
-audit:
- peerid: Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq
- tics: 1623830817245864895
- ip: 83.78.4.228
-prev: ZdtrjkYsAYUeBCs4DRjtVYwPevpxvHjGT2PRauANr3Vao
diff --git a/CAStore/nullblock.yml b/CAStore/nullblock.yml
deleted file mode 100644
index c854162..0000000
--- a/CAStore/nullblock.yml
+++ /dev/null
@@ -1,16 +0,0 @@
---- # null block
-ver: 0
-data:
- seq: -1
- payload: ~
- comment: "This is not a block (null block)"
-meta:
- seed: 0xb3560762
- salt: 12131054599640746025 # used in address computation
- salt: ~ # used in address computation
- txroot: ~
-audit:
- peerid: Anonymous
- tics: 0
- ip: 0.0.0.0
-prev: ~
diff --git a/README.md b/README.md
index d5dd6db..a84b700 100644
--- a/README.md
+++ b/README.md
@@ -12,11 +12,11 @@ layout: simple
- Protect against [double][14] spending
- [Transactions][11] can have additional data payload, signed by the sender (and there needs to be a way to [set it][5])
- Blocks can have additional data payload (and there needs to be a way to set it)
- - Implement a simple REST-like [web service API][1] which implements the following services and returns JSON data:
+ - Implement a simple REST-like [web service][1] [API](/api/) which implements the following services and returns JSON data:
* Query the [block count][2].
* Query a [single block][3] and return all its transaction data.
* Query a [single transaction][4] and return all its data.
- * [Create a transaction][5] from JSON data and accept it for [mining].
+ * Create a [transaction][5] from JSON [data][11] and accept it for [mining][6].
### Example of curl commands
@@ -36,7 +36,7 @@ layout: simple
### Security Warning
- Blockchain are transparent and public so we encrypt private keys and other sensitive data,
+ Blockchains are transparent and public so we encrypt private keys and other sensitive data,
however as it is just a toy, we expose **all the files** for educational purpose.
>> ** PLEASE DO NOT USE IN A PRODUCTION ENVIRONMENT **
@@ -59,14 +59,15 @@ layout: simple
[1]: webservice.html
[2]: http://127.0.0.1:8089/api/0.0/getheight
[3]: http://127.0.0.1:8089/api/0.0/getblock
-[4]: http://127.0.0.1:8089/api/0.0/gettx
-[5]: http://127.0.0.1:8089/api/0.0/settx
+[4]: http://127.0.0.1:8089/api/0.0/gettx?encode=json&addr=txcoin
+[5]: http://127.0.0.1:8089/api/settx.html
[6]: http://127.0.0.1:8089/api/0.0/minepool
-[7]: http://127.0.0.1:8089/api/0.0/getnodes
+[7]: http://127.0.0.1:8089/docs/nodes.html
+[7a]: http://127.0.0.1:8089/api/0.0/getnodes
[8]: http://127.0.0.1:8089/api/0.0/config
[9]: http://127.0.0.1:8089/docs/pow.html
[10]: http://127.0.0.1:8089/docs/difficulties.html
-[11]: http://127.0.0.1:8089/api/transacion.html
+[11]: http://127.0.0.1:8089/api/transaction.html
[12]: http://127.0.0.1:8089/docs/bkreward.html
[13]: http://127.0.0.1:8089/admin/keygen.html
[14]: http://127.0.0.1:8089/docs/UTXO.html
diff --git a/admin/config.md b/admin/config.md
new file mode 100644
index 0000000..c90e187
--- /dev/null
+++ b/admin/config.md
@@ -0,0 +1,18 @@
+---
+layout: simple
+---
+## Config parameters
+
+
+Important parameter to be updated:
+
+- genhash
+- txcoin
+- coinbase public key & signature
+
+
+file : [$SITE/config.yml][1]
+
+
+[1]: /api/v0.0/getcas?dir=.&addr=config
+
diff --git a/admin/index.md b/admin/index.md
new file mode 100644
index 0000000..9e44831
--- /dev/null
+++ b/admin/index.md
@@ -0,0 +1,21 @@
+---
+layout: simple
+---
+# ToyChain Admin Page
+
+1. [signup][1] ([keygen][1])
+1. [settings][2]
+1. [README][3]
+
+
+## Elliptic Curves Keys
+
+1. [EC keys][4]
+1. [coinbase key][5]
+
+
+[1]: keygen.html
+[2]: settings.html
+[3]: /README.html
+[4]: /api/v0.0/getcas?dir=secrets&addr=keys
+[5]: /api/v0.0/getcas?dir=.&addr=registration
diff --git a/admin/keygen.js b/admin/keygen.js
new file mode 100644
index 0000000..bd777a9
--- /dev/null
+++ b/admin/keygen.js
@@ -0,0 +1,18 @@
+const useCapture = true; // capture, bubbling: false
+var elem = document.getElementsByTagName('button')[0];
+elem.addEventListener('click',keygen,useCapture);
+
+function keygen(ev) {
+ console.log('keygen: %o',ev)
+ let name = document.getElementsByTagName('input')[0].value;
+ let namep = name.replace(/ /g,'+');
+ let url = api_url + `keygen?name=${namep}`;
+ let data = fetch(url).then(resp => resp.json()).
+ then(obj => {
+ let tarea = document.getElementsByTagName('textarea')[0];
+ tarea.innerText = JSON.stringify(obj.identity);
+
+ console.log('keygen.obj.keys:',obj.keys);
+ }).
+ catch(console.error);
+}
diff --git a/admin/keygen.md b/admin/keygen.md
new file mode 100644
index 0000000..56bc2f0
--- /dev/null
+++ b/admin/keygen.md
@@ -0,0 +1,22 @@
+---
+layout: simple
+base: "../"
+---
+## Toy-Chain : Key pair Generation
+
+
+
+identity:
+
+
+
+key files: [$SITE/secrets/keys.yml][1]
+
+
+
+
+[1]: /api/v0.0/getcas?dir=secrets&addr=keys
+
+
+
diff --git a/admin/manual-registration.md b/admin/manual-registration.md
new file mode 100644
index 0000000..8ecb953
--- /dev/null
+++ b/admin/manual-registration.md
@@ -0,0 +1,19 @@
+---
+layout: simple
+---
+# manual miner registration
+
+1. edit [templ/txcoin.yml][1]
+{% comment %}
+2. run ``signtx.pl templ/txcoin.yml``
+3. view [templ/txcoin.yml.sig][2]
+4. update [registration.yml][4]
+{%- endcomment -%}
+3. run [t/genesis.t][3]
+4. verify [registration.yml][4]
+
+
+[1]: /api/v0.0/getyml?f=templ/txcoin.yml
+[2]: /api/v0.0/getyml?f=templ/txcoin.yml.sig&encode=json
+[3]: /t/genesis.t
+[4]: /api/v0.0/getyml?f=registration.yml&encode=json
diff --git a/admin/new-settings.md b/admin/new-settings.md
new file mode 100644
index 0000000..f7c8f1c
--- /dev/null
+++ b/admin/new-settings.md
@@ -0,0 +1,27 @@
+---
+layout: simple
+---
+## ToyChain Settings
+
+In order to have a functional blockchain you need
+
+1. [generate][1] a node [keypair][9] (ECDSA for signing transactions)
+1. [register][2] as a miner by creating a coinbase transaction
+1. create [genesis][3] block
+1. update [config][10] file (and restart API)
+1. connect to peers on the [network][4]
+1. collect transactions from [txpool][5] and validate them
+1. [minepool][6]
+2. [explore][8] the [chain][7]
+
+[1]: /admin/keygen.html
+[2]: /admin/register.html
+[3]: /docs/genesis.html
+[4]: /api/nodes.html
+[5]: /docs/txpool.html
+[6]: /api/minepool.html
+[7]: /docs/chain.html
+[8]: /api/explore.html
+[9]: /api/v0.0/getcas?dir=secrets&addr=keys
+[10]: /admin/config.html
+[11]: /api/v0.0/getcas?dir=.&addr=config
diff --git a/admin/register.js b/admin/register.js
new file mode 100644
index 0000000..3bd12ab
--- /dev/null
+++ b/admin/register.js
@@ -0,0 +1,47 @@
+const useCapture = true; // capture, bubbling: false
+var elem = document.getElementsByTagName('button')[0];
+elem.addEventListener('click',register,useCapture);
+
+let promises = [];
+promises.push( get_config() );
+promises.push( get_keys() );
+
+function register(ev) {
+ console.log('register: %o',ev)
+
+ let name = document.getElementsByName('name')[0].value;
+ let peerid = document.getElementsByName('peerid')[0].value;
+ let minerid = document.getElementsByName('minerid')[0].value;
+ let account = document.getElementsByName('account')[0].value;
+ let bkreward = document.getElementsByName('bkreward')[0].value;
+
+ let namep = name.replace(/ /g,'+');
+ let url = api_url + `register?account=${namep}&bkreward=${bkreward}`;
+ let data = fetch(url).then(resp => resp.json());
+ console.log('register.data:',data);
+ return data;
+}
+
+Promise.all(promises).then( ar => {
+ let config = ar[0].config;
+ let keys = ar[1].data;
+ console.log('config:',config);
+ console.log('keys:',keys);
+
+ document.getElementsByName('name')[0].value = keys.identity.name;
+ document.getElementsByName('peerid')[0].value = keys.identity.public;
+ document.getElementsByName('minerid')[0].value = keys.miner.public;
+ document.getElementsByName('account')[0].value = keys.distribution.public;
+ document.getElementsByName('bkreward')[0].value = config.bkreward;
+
+}).
+catch(console.error);
+
+function get_config() {
+ let url = api_url + 'config';
+ return fetch(url).then(resp => resp.json()).catch(console.error)
+}
+function get_keys() {
+ let url = api_url + 'getcas?dir=secrets&addr=keys';
+ return fetch(url).then(resp => resp.json()).catch(console.error)
+}
diff --git a/admin/register.md b/admin/register.md
new file mode 100644
index 0000000..5955199
--- /dev/null
+++ b/admin/register.md
@@ -0,0 +1,21 @@
+---
+layout: simple
+base: "../"
+---
+## Toy-Chain : Miner Registration
+
+name: ([edit][1])
+ peerid:
+ minerid:
+ account:
+ block reward:
+ (not implemented yet: use [manual registration][2])
+
+confirmation:
+
+
+
+
+
+[1]: /admin/keygen.html
+[2]: /admin/manual-registration.html
diff --git a/admin/settings.md b/admin/settings.md
new file mode 100644
index 0000000..a6302cf
--- /dev/null
+++ b/admin/settings.md
@@ -0,0 +1,19 @@
+---
+layout: simple
+---
+## ToyChain Settings
+
+In order to have a functional blockchain you need
+
+1. [generate][1] a node [keypair][2] ([ECDSA] for signing transactions)
+1. [register][4] as a miner by creating a coinbase transaction
+
+
+### comming soon :
+
+1. [new-settings](new-settings.html)
+
+[1]: /admin/keygen.html
+[2]: /api/v0.0/getcas?dir=secrets&addr=keys
+[3]: /api/v0.0/getyml?f=secrets/keys.yml&encode=json
+[4]: /admin/register.html
diff --git a/api/audit.md b/api/audit.md
new file mode 100644
index 0000000..880bf02
--- /dev/null
+++ b/api/audit.md
@@ -0,0 +1,15 @@
+---
+layout: simple
+api_url: '/api/v0.0/'
+---
+## API audit
+
+This api call allow you to audit the server
+
+endpoint: '{{page.api_url}}audit'
+
+
+example: [{{page.api_url}}audit]({{page.api_url}}audit)
+
+
+
diff --git a/api/cmd.md b/api/cmd.md
new file mode 100644
index 0000000..497e1ad
--- /dev/null
+++ b/api/cmd.md
@@ -0,0 +1,15 @@
+---
+layout: simple
+api_url: '/api/v0.0/'
+---
+## API cmd
+
+This api call allow you to run generic commands on the server
+
+endpoint: '{{page.api_url}}cmd'
+
+
+example: [{{page.api_url}}cmd/what]({{page.api_url}}cmd/what)
+
+
+
diff --git a/api/config.md b/api/config.md
new file mode 100644
index 0000000..671796f
--- /dev/null
+++ b/api/config.md
@@ -0,0 +1,22 @@
+---
+layout: simple
+api_url: '/api/v0.0/'
+cmd: config
+---
+## API {{page.cmd}}
+
+This api call allow you see the {{page.cmd}} parameters
+
+endpoint: '{{page.api_url}}{{page.cmd}}'
+
+example: [{{page.api_url}}{{page.cmd}}]({{page.api_url}}{{page.cmd}})
+
+
+### Alternative
+
+you can also get the config.yml file directly:
+- [$SITE/config.yml](/api/v0.0/getcas?dir=.&addr=config)
+- [$SITE/config.yml](/config.yml)
+
+
+
diff --git a/api/env.md b/api/env.md
new file mode 100644
index 0000000..29f7ebf
--- /dev/null
+++ b/api/env.md
@@ -0,0 +1,16 @@
+---
+layout: simple
+api_url: '/api/v0.0/'
+cmd: env
+---
+## API {{page.cmd}}
+
+This api call allow you to {{page.cmd}} the server
+
+endpoint: '{{page.api_url}}{{page.cmd}}'
+
+
+example: [{{page.api_url}}{{page.cmd}}]({{page.api_url}}{{page.cmd}})
+
+
+
diff --git a/api/explore.md b/api/explore.md
new file mode 100644
index 0000000..781afd4
--- /dev/null
+++ b/api/explore.md
@@ -0,0 +1,16 @@
+---
+layout: simple
+api_url: '/api/v0.0/'
+cmd: explore
+---
+## API {{page.cmd}}
+
+This api call allow you to {{page.cmd}} the server
+
+endpoint: '{{page.api_url}}{{page.cmd}}'
+
+
+example: [{{page.api_url}}{{page.cmd}}]({{page.api_url}}{{page.cmd}})
+
+
+
diff --git a/api/getblock.js b/api/getblock.js
new file mode 100644
index 0000000..a8bd64f
--- /dev/null
+++ b/api/getblock.js
@@ -0,0 +1,22 @@
+
+var url = api_url + 'getblock'
+
+var elem = document.getElementsByTagName('div')[0];
+let button = document.getElementsByTagName('button')[0];
+
+
+
+let promised_peerid = fetch(url).
+ then(resp => resp.json()).
+ then(obj => {
+ console.log('peerid.obj:',obj);
+ let buf = elem.innerHTML;
+ buf = buf.replace(':peerid',obj.peerid);
+ buf = buf.replace(':name',obj.name);
+ elem.innerHTML = buf;
+ return obj
+ }).
+ catch(console.error);
+
+
+console.log('peerid.js loaded');
diff --git a/api/getblock.md b/api/getblock.md
new file mode 100644
index 0000000..79572be
--- /dev/null
+++ b/api/getblock.md
@@ -0,0 +1,24 @@
+---
+layout: simple
+api_url: '/api/v0.0/'
+cmd: getblock
+---
+## API {{page.cmd}}
+
+This api call allow you to see the content of a block
+
+endpoint: '{{page.api_url}}{{page.cmd}}'
+
+
+example: [{{page.api_url}}{{page.cmd}}?n=31]({{page.api_url}}{{page.cmd}}?n=31)
+
+n:
+ hash:
+ addr:
+
+
+## json:
+
+
+
+
diff --git a/api/index.md b/api/index.md
new file mode 100644
index 0000000..6e7dec2
--- /dev/null
+++ b/api/index.md
@@ -0,0 +1,51 @@
+---
+layout: simple
+base: "../"
+version: 'v0.0'
+api_url: '/api/v0.0'
+---
+# ToyChain API ({{page.version}})
+
+api endpoint : [http://127.0.0.1:8089/api/{{page.version}}/*][1]
+
+### API development status
+
+1. [status](/docs/status.html)
+2. [chain viewer](/docs/chain.html)
+
+### available commands :
+
+* [{{page.api_url}}/audit](audit.html)
+* [{{page.api_url}}/cmd](cmd.html)
+* [{{page.api_url}}/config](config.html)
+* [{{page.api_url}}/env](env.html)
+* [{{page.api_url}}/getblock](getblock.html)
+* [{{page.api_url}}/getcas](getcas.html)
+* [{{page.api_url}}/getchain](getchain.html)
+* [{{page.api_url}}/getheads](getheads.html)
+* [{{page.api_url}}/getheight](getheight.html)
+* [{{page.api_url}}/getpool](getpool.html)
+* [{{page.api_url}}/gettx](gettx.html)
+* [{{page.api_url}}/mergechain](mergechain.html)
+* [{{page.api_url}}/minepool](minepool.html)
+* [{{page.api_url}}/peerid](peerid.html)
+* [{{page.api_url}}/sendhead](sendhead.html)
+* [{{page.api_url}}/setcas](setcas.html)
+* [{{page.api_url}}/settx](settx.html)
+* [{{page.api_url}}/update](update.html)
+* [{{page.api_url}}/version](version.html)
+
+### CURL commands:
+
+- example of curl commands: [curl-test-script.sh](/curltest.sh)
+
+
+### Initial steps
+
+2. [register][2] yourself as a miner (in order to get the coinbase)
+1. create the [genesis][3] block
+
+[1]: /api/version
+[2]: /admin/register.html
+[3]: /docs/genesis.html
+
diff --git a/api/nodes.js b/api/nodes.js
new file mode 100644
index 0000000..2392bda
--- /dev/null
+++ b/api/nodes.js
@@ -0,0 +1,45 @@
+
+
+elem = document.getElementsByTagName('table')[0];
+
+getnodes();
+async function getnodes() {
+ let config = await fetch(api_url + 'config').
+ then(resp => resp.json()).
+ then(obj => { return obj.config }).
+ catch(console.error);
+ console.log('nodes.config:',config);
+
+ let n = 1;
+ let list = '
';
+ let nodes = [];
+ for (node of config.nodes) {
+ console.log('nodes.node:',node);
+ let [ip,port] = node.split(':');
+ let info = await get_info(node);
+ nodes.push(info);
+ let url=`http://${node}`;
+ let status='offline';
+ let info_url = `${url}${api_url}getinfo`;
+ list += `
';
+ let nodes = [];
+ for (node of config.nodes) {
+ console.log('nodes.node:',node);
+ let [ip,port] = node.split(':');
+ let info = await get_info(node);
+ nodes.push(info);
+ let url=`http://${node}`;
+ let status='offline';
+ let info_url = `${url}${api_url}getinfo`;
+ list += `
';
+ let elem = document.getElementById('list');
+ elem.innerHTML = list;
+ return nodes;
+}
+function get_info(node) {
+ let [ip,port] = node.split(':');
+ let remote_api_url = `http://${node}${api_url}`;
+ let promised = fetch(remote_api_url + 'getinfo').
+ then(resp => resp.json).
+ then(obj => { let info = obj.info; return info; }).
+ catch(console.error);
+ return promised;
+}
+
+
+
+console.log('heads.js loaded');
diff --git a/docs/block.md b/docs/block.md
new file mode 100644
index 0000000..e12c07a
--- /dev/null
+++ b/docs/block.md
@@ -0,0 +1,39 @@
+---
+layout: simple
+---
+# ToyChain's Block
+
+A block in ToyChain blockchain is 80 bytes
+
+n:
+ hash:
+ addr:
+ prev: :prev
+
+
+
+
+Here is the content of the requested block
+
+- seq: #.
+ payload : ":payload"
+- hash: :hash
+ pow: :pow
+- txroot: :txroot
+
+
+
+List of attached transactions :
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/chain.js b/docs/chain.js
new file mode 100644
index 0000000..008b2c2
--- /dev/null
+++ b/docs/chain.js
@@ -0,0 +1,30 @@
+
+
+getchain();
+function getchain() {
+ let promised = fetch(api_url + 'getchain').
+ then(resp => resp.json()).
+ then(obj => {
+ let elem = document.getElementById('json');
+ elem.innerText = JSON.stringify(obj);
+
+ let list = '
';
+ for (let bh of obj.chain) {
+ console.log('getchain.bh:',bh);
+ let blk_url = api_url + `getblock?hash=${bh}`;
+ list += `${bh}\n`
+ }
+ list += '
';
+ elem = document.getElementById('list');
+ elem.innerHTML = list;
+
+ return obj;
+ }).
+ catch(console.error);
+ promised.then(obj => { console.log('obj:',obj); return obj; });
+
+}
+
+// ----------------------------------------------------
+console.log('chain.js loaded');
+
diff --git a/docs/chain.md b/docs/chain.md
new file mode 100644
index 0000000..00a8084
--- /dev/null
+++ b/docs/chain.md
@@ -0,0 +1,22 @@
+---
+layout: simple
+---
+# ToyChain's Chain View
+
+The ToyChain blockchain is a list of basic 80 Bytes blocks,
+each block is address with a base58 encoded hash of 32B
+(i.e. ``32 * l(235) / l(58) = ~44 char.``).
+
+
+
+Here is the list all the blocks in the chain
+
+
+
+See also [HEADs][1]
+
+
+
+[1]: /docs/heads.html
+
+
diff --git a/docs/difficulties.md b/docs/difficulties.md
new file mode 100644
index 0000000..d66a456
--- /dev/null
+++ b/docs/difficulties.md
@@ -0,0 +1,23 @@
+---
+layout: simple
+---
+# block difficulties
+
+we use [hashcash][1] as a mechanism to protect the blockchain from a Sybil Attack.
+
+The difficulty is the number of hexadecimal digit we have to "resolve" in the block hash.
+
+Finding a block hash than match the required difficuly is the "work"
+and the hash itself is the [*proof of work*][1].
+
+example: block [Z9Pa9kcag3TBc6EX671u6Zwk7N6M7jTuQ5HPtjzDrpx4f][2] has is matching a difficulty of 4
+
+
+
+
+
+
+
+
+[1]: /docs/pow.html
+[2]: /api/0.0/getblock?hash=Z9Pa9kcag3TBc6EX671u6Zwk7N6M7jTuQ5HPtjzDrpx4f
diff --git a/docs/explorer.md b/docs/explorer.md
new file mode 100644
index 0000000..240f4ca
--- /dev/null
+++ b/docs/explorer.md
@@ -0,0 +1,27 @@
+---
+layout: simple
+---
+# Toy Chain Explorer
+
+The API server has an [explore][1] endpoint that allows to view all of the chain's "[internals][2]"
+
+You can explore the chain, blocks, transaction and more ...
+
+- get the [HEADs][3]
+- get the [chain][4]
+- get a [block][5]
+- get the [txpool][6]
+- get the [utxo][7] state
+- get a [transaction][8]
+- get [nodes][9]
+
+[1]: /api/explore.html
+[2]: /docs/internals.html
+
+[3]: /docs/heads.html
+[4]: /docs/chain.html
+[5]: /docs/block.html
+[6]: /docs/txpool.html
+[7]: /docs/utxo.html
+[8]: /docs/transactions.html
+[9]: /docs/nodes.html
diff --git a/docs/genesis.js b/docs/genesis.js
new file mode 100644
index 0000000..c68a3bc
--- /dev/null
+++ b/docs/genesis.js
@@ -0,0 +1,57 @@
+const useCapture = false; // capture, bubbling: false
+
+button = document.getElementsByTagName('button')[0];
+button.addEventListener('click',genesis,false);
+console.log(button)
+var payload = 'QmVnvdASdT1c9fJ2mcDhTAYhb63gcFRkiRmJW7NAm1YcSf';
+//var txcoinhash = 'ZCBtx7Wg59hvMogWDchKVcGUMo68qDe2dkRfzaskAh3G';
+//var prevhash = 'Z9BEeWD4Mww7yrXyPRXrfM2y6FxsQGfaNPzC8DxWq4ATq';
+var pow = '11501558695957493006';
+var comment = 'Genesis ~ Manuela J. Savina';
+
+// get default values (from nodes) ...
+let promised_config = fetch(api_url + 'config').
+ then(resp => resp.json()).
+ then(obj => { return obj.config }).
+ catch(console.error)
+
+let promised_nullhash = fetch(api_url + 'getjson?obj=Genesis::nullhash').
+ then(resp => resp.json()).
+ then(obj => { console.log('promised_nullhash.obj:',obj)
+ return obj;
+ }).
+ catch(console.error);
+
+Promise.all([promised_config, promised_nullhash]).then( _ => {
+ let [config,nullhash] = _;
+ console.log('genesis.config:',config);
+ document.getElementsByName('payload')[0].value = payload;
+ document.getElementsByName('txcoinhash')[0].value = config.txcoin;
+ document.getElementsByName('prevhash')[0].value = nullhash;
+ document.getElementsByName('pow')[0].value = pow;
+ document.getElementsByName('comment')[0].value = comment;
+}).catch(console.error);
+
+
+function genesis(ev) {
+ console.log('genesis.ev: %o',ev);
+ let query = {
+ "payload": document.getElementsByName('payload')[0].value,
+ "txcoin": document.getElementsByName('txcoinhash')[0].value,
+ "bkprev": document.getElementsByName('prevhash')[0].value,
+ "pow": document.getElementsByName('pow')[0].value,
+ "comment": document.getElementsByName('comment')[0].value
+ };
+ query_string = Object.keys(query).map( k => k +'='+ query[k] ).join('&');
+ let url = api_url + `creategen?${query_string}`;
+ document.getElementByName('pow')[0].value = 'working...';
+ let promised = fetch(url).
+ then(resp => resp.json()).
+ then(obj => {
+ console.log('genesis.obj:',obj);
+ document.getElementsByName('pow')[0].value = obj.pow;
+ }).
+ catch(console.error);
+}
+
+
diff --git a/docs/genesis.md b/docs/genesis.md
new file mode 100644
index 0000000..ef5c4a0
--- /dev/null
+++ b/docs/genesis.md
@@ -0,0 +1,27 @@
+---
+layout: simple
+---
+# ToyChain Genesis Block
+
+The genesis block is a regular block with
+only one [coinbase][1] transaction
+and a previous link that point to the [NullBlock][3]
+
+
+A block is consist of the following part :
+
+1. a payload
+2. a [coinbase][2] transaction
+
+3. a link to the previous block
+4. a proof of work
+5. an optional comment
+
+
+
+
+[1]: /docs/coinbase.html
+[2]: /api/v0.0/getyml?f=templ/txcoin.yml&encode=json
+[3]: /api/v0.0/getcas?addr=nullblock&dir=templ
+
+
diff --git a/docs/heads.js b/docs/heads.js
new file mode 100644
index 0000000..47fb19e
--- /dev/null
+++ b/docs/heads.js
@@ -0,0 +1,74 @@
+
+
+getheads();
+function getheads() {
+ let promised = fetch(api_url + 'getheads').
+ then(resp => resp.json()).
+ then(obj => {
+ let elem = document.getElementById('json');
+ elem.innerText = JSON.stringify(obj);
+
+ let list = '
';
+ for (let b of obj.HEADs) {
+ console.log('getheads.b:',b);
+ let blk_url = api_url + `getblock?hash=${b.bkhash}`;
+ let content_url = api_url + `getblock?addr=${b.bkaddr}`;
+ let peerid = b.bkcontent.audit.peerid;
+ let whois_url = api_url + `whois?pub=${peerid}`
+ list += `
';
+ let nodes = [];
+ for (node of config.nodes) {
+ console.log('nodes.node:',node);
+ let [ip,port] = node.split(':');
+ let info = await get_info(node);
+ nodes.push(info);
+ let url=`http://${node}`;
+ let status='offline';
+ let info_url = `${url}${api_url}getinfo`;
+ list += `
\n`
+ }
+ list += '';
+ document.getElementById('list').innerHTML = list;
+ }
+
+ return obj;
+ }).
+ catch(console.error);
+ promised.then(obj => { console.log('obj:',obj); return obj; });
+
+}
+
+// ----------------------------------------------------
+console.log('txpool.js loaded');
+
diff --git a/docs/minepool.md b/docs/minepool.md
new file mode 100644
index 0000000..8fa67cd
--- /dev/null
+++ b/docs/minepool.md
@@ -0,0 +1,30 @@
+---
+layout: simple
+---
+# ToyChain's Mining
+
+The ToyChain Mining is the action of
+
+- creating a new block to record transaction in the [txpool](txpool.html)
+- attaching the block to the [HEAD](heads.html) of the chain.
+- computing the hash of this block with enough [PoW](pow.html)
+- advertizing the new head of the chain
+
+height:
+HEAD:
+new block:
+
+
+
+([json][1])
+
+
+
+
+
+
+
+
+
+[1]: /api/0.0/getjson?obj=result
+
diff --git a/docs/mining.md b/docs/mining.md
new file mode 100644
index 0000000..3463323
--- /dev/null
+++ b/docs/mining.md
@@ -0,0 +1,24 @@
+---
+layout: simple
+---
+# ToyChain's Mining
+
+The ToyChain Mining is the action of
+
+- creating a new block to record transaction in the [txpool](txpool.html)
+- attaching the block to the [HEAD](heads.html) of the chain.
+- computing the hash of this block with enough [PoW](pow.html)
+- advertizing the new head of the chain
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/nodes.js b/docs/nodes.js
new file mode 100644
index 0000000..b1919b4
--- /dev/null
+++ b/docs/nodes.js
@@ -0,0 +1,30 @@
+
+
+getnodes();
+function getnodes() {
+ let promised = fetch(api_url + 'getnodes').
+ then(resp => resp.json()).
+ then(obj => {
+ document.getElementById('json').innerText = JSON.stringify(obj.api);
+
+ if (typeof(obj.api) != 'undefined') {
+ let list = '';
+ for (let node of obj.api) {
+ console.log('getnodes.node:',node);
+ let url = `http:/${node}/docs/chain.html`
+ list += `
\n`
+ }
+ list += '';
+ document.getElementById('list').innerHTML = list;
+ }
+
+ return obj;
+ }).
+ catch(console.error);
+ promised.then(obj => { console.log('obj:',obj); return obj; });
+
+}
+
+// ----------------------------------------------------
+console.log('nodes.js loaded');
+
diff --git a/docs/nodes.md b/docs/nodes.md
new file mode 100644
index 0000000..e42896e
--- /dev/null
+++ b/docs/nodes.md
@@ -0,0 +1,21 @@
+---
+layout: simple
+---
+# ToyChain Nodes
+
+getting nodes list : fixed network here (no discovery).
+
+
+
+
+> this node
+
+
+### API commands
+
+- [/api/v0.0/getnodes](/api/v0.0/getnodes)
+
+
+
+
+
diff --git a/docs/notes.md b/docs/notes.md
index 1471453..b4ff828 100644
--- a/docs/notes.md
+++ b/docs/notes.md
@@ -7,7 +7,7 @@ base: '../'
## Initial design choices
-- protocol/routing/network layer: websockets (multi nonblocking clients)
+- note that serialization with JSON doesn't guarante key's order when using maps, so for CAS storage yaml is prefered
- server-side fileformat : yaml
- client-side fileformat : JSON
@@ -22,6 +22,15 @@ base: '../'
- block: {address, previous, pow}
- use balances for state rather than TXO to avoid the need keep txo states, and link txi to utxo
+## Networking layer choise
+
+ initally we thought websocket would be the simple choice for the P2P network,
+ however the protocol implementation in perl is a little cumbersome, so we fall back
+ to simple tcp sockets, no ssl support for the first version !
+- blocking socket
+
+ next version :
+- protocol/routing/network layer: websockets (multi nonblocking clients)
## observation ...
@@ -53,9 +62,12 @@ base: '../'
- PoW can be replaced by ZK proof of some Work
- should it be txo which carries the burden of proof of work ?
- validator already do a great job making the system "alive"
-- block reward could be proportional to the number of tx in the block i.e. the "real" work is indeed the verif not a hash-puzzle
-
+- block reward could be proportional to the number of tx in the block
+ i.e. the "real" work is indeed the verif not a hash-puzzle.
- How to mitigate DDoS on Mempool ?
--
-- why would we want making block more and more difficult to add when technology advance ???
+ why would we want making block more and more difficult to add when technology advance ???
(how to make spice of spamming constant through technology ?)
+
+### misc & links
+
+- testing javascript with a [gist:42835214f63750080a8cb73d4be5a4a1](https://hologit-ml.ipns.cf-ipfs.com/tstanchfield/code.git)
diff --git a/docs/pow.js b/docs/pow.js
index 924ebfb..bbe28ac 100644
--- a/docs/pow.js
+++ b/docs/pow.js
@@ -1,4 +1,4 @@
-const useCapture = true; // capture, bubbling: false
+const useCapture = false; // capture, bubbling: false
button = document.getElementsByTagName('button')[0];
button.addEventListener('click',hashcash,false);
@@ -18,7 +18,7 @@ function hashcash(ev) {
then(obj => {
console.log('pow.hashcash.obj:',obj);
document.getElementsByName('hashcash')[0].innerText = '0x'+obj.hash;
- document.getElementsId('pow').innerText = obj.pow;
+ document.getElementById('pow').innerText = obj.pow;
}).
catch(console.error);
diff --git a/docs/status.md b/docs/status.md
new file mode 100644
index 0000000..569f9f0
--- /dev/null
+++ b/docs/status.md
@@ -0,0 +1,27 @@
+---
+layout: simple
+---
+# API implementation status ...
+
+### currently available
+
+- [heads](/docs/heads.html)
+- [chain](/docs/chain.html)
+- [block](/docs/block.html)
+- [transaction](/docs/transactions.html)
+- [txpool](/docs/txpool.html)
+
+### api commands
+
+- [utxo](/api/utxo.html)
+- [gettx](/api/gettx.html)
+- [settx](/api/settx.html)
+
+
+### coming soon
+
+- [UTXO](/docs/UTXO.html)
+- [explore](/api/explore.html)
+- [internals](/docs/internals.html)
+- [register](/admin/register.html)
+- [genesis](/docs/genesis.html)
diff --git a/docs/test.js b/docs/test.js
new file mode 100644
index 0000000..84a3f97
--- /dev/null
+++ b/docs/test.js
@@ -0,0 +1,30 @@
+
+
+testing();
+function testing() {
+ let promised = fetch(api_url + 'getnodes').
+ then(resp => resp.json()).
+ then(obj => {
+ document.getElementById('json').innerText = JSON.stringify(obj.api);
+
+ if (typeof(obj.api) != 'undefined') {
+ let list = '';
+ for (let item of obj.api) {
+ console.log('test.item:',item);
+ let url = api_url + `getcas?addr=${item}`;
+ list += `