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';
3 13     13   986 use v5.10;
  13         51  
4 13     13   75 use strict;
  13         59  
  13         315  
5 13     13   79 use warnings;
  13         27  
  13         441  
6 13     13   106 use Exporter qw(import);
  13         51  
  13         433  
7              
8 13     13   79 use Bitcoin::Crypto::Exception;
  13         44  
  13         342  
9 13     13   467 use Bitcoin::Crypto::Config;
  13         39  
  13         418  
10 13     13   525 use Bitcoin::Crypto::Helpers qw(verify_bytestring);
  13         33  
  13         5392  
11              
12             our @EXPORT_OK = qw(
13             validate_program
14             );
15              
16             our %EXPORT_TAGS = (all => [@EXPORT_OK]);
17              
18             our %validators = (
19             0 => sub {
20             my ($data) = @_;
21              
22             Bitcoin::Crypto::Exception::SegwitProgram->raise(
23             "incorrect witness program length"
24             ) unless length $data == 20 || length $data == 32;
25             return;
26             },
27             );
28              
29             sub common_validator
30             {
31 42     42 0 81 my ($data) = @_;
32              
33 42 100 100     192 Bitcoin::Crypto::Exception::SegwitProgram->raise(
34             "incorrect witness program length"
35             ) unless length $data >= 2 && length $data <= 40;
36 38         64 return;
37             }
38              
39             sub validate_program
40             {
41 43     43 1 1141 my ($program) = @_;
42 43         150 verify_bytestring($program);
43              
44 43         121 my $version = unpack "C", $program;
45 43 100 50     257 Bitcoin::Crypto::Exception::SegwitProgram->raise(
      33        
      66        
46             "incorrect witness program version " . ($version // "[null]")
47             ) unless defined $version && $version >= 0 && $version <= Bitcoin::Crypto::Config::max_witness_version;
48              
49 42         122 $program = substr $program, 1;
50 42         98 my $validator = $validators{$version};
51 42         117 common_validator($program);
52 38 100 66 0   249 if (defined $validator && ref $validator eq ref sub { }) {
53 27         77 $validator->($program);
54             }
55             else {
56 11         140 warn("No validator for SegWit program version $version is declared");
57             }
58              
59 35         173 return $version;
60             }
61              
62             1;
63              
64             __END__
65             =head1 NAME
66              
67             Bitcoin::Crypto::Segwit - Segregated Witness version definitions
68              
69             =head1 SYNOPSIS
70              
71             use Bitcoin::Crypto::Segwit qw(validate_program);
72              
73             my $program_version = validate_program($segwit_program);
74              
75             =head1 DESCRIPTION
76              
77             This module provides tools required to define and use a Segregated Witness version validator.
78              
79             =head1 FUNCTIONS
80              
81             =head2 validate_program
82              
83             $segwit_version = validate_program($program)
84              
85             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.
86              
87             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.
88              
89             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:
90              
91             use Bitcoin::Crypto::Segwit;
92             use Bitcoin::Crypto::Exception;
93              
94             $Bitcoin::Crypto::Segwit::validators{1} = sub {
95             my ($data) = @_;
96              
97             # perform validation
98             Bitcoin::Crypto::Exception::SegwitProgram->raise(
99             "validation of program version 1 failed"
100             ) if ...;
101              
102             # if validation is successful just do nothing
103             return;
104             };
105              
106              
107             =head1 EXCEPTIONS
108              
109             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:
110              
111             =over 2
112              
113             =item * SegwitProgram - a validation of a segwit program has failed
114              
115             =back
116              
117             =head1 SEE ALSO
118              
119             =over 2
120              
121             =item L<Bitcoin::Crypto::Exception>
122              
123             =item L<Bitcoin::Crypto::Bech32>
124              
125             =back
126              
127             =cut
128