Skip to content
Snippets Groups Projects
Commit 4f137abf authored by Robert Martin-Legene's avatar Robert Martin-Legene
Browse files

Rewrote for better database layout

parent d1780003
No related branches found
No related tags found
No related merge requests found
FROM debian FROM debian
RUN useradd --create-home --shell /bin/bash bfa && mkdir /home/bfa/collector RUN useradd --create-home --shell /bin/bash bfa && mkdir /home/bfa/collector
RUN apt-get update && apt-get upgrade -y RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y libjson-perl libnet-dns-perl libdbd-pg-perl libwww-perl vim RUN apt-get install -y libjson-perl libnet-dns-perl libdbd-pg-perl libwww-perl vim
COPY collector.pl /home/bfa/collector COPY collector.pl /home/bfa/collector
RUN chown -R bfa /home/bfa RUN chown -R bfa /home/bfa
USER bfa USER bfa
#CMD /home/bfa/collector/collector.sh ENV BFANODE public.47525974938.bfa.martin-legene.dk.
CMD sleep 14d #CMD /home/bfa/collector/collector.sh
CMD sleep 14d
\ No newline at end of file
...@@ -11,8 +11,8 @@ use LWP; ...@@ -11,8 +11,8 @@ use LWP;
use JSON; use JSON;
use Net::DNS; use Net::DNS;
use Net::DNS::Resolver; use Net::DNS::Resolver;
use DBI; use lib '.';
use "sql" use sql;
# 47525974938; # 47525974938;
my $netversion = Math::BigInt->new( "0xb10c4d39a" ); my $netversion = Math::BigInt->new( "0xb10c4d39a" );
...@@ -20,12 +20,9 @@ my $netversion = Math::BigInt->new( "0xb10c4d39a" ); ...@@ -20,12 +20,9 @@ my $netversion = Math::BigInt->new( "0xb10c4d39a" );
my $chainid = Math::BigInt->new( "0xbfa2018" ); my $chainid = Math::BigInt->new( "0xbfa2018" );
my $idcounter = 0; my $idcounter = 0;
my $ua; my $ua;
my @endpoints;
my @blockqueue; my @blockqueue;
my %sealers; my %sealers;
# Set maxruns to 1 if you want to just do a single run to keep my $sql;
# your database up-to-date.
my $maxruns = 0;
sub info(@) sub info(@)
{ {
...@@ -54,8 +51,9 @@ sub shorthash($) ...@@ -54,8 +51,9 @@ sub shorthash($)
sub rpcreq sub rpcreq
{ {
my ( $endpoint, my ( $opname, @params )= @_;
$opname, @params ) = @_; $ua = LWP::UserAgent->new( keep_alive => 10 )
if not defined $ua;
# $ua->ssl_opts( 'verify_hostname' => 0 ); # $ua->ssl_opts( 'verify_hostname' => 0 );
my %args = ( my %args = (
jsonrpc => '2.0', jsonrpc => '2.0',
...@@ -83,8 +81,12 @@ sub rpcreq ...@@ -83,8 +81,12 @@ sub rpcreq
push @args, $p; push @args, $p;
} }
my $args = '{' . join(',',@args) . '}'; my $args = '{' . join(',',@args) . '}';
die 'The environment variable $BFANODE must contain a URL for a ' .
'server to connect to (e.g. https://10.20.30.40/), but it it ' .
'not set. Stopped'
unless defined $ENV{'BFANODE'};
my $res = $ua->post( my $res = $ua->post(
$endpoint, $ENV{BFANODE},
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Content' => $args, 'Content' => $args,
); );
...@@ -94,88 +96,17 @@ sub rpcreq ...@@ -94,88 +96,17 @@ sub rpcreq
return $json->{'result'}; return $json->{'result'};
} }
sub endpoint_find
{
my $networknumber = $netversion->bstr;
my $res = Net::DNS::Resolver->new();
my $origin = 'bfa.martin-legene.dk';
my $fqdn = sprintf
'_rpc._tcp.public.%s.%s.',
$networknumber, $origin;
my $reply = $res->query( $fqdn, 'SRV' );
die "No SRV RR found for public endpoints. Stopped"
if not $reply;
my @answer;
@answer = rrsort( 'SRV', 'priority', $reply->answer );
die "DNS SRV query returned no SRV records. Stopped"
if not @answer;
my %protolookup = (
'_rpc' => 'http',
'_rpcs' => 'https',
);
@endpoints = ();
foreach my $answer ( @answer )
{
my $targetname = $answer->target;
info "Publicly open endpoint found at %s.\n", $targetname;
my $r_a = $res->query( $targetname, 'A' );
my $r_aaaa = $res->query( $targetname, 'AAAA' );
my @addresses = ();
push @addresses, rrsort( 'A', $r_a->answer )
if $r_a;
push @addresses, rrsort( 'AAAA', $r_aaaa->answer )
if $r_aaaa;
warn "No address found for $targetname,"
if not @addresses;
my $label1 = (split( /\./, $fqdn, 2 ))[0];
foreach my $address_rr ( @addresses )
{
next
if not exists $protolookup{$label1};
my $proto = $protolookup{$label1};
push @endpoints, sprintf(
'%s://%s:%s',
$proto,
$address_rr->address,
$answer->port
);
}
}
info "Preferring endpoint at %s\n", $endpoints[0];
}
sub getblock sub getblock
{ {
my $blockid = $_[0]; my $block = shift;
my $json; my $rpccmd = $block =~ /^(earliest|latest|pending)$/
$blockid = Math::BigInt->new( $blockid ) ? 'eth_getBlockByNumber'
if ref($blockid) eq '' : 'eth_getBlockByHash';
and $blockid =~ /^\d+$/; my $json = rpcreq( $rpccmd, $block, 'false' );
if ( ref $blockid eq 'Math::BigInt' or $blockid =~ /^(earliest|latest|pending)$/ )
{
my $specific = ref $blockid eq 'Math::BigInt'
? $blockid->as_hex
: $blockid;
$json = rpcreq(
$endpoints[0],
'eth_getBlockByNumber',
$specific, 'false' );
}
else
{
$sth_selectBlockByHash->execute( $blockid );
return if $sth_selectBlockByHash->fetch;
$json = rpcreq(
$endpoints[0],
'eth_getBlockByHash',
$blockid, 'false'
);
}
die "We should have received some kind of JSON from our RPC call, " . die "We should have received some kind of JSON from our RPC call, " .
"but apparently not. Stopped " "but apparently not. Stopped "
if not defined $json; if not defined $json;
$sth_selectBlockByHash->execute( $json->{'hash'} ); return if $sql->selectBlockByHash( $json->{'hash'} );
return if $sth_selectBlockByHash->fetch;
foreach my $key (qw( foreach my $key (qw(
timestamp gasUsed gasLimit difficulty number totalDifficulty size timestamp gasUsed gasLimit difficulty number totalDifficulty size
)) { )) {
...@@ -190,7 +121,7 @@ sub getblock ...@@ -190,7 +121,7 @@ sub getblock
$json->{'size'}, $json->{'size'},
$json->{'gasUsed'}, $json->{'gasUsed'},
$json->{'gasLimit'}; $json->{'gasLimit'};
$sth_insertBlock->execute( $sql->sth_insertBlock->execute(
lc $json->{'hash'}, lc $json->{'hash'},
lc $json->{'parentHash'}, lc $json->{'parentHash'},
$json->{'number'}, $json->{'number'},
...@@ -213,11 +144,11 @@ sub getblock ...@@ -213,11 +144,11 @@ sub getblock
sub getTransByHash sub getTransByHash
{ {
my $hash = $_[0]; my $hash = shift;
$sth_selectTransactionByHash->execute( $hash ); # Don't get it via RPC if we already have it in the database
return if $sth_selectTransactionByHash->fetch; return
if $sql->selectTransactionByHash( $hash );
my $json = rpcreq( my $json = rpcreq(
$endpoints[0],
'eth_getTransactionByHash', 'eth_getTransactionByHash',
$hash $hash
); );
...@@ -225,7 +156,6 @@ sub getTransByHash ...@@ -225,7 +156,6 @@ sub getTransByHash
my $rcpt = undef; my $rcpt = undef;
do { do {
$rcpt = rpcreq( $rcpt = rpcreq(
$endpoints[0],
'eth_getTransactionReceipt', 'eth_getTransactionReceipt',
$hash $hash
); );
...@@ -234,7 +164,7 @@ sub getTransByHash ...@@ -234,7 +164,7 @@ sub getTransByHash
sleep 1; sleep 1;
warn "Couldn't get the transaction receipt for $hash\n"; warn "Couldn't get the transaction receipt for $hash\n";
} }
} while not $rcpt and $max++ < 60; } while not $rcpt and $max++ < 10;
die "Couldn't get the transaction receipt for $hash\n" if not $rcpt; die "Couldn't get the transaction receipt for $hash\n" if not $rcpt;
$json->{'status'} = $rcpt->{'status'}; $json->{'status'} = $rcpt->{'status'};
$json->{'gasUsed'} = $rcpt->{'gasUsed'}; $json->{'gasUsed'} = $rcpt->{'gasUsed'};
...@@ -251,8 +181,11 @@ sub getTransByHash ...@@ -251,8 +181,11 @@ sub getTransByHash
shorthash $json->{'from'}, shorthash $json->{'from'},
shorthash $json->{'to'}; shorthash $json->{'to'};
my $input = $json->{'input'}; my $input = $json->{'input'};
$input =~ s/^0x//; my $inputlen = 0;
my $inputlen = length($input) / 2; if ( $input =~ /^0x/ )
{
$inputlen = (length($input)-2) / 2;
}
my @args = ( my @args = (
lc $json->{'hash'}, lc $json->{'hash'},
lc $json->{'blockHash'}, lc $json->{'blockHash'},
...@@ -262,31 +195,26 @@ sub getTransByHash ...@@ -262,31 +195,26 @@ sub getTransByHash
$json->{'value'}, $json->{'value'},
lc $json->{'from'}, lc $json->{'from'},
lc $json->{'to'}, lc $json->{'to'},
$inputlen,
$json->{'gasUsed'},
$json->{'status'}, $json->{'status'},
$json->{'gasUsed'},
$input,
$inputlen,
); );
my $function = $sth_insertTransaction;
if ( $json->{'contractAddress'} ) if ( $json->{'contractAddress'} )
{ {
push @args, $json->{'contractAddress'}; $sql->insertTransactionWithContractAddress( @args, lc $json->{'contractAddress'} );
$function = $sth_insertTransactionWithContractAddress; }
else
{
$sql->insertTransaction( @args );
} }
$function->execute( @args );
}
sub getTransRcptByHash
{
my $hash = $_[0];
} }
sub versioncheck sub versioncheck
{ {
my $n; my $n;
my $ok = 1; my $ok = 1;
$n = Math::BigInt->new( $n = Math::BigInt->new( rpcreq( "net_version" ) );
rpcreq( $endpoints[0], "net_version" )
);
if ( $n->bcmp( $netversion ) != 0 ) if ( $n->bcmp( $netversion ) != 0 )
{ {
warn "Network says it has net.version " warn "Network says it has net.version "
...@@ -298,9 +226,7 @@ sub versioncheck ...@@ -298,9 +226,7 @@ sub versioncheck
. ").\n"; . ").\n";
$ok = 0; $ok = 0;
} }
$n = Math::BigInt->new( $n = Math::BigInt->new( rpcreq( "eth_chainId" ) );
rpcreq( $endpoints[0], "eth_chainId" )
);
if ( $n->bcmp( $chainid ) != 0 ) if ( $n->bcmp( $chainid ) != 0 )
{ {
warn sprintf("Network says it has eth.chainId %s (%s). Expected %s (%s).\n", $n->bstr, $n->as_hex, $chainid->bstr, $chainid->as_hex); warn sprintf("Network says it has eth.chainId %s (%s). Expected %s (%s).\n", $n->bstr, $n->as_hex, $chainid->bstr, $chainid->as_hex);
...@@ -310,76 +236,56 @@ sub versioncheck ...@@ -310,76 +236,56 @@ sub versioncheck
return $ok; return $ok;
} }
sub sealer
{
my $hash = $_[0];
my $row;
die unless defined $hash;
return $sealers{$hash} if exists $sealers{$hash};
$sth_selectsealer->execute( $hash );
return $sealers{$hash} = $row->[0] if $row = $sth_selectsealer->fetch;
$sth_insertsealer->execute( $hash );
$sth_selectsealer->execute( $hash );
die "Apparently we failed to get find/create a new sealer. Stopped"
if not $row = $sth_selectsealer->fetch;
return $sealers{$hash} = $row->[0];
}
sub getsnap sub getsnap
{ {
my $number = $_[0]; my $blockhash = $_[0];
my @blocks;
$number = Math::BigInt->new( $number )
if ref($number) ne 'Math::BigInt';
my $json = rpcreq( my $json = rpcreq(
$endpoints[0], 'clique_getSnapshotAtHash',
'clique_getSnapshot', $blockhash
$number->as_hex
); );
# Sanity check 1 - does the lookup return the block?
return if not defined $json; return if not defined $json;
my $recents = $json->{'recents'}; my $recents = $json->{'recents'};
return if not defined $recents; # Blockhash of the requested block - we must use this for the insert
my $hash = $json->{'hash'}; $blockhash = $json->{'hash'};
my $count = 0; my $blocknumber = Math::BigInt->new( $json->{'number'} );
while ( exists $recents->{$number->bstr} ) my @infonumbers;
while ( not $blocknumber->is_zero )
{ {
push @blocks, $number->bstr; my $sealerhash = $recents->{$blocknumber->bstr};
$sth_selectBlockByHash->execute( $hash ); last if not defined $sealerhash;
my $row = $sth_selectBlockByHash->fetchrow_hashref; push @infonumbers, $blocknumber->bstr;
return if not defined $row; my $ref = $sql->selectBlockByHash( $blockhash );
my $newnumber = Math::BigInt->new( $row->{'number'} ); # Stop if we get to blocks which we still haven't stored in the db
return if $newnumber->bcmp($number) != 0; return ( undef, $blocknumber )
if not defined $ref;
# Stop if we got to a block with sealers. # Stop if we got to a block with sealers.
return if defined $row->{'sealer'}; return ( undef, $blocknumber )
my $sealerhash = $recents->{$number->bstr}; if exists $ref->{'sealerAccountId'} and defined $ref->{'sealerAccountId'};
return if not defined $sealerhash; $sql->updateWhoSealed( $sealerhash, $blockhash );
my $internalid = sealer( $sealerhash ); my $parentblockid = $ref->{'parentBlockhashId'};
return if not defined $internalid;
my $rows_affected = $sth_updatewhosealed->execute(
$internalid,
$hash
);
# For next block... # For next block...
$hash = $row->{'parentHash'}; $blockhash = $sql->selectBlockhashById( $parentblockid );
$number->bsub(1); $blocknumber->bsub(1);
} }
info "S Snapshot at block # @blocks.\n"; info "S Snapshot at block # @infonumbers.\n";
return $number; return ($blockhash, $blocknumber);
} }
# Find strands of blocks in the database which have their sealer set to NULL
sub allsnaps sub allsnaps
{ {
$sth_selectmaxunknownsigned->execute(); my $blockhash = $sql->selectMaxUnknownSigned;
my $unkn = $sth_selectmaxunknownsigned->fetchrow_hashref;
my $number = Math::BigInt->new( $unkn->{'number'} );
my $committer = 0; my $committer = 0;
while ( defined $number and not $number->is_zero ) while ( defined $blockhash )
{ {
$number = getsnap( $number ); my $blocknumber;
$dbh->commit ( $blockhash, $blocknumber )
= getsnap( $blockhash );
$sql->commit
if ( $committer++ % 75 ) == 0; if ( $committer++ % 75 ) == 0;
last if $blocknumber->is_zero;
} }
$dbh->commit;
} }
sub main sub main
...@@ -387,20 +293,15 @@ sub main ...@@ -387,20 +293,15 @@ sub main
$| = 1; $| = 1;
info "Connecting to database and setting up " info "Connecting to database and setting up "
. "prepared statements.\n"; . "prepared statements.\n";
sql::setup; $sql = sql->new();
#
info "Looking for public RPC endpoints of "
. "the BFA.\n";
$ua = LWP::UserAgent->new( keep_alive => 10 );
endpoint_find();
versioncheck(); versioncheck();
info "Looking for orphaned blocks in the " info "Looking for orphaned blocks in the "
. "database.\n"; . "database.\n";
push @blockqueue, sql::listOrphans(); push @blockqueue, sql->listOrphans();
while ( --$maxruns != 0 ) while ( 1 )
{ {
unshift @blockqueue, "latest"; unshift @blockqueue, 'latest';
while ( @blockqueue ) while ( @blockqueue )
{ {
my $maxinarow = 2500; my $maxinarow = 2500;
...@@ -408,7 +309,7 @@ sub main ...@@ -408,7 +309,7 @@ sub main
while @blockqueue and --$maxinarow; while @blockqueue and --$maxinarow;
# Find out who signed all blocks # Find out who signed all blocks
allsnaps(); allsnaps();
$dbh->commit; $sql->commit;
} }
sleep 5; sleep 5;
} }
......
...@@ -4,105 +4,322 @@ ...@@ -4,105 +4,322 @@
package sql; package sql;
use DBI; use DBI;
use base qw( Class::Accessor );
my @blockqueue; __PACKAGE__->mk_accessors( 'dbh' );
my $dbh; sub new
my $sth_insertBlock;
my $sth_selectBlockByHash;
my $sth_selectTransactionByHash;
my $sth_insertTransaction;
my $sth_insertTransactionWithContractAddress;
my $sth_insertsealer;
my $sth_selectsealer;
my $sth_updatewhosealed;
my $sth_selectmaxunknownsigned;
sub setup
{ {
$dbh = DBI->connect( my ( $class ) = @_;
my $self = bless {}, ref $class || $class;
$self->dbh( DBI->connect(
'dbi:Pg:dbname=postgres;host=postgres','postgres','onlythelonely', 'dbi:Pg:dbname=postgres;host=postgres','postgres','onlythelonely',
{AutoCommit=>0,RaiseError=>1} {AutoCommit=>0,RaiseError=>1}
) ));
or die DBI::errstr; return $self;
$sth_insertBlock = $dbh->prepare(q(
INSERT INTO blocks
( hash, parentHash, number, timestamp,
difficulty, gasUsed, gasLimit, size )
VALUES (?,?,?,?,?,?,?,?)
)) or die $DBI::errstr;
$sth_selectBlockByHash = $dbh->prepare(q(
SELECT parenthash,number,sealer
FROM blocks
WHERE hash=?
)) or die $DBI::errstr;
$sth_selectTransactionByHash
= $dbh->prepare(q(
SELECT "exists"
FROM transactions
WHERE hash=?
)) or die $DBI::errstr;
$sth_insertTransactionWithContractAddress
= $dbh->prepare(q(
INSERT INTO transactions
( hash, blockHash, nonce, gas,
gasPrice, value, _from, _to,
inputlen, gasUsed, status, contractAddress )
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
)) or die $DBI::errstr;
$sth_insertTransaction = $dbh->prepare(q(
INSERT INTO transactions
( hash, blockHash, nonce, gas,
gasPrice, value, _from, _to,
inputlen, gasUsed, status )
VALUES (?,?,?,?,?,?,?,?,?,?,?)
)) or die $DBI::errstr;
$sth_selectsealer = $dbh->prepare(q(
SELECT internalid
FROM sealers
WHERE hash=?
)) or die $DBI::errstr;
$sth_insertsealer = $dbh->prepare(q(
INSERT INTO sealers
( hash )
VALUES (?)
)) or die $DBI::errstr;
$sth_updatewhosealed = $dbh->prepare(q(
UPDATE blocks
SET sealer=?
WHERE hash=?
AND sealer IS NULL
)) or die $DBI::errstr;
$sth_selectmaxunknownsigned
= $dbh->prepare(q(
SELECT number
FROM blocks
WHERE number = (
SELECT MAX(number)
FROM blocks
WHERE sealer IS NULL
)
)) or die $DBI::errstr;
} }
sub listOrphans sub commit
{ {
my @results; my ( $self ) = @_;
my $sth_selectOrphans $self->dbh->commit;
= $dbh->prepare(q( }
SELECT parentHash,number
sub listOrphans
{
my ( $self ) = @_;
my $sth = $self->dbh->prepare(q(
SELECT parentBlockhashId,id
FROM blocks FROM blocks
WHERE parentHash NOT IN ( WHERE parentBlockhashId NOT IN (
SELECT hash SELECT id
FROM blocks FROM blocks
) )
)) or die $DBI::errstr; ));
$sth_selectOrphans->execute(); my @results;
while ( my $row = $sth_selectOrphans->fetch ) $sth->execute();
while ( my $row = $sth->fetchrow_arrayref )
{ {
# Block 0 has it's parent listed as 0x0{64} # Block 0 has it's parent listed as 0x0{64}
next if $row->[0] =~ /^0x0{64}$/; next if $row->[0] =~ /^0x0{64}$/;
push @results, $row->[0] push @results, $self->selectBlockhashById( $row->[0] );
}
$sth->finish;
return @results;
}
__PACKAGE__->mk_accessors( 'sth_insertTransactionWithContractAddress' );
sub insertTransactionWithContractAddress
{
my $self = shift;
if ( not defined $self->sth_insertTransactionWithContractAddress )
{
$self->sth_insertTransactionWithContractAddress(
$self->dbh->prepare(q(
INSERT INTO transactions
( hash, blockId, nonce, gas,
gasPrice, value, fromAccountId, toAccountId,
status, gasUsed, input, inputlen,
contractaddressAccountId )
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
))
);
}
$_[1] = $self->selectBlockhashByHash( $_[1] );
$self->sth_insertTransactionWithContractAddress->execute( @_ );
}
__PACKAGE__->mk_accessors( 'sth_insertTransaction' );
sub insertTransaction
{
my $self = shift;
$self->sth_insertTransaction(
$self->dbh->prepare(q(
INSERT INTO transactions
( hash, blockId, nonce, gas,
gasPrice, value, fromAccountId, toAccountId,
status, gasUsed, input, inputlen )
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
))
);
$_[1] = $self->selectBlockhashByHash( $_[1] );
$self->sth_insertTransaction->execute( @_ );
}
__PACKAGE__->mk_accessors( 'sth_selectBlockhashById' );
sub selectBlockhashById
{
my ( $self, $id ) = @_;
if ( not defined $self->sth_selectBlockhashById )
{
$self->sth_selectBlockhashById(
$self->dbh->prepare(q(
SELECT hash
FROM blockhash
WHERE id=?
))
);
}
$self->sth_selectBlockhashById->execute( $id );
my $ref = $self->sth_selectBlockhashById->fetchrow_arrayref;
$self->sth_selectBlockhashById->finish;
return
if not defined $ref;
return $ref->[0];
}
__PACKAGE__->mk_accessors( 'sth_selectBlockhashByHash' );
sub selectBlockhashByHash
{
my ( $self, $hash )= @_;
if ( not defined $self->sth_selectBlockhashByHash )
{
$self->sth_selectBlockhashByHash(
$self->dbh->prepare(q(
SELECT id
FROM blockhash
WHERE hash=?
))
);
}
my $inserts = 0;
while ( 1 )
{
# Try to look up the hash
$self->sth_selectBlockhashByHash->execute( $hash );
my $ref = $self->sth_selectBlockhashByHash->fetchrow_arrayref;
$self->sth_selectBlockhashByHash->finish;
# If found, return it immediately
return $ref->[0] if defined $ref;
# Do maximum 1 attempt to insert a hash
return if $inserts > 0;
# Insert a hash, because it is not already in the database.
$self->insertBlockhash( $hash );
# Avoid loops.
$inserts++;
}
}
__PACKAGE__->mk_accessors( 'sth_insertBlockhash' );
sub insertBlockhash
{
my ( $self, $hash )= @_;
if ( not defined $self->sth_insertBlockhash )
{
$self->sth_insertBlockhash(
$self->dbh->prepare(q(
INSERT INTO blockhash
( hash )
VALUES (?)
))
)
}
$self->sth_insertBlockhash->execute( $hash );
}
__PACKAGE__->mk_accessors( 'sth_selectAccountIdByAddress' );
my %account;
sub selectAccountIdByAddress
{
my ( $self, $address )= @_;
if ( not defined $self->sth_selectAccountIdByAddress )
{
$self->sth_selectAccountIdByAddress(
$self->dbh->prepare(q(
SELECT id
FROM account
WHERE address=?
))
);
}
while ( not exists $account{$address} )
{
# Try to look up the hash
$self->sth_selectAccountIdByAddress->execute( $address );
my $ref = $self->sth_selectAccountIdByAddress->fetchrow_arrayref;
$self->sth_selectAccountIdByAddress->finish;
# If found, return it immediately
if ( defined $ref )
{
$account{$address} = $row->[0];
last;
}
# Do maximum 1 attempt to insert a hash
# (this is actually a failure and should not happen)
return if $inserts > 0;
# Insert a hash, because it is not already in the database.
$self->insertAccount( $hash );
# Avoid loops.
$inserts++;
}
return $account{$address};
}
__PACKAGE__->mk_accessors( 'sth_insertAccount' );
sub insertAccount
{
my ( $self, $address )= @_;
if ( not defined $self->sth_insertAccount )
{
$self->sth_insertAccount(
$self->dbh->prepare(q(
INSERT INTO account
( address )
VALUES (?)
))
);
}
$self->sth_insertAccount->execute( $hash );
}
__PACKAGE__->mk_accessors( 'sth_insertBlock' );
sub insertBlock
{
my ( $self, $hash, $parentHash, $number, $timestamp, $difficulty, $gasUsed, $gasLimit, $size )
= @_;
if ( not defined $self->sth_insertBlock )
{
$self->sth_insertBlock(
$self->dbh->prepare(q(
INSERT INTO blocks
( id, parentBlockhashId, number, timestamp,
difficulty, gasUsed, gasLimit, size )
VALUES (?,?,?,?,?,?,?,?)
))
);
}
my $id = $self->selectBlockhashByHash( $hash );
my $parentid = $self->selectBlockhashByHash( $parentHash );
$self->sth_insertBlock->execute( $id, $parentid, $number, $timestamp, $difficulty, $gasUsed, $gasLimit, $size );
}
__PACKAGE__->mk_accessors( 'sth_selectBlockByHash' );
sub selectBlockByHash
{
my ( $self, $hash) = @_;
if ( not defined $self->sth_selectBlockByHash )
{
$self->sth_selectBlockByHash(
$self->dbh->prepare(q(
SELECT parenthash,number,sealer
FROM blocks
WHERE hash=?
))
);
}
$sth->sth_selectBlockByHash( $hash );
my $row = $sth->selectBlockByHash->fetchrow_hashref;
$sth->selectBlockByHash->finish;
return
if not defined $row;
return $row;
}
__PACKAGE__->mk_accessors( 'sth_selectTransactionByHash' );
sub selectTransactionByHash
{
my ( $self, $hash) = @_;
if ( not defined $self->sth_selectTransactionByHash )
{
$self->sth_selectTransactionByHash(
$self->dbh->prepare(q(
SELECT 1
FROM transactions
WHERE hash=?
))
);
}
$sth->sth_selectTransactionByHash( $hash );
my $row = $sth->selectTransactionByHash->fetchrow_hashref;
$sth->selectTransactionByHash->finish;
return
if not defined $row;
return $row;
}
__PACKAGE__->mk_accessors( 'sth_selectAccountIdByAddress' );
sub updateWhoSealed
{
my ( $self, $sealerhash, $blockhash ) = @_;
if ( not defined $self->sth_updatewhosealed )
{
$self->sth_updatewhosealed(
$self->dbh->prepare(q(
UPDATE blocks
SET sealerAccountId=?
WHERE id=?
AND sealerAccountId IS NULL
))
);
}
my $blockid = $self->selectBlockhashByHash( $blockhash );
my $sealerid = $self->selectSealerByHash( $sealerhash );
$self->sth_updatewhosealed->execute( $sealerid, $blockid );
}
__PACKAGE__->mk_accessors( 'sth_selectmaxunknownsigned' );
sub selectMaxUnknownSigned
{
my ( $self ) = @_;
if ( not defined $self->sth_selectmaxunknownsigned )
{
$self->sth_selectmaxunknownsigned(
$self->dbh->prepare(q(
SELECT id
FROM blocks
WHERE number = (
SELECT MAX(number)
FROM blocks
WHERE sealer IS NULL
)
))
);
} }
$self->sth_selectmaxunknownsigned->execute();
my $ref = $self->sth_selectmaxunknownsigned->fetchrow_hashref;
$self->sth_selectmaxunknownsigned->finish();
my $blockid = $ref->{'number'};
my $blockhash = $self->selectBlockhashById( $blockid );
return $blockhash;
} }
1; 1;
\ No newline at end of file
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
## POSTGRES SUPERUSER user name is postgres ## POSTGRES SUPERUSER user name is postgres
## POSTGRES SUPERUSER password is onlythelonely ## POSTGRES SUPERUSER password is onlythelonely
## POSTGRES USER dgsi has password bfa ## POSTGRES USER leer has password bfa defined in postgres/90-add-db-user.sh
# defined in postgres/90-add-db-user.sh
version: '3.4' version: '3.4'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment