Browse Source

release it all

master
Aaron J. Milius 3 years ago
committed by Brooke L. Rediker
parent
commit
e46b877c03
  1. 1
      .gitattributes
  2. 15
      CAStore/genesis.yml
  3. 16
      CAStore/nullblock.yml
  4. 15
      README.md
  5. 18
      admin/config.md
  6. 21
      admin/index.md
  7. 18
      admin/keygen.js
  8. 22
      admin/keygen.md
  9. 19
      admin/manual-registration.md
  10. 27
      admin/new-settings.md
  11. 47
      admin/register.js
  12. 21
      admin/register.md
  13. 19
      admin/settings.md
  14. 15
      api/audit.md
  15. 15
      api/cmd.md
  16. 22
      api/config.md
  17. 16
      api/env.md
  18. 16
      api/explore.md
  19. 22
      api/getblock.js
  20. 24
      api/getblock.md
  21. 51
      api/index.md
  22. 45
      api/nodes.js
  23. 31
      api/nodes.md
  24. 20
      api/peerid.js
  25. 15
      api/peerid.md
  26. 53
      api/transaction.js
  27. 43
      api/transaction.md
  28. 4
      bin/apirun
  29. 16
      bin/signtx.pl
  30. 5
      bin/yml2json.sh
  31. 34
      config.yml
  32. 23
      config0.yml
  33. 21
      curltest.sh
  34. 10
      docs/UTXO.md
  35. 111
      docs/block.js
  36. 39
      docs/block.md
  37. 30
      docs/chain.js
  38. 22
      docs/chain.md
  39. 23
      docs/difficulties.md
  40. 27
      docs/explorer.md
  41. 57
      docs/genesis.js
  42. 27
      docs/genesis.md
  43. 74
      docs/heads.js
  44. 23
      docs/heads.md
  45. 5
      docs/index.md
  46. 44
      docs/info.js
  47. 29
      docs/info.md
  48. 30
      docs/minepool.js
  49. 30
      docs/minepool.md
  50. 24
      docs/mining.md
  51. 30
      docs/nodes.js
  52. 21
      docs/nodes.md
  53. 22
      docs/notes.md
  54. 4
      docs/pow.js
  55. 27
      docs/status.md
  56. 30
      docs/test.js
  57. 42
      docs/test.md
  58. 51
      docs/transactions.js
  59. 46
      docs/transactions.md
  60. 28
      docs/txpool.js
  61. 21
      docs/txpool.md
  62. 32
      eckeygen.pl
  63. 2
      lib
  64. 10
      nodes/cloneit.sh
  65. 2
      salts/Genesis.yml
  66. BIN
      secrets/keys.yml
  67. BIN
      secrets/nicknames.yml
  68. 11
      t/blockaddr.t
  69. 6
      t/createtx.t
  70. BIN
      t/eckeys.t
  71. 2
      t/genesis.t
  72. 3
      t/hashcash.t
  73. 7
      templ/config.yml
  74. 1
      templ/genesis.yml
  75. 14
      templ/runtest.sh
  76. 17
      templ/runtime.yml
  77. 1
      templ/salt.yml
  78. 20
      templ/tx.yml
  79. 1
      templ/tx02.json
  80. 23
      templ/tx02.yml
  81. 35
      templ/tx03.json
  82. 17
      templ/txcb01.yml
  83. 17
      templ/txcoin.yml.sig
  84. 6
      templ/txexample.yml
  85. 3
      templ/txgen.yml
  86. 2
      templ/txnull.yml
  87. 19
      templ/txudj.yml
  88. 1
      templ/txvalid.json
  89. 18
      templ/txvalid.yml
  90. 11
      txpool/txgen.yml

1
.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

15
CAStore/genesis.yml

@ -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

16
CAStore/nullblock.yml

@ -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: ~

15
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

18
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

21
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

18
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);
}

22
admin/keygen.md

@ -0,0 +1,22 @@
---
layout: simple
base: "../"
---
## Toy-Chain : Key pair Generation
<input name="name" placeholder="name (optional)"><button>create</button>
identity:
<textarea>
</textarea>
<!--<button>save</button>-->
key files: [$SITE/secrets/keys.yml][1]
<script src="keygen.js"></script>
[1]: /api/v0.0/getcas?dir=secrets&addr=keys

19
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

27
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

47
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)
}

21
admin/register.md

@ -0,0 +1,21 @@
---
layout: simple
base: "../"
---
## Toy-Chain : Miner Registration
name: <input name="name" placeholder="your name"> ([edit][1])
<br>peerid: <input name="peerid" placeholder="peerid" size=44>
<br>minerid: <input name="minerid" placeholder="minerid" size=44>
<br>account: <input name="account" placeholder="publickey of coinbase destination" size=44>
<br>block reward:<input name="bkreward" placeholder="block reward" size=3>
<br><button>register</button> (not implemented yet: use [manual registration][2])
confirmation:
<span id=output></span>
<script src="register.js"></script>
[1]: /admin/keygen.html
[2]: /admin/manual-registration.html

19
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

15
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)

15
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)

22
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)

16
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}})

16
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}})

22
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');

24
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: <input name="n" type="integer" value="" placeholder="height of the block">
<br>hash: <input name="hash" type="text" value="" placeholder="hash value of the block">
<br>addr: <input name="addr" type="text" value="" placeholder="addr of the block content">
<button>view</button>
## json:
<textarea></textarea>
<script src="getblock.js"></script>

51
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

45
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 = '<ul>';
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 += `<li>node${n} (:${port}) <a href="${url}">${node}</a> ${status} <a href="${info_url}">information</a></li>\n`;
console.log('nodes.info:',info);
n++;
}
list += '</ul>';
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('peerid.js loaded');

31
api/nodes.md

@ -0,0 +1,31 @@
---
layout: simple
---
# Toy Chain : Peer Networks
We count :n active [nodes][1] on the *[ToyChain][2] MainNet* .
| nodename | port | endpoint | status | information |
|----------|------|----------|--------|-------------|
| :nname | :port | :url | :status | :info |
<div id=list></div>
<!--
<table>
<tr><th>ip</th><th>port</th><th>endpoint</th><th>information</th></tr>
<tr><td>:ip</td><td>:port</td><td>:url</td><td>:info</td></tr>
</table>
-->
<br>--&nbsp;
<br><small>by: <span id=sig></span> src: [md],[css],[js]</small>
<script src="nodes.js"></script>
[1]: /api/v0.0/getnodes
[2]: /toychain
[md]: nodes.md
[css]: /style.css
[js]: nodes.js

20
api/peerid.js

