From cf075fc8ed1d555e8733db5cf6fb4df5e3e04b24 Mon Sep 17 00:00:00 2001 From: "Aaron J. Milius" Date: Mon, 12 Jul 2021 17:50:18 +0200 Subject: [PATCH] library update (1770129) on Fri Jul 9 04:56:51 PM CEST 2021 --- genesis.yml => CAStore/genesis.yml | 0 CAStore/nullblock.yml | 16 ++++++ README.md | 69 +++++++++++++++++----- bin/signtx.pl | 66 +++++++++++++--------- config.yml | 21 ++++++- docs/index.md | 31 ++++++++++ notes.md => docs/notes.md | 11 +++- docs/pow.js | 43 ++++++++++++++ docs/pow.md | 88 +++++++++++++++++++++++++++++ lib | 2 +- nodes/cloneit.sh | 6 +- salts/Genesis.yml | 2 +- secrets/keys.yml | Bin 1331 -> 1310 bytes t/createtx.t | 42 ++++++++++++++ t/genesis.t | 6 +- t/hashcash.t | 8 ++- t/merkleroot.t | 3 +- txpool/txcoin.yml | 6 +- txpool/txgen.yml | 2 +- 19 files changed, 363 insertions(+), 59 deletions(-) rename genesis.yml => CAStore/genesis.yml (100%) create mode 100644 CAStore/nullblock.yml create mode 100644 docs/index.md rename notes.md => docs/notes.md (81%) create mode 100644 docs/pow.js create mode 100644 docs/pow.md create mode 100644 t/createtx.t diff --git a/genesis.yml b/CAStore/genesis.yml similarity index 100% rename from genesis.yml rename to CAStore/genesis.yml diff --git a/CAStore/nullblock.yml b/CAStore/nullblock.yml new file mode 100644 index 0000000..c854162 --- /dev/null +++ b/CAStore/nullblock.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: ~ diff --git a/README.md b/README.md index 36a641f..d5dd6db 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,51 @@ +--- +layout: simple +--- ## A toy chain -The chain should have these properties: +### The chain should have these properties: - - Running on at least 2 pre-defined nodes (IP addresses given in a config file / no additional discovery necessary)- - - PoW, with every node a miner- - - The difficulty is fixed (i.e., block time is not), each block rewards 100 coins- - - ECDSA cryptography; addresses may be pure public keys- - - Protect against double spending - - Transactions can have additional data payload, signed by the sender (and there needs to be a way to set it) + - Running on at least 2 pre-defined [nodes][7] (IP addresses given in a [config file][8] / no additional discovery necessary)- + - [PoW][9], with every node a miner- + - The [difficulty][10] is fixed (i.e., block time is not), each [block rewards][12] 100 coins- + - [ECDSA][13] cryptography; addresses may be pure public keys- + - 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 which implements the following services and returns JSON data: - * Query the block count. - * Query a single block and return all its transaction data. - * Query a single transaction and return all its data. - * Create a transaction from JSON data and accept it for mining + - Implement a simple REST-like [web service API][1] 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]. +### Example of curl commands + + ```sh + # getting block count + curl http://127.0.0.1:8089/api/0.0/getheight + # getting 4th block + curl http://127.0.0.1:8089/api/0.0/getblock?n=4 + # getting transaction Ztxrms5c5oKqb9Zof3xeC5Q2ZQjSaWv7FU4rAxe2s3sP + curl http://127.0.0.1:8089/api/0.0/gettx?txaddr=Ztxrms5c5oKqb9Zof3xeC5Q2ZQjSaWv7FU4rAxe2s3sP + # posting a transaction + cat txpool/tx.yml | sed -e "s/$/%0a/g" | curl -s -X POST http://127.0.0.1:8089/api/0.0/settx -d @- + # processing the txpool (mining) + curl http://127.0.0.1:8089/api/0.0/minepool + + ``` + +### Security Warning + + Blockchain 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 ** note: sensitive data are encrypted w/ git-crypt; - please send your public key if you need access + please send us your public key if you need access or ask for a shared DH secret - decrypt can be done with the command : ```sh @@ -30,3 +54,20 @@ The chain should have these properties: #gpg --decrypt local.key.asc | git-crypt unlock - ``` + + +[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 +[6]: http://127.0.0.1:8089/api/0.0/minepool +[7]: 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 +[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/bin/signtx.pl b/bin/signtx.pl index 8de0985..6753901 100755 --- a/bin/signtx.pl +++ b/bin/signtx.pl @@ -3,19 +3,17 @@ BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } } -use config; +use config qw(loadYaml $config); use essential qw(sdate version); use misc qw(khash yamlify); -use TXPOOL qw(saveTxPool); +use TXPOOL qw(saveTxPool txdigest); use CAStore qw(CASWrite); use ECKeys qw(ecsign ecverif getPeerid loadKeys); use YAML::Syck qw(LoadFile Dump DumpFile); -my $keys = loadKeys(); -foreach my $id (keys %{$keys}) { - my $pub = $keys->{$id}{public}; - $keys->{$pub}{id} = $id; -} +my $keys = loadKeys($ENV{SITE}.'/secrets/keys.yml'); +our $aliases = &loadYaml($ENV{SITE}.'/secrets/aliases.yml'); + my $keyfile = $ENV{SITE}.'/secrets/coinbase.yml'; if (-e $keyfile) { my $local_keys = &loadKeys($keyfile); @@ -25,42 +23,51 @@ if (-e $keyfile) { $keys->{coinbase} = $local_keys->{coinbase}; } } + +foreach my $id (keys %{$keys}) { # list all known aliases ... + my $pub = $keys->{$id}{public}; + $aliases->{$pub} = $id if (! defined $aliases->{$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); my $txf = shift; +my $tx = LoadFile($txf); my $date = (exists $tx->{timestamp})? &sdate($tx->{timestamp}) : &sdate(time); -my $tx = LoadFile($txf); my %signatures = (); my %delta = (); foreach my $sign (@{$tx->{signatures}}) { my ($pub) = keys %{$sign}; - $signatures{$pub} = $sign->{$pub}[0]; + $signatures{$pub} = $sign->{$pub}; $delta{$pub} = 0; } printf "--- signatures %s...\n",Dump(\%signatures); foreach my $in (@{$tx->{inputs}}) { my ($pub) = keys %{$in}; - my $id = (exists $keys->{$pub}{id}) ? $keys->{$pub}{id} : $pub; - $pub = $keys->{$id}{public} if (exists $keys->{$id}{public}); + my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub; + my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub; my $value = $in->{$pub}; $valuein += $value; $delta{$pub} -= $value; - printf "in: %s from %s (%s)\n",$pub,$id; + printf "in: %s from %s (%s)\n",$value,$id,$key58; } foreach my $out (@{$tx->{outputs}}) { my ($pub) = keys %{$out}; - my $id = (exists $keys->{$pub}{id}) ? $keys->{$pub}{id} : $pub; - $pub = $keys->{$id}{public} if (exists $keys->{$id}{public}); + my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub; + my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub; my $value = $out->{$pub}; $valueout += $value; $delta{$pub} += $value; - printf "out: %s to %s (%s)\n",$value,$pub,$id; + printf "out: %s to %s (%s)\n",$value,$id,$key58; } -if ($valuein != $valueout) { - printf "error: i:%s != o:%s\n",$valuein,$valueout; +if ($valuein < $valueout) { + printf "error: i:%s < o:%s\n",$valuein,$valueout; } my $txi = { timestamp => $tx->{timestamp}, @@ -84,33 +91,36 @@ my $txio = { foreach my $pub (keys %delta) { my $value = -$delta{$pub}; + my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub; if (exists $signatures{$pub}) { - my $id = (exists $keys->{$pub}{id}) ? $keys->{$pub}{id} : $pub; - my $key58 = (exists $keys->{$id}{public}) ? $keys->{$id}{public} : $pub; + my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub; my $msg; if ($value > 0) { # input - $msg = qq'["$pub","$value","$tx->{message}"]'; + $msg = sprintf q'[%s,%s,%s]',$pub,$value,&txdigest($txihash); + } elsif ($value == 0) { + $msg = sprintf q'[%s,%s,%s]',$pub,$value,&txdigest($txiohash); } else { # output - $msg = qq'["$id","$value","$tx->{txohash}"]'; + $msg = sprintf q'[%s,%s,%s]',$pub,$value,&txdigest($txohash); } printf "msg: %s\n",$msg; if (defined $signatures{$pub}) { + printf "signatures.%s: %s\n",$pub, join',',@{signatures{$pub}}; my $sig = $signatures{$pub}[0]; my $sigok = &ecverif($key58,$sig,$msg); printf "signature for %s (%s) ? %s\n",$id,$key58,($sigok)?'ok':'invalid'; if (! $sigok) { - my $sig = &ecsign($id,$msg); + my $sig = &ecsign($id,$msg); printf "sig: %s: %s (corrected)\n",$id,$sig; - $signatures{$pub} = [ $sig, $date ]; + $signatures{$pub} = [ $sig, $date, $msg ]; } } else { - my $id = (exists $keys->{$pub}{id}) ? $keys->{$pub}{id} : $pub; + my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub; if (exists $keys->{$id}{private}) { - my $sig = &ecsign($id,$msg); - printf "sig: %s: %s\n",$id,$sig; - $signatures{$pub} = [ $sig, $date ]; + my $sig = &ecsign($id,$msg); + printf "sig: %s: %s\n",$id,$sig; + $signatures{$pub} = [ $sig, $date, $msg ]; } else { - printf "sig: don't have private key for %s\n",$id; + printf "sig: don't have private key for %s\n",$id; } } } diff --git a/config.yml b/config.yml index 140f18c..81dcfda 100644 --- a/config.yml +++ b/config.yml @@ -1,12 +1,13 @@ --- # toychain's config -version: 1.06 +version: 1.12 chain: toychain apiver: '0.0' ipfsgw: 8390 port: 8089 -# p2p network = api+1 -apis: +# p2p network +# api = p2p+1 +nodes: - 127.0.0.1:8091 - 127.0.0.2:8093 - 127.0.0.3:8095 @@ -16,11 +17,25 @@ apis: # 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 # Proof of Work option diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..dcabbf9 --- /dev/null +++ b/docs/index.md @@ -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 + diff --git a/notes.md b/docs/notes.md similarity index 81% rename from notes.md rename to docs/notes.md index dba10c4..1471453 100644 --- a/notes.md +++ b/docs/notes.md @@ -1,3 +1,7 @@ +--- +layout: simple +base: '../' +--- # Design Notes @@ -48,5 +52,10 @@ - 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" that's already 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 + - How to mitigate DDoS on Mempool ? +- +- why would we want making block more and more difficult to add when technology advance ??? + (how to make spice of spamming constant through technology ?) diff --git a/docs/pow.js b/docs/pow.js new file mode 100644 index 0000000..924ebfb --- /dev/null +++ b/docs/pow.js @@ -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) + diff --git a/docs/pow.md b/docs/pow.md new file mode 100644 index 0000000..7647817 --- /dev/null +++ b/docs/pow.md @@ -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 :dif. + + +hash algo: +
data: + +
nonce: +
difficulty: +
hashcash: ? +
proof: :pow + + +--- + +## 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 + + + + diff --git a/lib b/lib index 8a8f4a6..d4bea95 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit 8a8f4a627abf429965d7d9db4ff519e83f57945c +Subproject commit d4bea95cde2025454813231b121ffffa846eee0a diff --git a/nodes/cloneit.sh b/nodes/cloneit.sh index 73d129a..1875888 100644 --- a/nodes/cloneit.sh +++ b/nodes/cloneit.sh @@ -5,7 +5,11 @@ while [ -e "node$i" ]; do i=$(expr $i + 1) done echo create node$i -#git clone --recursive git@git.toptal.com:screening/Michel-Combes node$i +if [ -d ../lib ]; then + git clone --recursive ../.git node$i +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 diff --git a/salts/Genesis.yml b/salts/Genesis.yml index 7a88f88..44db2a7 100644 --- a/salts/Genesis.yml +++ b/salts/Genesis.yml @@ -1 +1 @@ -salt: 8163726776976957032 +salt: 8163726777753892901 diff --git a/secrets/keys.yml b/secrets/keys.yml index 3437c4286efed7029b49907e00ab46bca277d662..2cda4b1b1583bf3c18f72d0cffd3aadb39af6365 100644 GIT binary patch literal 1310 zcmV+(1>yPtM@dveQdv+`0D`{P*1%L30uIqAmU=ezxa(RkZ2JVhq#gVmh;3Ds8v_jV zCcy8@+}j@Sc4PicMhTy!MjTS|>?v`E*RJWoYK&icAlSW5SNr5Qi5fP7c$>);ZLHpk z5S^=bdt-~up6!%%8E*5Nu&&;uRJeyB{vPh7vhmoL_J|L1b)Twj9le>%8N-O$@T?0` zCOd?}kfL!7)mS@cZtbxqq=L-QL$>#M;TRsoQ1VaK>=i#A_hh?H+E2pire7h`w983> zAmd*Tx8do8{KZfm)zb<8G`ibZ%NP>*@+zMGpkTB{+7GA4M&T{1HjMiTcwD}y3X|6J ziJw+qGc$LQTvr7MMCv5fn%o6NFrga{8(x1AK|wg`hHLh~TaD|+$TR`~6q%3P<%F@d zRWdPQI(gZKAc@uA>MxyqF^k|x?UN)j692fpY)$rE!1JgA)PebPEBAR9mg>#1(Il27 zOCItv&WU{9v=QRUc9t(^Bh5sHR*c~`^K?(s4tY@f`ide+0_%s~!-ybiX=*yLwsCe5 z_TrZNy~q*6ejxRTMP}EIK~WXfH^F=@%q3(X1tX_^t$YWXku8#z9%+71gfiA~i(yq| zQPGZOxglv%5V12YXr$^MdGe^louI>(tt$cEA3ZWcR?>hvw{WqMxxegyCWeHI1(XQ| zN>2<)+7U29$@|_=t4K=Ced{bOs*oS;hqphm`ArXXRpi9@U4P;0CF%VCk}9yh_g0g~ zreCOMl2p=03a8iOhn`)iF=F9!-_vw;uz>>GiQd%=iRKM(Ph}k`bpC7xa6gE!{gezyfM_{ z_v_G!+6TSV$gR&UtS+v-mc-awd&LY5%!QZIJvPumsAQMQ&SLcbk1PotYqyRZ~4#yA!V&Z9_WEg_btR01B`)0 z^)?er7s=Syx^DVa8Kv5}xeuc0BMjaVC01xivx8~>1C99{Bn^Jf7tt0{6p5-Ztw=e& zF+m@541r7zAvQ1C9BMT(pws}kpx~0Yl#gvn%wG3`b`k=j25AMyb9Fe;XeP|dl0?OF-W=-?Y4-Pbok57nwK)l z1u$+~D&-`F?m$yL;Dj$SQMMJco1qoP-xta7p$G+dWz<%9H>5}bYl%X3@Q3}RU}I@& z#2^bSP!nJd>+t*Ro5}T9$CPW2SIy9{N2X_-^?`Qs6jQo`6ZtGqXyFaQ7m literal 1331 zcmV-31)IQBb`TSD z*vz%Lph;N|xs;GG@|PPW^OjzLKxOvRo6QA_%XcrqV{zr~24+Lb@j$^8l`+YyCPQ_M zWKU`tF16eE9pRYV*NhM{14(=yebW=L9TYh&$_o4Wq44T_OR5&`ad%2AzIfxZrT^WA zPcd2_b7&hVfr;G7a3`zw=#&%G7X3HXF9a)D&5HB+n6AOS5Bg7{e^HqQxhv=Vx61_cm`P3Hr4_ zJ<6aDnM>U|uLv3>4e+4A63)v?gLj^GfI5+=NIr!S6R@P9YN-;8lLS$oaj2pn!J8Oq-&=0OBvM2s_e7RHt*z( z1v?$r%cR=6*SajKP91XM=+w_0KbYCz9>Nij5>9vlp>a{bW_IcC7<6T8e8@=H0$ya^ zt1%VX3;=oxu>*CspLy%37>@@F`v#*5fH=~VB}pslD;BNpx5aW`I%)~!$mC$Ne5}ov zKV@gbTg!#eh^2Rjzs!$YX?TtKN^I5013A)_StTo940-OX_!X9iJs)P6acaqSHn7!X z(a%{Jy9$)dAU(PhP;4V*Z9TM*N;@B64D7s1BOVsG&=O>vLI0DsAT~7Ld$xHyi@CkRO zqiBx+@6=(lp}H9a@ca24KXbI4);??X&9aZku_nbKPtQxi*gf^EW zc-_~oU~R8pvTo`9j?tliI&kt;<%sSEfpYOHHy@66aH$)74YRXTLqG3n<+Bthn6vqj zb6m;LHoNY#+3b)`Bgyi{1ZT0H2fy!C$47n3E+~4vE-74j@F5w;v_+xHjIFpgxhYqs z-1E7h#jyrN9i>WH0=(s{$PtOCdBGNHoC)h=-72hWgJoDi8>%(!FTnQS`6HiYjS#t9f#ncGLmJ~5?Oa{3*Zda%E13m zMq3WPwR5eGg1#>H>Kx9Fkrspmq-Z!S$28sVcfAfW`}_YXX0$6tH*H@I>Qy9|efQ)) z2d*K;i=PHY;5+blGMVNT+9c&t(9SRn01hkVZ&1tsA7)aD+yBQLIUsR_&A7Q(uZl}N zPgv5_Hu1w_f4DLD6Ys=EH8k4$$n^fQy9A9h4+#p;zKLQQ&$}l)!T%6;06n0W1PbpQ pgB#F`J;wS`?UI@0>!@Bv)L{$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; + diff --git a/t/genesis.t b/t/genesis.t index e142644..4559cc5 100644 --- a/t/genesis.t +++ b/t/genesis.t @@ -9,9 +9,9 @@ use DAG qw(DAGRead); my $genblock = $Genesis::genblock; my $genhash = $Genesis::genhash; -my $genaddr = $gendblock->{bkaddr}; -printf "genhash%s\n",$genhash; -printf "genaddr%s\n",$genaddr; +my $genaddr = $genblock->{bkaddr}; +printf "genhash: %s\n",$genhash; +printf "genaddr: %s\n",$genaddr; my $genbk = &DAGRead('blocks',$genhash); #printf "--- blk %s...\n",Dump($blk); diff --git a/t/hashcash.t b/t/hashcash.t index c4edf44..ff57793 100644 --- a/t/hashcash.t +++ b/t/hashcash.t @@ -25,9 +25,13 @@ printf "// testing $0\n"; my $n0 = rand64(); # n < 18446744073709551616 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); +printf "hc: %s %s %s\n",unpack('H*',$hc),$n,unpack'H*',pack('Q',$n); -my ($hc,$n) = &hashcash('SHA256','hello world',$n0,5); -printf "hc: %s %x %s\n",unpack('H*',$hc),$n,unpack'H*',pack('Q',$n); +#($hc,$n) = &hashcash('SHA256','hello world',$n0,5); +#printf "hc: %s %x %s\n",unpack('H*',$hc),$n,unpack'H*',pack('Q',$n); #my ($hc,$n) = &hashcash('SHA256','hello world',$n0,'abcdef'); #printf "hc: %s %x %s\n",unpack('H*',$hc),$n,unpack'H*',pack('Q',$n); diff --git a/t/merkleroot.t b/t/merkleroot.t index 152efec..27d0ff0 100644 --- a/t/merkleroot.t +++ b/t/merkleroot.t @@ -3,8 +3,9 @@ BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } } use TXPOOL qw(computeMerkleRoot mbase16); +$TXPOOL::dbug = 1; -my $a = [qw(a b c d e f g)]; +my $a = [map { 'Z'.$_; } qw(a b c d e f g)]; my $mr = &computeMerkleRoot($a); diff --git a/txpool/txcoin.yml b/txpool/txcoin.yml index 0042a1a..abebb11 100644 --- a/txpool/txcoin.yml +++ b/txpool/txcoin.yml @@ -1,11 +1,11 @@ --- -timestamp: '1625385951347499858' +message: This is a coinbase transaction of 100 coins to be distributed to Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq inputs: - coinbase: 100 -nonce: '3976914969180171529' outputs: - Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 100 -message: This is a coinbase transaction of 100 coins to be distributed to Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq +timestamp: '1625385951347499858' +nonce: '3976914969180171529' pow: '3976914969180292365' signatures: - coinbase: ~ diff --git a/txpool/txgen.yml b/txpool/txgen.yml index 2baa5ae..ac61f35 100644 --- a/txpool/txgen.yml +++ b/txpool/txgen.yml @@ -5,7 +5,7 @@ inputs: nonce: '3976914969180171529' outputs: - Z21GdiEggiGa7TPNaqGY8coBy97LoRNpPVu9fxig75nstq: 50 -payload: This is a coinbase transaction of 50 coins for the genesis block +message: This is a coinbase transaction of 50 coins for the genesis block pow: '3976914969180292365' signatures: - coinbase: Zan1RjVTw7GPVyd7aygjWSrGCtX3M8CVRu3NAyqLC8MToNPE93ju4RrFFjunnbeTYnudR2gSKCamK82xjEfWEtGzGvTRDw25MG