Bitcoin Forum
May 01, 2024, 06:35:23 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 [2]  All
  Print  
Author Topic: What's the largest number of transactions that have been in a block so far?  (Read 2100 times)
dserrano5
Legendary
*
Offline Offline

Activity: 1974
Merit: 1029



View Profile
June 07, 2013, 07:53:21 AM
 #21

Where's your tip address?!!?

Oh nice Smiley

<--- Firstbits 12345, ie 12345Vypv2QSmuRXcciT5oEB27mPbWGeva
1714545323
Hero Member
*
Offline Offline

Posts: 1714545323

View Profile Personal Message (Offline)

Ignore
1714545323
Reply with quote  #2

1714545323
Report to moderator
Make sure you back up your wallet regularly! Unlike a bank account, nobody can help you if you lose access to your BTC.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714545323
Hero Member
*
Offline Offline

Posts: 1714545323

View Profile Personal Message (Offline)

Ignore
1714545323
Reply with quote  #2

1714545323
Report to moderator
1714545323
Hero Member
*
Offline Offline

Posts: 1714545323

View Profile Personal Message (Offline)

Ignore
1714545323
Reply with quote  #2

1714545323
Report to moderator
1714545323
Hero Member
*
Offline Offline

Posts: 1714545323

View Profile Personal Message (Offline)

Ignore
1714545323
Reply with quote  #2

1714545323
Report to moderator
kjj
Legendary
*
Offline Offline

Activity: 1302
Merit: 1024



View Profile
June 07, 2013, 12:13:09 PM
 #22

Script written and running.

bitcoind seems to respond to a getblock request pretty slowly, so it will take a while to scan the entire blockchain...

Reading the block files directly would be much faster.

17Np17BSrpnHCZ2pgtiMNnhjnsWJ2TMqq8
I routinely ignore posters with paid advertising in their sigs.  You should too.
DannyHamilton
Legendary
*
Offline Offline

Activity: 3374
Merit: 4612



View Profile
June 07, 2013, 03:34:11 PM
 #23

Script written and running.
bitcoind seems to respond to a getblock request pretty slowly, so it will take a while to scan the entire blockchain...
Reading the block files directly would be much faster.

Absolutely, but I haven't figured out a good way to deal with variable length integers in perl yet.  I was able to write this script in 10 minutes and get an answer within a few hours.  That's much sooner than I would have gotten a full blockchain parser written.

The script I used was pretty simple and quick to put together, it isn't pretty, but it gets the job done:

Code:
#! /usr/bin/perl

use strict;
use warnings;
use mylibs::json;

sub get_credentials {
        my $envUserName = $ENV{'USER'};
        my $confFile = "/Users/".$envUserName."/Library/Application Support/Bitcoin/bitcoin.conf";
        my ($user, $password);
        my $server = 0;

        chomp $confFile;

        if (open(MYCONFFILE, "< " . $confFile)) {
                my(@lines) = <MYCONFFILE>;
                close(MYCONFFILE);

                foreach (@lines)
                {
                        chomp;
                        if ( /^rpcuser=(.*)$/i ) { $user = $1 }
                        elsif ( /^rpcpassword=(.*)$/i ) { $password = $1 }
                        elsif ( /server=1/i ) { $server = 1 }
                }
        }
        else {
                print "Error opening bitcoin.conf file $!\n";
                exit;
        }

        return $user, $password, $server;
}

################################################
#
#  BEGIN Main
#
################################################


###########
# Authentication
###########
my ($user, $password, $server) = get_credentials();


if ($server != 1) {
        print "ERROR: client is not running in server mode\n";
        exit;
}

###########
# Current Block Height
###########
my $currBlockCommand = "curl --silent --user " .
        $user                       .
        ":"                         .
        $password                   .
        " --data-binary '{\"method\": \"getblockcount\"}' http://127.0.0.1:8332/";

my $currIndexLine = `$currBlockCommand`;

my %currIndex = parse_json($currIndexLine);

###########
# Current Block Hash
###########
my $currHashCommand = "curl --silent --user " .
        $user                       .
        ":"                         .
        $password                   .
        " --data-binary '{\"method\": \"getblockhash\", \"params\": [" .
        ${$currIndex{"result"}} .
        "] }' http://127.0.0.1:8332/";

