File Coverage

blib/lib/Bitcoin/Crypto/Segwit.pm
Criterion Covered Total %
statement 34 34 100.0
branch 6 6 100.0
condition 9 14 64.2
subroutine 9 10 90.0
pod 1 2 50.0
total 59 66 89.3


line stmt bran cond sub pod time code
1             package Bitcoin::Crypto::Segwit;
2             $Bitcoin::Crypto::Segwit::VERSION = '1.008_01'; # TRIAL
3             $Bitcoin::Crypto::Segwit::VERSION = '1.00801';
4 13     13   1023 use v5.10;
  13         59  
5 13     13   72 use strict;
  13         30  
  13         291  
6 13     13   117 use warnings;
  13         37  
  13         480  
7 13     13   75 use Exporter qw(import);
  13         35  
  13         433  
8              
9 13     13   104 use Bitcoin::Crypto::Exception;
  13         29  
  13         444  
10 13     13   88 use Bitcoin::Crypto::Config;
  13         31  
  13         411  
11 13     13   97 use Bitcoin::Crypto::Helpers qw(verify_bytestring);
  13         44  
  13         5512  
12              
13             our @EXPORT_OK = qw(
14             validate_program
15             );
16              
17             our %EXPORT_TAGS = (all => [@EXPORT_OK]);
18              
19             our %validators = (
20             0 => sub {
21             my ($data) = @_;
22              
23             Bitcoin::Crypto::Exception::SegwitProgram->raise(
24             'incorrect witness program length'
25             ) unless length $data == 20 || length $data == 32;
26             return;
27             },
28             );
29              
30             sub common_validator
31             {
32 42     42 0 93 my ($data) = @_;
33              
34 42 100 100     182 Bitcoin::Crypto::Exception::SegwitProgram->raise(
35             'incorrect witness program length'
36             ) unless length $data >= 2 && length $data <= 40;
37 38         80 return;
38             }
39              
40             sub validate_program
41             {
42 43     43 1 1893 my ($program) = @_;
43 43         163 verify_bytestring($program);
44              
45 43         141 my $version = unpack 'C', $program;
46 43 100 50     285 Bitcoin::Crypto::Exception::SegwitProgram->raise(
      33        
      66        
47             'incorrect witness program version ' . ($version // '[null]')
48             ) unless defined $version && $version >= 0 && $version <= Bitcoin::Crypto::Config::max_witness_version;
49              
50 42         108 $program = substr $program, 1;
51 42         115 my $validator = $validators{$version};
52 42         125 common_validator($program);
53 38 100 66 0   263 if (defined $validator && ref $validator eq ref sub { }) {
54 27         100 $validator->($program);
55             }
56             else {
57 11         157 warn("No validator for SegWit program version $version is declared");
58             }
59              
60 35         186 return $version;
61             }
62              
63             1;
64              
65             __END__
66             =head1 NAME
67              
68             Bitcoin::Crypto::Segwit - Segregated Witness version definitions
69              
70             =head1 SYNOPSIS
71              
72             use Bitcoin::Crypto::Segwit qw(validate_program);
73              
74             my $program_version = validate_program($segwit_program);
75              
76             =head1 DESCRIPTION
77              
78             This module provides tools required to define and use a Segregated Witness version validator.
79              
80             =head1 FUNCTIONS
81              
82             =head2 validate_program
83              
84             $segwit_version = validate_program($program)
85              
86             Performs a segwit program validation on $program, which is expected to be a byte string in which the first byte is a segwit version. Based on this version a validator is invoked, present in %Bitcoin::Crypto::Segwit::validators module hash. If the validator is not defined for a segwit version being validated, a warning is issued.
87              
88             The function returns the detected segwit program version. Please note that it does not perform any more checks than ensuring the byte string is in correct format.
89              
90             The current implementation defines a validator for segwit version 0. In the future (when another segwit program version is defined) it might be neccessary to define another one in the program until it's added to the library. This can be done like so:
91              
92             use Bitcoin::Crypto::Segwit;
93             use Bitcoin::Crypto::Exception;
94              
95             $Bitcoin::Crypto::Segwit::validators{1} = sub {
96             my ($data) = @_;
97              
98             # perform validation
99             Bitcoin::Crypto::Exception::SegwitProgram->raise(
100             'validation of program version 1 failed'
101             ) if ...;
102              
103             # if validation is successful just do nothing
104             return;
105             };
106              
107              
108             =head1 EXCEPTIONS
109              
110             This module throws an instance of L<Bitcoin::Crypto::Exception> if it encounters an error. It can produce the following error types from the L<Bitcoin::Crypto::Exception> namespace:
111              
112             =over 2
113              
114             =item * SegwitProgram - a validation of a segwit program has failed
115              
116             =back
117              
118             =head1 SEE ALSO
119              
120             =over 2
121              
122             =item L<Bitcoin::Crypto::Exception>
123              
124             =item L<Bitcoin::Crypto::Bech32>
125              
126             =back
127              
128             =cut
129