File Coverage

blib/lib/Bitcoin/Crypto/Role/Key.pm
Criterion Covered Total %
statement 53 53 100.0
branch 8 8 100.0
condition 2 3 66.6
subroutine 18 18 100.0
pod 0 2 0.0
total 81 84 96.4


line stmt bran cond sub pod time code
1             package Bitcoin::Crypto::Role::Key;
2             $Bitcoin::Crypto::Role::Key::VERSION = '2.000_01'; # TRIAL
3             $Bitcoin::Crypto::Role::Key::VERSION = '2.00001';
4 16     16   8283 use v5.10;
  16         72  
5 16     16   121 use strict;
  16         45  
  16         343  
6 16     16   102 use warnings;
  16         47  
  16         431  
7 16     16   89 use Crypt::PK::ECC;
  16         34  
  16         803  
8 16     16   108 use Scalar::Util qw(blessed);
  16         51  
  16         882  
9 16     16   124 use Mooish::AttributeBuilder -standard;
  16         48  
  16         143  
10 16     16   2157 use Type::Params -sigs;
  16         58  
  16         107  
11              
12 16     16   7402 use Bitcoin::Crypto::Types qw(Object InstanceOf BIP44Purpose Enum);
  16         74  
  16         107  
13 16     16   61558 use Bitcoin::Crypto::Constants;
  16         51  
  16         471  
14 16     16   105 use Bitcoin::Crypto::Util qw(get_key_type);
  16         61  
  16         745  
15 16     16   104 use Bitcoin::Crypto::Helpers qw(ensure_length); # loads Math::BigInt
  16         45  
  16         671  
16 16     16   102 use Bitcoin::Crypto::Exception;
  16         54  
  16         2520  
17              
18             sub __create_key
19             {
20 566     566   133302 my ($entropy) = @_;
21              
22 566 100 66     3657 return $entropy
23             if blessed($entropy) && $entropy->isa('Crypt::PK::ECC');
24              
25 505         1573 my $is_private = get_key_type $entropy;
26              
27 505 100       1263 Bitcoin::Crypto::Exception::KeyCreate->raise(
28             'invalid entropy data passed to key creation method'
29             ) unless defined $is_private;
30              
31 504 100       1695 $entropy = ensure_length $entropy, Bitcoin::Crypto::Constants::key_max_length
32             if $is_private;
33              
34 504         2309 my $key = Crypt::PK::ECC->new();
35              
36             Bitcoin::Crypto::Exception::KeyCreate->trap_into(
37             sub {
38 504     504   2308792 $key->import_key_raw($entropy, Bitcoin::Crypto::Constants::curve_name);
39             }
40 504         34192 );
41              
42 503         14359 return $key;
43             }
44              
45 16     16   169 use Moo::Role;
  16         40  
  16         122  
46              
47             has param 'key_instance' => (
48             isa => InstanceOf ['Crypt::PK::ECC'],
49             coerce => \&__create_key,
50             );
51              
52             has param 'purpose' => (
53             isa => BIP44Purpose,
54             writer => 1,
55             clearer => 1,
56             required => 0,
57             );
58              
59             with qw(Bitcoin::Crypto::Role::Network);
60              
61             requires qw(
62             _is_private
63             );
64              
65             sub BUILD
66             {
67 547     547 0 34965 my ($self) = @_;
68              
69 547 100       4143 Bitcoin::Crypto::Exception::KeyCreate->raise(
70             'trying to create key from unknown key data'
71             ) unless $self->key_instance->is_private == $self->_is_private;
72             }
73              
74             signature_for has_purpose => (
75             method => Object,
76             positional => [BIP44Purpose],
77             );
78              
79             sub has_purpose
80             {
81             my ($self, $purpose) = @_;
82              
83             return !$self->purpose || $self->purpose == $purpose;
84             }
85              
86             # __create_key for object usage
87             sub _create_key
88             {
89 17     17   32 shift;
90 17         78 goto \&__create_key;
91             }
92              
93             signature_for raw_key => (
94             method => Object,
95             positional => [Enum [qw(private public public_compressed)], {optional => 1}],
96             );
97              
98             sub raw_key
99             {
100             my ($self, $type) = @_;
101              
102             unless (defined $type) {
103             $type = 'public_compressed';
104             if ($self->_is_private) {
105             $type = 'private';
106             }
107             elsif ($self->does('Bitcoin::Crypto::Role::Compressed') && !$self->compressed) {
108             $type = 'public';
109             }
110             }
111             return $self->key_instance->export_key_raw($type);
112             }
113              
114             sub curve_order
115             {
116 206     206 0 477 my ($self) = @_;
117              
118 206         885 return Math::BigInt->from_hex($self->key_instance->curve2hash->{order});
119             }
120              
121             1;
122