line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Finance::Libdogecoin::FFI; |
2
|
|
|
|
|
|
|
# ABSTRACT: Use features from libdogecoin via FFI |
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
610
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
24
|
|
5
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
19
|
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
578
|
use FFI::Platypus; |
|
1
|
|
|
|
|
6359
|
|
|
1
|
|
|
|
|
37
|
|
8
|
1
|
|
|
1
|
|
421
|
use FFI::CheckLib 0.28 'find_lib_or_die'; |
|
1
|
|
|
|
|
2386
|
|
|
1
|
|
|
|
|
55
|
|
9
|
1
|
|
|
1
|
|
409
|
use FFI::Platypus::Buffer qw( buffer_to_scalar grow set_used_length ); |
|
1
|
|
|
|
|
966
|
|
|
1
|
|
|
|
|
52
|
|
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
345
|
use Alien::Libdogecoin; |
|
1
|
|
|
|
|
35534
|
|
|
1
|
|
|
|
|
8
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
{ |
14
|
|
|
|
|
|
|
my $ffi = FFI::Platypus->new( |
15
|
|
|
|
|
|
|
api => 1, |
16
|
|
|
|
|
|
|
lib => [ |
17
|
|
|
|
|
|
|
find_lib_or_die lib => 'dogecoin', |
18
|
|
|
|
|
|
|
alien => [ 'Alien::Libdogecoin' ], |
19
|
|
|
|
|
|
|
], |
20
|
|
|
|
|
|
|
); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
while (my $sig = ) { |
23
|
|
|
|
|
|
|
chomp $sig; |
24
|
|
|
|
|
|
|
my ($return, $name, @args) = split /,/, $sig; |
25
|
|
|
|
|
|
|
$ffi->attach( $name => \@args => $return ); |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
*context_start = \&dogecoin_ecc_start; |
29
|
|
|
|
|
|
|
*context_stop = \&dogecoin_ecc_stop; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub _call_with_buffer_pair { |
33
|
7
|
|
|
7
|
|
15
|
my ($is_testnet, $priv_buffer_len, $pub_buffer_len, $function) = @_; |
34
|
|
|
|
|
|
|
|
35
|
7
|
|
|
|
|
23
|
grow( (my $privkeybuf), $priv_buffer_len ); |
36
|
7
|
|
|
|
|
18
|
grow( (my $pubkeybuf), $pub_buffer_len + 1); |
37
|
|
|
|
|
|
|
|
38
|
7
|
|
|
|
|
1092
|
$function->($privkeybuf, $pubkeybuf, $is_testnet); |
39
|
|
|
|
|
|
|
|
40
|
7
|
|
|
|
|
55
|
return( substr($privkeybuf, 0, $priv_buffer_len), substr($pubkeybuf, 0, $pub_buffer_len) ); |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub generate_key_pair { |
44
|
3
|
100
|
|
3
|
1
|
819
|
my $is_testnet = shift ? 1 : 0; |
45
|
3
|
|
|
|
|
10
|
return _call_with_buffer_pair( $is_testnet, 53, 34, \&generatePrivPubKeypair ); |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub verify_key_pair { |
49
|
6
|
|
|
6
|
1
|
1971
|
my ($priv_key, $pub_key, $is_testnet) = @_; |
50
|
|
|
|
|
|
|
|
51
|
6
|
|
|
|
|
292
|
return verifyPrivPubKeypair( $priv_key, $pub_key, !!$is_testnet ); |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub verify_p2pkh_address { |
55
|
3
|
|
|
3
|
1
|
7
|
my $address = shift; |
56
|
3
|
|
|
|
|
37
|
return !! verifyP2pkhAddress( $address, length($address) ); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub generate_hd_master_pub_key_pair { |
60
|
4
|
100
|
|
4
|
1
|
12
|
my $chaincode = shift ? 1 : 0; |
61
|
4
|
|
|
|
|
15
|
return _call_with_buffer_pair( $chaincode, 128, 35, \&generateHDMasterPubKeypair ); |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub generate_derived_hd_pub_key { |
65
|
2
|
|
|
2
|
1
|
8
|
my $master_priv_key = shift; |
66
|
2
|
|
|
|
|
7
|
grow my $pubkeybuf, 128; |
67
|
2
|
|
|
|
|
123
|
generateDerivedHDPubkey($master_priv_key, $pubkeybuf); |
68
|
|
|
|
|
|
|
|
69
|
2
|
|
|
|
|
6
|
return substr($pubkeybuf, 0, 128); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub verify_master_priv_pub_keypair { |
73
|
8
|
|
|
8
|
1
|
1272
|
my ($priv_key, $pub_key, $chaincode) = @_; |
74
|
8
|
100
|
|
|
|
17
|
$chaincode = $chaincode ? 1 : 0; |
75
|
|
|
|
|
|
|
|
76
|
8
|
|
|
|
|
349
|
return verifyHDMasterPubKeypair( $priv_key, $pub_key, $chaincode ); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
'much wow'; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=pod |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=encoding UTF-8 |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head1 NAME |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Finance::Libdogecoin::FFI - Use features from libdogecoin via FFI |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=head1 VERSION |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
version 1.20220814.2215 |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=head2 SYNOPSIS |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
To generate and verify a private/public keypair: |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# call this before all key-manipulation functions |
98
|
|
|
|
|
|
|
Finance::Libdogecoin::FFI::context_start(); |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my ($priv_key, $pub_key) = Finance::Libdogecoin::FFI::generate_key_pair(); |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
if (Finance::Libdogecoin::FFI::verify_key_pair( $priv_key, $pub_key )) { |
103
|
|
|
|
|
|
|
# ... key pair is valid |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# call this after all key-manipulation functions |
107
|
|
|
|
|
|
|
Finance::Libdogecoin::FFI::context_stop(); |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
From this example be aware of three things: |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=over 4 |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=item * First, call C before and C after any |
114
|
|
|
|
|
|
|
use of the key-manipulation functions. These start and finish the cryptographic |
115
|
|
|
|
|
|
|
context used in the underlying C library. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=item * Second, these function are available from the |
118
|
|
|
|
|
|
|
C namespace and are not exported by default. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=item * Third, these functions are minimally Perlish. A nicer interface should/will exist. |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=back |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head2 DESCRIPTION |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
This module provides a minimal FFI interface to C functions. It |
127
|
|
|
|
|
|
|
uses L to use a local installation of this library or the |
128
|
|
|
|
|
|
|
system version. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
See |
131
|
|
|
|
|
|
|
L |
132
|
|
|
|
|
|
|
for full documentation of the C library, including the principles |
133
|
|
|
|
|
|
|
behind the design. The API of this module follows the example of the Python |
134
|
|
|
|
|
|
|
bindings, though the C function calls are also available in this namespace. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 FUNCTIONS |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head3 C |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Initializes the C cryptography mechanism. Call this before using |
141
|
|
|
|
|
|
|
any other key-management functions. |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=head3 C |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
Finishes the C cryptography mechanism. Call this when you no |
146
|
|
|
|
|
|
|
longer need to use any other key-management functions. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=head3 C |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
The boolean C<$is_testnet> argument is optional; the default value is false. |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Generates and returns a private/public key pair for the network. The return value |
153
|
|
|
|
|
|
|
is two strings in base-58 encoding. Do not share the private key. Do not lose |
154
|
|
|
|
|
|
|
the private key. |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
The public key is a valid P2PKH address. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head3 C |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
The boolean C<$is_testnet> argument is optional; the default value is false. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Given two strings in base-58 encoding, returns a boolean value to indicate |
163
|
|
|
|
|
|
|
whether the pair is valid for the given network. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head3 C |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Given a public key, returns a boolean to indicate whether the address passes |
168
|
|
|
|
|
|
|
validation checks. This doesn't guarantee that an address I legitimate, but |
169
|
|
|
|
|
|
|
it can help decide whether it's worth sending to it at all. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=head3 C |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
The boolean C<$is_testnet> argument is optional; the default value is false. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Generates and returns a private/public key hierarchical deterministic pair for |
176
|
|
|
|
|
|
|
the network. The return value is two strings in base-58 encoding. Do not share |
177
|
|
|
|
|
|
|
the private key. Do not lose the private key. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head3 C |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Given a master key hierarchical deterministic key, derive and return a public |
182
|
|
|
|
|
|
|
key associated with the master. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head3 C |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
The boolean C<$is_testnet> argument is optional; the default value is false. |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Given two strings representing hierarchical deterministic keys (a master |
189
|
|
|
|
|
|
|
public key and a master private key) in base-58 encoding, returns a boolean |
190
|
|
|
|
|
|
|
value to indicate whether the pair both match and are valid for the given |
191
|
|
|
|
|
|
|
network. In other words, for the given network, can the public key be derived |
192
|
|
|
|
|
|
|
from the private key? |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head2 AUTHOR, COPYRIGHT, and LICENSE |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
Copyright (c) 2022, chromatic. Interface based on and derived from the C Python bindings. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head1 AUTHOR |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
chromatic |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
This software is Copyright (c) 2022 by chromatic. |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
This is free software, licensed under: |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
The MIT (X11) License |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=cut |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
__DATA__ |