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

  1. #!/usr/bin/perl
  2. BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } }
  3. use config qw(loadYaml $config);
  4. use essential qw(sdate version);
  5. use misc qw(khash yamlify);
  6. use TXPOOL qw(saveTxPool txdigest);
  7. use CAStore qw(CASWrite);
  8. use ECKeys qw(ecsign ecverif getPeerid loadKeys);
  9. use YAML::Syck qw(LoadFile Dump DumpFile);
  10. my $keys = loadKeys($ENV{SITE}.'/secrets/keys.yml');
  11. our $aliases = &loadYaml($ENV{SITE}.'/secrets/aliases.yml');
  12. my $keyfile = $ENV{SITE}.'/secrets/coinbase.yml';
  13. if (-e $keyfile) {
  14. my $local_keys = &loadKeys($keyfile);
  15. if (exists $keys->{coinbase}) {
  16. $keys->{coinbase}{private} = $local_keys->{coinbase}{private};
  17. } else {
  18. $keys->{coinbase} = $local_keys->{coinbase};
  19. }
  20. }
  21. foreach my $id (keys %{$keys}) { # list all known aliases ...
  22. my $pub = $keys->{$id}{public};
  23. $aliases->{$pub} = $id if (! defined $aliases->{$pub});
  24. printf " - %-13s: %-46s (%-36s);",$id,$pub,$keys->{$id}{name};
  25. printf " bot:%s\n", &botname::botname($pub);
  26. }
  27. printf "--- keys %s...\n",Dump($keys);
  28. #printf "--- aliases %s...\n",Dump($aliases);
  29. my $txf = shift;
  30. my $tx = LoadFile($txf);
  31. my $date = (exists $tx->{timestamp})? &sdate($tx->{timestamp}) : &sdate(time);
  32. my %signatures = ();
  33. my %delta = ();
  34. foreach my $sign (@{$tx->{signatures}}) {
  35. my ($pub) = keys %{$sign};
  36. $signatures{$pub} = $sign->{$pub};
  37. $delta{$pub} = 0;
  38. }
  39. printf "--- signatures %s...\n",Dump(\%signatures);
  40. foreach my $in (@{$tx->{inputs}}) {
  41. my ($pub) = keys %{$in};
  42. my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
  43. my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub;
  44. my $value = $in->{$pub};
  45. $valuein += $value;
  46. $delta{$pub} -= $value;
  47. printf "in: %s from %s (%s)\n",$value,$id,$key58;
  48. }
  49. foreach my $out (@{$tx->{outputs}}) {
  50. my ($pub) = keys %{$out};
  51. my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
  52. my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub;
  53. my $value = $out->{$pub};
  54. $valueout += $value;
  55. $delta{$pub} += $value;
  56. printf "out: %s to %s (%s)\n",$value,$id,$key58;
  57. }
  58. if ($valuein < $valueout) {
  59. printf "error: i:%s < o:%s\n",$valuein,$valueout;
  60. }
  61. my $txi = {
  62. timestamp => $tx->{timestamp},
  63. inputs => $tx->{inputs}
  64. };
  65. my $txo = {
  66. timestamp => $tx->{timestamp},
  67. message => $tx->{message},
  68. outputs => $tx->{outputs}
  69. };
  70. my $txio = {
  71. timestamp => $tx->{timestamp},
  72. message => $tx->{message},
  73. inputs => $tx->{inputs},
  74. outputs => $tx->{outputs}
  75. };
  76. my $txihash = khash('SHA256',yamlify($txi));
  77. my $txohash = khash('SHA256',yamlify($txo));
  78. my $txhash = khash('SHA256',yamlify($txio));
  79. foreach my $pub (keys %delta) {
  80. my $value = -$delta{$pub};
  81. my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
  82. if (exists $signatures{$pub}) {
  83. my $key58 = (exists $keys->{$id}) ? $keys->{$id}{public} : $pub;
  84. my $msg;
  85. if ($value > 0) { # input
  86. $msg = sprintf q'[%s,%s,%s]',$pub,$value,&txdigest($txihash);
  87. } elsif ($value == 0) {
  88. $msg = sprintf q'[%s,%s,%s]',$pub,$value,&txdigest($txiohash);
  89. } else { # output
  90. $msg = sprintf q'[%s,%s,%s]',$pub,$value,&txdigest($txohash);
  91. }
  92. printf "msg: %s\n",$msg;
  93. if (defined $signatures{$pub}) {
  94. printf "signatures.%s: %s\n",$pub, join',',@{signatures{$pub}};
  95. my $sig = $signatures{$pub}[0];
  96. my $sigok = &ecverif($key58,$sig,$msg);
  97. printf "signature for %s (%s) ? %s\n",$id,$key58,($sigok)?'ok':'invalid';
  98. if (! $sigok) {
  99. my $sig = &ecsign($id,$msg);
  100. printf "sig: %s: %s (corrected)\n",$id,$sig;
  101. $signatures{$pub} = [ $sig, $date, $msg ];
  102. }
  103. } else {
  104. my $id = (exists $aliases->{$pub}) ? $aliases->{$pub} : $pub;
  105. if (exists $keys->{$id}{private}) {
  106. my $sig = &ecsign($id,$msg);
  107. printf "sig: %s: %s\n",$id,$sig;
  108. $signatures{$pub} = [ $sig, $date, $msg ];
  109. } else {
  110. printf "sig: don't have private key for %s\n",$id;
  111. }
  112. }
  113. }
  114. }
  115. foreach my $sign (@{$tx->{signatures}}) {
  116. my ($pub) = keys %{$sign};
  117. $sign->{$pub} = $signatures{$pub};
  118. }
  119. printf "--- %s.sig: %s...\n",$txf,Dump($tx);
  120. DumpFile("$txf.sig",$tx);
  121. $tx->{nonce} = 3976914969180171529,
  122. my $txaddr = CASWrite($ENV{SITE}.'/txpool',$tx,$tx->{nonce},'txpool',$config->{difficulty});
  123. push @{$TXPOOL},$txaddr;
  124. &saveTxPool($TXPOOL);
  125. exit $?;