Aaron J. Milius
4 years ago
committed by
Brooke L. Rediker
19 changed files with 363 additions and 59 deletions
-
0CAStore/genesis.yml
-
16CAStore/nullblock.yml
-
69README.md
-
66bin/signtx.pl
-
21config.yml
-
31docs/index.md
-
11docs/notes.md
-
43docs/pow.js
-
88docs/pow.md
-
2lib
-
6nodes/cloneit.sh
-
2salts/Genesis.yml
-
BINsecrets/keys.yml
-
42t/createtx.t
-
6t/genesis.t
-
8t/hashcash.t
-
3t/merkleroot.t
-
6txpool/txcoin.yml
-
2txpool/txgen.yml
@ -0,0 +1,16 @@ |
|||||
|
--- # 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: ~ |
@ -0,0 +1,31 @@ |
|||||
|
--- |
||||
|
layout: simple |
||||
|
--- |
||||
|
# Toy Chain ... |
||||
|
|
||||
|
- [settings][6] |
||||
|
- [explorer][2] |
||||
|
- [web-service][7] |
||||
|
|
||||
|
### documentation |
||||
|
|
||||
|
- [README][3] |
||||
|
- [genesis][8] |
||||
|
- [transactions][9] |
||||
|
- [API][1] |
||||
|
- [notes][5] |
||||
|
|
||||
|
### Installation |
||||
|
|
||||
|
- [INSTALL.md][4] |
||||
|
|
||||
|
[1]: /api/ |
||||
|
[2]: /docs/explorer.html |
||||
|
[3]: /README.html |
||||
|
[4]: /INSTALL.md |
||||
|
[5]: /docs/notes.html |
||||
|
[6]: /admin/settings.html |
||||
|
[7]: /webservice.html |
||||
|
[8]: /docs/genesis.html |
||||
|
[9]: /docs/transactions.html |
||||
|
|
@ -0,0 +1,43 @@ |
|||||
|
const useCapture = true; // capture, bubbling: false
|
||||
|
|
||||
|
button = document.getElementsByTagName('button')[0]; |
||||
|
button.addEventListener('click',hashcash,false); |
||||
|
button.addEventListener('submit',hashcash,false); |
||||
|
console.log(button) |
||||
|
|
||||
|
function hashcash(ev) { |
||||
|
console.log('hashcash.ev: %o',ev); |
||||
|
let algo = document.getElementsByName('algo')[0].value; |
||||
|
let data = document.getElementsByName('data')[0].value; |
||||
|
let nonce = document.getElementsByName('nonce')[0].value || '12131054600136590020'; |
||||
|
let dif = document.getElementsByName('dif')[0].value; |
||||
|
let url = api_url + `hashcash?a=${algo}&b=${data}&n=${nonce}&d=${dif}` |
||||
|
document.getElementById('pow').innerText = 'no-proof'; |
||||
|
let promised = fetch(url). |
||||
|
then(resp => resp.json()). |
||||
|
then(obj => { |
||||
|
console.log('pow.hashcash.obj:',obj); |
||||
|
document.getElementsByName('hashcash')[0].innerText = '0x'+obj.hash; |
||||
|
document.getElementsId('pow').innerText = obj.pow; |
||||
|
|
||||
|
}). |
||||
|
catch(console.error); |
||||
|
} |
||||
|
|
||||
|
let url = api_url + 'config'; |
||||
|
|
||||
|
let promised = fetch(url). |
||||
|
then(resp => resp.json()). |
||||
|
then(obj => { |
||||
|
console.log('pow.obj.config:',obj.config); |
||||
|
let dif = obj.config.difficulty |
||||
|
console.log('pow.dif:',dif); |
||||
|
let elem = document.getElementById('dif'); |
||||
|
elem.innerText = dif; |
||||
|
//let buf = elem.innerHTML; buf = buf.replace(':dif',dif); elem.innerHTML = buf;
|
||||
|
elem = document.getElementsByName('dif')[0]; |
||||
|
elem.value = dif; |
||||
|
return obj.config |
||||
|
}). |
||||
|
catch(console.error) |
||||
|
|
@ -0,0 +1,88 @@ |
|||||
|
--- |
||||
|
layout: simple |
||||
|
--- |
||||
|
# Proof of Work |
||||
|
|
||||
|
We use a [hashcash][1] type of proof of work (see also [Adam Back][ab] annonce) |
||||
|
where the difficulities is set to <span id=dif><i>:dif</i></span>. |
||||
|
|
||||
|
|
||||
|
hash algo: <input name="algo" value="SHA256" size="7"> |
||||
|
<br>data: <input name="data" value="some data" size=24> |
||||
|
<!-- perl -Ilib -Mmisc -e 'print $misc::inonce' |
||||
|
5: 12131054599640746025 |
||||
|
6: 12131054600136000000 |
||||
|
8: 12131054604672000000 |
||||
|
--> |
||||
|
<br>nonce: <input name="nonce" value="12131054604672000000" size=20> |
||||
|
<br>difficulty: <input name="dif" value="7" size="2"> |
||||
|
<br>hashcash: <span name="hashcash"><i>?</i></span> |
||||
|
<br>proof: <span id="pow"><i>:pow</i></span> |
||||
|
<button>compute</button> |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## note: |
||||
|
|
||||
|
- perl hashcash : [/lib/Chain.pm#hashcash](/lib/Chain.pm#hashcash) |
||||
|
- original hashcash's [gi(s)t]: <[gist:8748be59087e244f916618ac2d66ae3b][hologit]> (SHA1 based) |
||||
|
|
||||
|
### code |
||||
|
```perl |
||||
|
# ----------------------------------------------------- |
||||
|
sub hashcash { # ex: hashcash('SHA256',$data,$nonce,7); |
||||
|
my $alg = shift; |
||||
|
my $difficulty = pop; # difficulty < 8 |
||||
|
my $nonce = pop; # 64 bits of nonce |
||||
|
my $n = $nonce; |
||||
|
printf "hashcash.nonce: %s\n",$nonce; |
||||
|
printf "hashcash.difficulty: %s\n",$difficulty; |
||||
|
#printf "data: %s\n",join'',@_; |
||||
|
my $l = 0; |
||||
|
my $match = '8'.substr('0'x$difficulty,0,$l); # set the MSB to 1 to avoid padding problems |
||||
|
my $iv; |
||||
|
use Crypt::Digest qw(); |
||||
|
my $msg = Crypt::Digest->new($alg) or die $!; |
||||
|
$msg->add(join'',@_); |
||||
|
#printf "iv: %s\n",$msg->hexdigest(); |
||||
|
my $h16; |
||||
|
my $pn = pack'Q',$nonce; # Quad |
||||
|
while (1) { # length($pn) < $difficulty) { |
||||
|
$iv = $msg->clone; |
||||
|
$iv->add($pn); |
||||
|
$h16 = $iv->hexdigest(); |
||||
|
if (substr($h16,0,$l+1) eq $match) { |
||||
|
my $elapse = time - $^T + 1; |
||||
|
if ($0 =~ m/\.t$/) { $elapse = 3; } |
||||
|
my $rate = ($n - $nonce) / $elapse / 1000; |
||||
|
#printf "%d: %s %s %s %.0fkH/s %.1fmin\n",$l, $n,unpack('H*',$pn),$h16,$rate,$elapse/60; |
||||
|
# count any zeros : ($h16 =~ m/0/g) ! |
||||
|
my $zc = ($h16 =~ /80+/) ? length($&) : 0; |
||||
|
#print "zc: $zc\n"; |
||||
|
$l = $zc; |
||||
|
last if $zc >= $difficulty; |
||||
|
$match = '8'.substr('0'x$l,0,$l); |
||||
|
#} else { |
||||
|
# printf "%d: %s %s %s %s\r",$l, $n,unpack('H*',$pn),$h16,$match; |
||||
|
} |
||||
|
$pn = pack('Q',$n++); |
||||
|
} |
||||
|
return pack('H*',$h16),$n-1; |
||||
|
} |
||||
|
# ----------------------------------------------------- |
||||
|
|
||||
|
|
||||
|
``` |
||||
|
|
||||
|
[1]: http://www.hashcash.org/papers/hashcash.pdf |
||||
|
[ab]: http://www.hashcash.org/papers/announce.txt |
||||
|
[2]: https://www.cs.jhu.edu/~rdas/finalreport.pdf |
||||
|
[3]: https://www.arijuels.com/wp-content/uploads/2013/09/JB99.pdf |
||||
|
[4]: http://pubs.sciepub.com/jcsa/5/2/2/index.html |
||||
|
[4d]: http://www.sciepub.com/portal/downloads?doi=10.12691/jcsa-5-2-2&filename=jcsa-5-2-2.pdf |
||||
|
[hologit]: https://hologit-ml.ipns.cf-ipfs.com/cbuquo/hashcash.git |
||||
|
[gist]: git@gist.github.com:8748be59087e244f916618ac2d66ae3b.git |
||||
|
|
||||
|
|
||||
|
|
||||
|
<script src="pow.js"></script> |
@ -1 +1 @@ |
|||||
Subproject commit 8a8f4a627abf429965d7d9db4ff519e83f57945c |
|
||||
|
Subproject commit d4bea95cde2025454813231b121ffffa846eee0a |
@ -1 +1 @@ |
|||||
salt: 8163726776976957032 |
|
||||
|
salt: 8163726777753892901 |
@ -0,0 +1,42 @@ |
|||||
|
# |
||||
|
|
||||
|
BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } } |
||||
|
|
||||
|
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); |
||||
|
|
||||
|
$UTXO->{$ECKeys::keys->{faucet}{public}} = 1; |
||||
|
printf "--- UTXO %s...\n",Dump($UTXO); |
||||
|
|
||||
|
my $tx = { |
||||
|
message => 'this is a test transaction', |
||||
|
inputs => [ { 'faucet' => 1 } ], |
||||
|
outputs => [ { 'self' => 1 } ] |
||||
|
}; |
||||
|
my ($txaddr,$tx) = &createTx($tx,'txpool'); |
||||
|
printf "txaddr: %s\n",$txaddr; |
||||
|
|
||||
|
my $txok = &isTxValid($tx); |
||||
|
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"; |
||||
|
|
||||
|
#my $txp = &CASRead($ENV{SITE}.'/txpool',$txaddr); |
||||
|
#printf "--- txp %s...\n",Dump($txp); |
||||
|
|
||||
|
|
||||
|
|
||||
|
exit $?; |
||||
|
|
||||
|
1; |
||||
|
|
@ -1,11 +1,11 @@ |
|||||
--- |
--- |
||||
timestamp: '1625385951347499858' |
|
||||
|
message: This is a coinbase transaction of 100 coins to be distributed to Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq |
||||
inputs: |
inputs: |
||||
- coinbase: 100 |
- coinbase: 100 |
||||
nonce: '3976914969180171529' |
|
||||
outputs: |
outputs: |
||||
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 100 |
- Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 100 |
||||
message: This is a coinbase transaction of 100 coins to be distributed to Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq |
|
||||
|
timestamp: '1625385951347499858' |
||||
|
nonce: '3976914969180171529' |
||||
pow: '3976914969180292365' |
pow: '3976914969180292365' |
||||
signatures: |
signatures: |
||||
- coinbase: ~ |
- coinbase: ~ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue