#!/usr/bin/perl BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } } use config qw(loadYaml $config); use essential qw(sdate version); use misc qw(khash yamlify); 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($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); if (exists $keys->{coinbase}) { $keys->{coinbase}{private} = $local_keys->{coinbase}{private}; } else { $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 %signatures = (); my %delta = (); foreach my $sign (@{$tx->{signatures}}) { my ($pub) = keys %{$sign}; $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 $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",$value,$id,$key58; } foreach my $out (@{$tx->{outputs}}) { my ($pub) = keys %{$out}; 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,$id,$key58; } if ($valuein < $valueout) { printf "error: i:%s < o:%s\n",$valuein,$valueout; } my $txi = { timestamp => $tx->{timestamp}, inputs => $tx->{inputs} }; my $txo = { timestamp => $tx->{timestamp}, message => $tx->{message}, outputs => $tx->{outputs} }; my $txio = { timestamp => $tx->{timestamp}, message => $tx->{message}, inputs => $tx->{inputs}, outputs => $tx->{outputs} }; my $txihash = khash('SHA256',yamlify($txi)); my $txohash = khash('SHA256',yamlify($txo)); my $txhash = khash('SHA256',yamlify($txio)); foreach my $pub (keys %delta) { my $value = -$delta{$pub}; my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub; if (exists $signatures{$pub}) { my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub; my $msg; if ($value > 0) { # input $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 = 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); printf "sig: %s: %s (corrected)\n",$id,$sig; $signatures{$pub} = [ $sig, $date, $msg ]; } } else { 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, $msg ]; } else { printf "sig: don't have private key for %s\n",$id; } } } } foreach my $sign (@{$tx->{signatures}}) { my ($pub) = keys %{$sign}; $sign->{$pub} = $signatures{$pub}; } printf "--- %s.sig: %s...\n",$txf,Dump($tx); DumpFile("$txf.sig",$tx); $tx->{nonce} = 3976914969180171529, my $txaddr = CASWrite($ENV{SITE}.'/txpool',$tx,$tx->{nonce},'txpool',$config->{difficulty}); push @{$TXPOOL},$txaddr; &saveTxPool($TXPOOL); exit $?;