File Coverage

blib/lib/Bitcoin/Crypto/Role/Key.pm
Criterion Covered Total %
statement 56 57 98.2
branch 15 16 93.7
condition 5 6 83.3
subroutine 17 18 94.4
pod 0 2 0.0
total 93 99 93.9


line stmt bran cond sub pod time code
1             package Bitcoin::Crypto::Role::Key;
2             $Bitcoin::Crypto::Role::Key::VERSION = '1.008';
3 10     10   5084 use v5.10;
  10         48  
4 10     10   88 use strict;
  10         39  
  10         199  
5 10     10   107 use warnings;
  10         25  
  10         354  
6 10     10   75 use Types::Standard qw(InstanceOf);
  10         27  
  10         91  
7 10     10   20261 use Crypt::PK::ECC;
  10         31  
  10         450  
8 10     10   80 use Scalar::Util qw(blessed);
  10         26  
  10         463  
9              
10 10     10   2147 use Bitcoin::Crypto::Types qw(BIP44Purpose);
  10         29  
  10         110  
11 10     10   5023 use Bitcoin::Crypto::Config;
  10         25  
  10         300  
12 10     10   3907 use Bitcoin::Crypto::Util qw(get_key_type);
  10         32  
  10         609  
13 10     10   71 use Bitcoin::Crypto::Helpers qw(ensure_length);
  10         41  
  10         426  
14 10     10   75 use Bitcoin::Crypto::Exception;
  10         21  
  10         207  
15 10     10   57 use Moo::Role;
  10         22  
  10         90  
16              
17             with "Bitcoin::Crypto::Role::Network";
18              
19             has "key_instance" => (
20             is => "ro",
21             isa => InstanceOf ["Crypt::PK::ECC"],
22             required => 1,
23             );
24              
25             has 'purpose' => (
26             is => 'ro',
27             isa => BIP44Purpose,
28             writer => '_set_purpose',
29             predicate => 'has_purpose',
30             clearer => 'clear_purpose',
31             required => 0,
32             );
33              
34 0     0   0 sub _is_private { undef }
35              
36             sub _build_args
37             {
38 131     131   324 my ($class, @params) = @_;
39              
40 131 50       471 Bitcoin::Crypto::Exception::KeyCreate->raise(
41             "invalid arguments passed to key constructor"
42             ) unless @params == 1;
43              
44             return
45 131         404 key_instance => $class->_create_key($params[0]);
46             }
47              
48             around BUILDARGS => sub {
49             my ($orig, $class) = @_;
50             my %params = $class->_build_args(splice @_, 2);
51              
52             Bitcoin::Crypto::Exception::KeyCreate->raise(
53             "trying to create key from unknown key data"
54             ) unless $params{key_instance}->is_private() == $class->_is_private;
55              
56             return $class->$orig(%params);
57             };
58              
59             sub _create_key
60             {
61 561     561   1159 my ($class, $entropy) = @_;
62              
63 561 100 66     2479 return $entropy
64             if blessed($entropy) && $entropy->isa("Crypt::PK::ECC");
65              
66 501         1478 my $is_private = get_key_type $entropy;
67              
68 501 100       1131 Bitcoin::Crypto::Exception::KeyCreate->raise(
69             "invalid entropy data passed to key creation method"
70             ) unless defined $is_private;
71              
72 500 100       1582 $entropy = ensure_length $entropy, Bitcoin::Crypto::Config::key_max_length
73             if $is_private;
74              
75 500         1863 my $key = Crypt::PK::ECC->new();
76              
77             Bitcoin::Crypto::Exception::KeyCreate->trap_into(
78             sub {
79 500     500   2522844 $key->import_key_raw($entropy, Bitcoin::Crypto::Config::curve_name);
80             }
81 500         29723 );
82              
83 499         3723 return $key;
84             }
85              
86             sub set_purpose
87             {
88 280     280 0 606 my ($self, $purpose) = @_;
89 280 100       3041 $self->_set_purpose($purpose)
90             if $purpose;
91             }
92              
93             sub raw_key
94             {
95 1139     1139 0 2299 my ($self, $type) = @_;
96              
97 1139 100       2534 unless (defined $type) {
98 570         944 $type = "public_compressed";
99 570 100 100     1389 if ($self->_is_private) {
    100          
100 443         870 $type = "private";
101             }
102             elsif ($self->does("Bitcoin::Crypto::Role::Compressed") && !$self->compressed) {
103 7         483 $type = "public";
104             }
105             }
106 1139         16577 return $self->key_instance->export_key_raw($type);
107             }
108              
109             1;
110