@ -0,0 +1,20 @@
var url = api_url + 'peerid'
elem = document.getElementsByTagName('div')[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');

15
api/peerid.md

@ -0,0 +1,15 @@
---
layout: simple
---
# API Peerid
This page allow you to see your peerid (i.e. node identity)
```
your peerid is :peerid;
your name is :name;
```
<script src="peerid.js"></script>

53
api/transaction.js

@ -0,0 +1,53 @@
let button = document.getElementById('submit');
button.addEventListener('click',createtx,false);
loadtx('templ/txexample.yml');
function createtx() {
let txyml = document.getElementsByName('tx').value;
let promised = fetch(api_url + 'settx?',{method:'POST',data}).
then(resp => resp.json()).
then(obj => {
elem = document.getElementById('json');
elem.innerText = JSON.stringify(obj);
let bkcontent = obj.bkcontent;
let txmerkle = bkcontent.txmeta.merkle
if (typeof(txmerkle) != 'undefined') {
let list = '<ul>';
for (let txa of txmerkle) {
console.log('getblock.txa:',txa);
let tx_url = api_url + `gettx?addr=${txa}`
list += `<li><a href="${tx_url}">${txa}</a></li>`
}
list += '</ul>';
elem = document.getElementById('list');
elem.innerHTML = list;
}
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
function loadtx(f) {
let url = api_url + `getyml?f=${f}`;
let promised = fetch(`/${f}`).
then(resp => resp.text()).
then(yaml => {
document.getElementsByName('tx')[0].value = yaml;
return yaml;
}).
catch(console.error);
}
// ----------------------------------------------------
console.log('transaction.js loaded');

43
api/transaction.md

@ -0,0 +1,43 @@
---
layout: simple
---
## ToyChain Transaction
Transactions block is an added record to the block which allow to attached values transfer to the block.
A transaction descript a transfer of value between account protected via [ECC][1]
(we use [secp256k1][5] see code [ECKeys.pm][2]).
You can register your [keypair][4] in the [admin](/admin/) section under [signup / keygen][3].
A transaction has inputs, outputs, and signatures,
in order be valid
- the total of inputs must be greater than the total of ouputs
- every account on the input side must have enough balance to satisfy the transactions
- all signature attached to the transaction must be authentic and the signed message not tempered
example of transaction in ([yaml][6] format)
<textarea name=tx rows=7></textarea>
{% comment %}
<button id=sign>sign</button>
<button id=validate>validate</button>
{%- endcomment -%}
<button id=submit>submit</button>
<textarea id=json></textarea>
txaddr: <span id=txaddr><i>:txaddr</i></span>
[1]: https://duckduckgo.com?q=Elliptic+Curve+Cryptography
[2]: /lib/ECKeys.pm
[3]: /admin/keygen.html
[4]: /templ/keys.yml
[5]: https://duckduckgo.com?q=secp256k1+!g
[6]: /templ/txexample.yml
<a href="/docs/txpool.html"><button id=txpool>txpool</button></a>
<script src="transaction.js"></script>

4
bin/apirun.pl → bin/apirun

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
#
# Intent: testing the API server
# Intent: running the ToyChain API server
#
use lib 'lib';
@ -12,7 +12,7 @@ apigw_run();
exit $?;
1; # $Source: /my/perl/script/testapi.pl $
1; # $Source: /my/perl/script/apigw.pl $

16
bin/signtx.pl

@ -12,7 +12,7 @@ use ECKeys qw(ecsign ecverif getPeerid loadKeys);
use YAML::Syck qw(LoadFile Dump DumpFile);
my $keys = loadKeys($ENV{SITE}.'/secrets/keys.yml');
our $aliases = &loadYaml($ENV{SITE}.'/secrets/aliases.yml');
our $nicknames = &loadYaml($ENV{SITE}.'/secrets/nicknames.yml');
my $keyfile = $ENV{SITE}.'/secrets/coinbase.yml';
if (-e $keyfile) {
@ -24,15 +24,15 @@ if (-e $keyfile) {
}
}
foreach my $id (keys %{$keys}) { # list all known aliases ...
foreach my $id (keys %{$keys}) { # list all known nicknames ...
my $pub = $keys->{$id}{public};
$aliases->{$pub} = $id if (! defined $aliases->{$pub});
$nicknames->{$pub} = $id if (! defined $nicknames->{$pub});
printf " - %-13s: %-46s (%-36s);",$id,$pub,$keys->{$id}{name};
printf " bot:%s\n", &botname::botname($pub);
}
printf "--- keys %s...\n",Dump($keys);
#printf "--- aliases %s...\n",Dump($aliases);
#printf "--- nicknames %s...\n",Dump($nicknames);
my $txf = shift;
my $tx = LoadFile($txf);
@ -50,7 +50,7 @@ foreach my $sign (@{$tx->{signatures}}) {
printf "--- signatures %s...\n",Dump(\%signatures);
foreach my $in (@{$tx->{inputs}}) {
my ($pub) = keys %{$in};
my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
my $id = (exists $nicknames->{$pub}) ? $nicknames->{$pub} : $pub;
my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub;
my $value = $in->{$pub};
$valuein += $value;
@ -59,7 +59,7 @@ foreach my $in (@{$tx->{inputs}}) {
}
foreach my $out (@{$tx->{outputs}}) {
my ($pub) = keys %{$out};
my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
my $id = (exists $nicknames->{$pub}) ? $nicknames->{$pub} : $pub;
my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub;
my $value = $out->{$pub};
$valueout += $value;
@ -91,7 +91,7 @@ my $txio = {
foreach my $pub (keys %delta) {
my $value = -$delta{$pub};
my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
my $id = (exists $nicknames->{$pub}) ? $nicknames->{$pub} : $pub;
if (exists $signatures{$pub}) {
my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub;
my $msg;
@ -114,7 +114,7 @@ foreach my $pub (keys %delta) {
$signatures{$pub} = [ $sig, $date, $msg ];
}
} else {
my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
my $id = (exists $nicknames->{$pub}) ? $nicknames->{$pub} : $pub;
if (exists $keys->{$id}{private}) {
my $sig = &ecsign($id,$msg);
printf "sig: %s: %s\n",$id,$sig;

5
bin/yml2json.sh

@ -0,0 +1,5 @@
#
cat $1 | json_xs -f yaml -t json | tee ${1%.*}.json
echo ''
ls -l ${1%.*}.json

34
config.yml

@ -1,45 +1,29 @@
--- # toychain's config
version: 1.12
version: 1.13
chain: toychain
apiver: '0.0'
ipfsgw: 8390
# ------------------------------------------
# node specifics
port: 8089
# ------------------------------------------
# p2p network
# api = p2p+1
nodes:
# - 127.0.0.1:8089
- 127.0.0.1:8091
- 127.0.0.2:8093
- 127.0.0.3:8095
- 127.0.0.4:8097
- 127.0.0.5:8099
# ------------------------------------------
# block parameters :
bkver: 0
bkreward: 100
coinbase:
reward: 50
public: ZPD9SRTr5ZMx6coZV6NrUxgmVfCkqB55gTdAwJKQVjp7W
signature: ~
genhash: Z9BEepHz9jLWzNebDEZTrEKusuU9zomFoaaPxngCQ5D39
genhash: Z9BEdvJt9F2xeY6BP3gXMvGikFvcUv1kvESQyhSKznLDi
genhash: Z9BEeytxKdWLtGhirNstvvRtJ4273GmVqJ7r2pKmoCR7G
genhash: Z9BEdXmPNa1DkEJKQ1BhuMg7M1nHRD6NLKoXpJ6X84NqK
nullhash: Z9BEeWD4Mww7yrXyPRXrfM2y6FxsQGfaNPzC8DxWq4ATq
txgen: Ztxrms5c5oKqb9Zof3xeC5Q2ZQjSaWv7FU4rAxe2s3sP
txgen: ZTxoBj3SNdKGMxXLTdxScnmScN7uCveoM2zPmDoMS4CN
txgen: ZTxGeH4J9oWMci2pcJ7yZ1baMb47i7zd6ihHissKifvQ
txcoin: ZCBuCkQFRBeiGnANEwb65TZptSTUpm62WYS4Xj9gkMLU
txcoin: ZCBtx9SS9n57R2cx3AAuRDKJ4b9WsWA5MoTVEtxGQAdV
txcoin: ZCBtx7Wg59hvMogWDchKVcGUMo68qDe2dkRfzaskAh3G
reward: 100
# Proof of Work option
difficulty: 5
maxdiff: 7
# CAstore options
trackmode: 1
# ------------------------------------------

23
config0.yml

@ -1,23 +0,0 @@
--- # toychain's config
version: 1.06
chain: toychain
apiver: '0.0'
ipfsgw: 8390
port: 8089
# p2p network = api+1
apis:
- 127.0.0.1:8091
- 127.0.0.2:8093
- 127.0.0.3:8095
- 127.0.0.4:8097
- 127.0.0.5:8099
# block parameters :
bkver: 0
bkreward: 100
# Proof of Work option
difficulty: 5
maxdiff: 7
# CAstore options
trackmode: 1

21
curltest.sh

@ -1,7 +1,7 @@
#
#curl http://127.0.0.1:8089/api/0.0/version
#curl http://127.0.0.1:8089/api/0.0/audit
curl http://127.0.0.1:8089/api/version
curl http://127.0.0.1:8089/api/0.0/audit
curl http://127.0.0.1:8089/api/0.0/getheight
echo ''
curl http://127.0.0.1:8089/api/0.0/getheads
@ -12,11 +12,19 @@ curl -s http://127.0.0.1:8089/api/0.0/getblock?n=30
echo ''
curl -s http://127.0.0.1:8089/api/0.0/gettx?txaddr=ZTxB1ritiikyhjTXg28V7AjfqwkDyD8woJoz1yjC1T75
echo ''
curl -s http://127.0.0.1:8089/api/0.0/gettx?txaddr=ZtxqdiZ8wwpEN5dScJf1byU6hjfBLoSrFmCrUVNJmqPc
curl -s http://127.0.0.1:8089/api/0.0/gettx?txaddr=ZtxqdiZ8wwpEN5dScJf1byU6hjfBLoSrFmCrUVNJmqPc&encode=json
echo ''
curl -s http://127.0.0.1:8089/api/0.0/gettx?txaddr=Ztxrms5c5oKqb9Zof3xeC5Q2ZQjSaWv7FU4rAxe2s3sP
curl -s http://127.0.0.1:8089/api/0.0/gettx?txaddr=Ztxrms5c5oKqb9Zof3xeC5Q2ZQjSaWv7FU4rAxe2s3sP&encode=base58f
echo ''
cat txpool/tx.yml | sed -e "s/$/%0a/g" | curl -s -X POST http://127.0.0.1:8089/api/0.0/settx -d @-
# verifying a transaction
cat $SITE/templ/tx.yml | sed -e "s/$/%0a/g" | curl -s -X POST http://127.0.0.1:8089/api/0.0/istxvalid -d @-
cat $SITE/templ/tx02.yml | sed -e "s/$/%0a/g" | curl -s -X POST http://127.0.0.1:8089/api/0.0/istxvalid -d @-
cat $SITE/templ/tx02.json | curl -s -X POST http://127.0.0.1:8089/api/0.0/istxvalid -d @-
# sending a transaction
cat $SITE/templ/tx02.yml | sed -e "s/$/%0a/g" | curl -s -X POST http://127.0.0.1:8089/api/0.0/settx -d @-
cat $SITE/templ/tx02.json | curl -s -X POST http://127.0.0.1:8089/api/0.0/settx -d @-
cat txudj.yml | json_xs -f yaml | curl -s -X POST http://127.0.0.1:8089/api/0.0/istxvalid -d @-
curl -s http://127.0.0.1:8089/api/0.0/gettx?txaddr=ZtxiE2X3R7DbmrZXQrfkrRjcgvYjjJhLVBZjTJMY1zVi
echo ''
@ -25,6 +33,9 @@ echo ''
curl -s http://127.0.0.1:8089/api/0.0/getpool
echo ''
curl -s http://127.0.0.1:8089/api/0.0/minepool
echo ''
curl -s http://127.0.0.1:8089/api/0.0/sendhead?hash=Z9BEe8qEZdsfsySpFQFgfUvo7zwYnVPPrdizGmS1JhDvt
echo ''
curl -s "http://127.0.0.1:8089/api/0.0/getcas?addr=ZNULLSNLDcn169AJMjXuVLrQBPDFZoF3nzz4HiqvaFsA&dir=CAStore"
echo ''

10
docs/UTXO.md

@ -0,0 +1,10 @@
---
layout: simple
---
# Unspend TXO
The unspend transaction outputs are defining the (mutable) state of the blockchain,
we choose to aggregate them per addresses such that we only have to store the balance of addresses which
have a positive balance; rather than maintaning a complete list of unspend transactions.
- [UTXO](/api/v0.0/getjson?obj=TXPOOL::UTXO)

111
docs/block.js

@ -0,0 +1,111 @@
let button = document.getElementsByTagName('button')[0];
button.addEventListener('click',getblock,false);
function getblock() {
let n = document.getElementsByName('n').value;
let hash = document.getElementsByName('hash').value;
let addr = document.getElementsByName('addr').value;
let query = [];
if (n != '') {
query.push(`n=${n}`)
} else if (hash != '') {
query.push(`hash=${hash}`)
} else if (addr != '') {
query.push(`addr=${addr}`)
}
document.getElementById('comment').innerText = '';
let promised = fetch(api_url + 'getblock?' + query.join('&')).
then(resp => resp.json()).
then(obj => {
let elem;
let payload_value = obj.bkcontent.data.payload;
let payload_url = `/api/getblock?addr=${obj.bkaddr}`
if (payload_value.match('/ipfs/')) {
payload_url = 'https://ipfs.blockringtm.ml'+ payload_value
} else if (payload_value.match('/https?:|\.htm/')) {
payload_url = payload_value;
}
let payload_link = `<a href="${payload_url}">${payload_value}</a>`;
document.getElementsByName('hash')[0].value = obj.bkhash;
document.getElementsByName('addr')[0].value = obj.bkaddr;
document.getElementById('prev').innerHTML = `<a href="/api/v0.0/getblock?hash=${obj.bkprev}">${obj.bkprev}</a>`;
document.getElementById('seq').innerText = obj.bkcontent.data.seq;
document.getElementById('payload').innerHTML = payload_link;
document.getElementById('comment').innerText = obj.bkcontent.data.comment;
document.getElementById('txroot').innerText = obj.bkcontent.meta.txroot || '?';
document.getElementById('hash').innerText = obj.bkhash
document.getElementById('pow').innerText = obj.pow
document.getElementById('api').innerHTML = `(<a href="/api/v0.0/getblock?hash=${obj.bkhash}">json</a>)`;
elem = document.getElementById('json');
elem.innerText = JSON.stringify(obj);
let bkcontent = obj.bkcontent;
let txmerkle = bkcontent.txmeta.merkle
if (typeof(txmerkle) != 'undefined') {
let list = '<ul>';
for (let txa of txmerkle) {
console.log('getblock.txa:',txa);
let tx_url = api_url + `gettx?addr=${txa}`
list += `<li><a href="${tx_url}">${txa}</a></li>`
}
list += '</ul>';
elem = document.getElementById('list');
elem.innerHTML = list;
}
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
// ----------------------------------------------------
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 = '<ul>';
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 += `<li>node${n} (:${port}) <a href="${url}">${node}</a> ${status} <a href="${info_url}">information</a></li>\n`;
console.log('nodes.info:',info);
n++;
}
list += '</ul>';
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');

39
docs/block.md

@ -0,0 +1,39 @@
---
layout: simple
---
# ToyChain's Block
A block in ToyChain blockchain is 80 bytes
n: <input name=n size=3> <span id=comment></span>
<br>hash: <input name=hash size=43>
<br>addr: <input name=addr size=43>
<br>prev: <span id=prev><i>:prev</i></span>
<br><button>fetch</button>
<textarea id=json></textarea>
Here is the content of the requested block <span id=api></span>
- seq: <span id=seq>#.</span>
payload : "<span id=payload><i>:payload</i></span>"
- hash: <span id=hash><i>:hash</i></span>
pow: <span id=pow><i>:pow</i></span>
- txroot: <span id=txroot><i>:txroot</i></span>
<div id=content></div>
List of attached transactions :
<div id=list></div>
<script src="block.js"></script>

30
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 = '<pre>';
for (let bh of obj.chain) {
console.log('getchain.bh:',bh);
let blk_url = api_url + `getblock?hash=${bh}`;
list += `<a href="${blk_url}">${bh}</a>\n`
}
list += '</pre>';
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');

22
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.``).
<textarea id=json></textarea>
Here is the list all the blocks in the chain
<div id=list></div>
See also [HEADs][1]
<script src="chain.js"></script>
[1]: /docs/heads.html

23
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

27
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

57
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);
}

27
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 <input name=payload>
2. a [coinbase][2] transaction <input name=txcoinhash>
<!--2. a transactions list (merkle tree) <input name=txpool disabled> -->
3. a link to the previous block <input name=prevhash disabled>
4. a proof of work <input name=pow>
5. an optional comment <input name=comment>
<button>create</button>
[1]: /docs/coinbase.html
[2]: /api/v0.0/getyml?f=templ/txcoin.yml&encode=json
[3]: /api/v0.0/getcas?addr=nullblock&dir=templ
<script src="genesis.js"></script>

74
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 = '<ul>';
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 += `<li><a href="${blk_url}">${b.bkhash}</a> by <a href="${whois_url}">${peerid}</a>: `+
`<a href="${content_url}">${b.bkaddr}</a> ${b.bkprev} pow:${b.pow}</li>`;
}
list += '</ul>';
elem = document.getElementById('list');
elem.innerHTML = list;
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
// ----------------------------------------------------
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 = '<ul>';
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 += `<li>node${n} (:${port}) <a href="${url}">${node}</a> ${status} <a href="${info_url}">information</a></li>\n`;
console.log('nodes.info:',info);
n++;
}
list += '</ul>';
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');

23
docs/heads.md

@ -0,0 +1,23 @@
---
layout: simple
---
# ToyChain's HEADs
The ToyChain blockchain as many as head as there are nodes that holds differents forks.
<textarea id=json></textarea>
Here is the list with their respective owners
<div id=list></div>
<script src="heads.js"></script>

5
docs/index.md

@ -3,6 +3,7 @@ layout: simple
---
# Toy Chain ...
- [information][11]
- [settings][6]
- [explorer][2]
- [web-service][7]
@ -12,7 +13,7 @@ layout: simple
- [README][3]
- [genesis][8]
- [transactions][9]
- [API][1]
- [API][1] ([status][10])
- [notes][5]
### Installation
@ -28,4 +29,6 @@ layout: simple
[7]: /webservice.html
[8]: /docs/genesis.html
[9]: /docs/transactions.html
[10]: /docs/status.html
[11]: /docs/info.html

44
docs/info.js

@ -0,0 +1,44 @@
// getting node information ...
info();
function info() {
let promised = fetch(api_url + 'getinfo').
then(resp => resp.json()).
then(obj => {
document.getElementById('json').innerText = JSON.stringify(obj.info);
let p = document.getElementsByTagName('p')[0];
let buf = p.innerHTML;
buf = buf.replace(':nodeid',obj.info.nodeid);
buf = buf.replace(':port',obj.info.port);
buf = buf.replace(':botname',obj.info.botname);
buf = buf.replace(':owner',obj.info.owner);
buf = buf.replace(':peerid',obj.info.peerid);
buf = buf.replace(':height',obj.info.height);
buf = buf.replace(/:head/g,obj.info.head);
buf = buf.replace(/:genesis/g,obj.info.genesis);
p.innerHTML = buf;
if (typeof(obj.api) != 'undefined') {
let list = '<ol>';
for (let item of obj.api) {
console.log('test.item:',item);
let url = api_url + `getcas?addr=${item}`;
list += `<li><a href="${url}">${item}</a></li>\n`
}
list += '</ol>';
document.getElementById('list').innerHTML = list;
}
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
// ----------------------------------------------------
console.log('info.js loaded');

29
docs/info.md

@ -0,0 +1,29 @@
---
layout: simple
---
# Nodes' Information
<p>
nodeid: :nodeid
<br>port: :port
<br>botname: :botname
<br>owner: :owner
<br>peerid: :peerid
<br>
<br>block height: :height
<br>head bkhash: <a href="/api/v0.0/getblock?hash=:head">:head</a>
<br>genesis bkhash: <a href="/api/v0.0/getblock?hash=:genesis">:genesis</a>
</p>
<textarea id=json></textarea>
([json](/api/0.0/getjson?obj=result))
<div id=list></div>
<a href="/docs/"><button id=docs>documentation</button></a>
<script src="info.js"></script>

30
docs/minepool.js

@ -0,0 +1,30 @@
minepool();
function minepool() {
let promised = fetch(api_url + 'minepool').
then(resp => resp.json()).
then(obj => {
document.getElementById('json').innerText = JSON.stringify(obj);
if (typeof(obj.txpool) != 'undefined') {
let list = '<ol>';
for (let txa of obj.txpool) {
console.log('getpool.bh:',txa);
let tx_url = api_url + `gettx?addr=${txa}`;
list += `<li><a href="${tx_url}">${txa}</a></li>\n`
}
list += '</ol>';
document.getElementById('list').innerHTML = list;
}
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
// ----------------------------------------------------
console.log('txpool.js loaded');

30
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: <span id=height></span>
HEAD: <span id=head></span>
new block: <span id=new></span>
<textarea id=json></textarea>
([json][1])
<div id=list></div>
<a href="/docs/chain.html"><button id=chain>chain view</button></a>
<script src="minepool.js"></script>
[1]: /api/0.0/getjson?obj=result

24
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
<textarea id=json></textarea>
<div id=list></div>
<a href="/docs/chain.html"><button id=chain>chain view</button></a>
<script src="mining.js"></script>

30
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 = '<ol>';
for (let node of obj.api) {
console.log('getnodes.node:',node);
let url = `http:/${node}/docs/chain.html`
list += `<li><a href="${url}">${node}</a></li>\n`
}
list += '</ol>';
document.getElementById('list').innerHTML = list;
}
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
// ----------------------------------------------------
console.log('nodes.js loaded');

21
docs/nodes.md

@ -0,0 +1,21 @@
---
layout: simple
---
# ToyChain Nodes
getting nodes list : fixed network here (no discovery).
<textarea id=json></textarea>
<div id=list></div>
&gt; <a href="javascript:location.href=location.origin+'/docs/chain.html';">this node</a>
### API commands
- [/api/v0.0/getnodes](/api/v0.0/getnodes)
<script src="nodes.js"></script>
<a href="/docs/"><button id=docs>documentation</button></a>

22
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 &amp; links
- testing javascript with a [gist:42835214f63750080a8cb73d4be5a4a1](https://hologit-ml.ipns.cf-ipfs.com/tstanchfield/code.git)

4
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);

27
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)

30
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 = '<ol>';
for (let item of obj.api) {
console.log('test.item:',item);
let url = api_url + `getcas?addr=${item}`;
list += `<li><a href="${url}">${item}</a></li>\n`
}
list += '</ol>';
document.getElementById('list').innerHTML = list;
}
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
// ----------------------------------------------------
console.log('txpool.js loaded');

42
docs/test.md

@ -0,0 +1,42 @@
---
layout: simple
---
# Testing the ToyChain
testing the API ...
### internals
- [getnodes](/api/v0.0/getnodes)
- [chain](/api/v0.0/getjson?obj=toychain::chain)
- [TXPOOL](/api/v0.0/getjson?obj=TXPOOL::TXPOOL)
- [UTXO](/api/v0.0/getjson?obj=TXPOOL::UTXO)
- [getregs](/api/v0.0/getjson?obj=registration)
- [getruntime](/api/v0.0/getjson?obj=runtime)
- [txcoin](/api/v0.0/getjson?obj=Genesis::txcoin)
- [getnick](/api/v0.0/getjson?obj=nicknames)
- [getkeys](/api/v0.0/getjson?obj=keys)
### source :
- [config](/lib/config.pm)
- [toychain](/lib/toychain.pm)
- [Chain](/lib/Chain.pm)
- [ECKeys](/lib/ECKeys.pm)
- [Genesis](/lib/Genesis.pm)
- [API](/lib/API.pm)
### nodes :
<div id=list></div>
<textarea id=json></textarea>
<a href="/docs/"><button id=docs>documentation</button></a>
<script src="test.js"></script>

51
docs/transactions.js

@ -0,0 +1,51 @@
let button = document.getElementsByTagName('button')[0];
button.addEventListener('click',gettx,false);
function gettx() {
let addr = document.getElementsByName('addr')[0].value;
let url = api_url + 'gettx?addr=' + addr;
document.getElementById('url').innerHTML = `<a href=${url}>${url}</a>`;
let promised = fetch(url).
then(resp => resp.json()).
then(obj => {
let elem = document.getElementById('json');
elem.innerText = JSON.stringify(obj.tx);
console.log('obj.tx',obj.tx);
document.getElementById('txroot').innerText = obj.tx.txroot
document.getElementById('pow').innerText = obj.tx.pow
let list = ''
for (let i of obj.tx.inputs) {
public = Object.keys(i)[0];
list += `<li>${public} ${i[public]}</li>`;
}
document.getElementById('in').innerHTML = list;
list = ''
for (let o of obj.tx.outputs) {
public = Object.keys(o)[0];
list += `<li>${public} ${o[public]}</li>`;
}
document.getElementById('out').innerHTML = list;
list = ''
for (let s of obj.tx.signatures) {
public = Object.keys(s)[0];
list += `<li>${public} ${s[public][0]}</li>`;
}
document.getElementById('sig').innerHTML = list;
document.getElementById('yaml').innerText = obj.yaml;
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj.tx; });
}
// ----------------------------------------------------
console.log('transactions.js loaded');

46
docs/transactions.md

@ -0,0 +1,46 @@
---
layout: simple
---
# Transactions
There are two types:
1. mempool transactions : pending validation
2. block transactions : confirmed transactions (organized in merkle tree)
You can create a [transaction][1] using the [settx][2] [API][3] call.
You can view transactions with the address :
addr: <input name=addr size=38 value="ZtxZojTad7bmjVKH67eeRGeaEKkTNQtEdiTxEMKFXGbC">
<button>view</button>
<textarea id=json></textarea>
txroot: <span id=txroot></span>
<br>pow: <span id=pow></span>
<br>url: <span id=url></span>
### inputs
<ol id=in></ol>
### outputs
<ol id=out></ol>
### signatures
<ol id=sig></ol>
----
<pre id=yaml></pre>
[1]: /api/transaction.html
[2]: /api/settx.html
[3]: /api/
<script src="transactions.js"></script>

28
docs/txpool.js

@ -0,0 +1,28 @@
getpool();
function getpool() {
let promised = fetch(api_url + 'getpool').
then(resp => resp.json()).
then(obj => {
document.getElementById('json').innerText = JSON.stringify(obj);
let list = '<ol>';
for (let txa of obj.txpool) {
console.log('getpool.bh:',txa);
let tx_url = api_url + `gettx?addr=${txa}`;
list += `<li><a href="${tx_url}">${txa}</a></li>\n`
}
list += '</ol>';
document.getElementById('list').innerHTML = list;
return obj;
}).
catch(console.error);
promised.then(obj => { console.log('obj:',obj); return obj; });
}
// ----------------------------------------------------
console.log('txpool.js loaded');

21
docs/txpool.md

@ -0,0 +1,21 @@
---
layout: simple
---
# ToyChain's TxPool View
The ToyChain [TxPool][1] is a list of pending transactions
<textarea id=json></textarea>
Here is the list all the transactions in the pool
<div id=list></div>
<a href="/docs/minepool.html"><button id=minepool>minepool</button></a>
<script src="txpool.js"></script>
[1]: /api/v0.0/getjson?obj=TXPOOL::TXPOOL

32
eckeygen.pl

@ -1,32 +0,0 @@
#!/usr/bin/perl
#
# testing out ecdsa key generation ...
use Crypt::PK::ECC;
use YAML::Syck qw(Dump);
#Key generation
my $pk = Crypt::PK::ECC->new();
$pk->generate_key('secp256k1');
my $private_der = $pk->export_key_der('private');
my $public_pem = $pk->export_key_pem('public');
local *PK;
open PK,'>','eckey-priv.der'; binmode(PK);
print PK $private_der;
close
open PK,'>','eckey-pub.pem';
print PK $public_pem;
close PK;
open PK,'>','eckey.yml';
print PK "--- # eckey\n";
printf PK "pk: %s\n",Dump($pk->key2hash);
printf PK "...\n";
close PK;
exit $?;
1; # $Source: /my/perl/script/eckeygen.pl $

2
lib

@ -1 +1 @@
Subproject commit d4bea95cde2025454813231b121ffffa846eee0a
Subproject commit d1fd3ef3a87ec1bd14c33ef19e106c86fde4e78f

10
nodes/cloneit.sh

@ -10,14 +10,14 @@ if [ -d ../lib ]; then
else
git clone --recursive git@git.toptal.com:screening/Michel-Combes node$i
fi
port=$(expr 8089 + 2 \* $i )
echo "node$i: port=$port"
rm node$i/config.yml
sed -e "s/port: .*/port: $port/" node$i/config0.yml > node$i/config.yml
cd node$i
gpg --decrypt local.key.asc | git-crypt unlock -
port=$(expr 8089 + 2 \* $i )
echo "node$i: port=$port"
rm config.yml
sed -e "s/port: .*/port: $port/" templ/config.yml > config.yml
exit $?;
true;

2
salts/Genesis.yml

@ -1 +1 @@
salt: 8163726777753892901
salt: 8163726777754382880

BIN
secrets/keys.yml

BIN
secrets/nicknames.yml

11
t/blockaddr.t

@ -13,12 +13,15 @@ BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } }
#use if -e $LIB, $LIB.'/seed';
use seed qw(rand64);
use toychain qw(blockHash displayBlock);
use functions qw(displayBlock);
use toychain qw(blockHash);
use YAML::Syck qw(Dump);
print "// testing blockaddr\n";
printf "chain.hash %s\n",$toychain::chain->[-1];
printf "head.addr %s\n",$toychain::HEADs[0]->{bkaddr};
my $block0 = $toychain::HEADs[0];
# f96885aa : 21.4min
# 044ce1de : 20.5min
@ -28,10 +31,10 @@ my $n0 = rand64(); # n < 18446744073709551616
printf "n0:%s\n",$n0;
}
displayBlock($toychain::genesis);
displayBlock($block0);
my $hash = &blockHash($toychain::genesis);
printf "genesis.hash %s\n",$hash;
my $hash = &blockHash($block0);
printf "head.hash %s\n",$hash;
print ".\n";
exit $?;

6
t/createtx.t

@ -6,7 +6,7 @@ use TXPOOL qw($TXPOOL $UTXO createTx isTxValid addTxPool);
use CAStore qw(CASRead);
use YAML::Syck qw(Dump);
printf "--- keys %s...\n",Dump($ECKeys::keys);
printf "--- aliases %s...\n",Dump($ECKeys::aliases);
printf "--- nicknames %s...\n",Dump($ECKeys::nicknames);
$UTXO->{$ECKeys::keys->{faucet}{public}} = 1;
printf "--- UTXO %s...\n",Dump($UTXO);
@ -25,11 +25,13 @@ printf "is %s valid: ? %s\n",$txaddr,$txok;
if ($txok) {
&addTxPool($txaddr);
}
# --------------------------------------------
print "TxPool:\n";
for my $i (0 .. $#$TXPOOL) {
printf " %d. %s\n",$i,$TXPOOL->[$i];
}
print ".]n";
print ".\n";
# --------------------------------------------
#my $txp = &CASRead($ENV{SITE}.'/txpool',$txaddr);
#printf "--- txp %s...\n",Dump($txp);

BIN
t/eckeys.t

2
t/genesis.t

@ -2,9 +2,9 @@
BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } }
use Genesis;
use functions qw(displayBlock);
use DAG qw(DAGRead);
use Genesis;
my $genblock = $Genesis::genblock;

3
t/hashcash.t

@ -27,7 +27,8 @@ printf "n0:%s\n",$n0;
#my ($hc,$n) = &hashcash('SHA256','some data',12131054599640746025,6);
#my ($hc,$n) = &hashcash('SHA256','some data',12131054600136590019,8);
my ($hc,$n) = &hashcash('SHA256','some data',12131054604673102375,9);
#my ($hc,$n) = &hashcash('SHA256','some data',12131054702324971967,9);
my ($hc,$n) = &hashcash('SHA256','some data',12131054800000000000,6);
printf "hc: %s %s %s\n",unpack('H*',$hc),$n,unpack'H*',pack('Q',$n);
#($hc,$n) = &hashcash('SHA256','hello world',$n0,5);

7
templ/config.yml

@ -1,8 +1,7 @@
--- # toychain's config
version: 1.06
version: 1.13
chain: toychain
apiver: '0.0'
ipfsgw: 8390
port: 8089
# p2p network = api+1
@ -21,3 +20,7 @@ difficulty: 5
maxdiff: 7
# CAstore options
trackmode: 1
# misc.
ipfsgw: 8390

1
templ/genesis.yml

@ -10,6 +10,7 @@ meta:
txroot: ~
audit:
peerid: Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq
nodeid: ~
tics: 1623830817245864895
ip: 83.78.4.228
prev: ZdtrjkYsAYUeBCs4DRjtVYwPevpxvHjGT2PRauANr3Vao

14
templ/runtest.sh

@ -0,0 +1,14 @@
set -e
for f in tx*.yml; do
echo f: $f
#cat $f | sed -e "s/$/%0a/g" | curl -s -X POST http://127.0.0.1:8089/api/0.0/istxvalid -d @-
cat $f | json_xs -f yaml | grep -v 'null' | curl -s -X POST http://127.0.0.1:8089/api/0.0/settx -d @-
echo ''
done
for f in tx*.json; do
cat $f | curl -s -X POST http://127.0.0.1:8089/api/0.0/settx -d @-
echo ''
done

17
templ/runtime.yml

@ -0,0 +1,17 @@
--- # toychain's runtime state
# cashash mode
trackmode: 1
# verification node
skip_balance_check: 1
# special blocks:
genhash: ~
nullhash: ~
# transactions:
txgen: ~
txcoin: ~
# misc.
ipfsgw: 8390

1
templ/salt.yml

@ -0,0 +1 @@
salt: 3029492618445148610

20
templ/tx.yml

@ -0,0 +1,20 @@
---
inputs:
-
Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 11
outputs:
-
ZF2egd6zrw6EcLJt5TmKPzjMSMpyVmkRCKKehLaaakZEU: 7
-
ZCCWdhnf5aQ3oFMt6JxULAjmCNkB8DNaLpB3Fzcc6V3PN: 1
-
Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 3
payload: This is an example of transaction
signatures:
-
Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq:
- Zan1RjNCSDtQtvuBVNvwvNKwWDwN9tPRGFbmmRoJQFeophTFHq6cAsvskowPgHpKWR1LUc5usEwqRLyxcGLzYYc91k8VENiT4H
-
ZCCWdhnf5aQ3oFMt6JxULAjmCNkB8DNaLpB3Fzcc6V3PN:
- Z381YwxTinKz9QgQQzbRSfi4C9B9GTHJhv6TPiq5qeffrLneeST9QtNeueMXsUVzXmA1jTycJAti5D5YdZRojx7kTDRVv1WoD
timestamp: '1623683269225552702'

1
templ/tx02.json

@ -0,0 +1 @@
{"signatures":[{"michelc":["ZHjX1cinn46FbTioY43qo2ZmfgnjZzXKRMiVN3tZRbxkzg61hNdKRoGptqeFa2tT5kzHqrSUTNcHFTfsLYSz5eDRGXmL3wzc1Gt","2021-06-14 19.54.28","[michelc,0,a]"]},{"anonymous":["ZHjX1cin92axvE1YtoPZyakN1HSFZmXpFxqSVqaWz1S3eyVA5rxTohXUcjcR5sPG9apfTEy34dSUyMPPuN2ngQNDMEFrEgZqbMN","2021-06-14 19.54.28","[anonymous,0,a]"]}],"inputs":[{"ZX3hz85Vayc3Nhfs43ADhTeJXkDJ3fnXtfRiDW4pQzYRQ":"6"}],"nonce":"3976914969180171529","pow":"3976914969180292365","timestamp":"1623693268225555737","outputs":[{"Z24zaLMH6SCfAoC8ndS9XunjrkVpZW5tprhrZdSq3CcXWQ":"3"},{"Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq":"2"}],"message":"This is an other example for transaction"}

23
templ/tx02.yml

@ -0,0 +1,23 @@
---
message: This is an other example for transaction
inputs:
- ZX3hz85Vayc3Nhfs43ADhTeJXkDJ3fnXtfRiDW4pQzYRQ: 3
nonce: '3976914969180171529'
outputs:
-
Z24zaLMH6SCfAoC8ndS9XunjrkVpZW5tprhrZdSq3CcXWQ: 3
-
Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 2
pow: '3976914969180292365'
signatures:
-
michelc:
- ZHjX1cinn46FbTioY43qo2ZmfgnjZzXKRMiVN3tZRbxkzg61hNdKRoGptqeFa2tT5kzHqrSUTNcHFTfsLYSz5eDRGXmL3wzc1Gt
- 2021-06-14 19.54.28
- "[michelc,0,a]"
-
anonymous:
- ZHjX1cin92axvE1YtoPZyakN1HSFZmXpFxqSVqaWz1S3eyVA5rxTohXUcjcR5sPG9apfTEy34dSUyMPPuN2ngQNDMEFrEgZqbMN
- 2021-06-14 19.54.28
- "[anonymous,0,a]"
timestamp: '1623693268225555737'

35
templ/tx03.json

@ -0,0 +1,35 @@
{
"inputs" : [
{
"ZX3hz85Vayc3Nhfs43ADhTeJXkDJ3fnXtfRiDW4pQzYRQ" : "5"
}
],
"message" : "This is an other example for transaction",
"nonce" : "3976914969180171529",
"outputs" : [
{
"Z24zaLMH6SCfAoC8ndS9XunjrkVpZW5tprhrZdSq3CcXWQ" : "3"
},
{
"Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq" : "2"
}
],
"pow" : "3976914969180292365",
"signatures" : [
{
"michelc" : [
"ZHjX1cinn46FbTioY43qo2ZmfgnjZzXKRMiVN3tZRbxkzg61hNdKRoGptqeFa2tT5kzHqrSUTNcHFTfsLYSz5eDRGXmL3wzc1Gt",
"2021-06-14 19.54.28",
"[michelc,0,a]"
]
},
{
"anonymous" : [
"ZHjX1cin92axvE1YtoPZyakN1HSFZmXpFxqSVqaWz1S3eyVA5rxTohXUcjcR5sPG9apfTEy34dSUyMPPuN2ngQNDMEFrEgZqbMN",
"2021-06-14 19.54.28",
"[anonymous,0,a]"
]
}
],
"timestamp" : "1623693268225555737"
}

17
templ/txcb01.yml

@ -0,0 +1,17 @@
---
message: approved 100 coins transaction for blocks mined by Florence M. Buzick for Luke S. Didyk
timestamp: '1626168575783464960'
inputs:
- coinbase: 100
nonce: '7717044746294770303'
outputs:
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 100
- miner: 0
pow: '7717044746294792842'
signatures:
- coinbase:
- Zan1RjQUyrJ3JizN1nERKLNWukKB11QMuFEEV6LrdQtYLPncesNz26jdgp1WfM5Ky2DTgJZHwVpFkem39Z846F2rjKwwcMRC4h
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq:
- Z381YwxUem1mcUiuBAuXevAJ8zaWhHRL9uCsx1Qix21gbSSpszfnwF1qVCxsPCHj7HPeLetVpKJaok3UH3gQ72AEXfTbmqcEW
- miner:
- ZHjX1cinqAEpNp7wUuX6P2jXWzZFRGQvuCtG78bVRv6w3hrXU2xihQKBDnniee4yA5sRzbxUZgqnzvzQfJsUQCzUf7T9xUDisF6

17
txpool/txcoin.yml → templ/txcoin.yml.sig

@ -1,11 +1,16 @@
---
message: This is a coinbase transaction of 100 coins to be distributed to Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq
inputs:
- coinbase: 100
outputs:
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 100
timestamp: '1625385951347499858'
-
coinbase: 100
message: This is a coinbase transaction of 100 coins to be distributed to Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq
nonce: '3976914969180171529'
outputs:
-
Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 100
pow: '3976914969180292365'
signatures:
- coinbase: ~
-
coinbase:
- Z381YwyamFBjdvLNZCUcfoTqNQpxBzCznG9yaYsdFSztN4z9ZEyGDvpjnY33nq91WdjYk6zMuuUDdtvw5nxo6MYKVHcxPYGMJ
- 2021-07-07 22.49.00
timestamp: '1625385951347499858'

6
templ/txexemple.yml → templ/txexample.yml

@ -1,9 +1,9 @@
---
message: This is an exemple of transaction with 3 coins going to Trina M. and 2 coins to Michel C.
--- # Example of Transaction of the ToyChain
message: This is an example of transaction with 3 coins going to Trina M. and 2 coins to Michel C.
timestamp: '1623693268225555737'
nonce: '3976914969180171529'
inputs:
- ZX3hz85Vayc3Nhfs43ADhTeJXkDJ3fnXtfRiDW4pQzYRQ: 3
- ZX3hz85Vayc3Nhfs43ADhTeJXkDJ3fnXtfRiDW4pQzYRQ: 6
outputs:
- Z24zaLMH6SCfAoC8ndS9XunjrkVpZW5tprhrZdSq3CcXWQ: 3
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 2

3
templ/txgen.yml

@ -8,4 +8,5 @@ outputs:
message: This is a coinbase transaction of 50 coins for the genesis block
pow: '3976914969180292365'
signatures:
- coinbase: Zan1RjVTw7GPVyd7aygjWSrGCtX3M8CVRu3NAyqLC8MToNPE93ju4RrFFjunnbeTYnudR2gSKCamK82xjEfWEtGzGvTRDw25MG
- coinbase:
- Zan1RjVTw7GPVyd7aygjWSrGCtX3M8CVRu3NAyqLC8MToNPE93ju4RrFFjunnbeTYnudR2gSKCamK82xjEfWEtGzGvTRDw25MG

2
templ/txnull.yml

@ -0,0 +1,2 @@
---
...

19
templ/txudj.yml

@ -0,0 +1,19 @@
---
inputs:
- ZX3hz85Vayc3Nhfs43ADhTeJXkDJ3fnXtfRiDW4pQzYRQ: 8
message: This is an exemple of transaction with 3 coins going to Trina M. and 2 coins to Michel C.
nonce: '3976914969180171529'
outputs:
- Z24zaLMH6SCfAoC8ndS9XunjrkVpZW5tprhrZdSq3CcXWQ: 3
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 2
pow: '3976914969180879919'
signatures:
- michelc:
- ZHjX1cinn46FbTioY43qo2ZmfgnjZzXKRMiVN3tZRbxkzg61hNdKRoGptqeFa2tT5kzHqrSUTNcHFTfsLYSz5eDRGXmL3wzc1Gt
- 2021-06-14 19.54.28
- "[michelc,0,a]"
- anonymous:
- ZHjX1cin92axvE1YtoPZyakN1HSFZmXpFxqSVqaWz1S3eyVA5rxTohXUcjcR5sPG9apfTEy34dSUyMPPuN2ngQNDMEFrEgZqbMN
- 2021-06-14 19.54.28
- "[anonymous,0,a]"
timestamp: '1623693268225555737'

1
templ/txvalid.json

@ -0,0 +1 @@
{"txaddr":"ZCBtx7Wg59hvMogWDchKVcGUMo68qDe2dkRfzaskAh3G","outputs":[{"Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq":"100"},{"miner":"0"}],"message":"agreed to give 100 for coinbase transaction to Z21G...stq","nonce":"7717044746241858558","inputs":[{"coinbase":"100"}],"timestamp":"1625714463012468224","signatures":[{"coinbase":["ZHjX1cinHZFWDANGjhJtVn9QMcj4Ra1ejfcZCoccEpLBstEKXD2cvV3b1pP2kC4uhr4BS5g7sARoXarh2C9MyD2e2hpCCvgNYMx"]},{"Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq":["Zan1RjVTEjuzF4fi8FPrWxnsnba6p8co5Kcwob6DWoxFU17cuSNQMogKqfhE5WNFgPu1aD77kLcYkBaHoBh4QNq8NPtpMVkHCx"]},{"miner":["Z381YwxKfWGTkTz8iC7NFxD3wCXwRNWBPeyoGxBVTprpbKP8fC48e4b31i9mcjcrsdVJvon91rUtXZBDv9C1KcvthF5oX4v86"]}],"pow":"7717044746294553205"}

18
templ/txvalid.yml

@ -0,0 +1,18 @@
---
txaddr: ZCBtx7Wg59hvMogWDchKVcGUMo68qDe2dkRfzaskAh3G
message: agreed to give 100 for coinbase transaction to Z21G...stq
timestamp: '1625714463012468224'
inputs:
- coinbase: 100
outputs:
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 100
- miner: 0
nonce: '7717044746241858558'
pow: '7717044746294553205'
signatures:
- coinbase:
- ZHjX1cinHZFWDANGjhJtVn9QMcj4Ra1ejfcZCoccEpLBstEKXD2cvV3b1pP2kC4uhr4BS5g7sARoXarh2C9MyD2e2hpCCvgNYMx
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq:
- Zan1RjVTEjuzF4fi8FPrWxnsnba6p8co5Kcwob6DWoxFU17cuSNQMogKqfhE5WNFgPu1aD77kLcYkBaHoBh4QNq8NPtpMVkHCx
- miner:
- Z381YwxKfWGTkTz8iC7NFxD3wCXwRNWBPeyoGxBVTprpbKP8fC48e4b31i9mcjcrsdVJvon91rUtXZBDv9C1KcvthF5oX4v86

11
txpool/txgen.yml

@ -1,11 +0,0 @@
---
timestamp: '1623683269225552702'
inputs:
- coinbase: 50
nonce: '3976914969180171529'
outputs:
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 50
message: This is a coinbase transaction of 50 coins for the genesis block
pow: '3976914969180292365'
signatures:
- coinbase: Zan1RjVTw7GPVyd7aygjWSrGCtX3M8CVRu3NAyqLC8MToNPE93ju4RrFFjunnbeTYnudR2gSKCamK82xjEfWEtGzGvTRDw25MG
Loading…
Cancel
Save