use v6.d; use Test; use Test::Mock; use Bitcoin::Core::Secp256k1; plan 3; my $secp256k1 = Bitcoin::Core::Secp256k1.new; subtest { plan 2; my $data = { key => 'e87c09fe1e33f5bd846e51a14ccbdf1d583de3eed34558f14406133fa5176195', recover => { 0 => '445228b342475e525b26adc8587a6086fab77d33f4c40b00ed418f5243f24cdb', 1 => 'a1bf4f16de2c0c5790593cf22333fef48502b228ff59118aa44539dab425ec49' } }; for $data.keys -> $key { my $signature = $secp256k1.ecdsa_sign(:privkey($data), :msg($data{$key}), :recover(True)); my $serialized = $secp256k1.recoverable_signature_serialize(:sig($signature)); is $serialized, $key.Int, 'recovery ' ~ $key.Int.Bool; } }, 'Secp256k1 recovery bit'; subtest { plan 1; my $data = { key => 'e87c09fe1e33f5bd846e51a14ccbdf1d583de3eed34558f14406133fa5176195', msg => '445228b342475e525b26adc8587a6086fab77d33f4c40b00ed418f5243f24cdb' }; my $sig_regular = $secp256k1.ecdsa_sign(:privkey($data), :msg($data), :recover(False)); my $sig_recover = $secp256k1.ecdsa_sign(:privkey($data), :msg($data), :recover(True)); my $converted = $secp256k1.recoverable_signature_convert(:sig($sig_recover)); is-deeply $sig_regular, $converted, 'recoverable to regular convert'; }, 'Secp256k1 serialize verify'; subtest { plan 1; my UInt $iterations = 100; my Bool $subtestok = True; for ^$iterations { my $data = { key => 'e87c09fe1e33f5bd846e51a14ccbdf1d583de3eed34558f14406133fa5176195', msg => random32bytes() }; my $pubkey = $secp256k1.create_public_key(:privkey($data)); my $sig = $secp256k1.ecdsa_sign(:privkey($data), :msg($data), :recover(True)); if !$secp256k1.ecdsa_recover(:pubkey($pubkey), :sig($sig), :msg($data)) { $subtestok = False; last; } } ok $subtestok, sprintf("recover %d messages by signatures", $iterations); }, 'Secp256k1 recover messages'; done-testing; sub random32bytes returns Str { my $buffer = buf8.new; while $buffer.bytes < 32 { $buffer.push(255.rand.Int || 0xff); } return $buffer.map({$_ < 16 ?? '0' ~ $_.base(16) !! $_.base(16)}).join(q{}).lc; }