Skip to content

Commit

Permalink
Add tx verification check for output value not exceeding input
Browse files Browse the repository at this point in the history
  • Loading branch information
bbrtj committed Oct 6, 2023
1 parent e063a9d commit 2c9e41e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
9 changes: 9 additions & 0 deletions lib/Bitcoin/Crypto/Transaction.pm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use Mooish::AttributeBuilder -standard;
use Type::Params -sigs;
use Scalar::Util qw(blessed);
use Carp qw(carp);
use List::Util qw(sum);

use Bitcoin::Crypto qw(btc_script btc_utxo);
use Bitcoin::Crypto::Constants;
Expand Down Expand Up @@ -469,6 +470,14 @@ sub verify

my @inputs = @{$self->inputs};

# amount checking
my $total_in = sum map { $_->utxo->output->value } @inputs;
my $total_out = sum map { $_->value } @{$self->outputs};

Bitcoin::Crypto::Exception::Transaction->raise(
'output value exceeds input'
) if $total_in < $total_out;

# locktime checking
if (
$self->locktime > 0 && grep {
Expand Down
22 changes: 21 additions & 1 deletion t/40-transaction/80-edge-cases.t
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ subtest 'should checksig a non-standard transaction' => sub {

# Manual signing
my $input = $tx->inputs->[0];
my $sighash = Bitcoin::Crypto::Constants::sighash_none;
my $digest = $tx->get_digest(
signing_index => 0,
signing_subscript => $input->utxo->output->locking_script->to_serialized,
sighash => $sighash,
);
my $signature = $prv->sign_message($digest);
$signature .= pack 'C', Bitcoin::Crypto::Constants::sighash_all;
$signature .= pack 'C', $sighash;
$input->signature_script
->push("\x01")
->push($signature)
Expand All @@ -56,6 +58,24 @@ subtest 'should checksig a non-standard transaction' => sub {
lives_ok { $tx->verify } 'input verification ok';
};

subtest 'should not allow input value smaller than output' => sub {

# reuse previous $tx

$tx->add_output(
value => 1,
locking_script => [
P2PKH => $prv->get_public_key->get_legacy_address,
],
);

throws_ok {
$tx->verify
} 'Bitcoin::Crypto::Exception::Transaction';

like $@, qr/value exceeds input/, 'error message ok';
};

subtest 'should serialize and deserialize mixed segwit txs' => sub {

my $txid = '76899e00277359a639ae138759a1363ceb7a230fea5f9a6bf8c573f7c61706fd';
Expand Down

0 comments on commit 2c9e41e

Please sign in to comment.