From 16315b7048134a7bde3d4c060a0d05a560cb0ff5 Mon Sep 17 00:00:00 2001 From: Robert Martin-Legene <robert@nic.ar> Date: Tue, 11 Sep 2018 17:11:12 -0300 Subject: [PATCH] transactors traverses the blockchain\'s transactions and finds out who has ever received ether --- bin/transactors.pl | 262 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100755 bin/transactors.pl diff --git a/bin/transactors.pl b/bin/transactors.pl new file mode 100755 index 0000000..d5018b0 --- /dev/null +++ b/bin/transactors.pl @@ -0,0 +1,262 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; +use IO::File; +use Math::BigInt; +use Carp; +$Carp::Verbose = 1; + +die "\$BFAHOME not set. Did you source bfa/bin/env ?\n" + unless exists $ENV{BFAHOME}; +chdir "$ENV{BFAHOME}" or die $!; + +package tools; +my $rpcport; +my $ua = LWP::UserAgent->new; + +sub new +{ + my $class = shift; + return bless {@_}, ref $class || $class; +} + +sub wait +{ + my $i = ++$_[0]->{'wait'}; + printf "%s%c[D", substr('|/-\\', $i%4, 1), 27; + sleep 1; +} + +sub cat($) +{ + my ($filename) = @_; + my $fh = IO::File->new($filename) or return; + return join('', $fh->getlines); +} + +sub hex2string($) +{ + my ($msg)=@_; + my $txt = ''; + while ($msg ne '') + { + my $i=hex( substr($msg,0,2) ); + my $c='.'; + $c=chr($i) if $i >= 32 and $i <= 127; + $txt .= $c; + $msg=substr $msg, 2; + } + return $txt; +} + +sub rpcreq +{ + my ( $opname, @params ) = @_; + if ( not defined $rpcport ) + { + $rpcport = tools::cat "$ENV{BFAHOME}/network5445/node1/rpcport" or die; + } + my $req = HTTP::Request->new( POST => "http://127.0.0.1:$rpcport" ); + $req->content_type('application/json'); + my $extra = scalar @params + ? sprintf(qq(,\"params\":[%s]), join(',', @params)) + : ''; + $req->content( qq({"jsonrpc":"2.0","method":"${opname}"${extra},"id":1})); + my $res = $ua->request($req); + die $res->status_line + unless $res->is_success; + return $res->content; +} + +package balance; +use JSON; + +sub new +{ + my ($class, $acct, $at) = @_; + my $self = bless {}, ref $class || $class; + $self->get( $acct, $at ) if defined $acct; + return $self; +} + +sub acct +{ + my ($self, $acct) = @_; + if ( defined $acct ) + { + $acct = '0x'.$acct if $acct !~ /^0x/; + $self->{'_acct'} = $acct; + } + return unless exists $self->{'_acct'}; + return $self->{'_acct'}; +} + +sub at +{ + my ($self, $at) = @_; + $self->{'_at'} = $at if defined $at; + return sprintf('0x%x', $self->{'_at'}) if exists $self->{'_at'}; + return 'latest'; +} + +sub get +{ + my ($self, $acct, $at) = @_; + $self->acct($acct) if defined $acct; + $self->at($at) if defined $at; + my @params = ( sprintf(qq("%s","%s"),$self->acct,$self->at) ); + my $content = tools::rpcreq( 'eth_getBalance', @params ); + my $json; + eval { $json = decode_json( $content ) }; + my $error = error->new( $content ); + if ( $error ) + { + my $msg = ''; + return 'NOTFOUND' if $error->message =~ /^missing trie node /; + die join(' * ', @params, $content); + return; + } + die if not exists $json->{'result'}; + die if not defined $json->{'result'}; + return Math::BigInt->from_hex( $json->{'result'} ); +} + + +package error; +use JSON; + +sub new +{ + my ($class, $json_in) = @_; + my $json; + eval { $json = decode_json( $json_in ) }; + return unless defined $json; + return unless exists $json->{'error'}; + my $self = bless { + '_code' => undef, + '_message' => undef, + }, ref $class || $class; + $self->code( $json->{'error'}->{'code'} ) if exists $json->{'error'}->{'code'}; + $self->message( $json->{'error'}->{'message'} ) if exists $json->{'error'}->{'message'}; + return $self; +} + +sub code +{ + my ( $self, $val ) = @_; + $self->{'_code'} = $val if scalar @_ > 1; + return $self->{'_code'}; +} + +sub message +{ + my ( $self, $val ) = @_; + $self->{'_message'} = $val if scalar @_ > 1; + return $self->{'_message'}; +} + +package block; +use LWP; +use JSON; + +sub new +{ + my ( $class, $json_raw ) = @_; + return unless defined $json_raw; + return if $json_raw eq ''; + my $self = bless {}, ref $class || $class; + $self->{'json_raw'} = $json_raw; + eval { $self->{'json'} = decode_json( $json_raw ) }; + return if $@; + $self->error( error->new($json_raw) ); + return $self; +} + +sub error +{ + return if not exists $_[0]->{'error'}; + return $_[0]->{'error'}; +} + + +sub json +{ + return unless exists $_[0]->{'json'}; + return $_[0]->{'json'}; +} + +sub result +{ + return unless exists $_[0]->{'json'}->{'result'}; + return $_[0]->{'json'}->{'result'}; +} + +sub number +{ + return if not exists $_[0]->result->{'number'}; + return hex( $_[0]->result->{'number'} ); +} + +sub timestamp +{ + return if not exists $_[0]->result->{'timestamp'}; + return hex( $_[0]->result->{'timestamp'} ); +} + +sub miner +{ + return if not exists $_[0]->result->{'miner'}; + return $_[0]->result->{'miner'}; +} + +sub get($;$) +{ + my ($number) = @_; + $number = sprintf('0x%x', $number) if $number ne 'earliest'; + my $cachefile = "cache/block.$number"; + my $content = tools::rpcreq( 'eth_getBlockByNumber', qq("$number"), "true"); + my $block = block->new( $content ); + return if not defined $block; + return if not exists $block->{'json'}; + die $block->error->message + if $block->error; + return if not $block->result; + return $block; +} + +sub tx { + my ($self) = @_; + return $self->result->{'transactions'}; +} + +package main; + +my $number = shift || 'earliest'; +my $_rcpts; + +sub rcpt +{ + return 0 if exists $_rcpts->{$_[0]}; + $_rcpts->{$_[0]} = 1; + return 1; +} + +while ( 1 ) +{ + my $block = block::get($number); + exit 0 if not defined $block; +use Data::Dumper; print Dumper( $block->result ); +die $block->miner; + rcpt( $block->miner ); + my $txref = $block->tx; + for my $tx (@$txref) + { + my $from = $tx->{'from'}; + my $to = $tx->{'to'}; + my $value = $tx->{'value'}; + next if $value eq '0x0'; + printf "%s\n", $to if rcpt( $to ); + } + $number = $block->number + 1; +} -- GitLab