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 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'); diff --git a/api/nodes.md b/api/nodes.md new file mode 100644 index 0000000..8c431f2 --- /dev/null +++ b/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 | + +
+ + + +
--  +
by: src: [md],[css],[js] + + + +[1]: /api/v0.0/getnodes +[2]: /toychain +[md]: nodes.md +[css]: /style.css +[js]: nodes.js diff --git a/api/peerid.js b/api/peerid.js new file mode 100644 index 0000000..7faf1d1 --- /dev/null +++ b/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'); diff --git a/api/peerid.md b/api/peerid.md new file mode 100644 index 0000000..0b0872e --- /dev/null +++ b/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; +``` + + + diff --git a/api/transaction.js b/api/transaction.js new file mode 100644 index 0000000..28507f7 --- /dev/null +++ b/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 = ''; + 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'); diff --git a/api/transaction.md b/api/transaction.md new file mode 100644 index 0000000..76c177f --- /dev/null +++ b/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) + + +{% comment %} + + +{%- endcomment -%} + + + + +txaddr: :txaddr + +[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 + + + + diff --git a/bin/apirun.pl b/bin/apirun similarity index 55% rename from bin/apirun.pl rename to bin/apirun index 8280e64..dd38ba8 100755 --- a/bin/apirun.pl +++ b/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 $ diff --git a/bin/signtx.pl b/bin/signtx.pl index 6753901..379aa42 100755 --- a/bin/signtx.pl +++ b/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; diff --git a/bin/yml2json.sh b/bin/yml2json.sh new file mode 100755 index 0000000..77139c1 --- /dev/null +++ b/bin/yml2json.sh @@ -0,0 +1,5 @@ +# + +cat $1 | json_xs -f yaml -t json | tee ${1%.*}.json +echo '' +ls -l ${1%.*}.json diff --git a/config.yml b/config.yml index 81dcfda..7310d68 100644 --- a/config.yml +++ b/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 +# ------------------------------------------ diff --git a/config0.yml b/config0.yml deleted file mode 100644 index b4be93b..0000000 --- a/config0.yml +++ /dev/null @@ -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 diff --git a/curltest.sh b/curltest.sh index 592dc68..94ea2d5 100644 --- a/curltest.sh +++ b/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 '' diff --git a/docs/UTXO.md b/docs/UTXO.md new file mode 100644 index 0000000..eeb83dd --- /dev/null +++ b/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) diff --git a/docs/block.js b/docs/block.js new file mode 100644 index 0000000..c701cf6 --- /dev/null +++ b/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 = `${payload_value}`; + + document.getElementsByName('hash')[0].value = obj.bkhash; + document.getElementsByName('addr')[0].value = obj.bkaddr; + document.getElementById('prev').innerHTML = `${obj.bkprev}`; + 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 = `(json)`; + + elem = document.getElementById('json'); + elem.innerText = JSON.stringify(obj); + + let bkcontent = obj.bkcontent; + let txmerkle = bkcontent.txmeta.merkle + if (typeof(txmerkle) != 'undefined') { + let list = ''; + 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 = ''; + 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 = ''; + 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 = ''; + 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/heads.md b/docs/heads.md new file mode 100644 index 0000000..6d5074c --- /dev/null +++ b/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. + + + +Here is the list with their respective owners + +
+ + + + + + + + + + + diff --git a/docs/index.md b/docs/index.md index dcabbf9..6e272c9 100644 --- a/docs/index.md +++ b/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 diff --git a/docs/info.js b/docs/info.js new file mode 100644 index 0000000..3f51726 --- /dev/null +++ b/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 = '
    '; + for (let item of obj.api) { + console.log('test.item:',item); + let url = api_url + `getcas?addr=${item}`; + list += `
  1. ${item}
  2. \n` + } + list += '
'; + document.getElementById('list').innerHTML = list; + } + + return obj; + }). + catch(console.error); + promised.then(obj => { console.log('obj:',obj); return obj; }); + +} + +// ---------------------------------------------------- +console.log('info.js loaded'); + diff --git a/docs/info.md b/docs/info.md new file mode 100644 index 0000000..a8cb01a --- /dev/null +++ b/docs/info.md @@ -0,0 +1,29 @@ +--- +layout: simple +--- +# Nodes' Information + +

+nodeid: :nodeid +
port: :port +
botname: :botname +
owner: :owner +
peerid: :peerid +
+
block height: :height +
head bkhash: :head +
genesis bkhash: :genesis +

+ + + +([json](/api/0.0/getjson?obj=result)) + +
+ + + + + + + diff --git a/docs/minepool.js b/docs/minepool.js new file mode 100644 index 0000000..f4c524c --- /dev/null +++ b/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 = '
    '; + for (let txa of obj.txpool) { + console.log('getpool.bh:',txa); + let tx_url = api_url + `gettx?addr=${txa}`; + list += `
  1. ${txa}
  2. \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 += `
  1. ${node}
  2. \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 += `
  1. ${item}
  2. \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/test.md b/docs/test.md new file mode 100644 index 0000000..89a17cc --- /dev/null +++ b/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 : + +
+ + + + + + + + + + diff --git a/docs/transactions.js b/docs/transactions.js new file mode 100644 index 0000000..cc949fe --- /dev/null +++ b/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 = `${url}`; + + 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 += `
  • ${public} ${i[public]}
  • `; + } + document.getElementById('in').innerHTML = list; + list = '' + for (let o of obj.tx.outputs) { + public = Object.keys(o)[0]; + list += `
  • ${public} ${o[public]}
  • `; + } + document.getElementById('out').innerHTML = list; + list = '' + for (let s of obj.tx.signatures) { + public = Object.keys(s)[0]; + list += `
  • ${public} ${s[public][0]}
  • `; + } + 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'); diff --git a/docs/transactions.md b/docs/transactions.md new file mode 100644 index 0000000..1aa6634 --- /dev/null +++ b/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: + + + + +txroot: +
    pow: +
    url: + +### inputs + +
      + +### outputs + +
        + +### signatures + +
          + +---- + +
          
          +
          +
          +[1]: /api/transaction.html
          +[2]: /api/settx.html
          +[3]: /api/
          +
          +
          diff --git a/docs/txpool.js b/docs/txpool.js
          new file mode 100644
          index 0000000..202bbf9
          --- /dev/null
          +++ b/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 = '
            '; + for (let txa of obj.txpool) { + console.log('getpool.bh:',txa); + let tx_url = api_url + `gettx?addr=${txa}`; + list += `
          1. ${txa}
          2. \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/txpool.md b/docs/txpool.md new file mode 100644 index 0000000..09913c1 --- /dev/null +++ b/docs/txpool.md @@ -0,0 +1,21 @@ +--- +layout: simple +--- +# ToyChain's TxPool View + +The ToyChain [TxPool][1] is a list of pending transactions + + + +Here is the list all the transactions in the pool + +
          + + + + + + +[1]: /api/v0.0/getjson?obj=TXPOOL::TXPOOL + + diff --git a/eckeygen.pl b/eckeygen.pl deleted file mode 100644 index 71a3ce6..0000000 --- a/eckeygen.pl +++ /dev/null @@ -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 $ diff --git a/lib b/lib index d4bea95..d1fd3ef 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit d4bea95cde2025454813231b121ffffa846eee0a +Subproject commit d1fd3ef3a87ec1bd14c33ef19e106c86fde4e78f diff --git a/nodes/cloneit.sh b/nodes/cloneit.sh index 1875888..bb51b6e 100644 --- a/nodes/cloneit.sh +++ b/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; diff --git a/salts/Genesis.yml b/salts/Genesis.yml index 44db2a7..2659bb2 100644 --- a/salts/Genesis.yml +++ b/salts/Genesis.yml @@ -1 +1 @@ -salt: 8163726777753892901 +salt: 8163726777754382880 diff --git a/secrets/keys.yml b/secrets/keys.yml index 2cda4b1..8f3974d 100644 Binary files a/secrets/keys.yml and b/secrets/keys.yml differ diff --git a/secrets/nicknames.yml b/secrets/nicknames.yml new file mode 100644 index 0000000..1ddba7b Binary files /dev/null and b/secrets/nicknames.yml differ diff --git a/t/blockaddr.t b/t/blockaddr.t index 06a12ff..b506cba 100644 --- a/t/blockaddr.t +++ b/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 $?; diff --git a/t/createtx.t b/t/createtx.t index a948cc2..768577b 100644 --- a/t/createtx.t +++ b/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); diff --git a/t/eckeys.t b/t/eckeys.t index 6888acf..56011fd 100644 Binary files a/t/eckeys.t and b/t/eckeys.t differ diff --git a/t/genesis.t b/t/genesis.t index 4559cc5..74f090b 100644 --- a/t/genesis.t +++ b/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; diff --git a/t/hashcash.t b/t/hashcash.t index ff57793..af4e261 100644 --- a/t/hashcash.t +++ b/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); diff --git a/templ/config.yml b/templ/config.yml index b4be93b..8018ce7 100644 --- a/templ/config.yml +++ b/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 diff --git a/templ/genesis.yml b/templ/genesis.yml index 781ba46..304b67d 100644 --- a/templ/genesis.yml +++ b/templ/genesis.yml @@ -10,6 +10,7 @@ meta: txroot: ~ audit: peerid: Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq + nodeid: ~ tics: 1623830817245864895 ip: 83.78.4.228 prev: ZdtrjkYsAYUeBCs4DRjtVYwPevpxvHjGT2PRauANr3Vao diff --git a/templ/runtest.sh b/templ/runtest.sh new file mode 100644 index 0000000..288cde9 --- /dev/null +++ b/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 + diff --git a/templ/runtime.yml b/templ/runtime.yml new file mode 100644 index 0000000..06a31b5 --- /dev/null +++ b/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 diff --git a/templ/salt.yml b/templ/salt.yml new file mode 100644 index 0000000..54e8b18 --- /dev/null +++ b/templ/salt.yml @@ -0,0 +1 @@ +salt: 3029492618445148610 diff --git a/templ/tx.yml b/templ/tx.yml new file mode 100644 index 0000000..a4aa304 --- /dev/null +++ b/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' diff --git a/templ/tx02.json b/templ/tx02.json new file mode 100644 index 0000000..9889b69 --- /dev/null +++ b/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"} diff --git a/templ/tx02.yml b/templ/tx02.yml new file mode 100644 index 0000000..c7ce26e --- /dev/null +++ b/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' diff --git a/templ/tx03.json b/templ/tx03.json new file mode 100644 index 0000000..0d2269d --- /dev/null +++ b/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" +} diff --git a/templ/txcb01.yml b/templ/txcb01.yml new file mode 100644 index 0000000..77a767a --- /dev/null +++ b/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 diff --git a/txpool/txcoin.yml b/templ/txcoin.yml.sig similarity index 50% rename from txpool/txcoin.yml rename to templ/txcoin.yml.sig index abebb11..5cb2bac 100644 --- a/txpool/txcoin.yml +++ b/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' diff --git a/templ/txexemple.yml b/templ/txexample.yml similarity index 77% rename from templ/txexemple.yml rename to templ/txexample.yml index 6f222b8..76e1472 100644 --- a/templ/txexemple.yml +++ b/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 diff --git a/templ/txgen.yml b/templ/txgen.yml index ac61f35..225a490 100644 --- a/templ/txgen.yml +++ b/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 diff --git a/templ/txnull.yml b/templ/txnull.yml new file mode 100644 index 0000000..8c61676 --- /dev/null +++ b/templ/txnull.yml @@ -0,0 +1,2 @@ +--- +... diff --git a/templ/txudj.yml b/templ/txudj.yml new file mode 100644 index 0000000..9fdedfa --- /dev/null +++ b/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' diff --git a/templ/txvalid.json b/templ/txvalid.json new file mode 100644 index 0000000..3d999d3 --- /dev/null +++ b/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"} \ No newline at end of file diff --git a/templ/txvalid.yml b/templ/txvalid.yml new file mode 100644 index 0000000..20ae46c --- /dev/null +++ b/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 diff --git a/txpool/txgen.yml b/txpool/txgen.yml deleted file mode 100644 index ac61f35..0000000 --- a/txpool/txgen.yml +++ /dev/null @@ -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