my $currHashLine = `$currHashCommand`;

my %currHash = parse_json($currHashLine);

###########
# Current Block Details
###########
my $blockDetailsCommand = "curl --silent --user " .
        $user                       .
        ":"                         .
        $password                   .
        " --data-binary '{\"method\": \"getblock\", \"params\": [\"" .
        ${$currHash{"result"}} .
        "\"] }' http://127.0.0.1:8332/";

my $blockDetailsLine = `$blockDetailsCommand`;

my %blockDetails = parse_json($blockDetailsLine);

###########
# Loop through blocks
###########
my $maxTxQty = @{$blockDetails{"result"}{"tx"}};
my $biggestBlock = ${$blockDetails{"result"}{"hash"}};
my $blockTxQty;
my $progress = 0;

while (exists $blockDetails{"result"}{"previousblockhash"}) {
  if ( $progress++ % 100 == 0) {
    print $progress . " , " . $biggestBlock . " , " . $maxTxQty . "\n";
  }
  $blockDetailsCommand = "curl --silent --user " .
          $user                       .
          ":"                         .
          $password                   .
          " --data-binary '{\"method\": \"getblock\", \"params\": [\"" .
          ${$blockDetails{"result"}{"previousblockhash"}} .
          "\"] }' http://127.0.0.1:8332/";

  $blockDetailsLine = `$blockDetailsCommand`;

  %blockDetails = parse_json($blockDetailsLine);

  $blockTxQty = @{$blockDetails{"result"}{"tx"}};
  if ($maxTxQty < $blockTxQty) {
    $maxTxQty = $blockTxQty;
    $biggestBlock = ${$blockDetails{"result"}{"hash"}}
  }
}

print "Block:" . $biggestBlock . ", TxQty:" . $maxTxQty . "\n";
sgravina
Sr. Member
****
Offline Offline

Activity: 451
Merit: 250



View Profile
June 07, 2013, 04:41:22 PM
 #24

Mine is a very general argument.

And therefor not mathematically accurate.

Regardless, having searched through the entire blockchain, the block with the lowest value hash so far is:
000000000000000006582fa9652895fda92c757ae6beee9dfbc3932125b5ab8e

What difficulty does this correspond to.  Looks like it wins my contest.
chriswilmer (OP)
Legendary
*
Offline Offline

Activity: 1008
Merit: 1000


View Profile WWW
June 08, 2013, 07:32:25 AM
 #25

Where's your tip address?!!?

Oh nice Smiley

<--- Firstbits 12345, ie 12345Vypv2QSmuRXcciT5oEB27mPbWGeva

Sent!
dserrano5
Legendary
*
Offline Offline

Activity: 1974
Merit: 1029



View Profile
June 08, 2013, 01:47:00 PM
 #26

Absolutely, but I haven't figured out a good way to deal with variable length integers in perl yet.  I was able to write this script in 10 minutes and get an answer within a few hours.  That's much sooner than I would have gotten a full blockchain parser written.

Look at sub read_var_int in my quick n dirty parser:

Code:
#!/usr/bin/perl

use warnings;
use strict;
use List::MoreUtils qw/natatime/;
use Data::Dumper;

my $MAGIC = 3652501241;
my $BLOCKS_DIR = '/home/btc/.bitcoin/blocks';

## xxd-like output
sub print_dump {
    my ($data) = @_;

    my $offset = 0;
    open my $fd, '<', \$data or die "open: $!";
    while (1) {
        my $read = read $fd, my $bytes, 16;
        last unless $read;
        my @bytes = split '', $bytes;
        my $rawchars = $bytes; $rawchars =~ s/[^ -~]/./g;
        my @hexpairs;
        my $iter = natatime 2, @bytes;
        while (my @vals = $iter->()) {
            push @hexpairs, join '', map { sprintf '%02x', ord } @vals;
        }
        printf "%08x: %-39s  %s\n", $offset, (join ' ', @hexpairs), $rawchars;
        $offset += $read;
    }
    close $fd;
}

