Bitcoin-Crypto
view release on metacpan or search on metacpan
lib/Bitcoin/Crypto/Transaction/Digest.pm view on Meta::CPAN
taproot_ext_flag
taproot_ext
taproot_annex
)
],
);
has field '_cache' => (
isa => HashRef,
default => sub { {} },
);
sub get_digest
{
my ($self) = @_;
my $input = $self->transaction->inputs->[$self->signing_index];
Bitcoin::Crypto::Exception::Transaction->raise(
"can't find input with index " . $self->signing_index
) unless $input;
my $procedure = '_get_digest_default';
if ($input->is_taproot) {
$procedure = '_get_digest_taproot';
}
elsif ($input->is_segwit) {
$procedure = '_get_digest_segwit';
}
return $self->$procedure();
}
sub _get_digest_default
{
my ($self) = @_;
my $sighash = $self->_default_sighash(SIGHASH_ALL);
my $sighash_type = $sighash & 31;
my $anyonecanpay = $sighash & SIGHASH_ANYONECANPAY;
my $transaction = $self->transaction;
my $tx_copy = $transaction->clone;
my $signing_index = $self->signing_index;
my $inputs = $transaction->inputs;
my $copy_inputs = $tx_copy->inputs;
@{$copy_inputs} = ();
foreach my $input_ind (keys @{$inputs}) {
# no other inputs if anyonecanpay - skip cloning and all other work
next if $anyonecanpay && $input_ind != $signing_index;
my $input = $inputs->[$input_ind]->clone;
if ($input_ind == $signing_index) {
my $subscript = $self->signing_subscript;
if (!$subscript) {
Bitcoin::Crypto::Exception::Transaction->raise(
"can't guess the subscript from a non-standard transaction"
) unless $input->utxo->output->is_standard;
$subscript = $input->script_base;
}
$input->set_signature_script($subscript);
}
else {
$input->set_signature_script('');
$input->set_sequence_no(0)
if $sighash_type == SIGHASH_NONE
|| $sighash_type == SIGHASH_SINGLE;
}
push @{$copy_inputs}, $input;
}
# Handle output work for sighashes
if ($sighash_type == SIGHASH_NONE) {
@{$tx_copy->outputs} = ();
}
elsif ($sighash_type == SIGHASH_SINGLE) {
my $outputs = $transaction->outputs;
my $copy_outputs = $tx_copy->outputs;
@{$copy_outputs} = ();
if ($signing_index >= @{$outputs}) {
# this should verify with constant digest (without hashing)
return Bitcoin::Crypto::Transaction::Digest::Result->new(
hash => scalar reverse ensure_length("\x01", 32),
);
}
foreach my $output (@{$outputs}[0 .. $signing_index - 1]) {
my $output_copy = $output->clone;
$output_copy->set_locking_script('');
$output_copy->set_max_value;
push @{$copy_outputs}, $output_copy;
}
push @{$copy_outputs}, $outputs->[$signing_index];
}
my $serialized = $tx_copy->to_serialized(witness => 0);
$serialized .= pack 'V', $sighash;
return Bitcoin::Crypto::Transaction::Digest::Result->new(preimage => $serialized);
}
sub _get_digest_segwit
{
my ($self) = @_;
my $sighash = $self->_default_sighash(SIGHASH_ALL);
my $sighash_type = $sighash & 31;
my $anyonecanpay = $sighash & SIGHASH_ANYONECANPAY;
my $signing_index = $self->signing_index;
( run in 1.129 second using v1.01-cache-2.11-cpan-39bf76dae61 )