Business-Bitcoin

 view release on metacpan or  search on metacpan

lib/Business/Bitcoin/Request.pm  view on Meta::CPAN

  my $curve = Math::EllipticCurve::Prime->from_name('secp256k1');
  my $xpubdata =  Math::BigInt->new(_decode58($xpub))->as_hex;
  $xpubdata =~ /.(.{8})(..)(.{8})(.{8})(.{64})(.{66})(.*)/;
  my ($ver, $depth, $fp, $i, $c, $Kc) = ($1, $2, $3, $4, $5, $6);
  my $K = Math::EllipticCurve::Prime::Point->from_hex(_decompress($Kc));
  if ($bizbtc->path eq 'electrum') {
    # m/0
    my ($Ki, $ci) = _CKDpub($K, $c, 0);
    # m/0/$index
    my ($Ki2, $ci2) = _CKDpub($Ki, $ci, $index);
    return _address(_compress($Ki2));
  }
  else {
    my ($Ki, $ci) = _CKDpub($K, $c, $index);
    return _address(_compress($Ki));
  }
}

sub _CKDpub {
  my ($K, $c, $i) = @_;
  my $curve = Math::EllipticCurve::Prime->from_name('secp256k1');
  my $data = pack('H*', _compress($K)) . pack ('L>', $i);
  my $hmac = hmac_sha512_hex($data, pack('H*', $c)); $hmac =~ /(.{64})(.{64})/;
  my ($Il, $ci) = ($1, $2);
  my $Ki = $curve->g->multiply(Math::BigInt->from_hex($Il))->add($K);
  return ($Ki, $ci);
}

sub _address {
  my $sha256 = sha256(pack('H*', shift));
  my $id = '00' . Crypt::RIPEMD160->hexhash($sha256); $id =~ s/\s//g;
  my $checksum = substr(sha256_hex(sha256(pack('H*', $id))), 0, 8);
  my $address = _encode58(Math::BigInt->from_hex($id . $checksum));
  my $leadingones;
  while ($id =~ /^(00)/) { $leadingones .= '1'; $id =~ s/^00//; }
  return $leadingones . $address;
}

sub _decompress {
  my $Kc = shift; $Kc =~ /^(..)(.*)/;
  my $i = $1; my $K = '04' . '0' x (64 - length($2)) . $2; my $x = Math::BigInt->from_hex($2);
  my $curve = Math::EllipticCurve::Prime->from_name('secp256k1');
  my ($p, $a, $b) = ($curve->p, $curve->a, $curve->b);
  my $y = ($x->bmodpow(3,$p)+$a*$x+$b)->bmodpow(($p+1)/4,$p);
  $y = $p - $y if $i%2 ne $y%2;
  my $yhex = $y->as_hex; $yhex =~ s/^0x//;
  $K .= '0' x (64 - length($yhex)) . $yhex;
  return $K;
}

sub _compress {
  my $K = shift;
  my $Kc = $K->x->as_hex; $Kc =~ s/^0x//;
  $Kc = '0' x (64 - length($Kc)) . $Kc;
  $Kc = ($K->y % 2 ? '03' : '02') . $Kc;
}

sub _decode58 {
  my $todecode = shift;
  $todecode =~ tr/A-HJ-NP-Za-km-z/a-km-zA-HJ-NP-Z/;
  my $decoded = decode_base58($todecode);
}

sub _encode58 {
  my $encoded = encode_base58(shift);
  $encoded =~ tr/a-km-zA-HJ-NP-Z/A-HJ-NP-Za-km-z/;
  return $encoded;
}

sub AUTOLOAD {
  my $self = shift; (my $auto = $AUTOLOAD) =~ s/.*:://;
  return if $auto eq 'DESTROY';
  if ($auto =~ /^(confirmations|processed|status|amount|reference|error)$/x and defined $_[0]) {
    $self->{"\u$auto"} = shift;
  }
  if ($auto =~ /^(reqid|amount|address|reference|version|created|confirmations|processed|status|error)$/x) {
    return $self->{"\u$auto"};
  }
  if ($auto =~ /^(db|id)$/x) {
    return $self->{"\U$auto"};
  }
  die "Could not AUTOLOAD method $auto.";
}

1; # End of Business::Bitcoin::Request

=head1 NAME

Business::Bitcoin::Request - Bitcoin payment request

=head1 VERSION

 $Revision: 1.051 $
 $Date: Tue Oct 16 22:26:58 PDT 2018 $

=head1 SYNOPSIS

Business::Bitcoin::Request objects represent Bitcoin payment requests
generated by Business::Bitcoin.

    use Business::Bitcoin;

    my $bizbtc = new Business::Bitcoin (DB => '/tmp/bizbtc.db',
                                        XPUB => 'xpub...');

    my $request = $bizbtc->request(Amount => 4200);

    print ($request->verify ? "Verified\n" : "Verification failed\n");

=head1 METHODS

=head2 new

Not intended to be called directly. Business::Bitcoin::Request objects
should be created by calling the request method on a Business::Bitcoin
object.

=head2 commit

Commit the Request object to the requests database. Only the
'processed' and 'status' fields are updated in the database.



( run in 1.147 second using v1.01-cache-2.11-cpan-40ba7b3775d )