You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

145 lines
4.3 KiB

#!/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 $?;