sub read_var_int {
    my ($fd, $rem) = @_;
    my $val;

    my $read = read $fd, $val, 1; $$rem -= 1;
    if (!$read) { return undef; }
    $val = unpack 'C', $val;
    if ($val == 0xfd) {
        $read = read $fd, $val, 2; $$rem -= 2;
        $val = unpack 'S', $val;
    } elsif ($val == 0xfe) {
        $read = read $fd, $val, 4; $$rem -= 4;
        $val = unpack 'L', $val;
    } elsif ($val == 0xff) {
        $read = read $fd, $val, 8; $$rem -= 8;
        $val = unpack 'Q', $val;
    }

    return $val;
}

sub read_inputs {
    my ($fd, $count, $rem) = @_;
    my $read;  ## should be used to check ret vals from read/sysread
    my $inputs;

    for my $input (1 .. $count) {
        my ($prev_txid, $prev_idx, $sig_script, $seq);

        $read = read $fd, $prev_txid, 32; $$rem -= 32;
        $prev_txid = unpack 'H64', $prev_txid;
        #print "    prev_txid ($prev_txid)\n";

        $read = read $fd, $prev_idx, 4; $$rem -= 4;
        $prev_idx = unpack 'L', $prev_idx;
        #print "    prev_idx ($prev_idx)\n";

        my $sig_script_len = read_var_int $fd, $rem;
        if (!defined $sig_script_len) { print 'sig_script_len undef'; die; }

        $read = read $fd, $sig_script, $sig_script_len; $$rem -= $sig_script_len;
        #printf "    sig_script: %d bytes\n", length $sig_script;

        $read = read $fd, $seq, 4; $$rem -= 4;
        $seq = unpack 'L', $seq;
        #print "    seq ($seq)\n";

        push @$inputs, {
            prev_txid  => $prev_txid,
            prev_idx   => $prev_idx,
            sig_script => $sig_script,
            seq        => $seq,
        }
    }

    return $inputs;
}

sub read_outputs {
    my ($fd, $count, $rem) = @_;
    my $read;  ## should be used to check ret vals from read/sysread
    my $outputs;

    for my $output (1 .. $count) {
        my ($val, $pubkey_script_len, $pubkey_script);

        $read = read $fd, $val, 8; $$rem -= 8;
        $val = unpack 'Q', $val;

        $pubkey_script_len = read_var_int $fd, $rem;
        if (!defined $pubkey_script_len) { print 'pubkey_script_len undef'; die; }

        $read = read $fd, $pubkey_script, $pubkey_script_len; $$rem -= $pubkey_script_len;
        #printf "    pubkey_script: %d bytes\n", length $pubkey_script;

        push @$outputs, {
            val           => $val,
            pubkey_script => $pubkey_script,
        };
    }

    return $outputs;
}

sub parse_txs {
    my ($txn_data, $len) = @_;
    my $read;  ## should be used to check ret vals from read/sysread
    my $txs;

    my $remaining = $len;
    open my $txn_fd, '<', \$txn_data or die "open: $!";

    my $txn_count = read_var_int $txn_fd, \$remaining;
    if (!defined $txn_count) { print 'txn_count undef'; die; }
    #print "  txn_count ($txn_count)\n";

    #print_dump $txn_data;

    my ($tx_ver, $input_count, $inputs, $output_count, $outputs, $lock_time);
    for my $tx_idx (1 .. $txn_count) {
        $read = read $txn_fd, $tx_ver, 4; $remaining -= 4;
        $tx_ver = unpack 'L', $tx_ver;
        #print "    tx_ver ($tx_ver)\n";

        $input_count = read_var_int $txn_fd, \$remaining;
        if (!defined $input_count) { print 'input_count undef'; die; }
        #print "    input_count ($input_count)\n";

        $inputs = read_inputs $txn_fd, $input_count, \$remaining;
        #print Data::Dumper->Dump ([$inputs],['inputs']);

        $output_count = read_var_int $txn_fd, \$remaining;
        if (!defined $output_count) { print 'output_count undef'; die; }
        #print "    output_count ($output_count)\n";

        $outputs = read_outputs $txn_fd, $output_count, \$remaining;
        #print Data::Dumper->Dump ([$outputs],['outputs']);

        $read = read $txn_fd, $lock_time, 4; $remaining -= 4;
        $lock_time = unpack 'L', $lock_time;
        #print "    lock_time ($lock_time)\n";

        push @$txs, {
            version   => $tx_ver,
            inputs    => $inputs,
            outputs   => $outputs,
            lock_time => $lock_time,
        };
    }

    return $txs;
}

