Skip to content

Commit

Permalink
Implement taproot address generation
Browse files Browse the repository at this point in the history
  • Loading branch information
bbrtj committed Sep 28, 2024
1 parent e21ebf2 commit 1c1139f
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 4 deletions.
2 changes: 1 addition & 1 deletion cpanfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ requires 'Mooish::AttributeBuilder' => '1.001';
requires 'Type::Tiny' => '2';
requires 'List::Util' => '1.33';
requires 'CryptX' => '0.074';
requires 'Bitcoin::Secp256k1' => 0;
requires 'Bitcoin::Secp256k1' => '0.003';
requires 'Bitcoin::BIP39' => '0.002';
requires 'namespace::clean' => '0.27';
requires 'Try::Tiny' => 0;
Expand Down
9 changes: 7 additions & 2 deletions lib/Bitcoin/Crypto/Key/Public.pm
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use Bitcoin::Crypto::Base58 qw(encode_base58check);
use Bitcoin::Crypto::Bech32 qw(encode_segwit);
use Bitcoin::Crypto::Types -types;
use Bitcoin::Crypto::Constants;
use Bitcoin::Crypto::Util qw(hash160 get_public_key_compressed);
use Bitcoin::Crypto::Util qw(hash160 get_public_key_compressed tagged_hash);
use Bitcoin::Crypto::Helpers qw(ecc);

use namespace::clean;

Expand Down Expand Up @@ -117,7 +118,11 @@ sub witness_program
shift->get_hash;
},
+Bitcoin::Crypto::Constants::taproot_witness_version => sub {
shift->raw_key('public_taproot');
my $self = shift;
my $internal = $self->raw_key('public_taproot');
my $tweaked = tagged_hash($internal, 'TapTweak');
my $combined = ecc->combine_public_keys(ecc->create_public_key($tweaked), "\02" . $internal);
return substr $combined, 1;
},
};

Expand Down
14 changes: 14 additions & 0 deletions t/Taproot/BIP86.t
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ use Bitcoin::Crypto::Util qw(to_format);
# https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors

my @cases = (
{
bip44 => {
purpose => Bitcoin::Crypto::Constants::bip44_taproot_purpose,
},
xprv =>
'xprvA449goEeU9okwCzzZaxiy475EQGQzBkc65su82nXEvcwzfSskb2hAt2WymrjyRL6kpbVTGL3cKtp9herYXSjjQ1j4stsXXiRF7kXkCacK3T',
xpub =>
'xpub6H3W6JmYJXN49h5TfcVjLC3onS6uPeUTTJoVvRC8oG9vsTn2J8LwigLzq5tHbrwAzH9DGo6ThGUdWsqce8dGfwHVBxSbixjDADGGdzF7t2B',
internal_key => 'cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115',
output_key => 'a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c',
scriptPubKey => '5120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c',
address => 'bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr',
},
{
bip44 => {
purpose => Bitcoin::Crypto::Constants::bip44_taproot_purpose,
Expand Down Expand Up @@ -49,6 +62,7 @@ foreach my $case_ind (0 .. $#cases) {
is to_format [base58 => $key->get_public_key->to_serialized], $case->{xpub}, 'extended public key ok';

$key = $key->get_basic_key;

#is to_format [hex => $key->get_public_key->to_serialized], $case->{internal_key}, 'private key ok';
is $key->get_public_key->get_address, $case->{address}, 'address ok';
};
Expand Down
6 changes: 5 additions & 1 deletion t/Util.t
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,11 @@ subtest 'testing tagged_hash' => sub {
my $tag = 'ąść';

#is(tagged_hash($data, $tag), sha256(sha256(encode 'UTF-8', $tag) . sha256(encode 'UTF-8', $tag) . $data), 'tagged_hash ok');
is(tagged_hash($data, $tag), sha256(sha256(encode 'UTF-8', $tag) . sha256(encode 'UTF-8', $tag) . $data), 'tagged_hash ok');
is(
tagged_hash($data, $tag),
sha256(sha256(encode 'UTF-8', $tag) . sha256(encode 'UTF-8', $tag) . $data),
'tagged_hash ok'
);
};

done_testing;
Expand Down

0 comments on commit 1c1139f

Please sign in to comment.