File Coverage

blib/lib/Bitcoin/Crypto/Exception.pm
Criterion Covered Total %
statement 101 101 100.0
branch 7 10 70.0
condition n/a
subroutine 30 30 100.0
pod 4 4 100.0
total 142 145 97.9


line stmt bran cond sub pod time code
1             package Bitcoin::Crypto::Exception;
2             $Bitcoin::Crypto::Exception::VERSION = '1.008_01'; # TRIAL
3             $Bitcoin::Crypto::Exception::VERSION = '1.00801';
4 19     19   146808 use v5.10;
  19         94  
5 19     19   140 use strict;
  19         48  
  19         430  
6 19     19   101 use warnings;
  19         57  
  19         519  
7 19     19   5676 use Moo;
  19         73860  
  19         129  
8 19     19   25051 use Mooish::AttributeBuilder -standard;
  19         20835  
  19         145  
9              
10 19     19   9772 use Bitcoin::Crypto::Types qw(Str Maybe ArrayRef);
  19         73  
  19         313  
11              
12 19     19   82779 use namespace::clean;
  19         301716  
  19         168  
13              
14             use overload
15 19         186 q{""} => "as_string",
16 19     19   7173 fallback => 1;
  19         62  
17              
18             has param 'message' => (
19             isa => Str,
20             );
21              
22             has field 'caller' => (
23             isa => Maybe [ArrayRef],
24             default => sub {
25             for my $call_level (1 .. 10) {
26             my ($package, $file, $line) = caller $call_level;
27             if (defined $package && $package !~ /^Bitcoin::Crypto/) {
28             return [$package, $file, $line];
29             }
30             }
31             return undef;
32             },
33             );
34              
35             sub raise
36             {
37 67     67 1 937 my ($self, $error) = @_;
38              
39 67 50       195 unless (ref $self) {
40 67         1588 $self = $self->new(message => $error);
41             }
42              
43 67         4437 die $self;
44             }
45              
46             sub throw
47             {
48 6     6 1 597 goto \&raise;
49             }
50              
51             sub trap_into
52             {
53 554     554 1 2616 my ($class, $sub) = @_;
54              
55             # make sure we use class name
56 554 50       1424 $class = ref $class
57             if ref $class;
58              
59 554         892 my $ret;
60 554         895 my $error = do {
61 554         906 local $@;
62 554         1093 my $failure = not eval {
63 554         1258 $ret = $sub->();
64 549         284122 return 1;
65             };
66              
67 554 100       3321 $@ || $failure;
68             };
69              
70 554 100       1415 if ($error) {
71              
72             # make sure we stringify the error
73 5         42 $class->throw("$error");
74             }
75              
76 549         1764 return $ret;
77             }
78              
79             sub as_string
80             {
81 5     5 1 2425 my ($self) = @_;
82              
83 5         28 my $raised = $self->message;
84 5         24 $raised =~ s/\s$//g;
85 5         19 my $caller = $self->caller;
86 5 50       18 if (defined $caller) {
87 5         21 $raised .= ' (raised at ' . $caller->[1] . ', line ' . $caller->[2] . ')';
88             }
89 5         35 return 'An error occured in Bitcoin subroutines: ' . $raised;
90             }
91              
92             {
93              
94             package Bitcoin::Crypto::Exception::Sign;
95             $Bitcoin::Crypto::Exception::Sign::VERSION = '1.008_01'; # TRIAL
96             $Bitcoin::Crypto::Exception::Sign::VERSION = '1.00801';
97 19     19   20286 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         5988  
  19         131  
98              
99             }
100              
101             {
102              
103             package Bitcoin::Crypto::Exception::Verify;
104             $Bitcoin::Crypto::Exception::Verify::VERSION = '1.008_01'; # TRIAL
105             $Bitcoin::Crypto::Exception::Verify::VERSION = '1.00801';
106 19     19   1919 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         56  
  19         84  
107             }
108              
109             {
110              
111             package Bitcoin::Crypto::Exception::KeyCreate;
112             $Bitcoin::Crypto::Exception::KeyCreate::VERSION = '1.008_01'; # TRIAL
113             $Bitcoin::Crypto::Exception::KeyCreate::VERSION = '1.00801';
114 19     19   1772 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         78  
  19         112  
115             }
116              
117             {
118              
119             package Bitcoin::Crypto::Exception::KeyDerive;
120             $Bitcoin::Crypto::Exception::KeyDerive::VERSION = '1.008_01'; # TRIAL
121             $Bitcoin::Crypto::Exception::KeyDerive::VERSION = '1.00801';
122 19     19   1794 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         55  
  19         131  
123             }
124              
125             {
126              
127             package Bitcoin::Crypto::Exception::MnemonicGenerate;
128             $Bitcoin::Crypto::Exception::MnemonicGenerate::VERSION = '1.008_01'; # TRIAL
129             $Bitcoin::Crypto::Exception::MnemonicGenerate::VERSION = '1.00801';
130 19     19   1821 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         82  
  19         106  
131             }
132              
133             {
134              
135             package Bitcoin::Crypto::Exception::MnemonicCheck;
136             $Bitcoin::Crypto::Exception::MnemonicCheck::VERSION = '1.008_01'; # TRIAL
137             $Bitcoin::Crypto::Exception::MnemonicCheck::VERSION = '1.00801';
138 19     19   1806 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         78  
  19         147  
139             }
140              
141             {
142              
143             package Bitcoin::Crypto::Exception::Base58InputFormat;
144             $Bitcoin::Crypto::Exception::Base58InputFormat::VERSION = '1.008_01'; # TRIAL
145             $Bitcoin::Crypto::Exception::Base58InputFormat::VERSION = '1.00801';
146 19     19   1931 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         74  
  19         127  
147             }
148              
149             {
150              
151             package Bitcoin::Crypto::Exception::Base58InputChecksum;
152             $Bitcoin::Crypto::Exception::Base58InputChecksum::VERSION = '1.008_01'; # TRIAL
153             $Bitcoin::Crypto::Exception::Base58InputChecksum::VERSION = '1.00801';
154 19     19   1900 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         47  
  19         138  
155             }
156              
157             {
158              
159             package Bitcoin::Crypto::Exception::Bech32InputFormat;
160             $Bitcoin::Crypto::Exception::Bech32InputFormat::VERSION = '1.008_01'; # TRIAL
161             $Bitcoin::Crypto::Exception::Bech32InputFormat::VERSION = '1.00801';
162 19     19   1919 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         65  
  19         158  
163             }
164              
165             {
166              
167             package Bitcoin::Crypto::Exception::Bech32InputData;
168             $Bitcoin::Crypto::Exception::Bech32InputData::VERSION = '1.008_01'; # TRIAL
169             $Bitcoin::Crypto::Exception::Bech32InputData::VERSION = '1.00801';
170 19     19   2572 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         51  
  19         116  
171             }
172              
173             {
174              
175             package Bitcoin::Crypto::Exception::Bech32Type;
176             $Bitcoin::Crypto::Exception::Bech32Type::VERSION = '1.008_01'; # TRIAL
177             $Bitcoin::Crypto::Exception::Bech32Type::VERSION = '1.00801';
178 19     19   1944 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         59  
  19         89  
179             }
180              
181             {
182              
183             package Bitcoin::Crypto::Exception::Bech32InputChecksum;
184             $Bitcoin::Crypto::Exception::Bech32InputChecksum::VERSION = '1.008_01'; # TRIAL
185             $Bitcoin::Crypto::Exception::Bech32InputChecksum::VERSION = '1.00801';
186 19     19   1826 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         108  
  19         126  
187             }
188              
189             {
190              
191             package Bitcoin::Crypto::Exception::SegwitProgram;
192             $Bitcoin::Crypto::Exception::SegwitProgram::VERSION = '1.008_01'; # TRIAL
193             $Bitcoin::Crypto::Exception::SegwitProgram::VERSION = '1.00801';
194 19     19   1857 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         53  
  19         158  
195             }
196              
197             {
198              
199             package Bitcoin::Crypto::Exception::ValidationTest;
200             $Bitcoin::Crypto::Exception::ValidationTest::VERSION = '1.008_01'; # TRIAL
201             $Bitcoin::Crypto::Exception::ValidationTest::VERSION = '1.00801';
202 19     19   1840 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         66  
  19         159  
203             }
204              
205             {
206              
207             package Bitcoin::Crypto::Exception::ScriptOpcode;
208             $Bitcoin::Crypto::Exception::ScriptOpcode::VERSION = '1.008_01'; # TRIAL
209             $Bitcoin::Crypto::Exception::ScriptOpcode::VERSION = '1.00801';
210 19     19   1898 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         57  
  19         98  
211             }
212              
213             {
214              
215             package Bitcoin::Crypto::Exception::ScriptPush;
216             $Bitcoin::Crypto::Exception::ScriptPush::VERSION = '1.008_01'; # TRIAL
217             $Bitcoin::Crypto::Exception::ScriptPush::VERSION = '1.00801';
218 19     19   1776 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         52  
  19         139  
219             }
220              
221             {
222              
223             package Bitcoin::Crypto::Exception::NetworkConfig;
224             $Bitcoin::Crypto::Exception::NetworkConfig::VERSION = '1.008_01'; # TRIAL
225             $Bitcoin::Crypto::Exception::NetworkConfig::VERSION = '1.00801';
226 19     19   1889 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         94  
  19         95  
227             }
228              
229             {
230              
231             package Bitcoin::Crypto::Exception::AddressGenerate;
232             $Bitcoin::Crypto::Exception::AddressGenerate::VERSION = '1.008_01'; # TRIAL
233             $Bitcoin::Crypto::Exception::AddressGenerate::VERSION = '1.00801';
234 19     19   1851 use parent -norequire, 'Bitcoin::Crypto::Exception';
  19         85  
  19         115  
235             }
236              
237             1;
238              
239             __END__
240             =head1 NAME
241              
242             Bitcoin::Crypto::Exception - Exception class for Bitcoin::Crypto purposes
243              
244             =head1 SYNOPSIS
245              
246             use Try::Tiny;
247              
248             try {
249             decode_segwit('Not a segwit address');
250             } catch {
251             my $error = $_;
252              
253             # $error is an instance of Bitcoin::Crypto::Exception and stringifies automatically
254             warn "$error";
255              
256             # but also contains some information about the problem to avoid regex matching
257             if ($error->isa('Bitcoin::Crypto::Exception::Bech32InputFormat')) {
258             log $error->message;
259             }
260             };
261              
262             =head1 DESCRIPTION
263              
264             A wrapper class with automatic stringification and standarized raising.
265             Contains many other inline packages that identify parts that went wrong (like Bitcoin::Crypto::Exception::Sign for errors in signature generation).
266             See individual Bitcoin::Crypto packages documentation to see the exception classes to check for extra control flow when needed.
267              
268             =head1 FUNCTIONS
269              
270             =head2 message
271              
272             $error_string = $object->message()
273              
274             Returns the error message (a string).
275              
276             =head2 caller
277              
278             $caller_aref = $object->caller()
279              
280             Returns an array ref containing: package name, file name and line number (same as C<[caller()]> perl expression). It will contain the data for the first code from outside Bitcoin::Crypto which called it. May be undefined if it cannot find a calling source.
281              
282             =head2 as_string
283              
284             $error_info = $object->as_string()
285              
286             Stringifies the error, using the C<message> method, C<caller> method and some extra text for context.
287              
288             =head2 raise
289              
290             $object->raise()
291             $class->raise($message)
292              
293             Creates a new instance and throws it. If used on an object, throws it right away.
294              
295             use Try::Tiny;
296              
297             try {
298             # throws, but will be catched
299             Bitcoin::Crypto::Exception->raise('something went wrong');
300             } catch {
301             my $exception = $_;
302              
303             # throws again
304             $exception->raise;
305             };
306              
307             =head2 throw
308              
309             An alias to C<raise>.
310              
311             =head2 trap_into
312              
313             $sub_result = $class->trap_into($sub)
314              
315             Executes the subroutine given as the only parameter inside an C<eval>. Any exceptions thrown inside the subroutine C<$sub> will be re-thrown after turning them into objects of the given class. If no exception is thrown, method returns the value returned by C<$sub>.
316              
317             my $result = Bitcoin::Crypto::Exception->trap_into(sub {
318             die 'something went wrong';
319             });
320              
321             =cut
322