sub parse_block {
    my ($height, $block_data, $len) = @_;
    my $read;  ## should be used to check ret vals from read/sysread

    my $remaining = $len;
    open my $block_fd, '<', \$block_data or die "open: $!";

    my $block_header;
    $read = read $block_fd, $block_header, 80; $remaining -= 80;

    my ($ver, $prev_block, $mrkl, $ts, $bits, $nonce) = unpack 'L H64 H64 L H8 L', $block_header;
    $prev_block = reverse $prev_block=~/../g;
    $mrkl = reverse $mrkl=~/../g;

    my $txn_data;
    $read = read $block_fd, $txn_data, $remaining;

    close $block_fd;

    #my $tx = parse_txs $txn_data, $remaining;  ## commented out for faster parsing

    return {
        version     => $ver,
        height      => $height,
        prev_block  => $prev_block,
        merkle_tree => $mrkl,
        timestamp   => $ts,
        bits        => $bits,
        nonce       => $nonce,
        #tx          => $tx,
    };
}

my $blk_file_num = -1;
my $fd;
sub open_next_blk_file {
    close $fd if defined $fd;
    $blk_file_num++;
    my $blkfile = sprintf "$BLOCKS_DIR/blk%05d.dat", $blk_file_num;
    sysopen $fd, $blkfile, 0 or die "sysopen: $!";
    binmode $fd;
}

#################################################################################################

open_next_blk_file;

my $height = 0;
my %prev_blocks_seen;
while (1) {
    my $read;  ## should be used to check ret vals from read/sysread
    my $data;
    my ($magic, $len, $remaining);

    $read = sysread $fd, $data, 8;
    if (!defined $read) { die "sysread: $!"; }
    if (!$read) {
        warn "sysread: null, going to next file";
        open_next_blk_file;
        redo;
    }
    if ($read < 8) {
        warn "sysread: short read, going to next file";
        open_next_blk_file;
        redo;
    }
    ($magic, $len) = unpack 'L L', $data;
    $remaining = $len;
    next unless $magic;    ## magic == 0, probably near end of file
    if ($MAGIC != $magic) { die "got magic ($magic) instead of ($MAGIC) at block $height\n"; }
    ## read whole block
    $read = sysread $fd, $data, $len;
    if ($len != $read) { $read or last; die "sysread: $!"; }

    #print_dump $block_data;
    my $block = parse_block $height, $data, $len;
    ## orphan detection, untested on orphan chains larger than one single block
    if ($height and exists $prev_blocks_seen{ $block->{'prev_block'} }) {
        my $to_downgrade = ($height-1) - $prev_blocks_seen{ $block->{'prev_block'} };
        warn "orphan, height ($block->{'height'}) pb ($block->{'prev_block'}) ts ($block->{'timestamp'}) to_downgrade ($to_downgrade)\n";
        $height -= ($height-1) - $prev_blocks_seen{ $block->{'prev_block'} };
        next;
    }
    print "$height,$len\n";
#    if (128352 == $block->{'height'}) {
#        use bignum;
#        my $bits = join '', reverse $block->{'bits'} =~ /../g;
#        my ($b1, $b2) = map { hex $_ } $bits =~ /^(..)(.*)$/;
#        my $diff = (0xffff << 208) / ($b2 * 2 ** (8 * ($b1-3)));
#        $block->{'difficulty'} = "$diff";
#
#        print Data::Dumper->Dump ([$block],['block']);
#    }

    $prev_blocks_seen{ $block->{'prev_block'} } = $height;
    $height++;
}
close $fd;


Sent!

Thank you!
Pages: « 1 [2]  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!