Skip to content

pyln-testing raises ValueError if a wrong psbt is passed to openchannel_update #8953

Description

@enaples

Issue reproduction

Run the following test (#8947):

@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
@pytest.mark.openchannel('v2')
def test_openchannel_wrong_psbt_doesnt_crash_peer(node_factory, bitcoind):
    """Test passing a wrong PSBT to openchannel_update must not crash the peer.
    """
    l1, l2 = node_factory.get_nodes(2, opts={'may_reconnect': True})
    l1.rpc.connect(l2.info['id'], 'localhost', l2.port)

    chan_amount = 100000
    amount_btc = 0.02

    # Fund l1 with two separate UTXOs so we can build two genuinely different PSBTs
    bitcoind.rpc.sendmany("", {
        l1.rpc.newaddr()['p2tr']: amount_btc,
        l1.rpc.newaddr()['p2tr']: amount_btc,
    })
    bitcoind.generate_block(1)
    wait_for(lambda: len(l1.rpc.listfunds()['outputs']) >= 2)

    utxos = l1.rpc.listfunds()['outputs']
    utxo_a = '{}:{}'.format(utxos[0]['txid'], utxos[0]['output'])
    utxo_b = '{}:{}'.format(utxos[1]['txid'], utxos[1]['output'])

    # Build two PSBTs spending different UTXOs
    psbt_a_res = l1.rpc.utxopsbt(chan_amount, 'opening', 250, [utxo_a],
                                  excess_as_change=True)
    psbt_b = l1.rpc.utxopsbt(chan_amount, 'opening', 250, [utxo_b],
                              excess_as_change=True)['psbt']
    funding_feerate = '{}perkw'.format(psbt_a_res['feerate_per_kw'])

    init = l1.rpc.openchannel_init(l2.info['id'], chan_amount, psbt_a_res['psbt'],
                                   funding_feerate=funding_feerate)
    chan_id = init['channel_id']

    # Pass the wrong PSBT (different inputs).
    # FIXME: ideally this would raise a more specific error about the PSBT mismatch, 
    # but it raises a ValueError from pyl-testing library.
    with pytest.raises(ValueError):
        l1.rpc.openchannel_update(chan_id, psbt_b)

    # l2 must still be running and responsive
    assert l2.rpc.getinfo()['id'] == l2.info['id']

Error logs

FAILED tests/test_opening.py::test_openchannel_wrong_psbt_doesnt_crash_peer - jsonschema.exceptions.ValidationError: 'funding_outnum' is a required property

Failed validating 'required' in schema:
    {'required': ['channel_id',
                  'psbt',
                  'commitments_secured',
                  'channel_type',
                  'funding_outnum'],
     'additionalProperties': False,
     'properties': {'channel_id': {'type': 'hash',
                                   'description': ['The channel id of the '
                                                   'channel.']},
                    'channel_type': {'type': 'object',
                                     'description': ['Channel_type as '
                                                     'negotiated with '
                                                     'peer.'],
                                     'added': 'v24.02',
                                     'additionalProperties': False,
                                     'required': ['bits', 'names'],
                                     'properties': {'bits': {'type': 'array',
                                                             'description': ['Each '
                                                                             'bit '
                                                                             'set '
                                                                             'in '
                                                                             'this '
                                                                             'channel_type.'],
                                                             'added': 'v24.02',
                                                             'items': {'type': 'u32',
                                                                       'description': ['Bit '
                                                                                       'number.']}},
                                                    'names': {'type': 'array',
                                                              'description': ['Feature '
                                                                              'name '
                                                                              'for '
                                                                              'each '
                                                                              'bit '
                                                                              'set '
                                                                              'in '
                                                                              'this '
                                                                              'channel_type. '
                                                                              'Note '
                                                                              'that '
                                                                              '*anchors_zero_fee_htlc_tx* '
                                                                              'is '
                                                                              'a '
                                                                              'deprecated '
                                                                              'synonym '
                                                                              'for '
                                                                              '*anchors*.'],
                                                              'added': 'v24.02',
                                                              'items': {'type': 'string',
                                                                        'enum': ['static_remotekey/even',
                                                                                 'anchor_outputs/even',
                                                                                 'anchors_zero_fee_htlc_tx/even',
                                                                                 'anchors/even',
                                                                                 'scid_alias/even',
                                                                                 'zeroconf/even'],
                                                                        'description': ['Name '
                                                                                        'of '
                                                                                        'feature '
                                                                                        'bit.']}}}},
                    'psbt': {'type': 'string',
                             'description': ['The PSBT of the funding '
                                             'transaction.']},
                    'commitments_secured': {'type': 'boolean',
                                            'description': ['Whether the '
                                                            '*psbt* is '
                                                            'complete (if '
                                                            'true, sign '
                                                            '*psbt* and '
                                                            'call '
                                                            '`openchannel_signed` '
                                                            'to complete '
                                                            'the channel '
                                                            'open).']},
                    'funding_outnum': {'type': 'u32',
                                       'description': ['The index of the '
                                                       'funding output in '
                                                       'the psbt.']},
                    'close_to': {'type': 'hex',
                                 'description': ['Scriptpubkey which we '
                                                 'have to close to if we '
                                                 'mutual close.']},
                    'requires_confirmed_inputs': {'type': 'boolean',
                                                  'description': ['Does '
                                                                  'peer '
                                                                  'require '
                                                                  'confirmed '
                                                                  'inputs '
                                                                  'in '
                                                                  'psbt?']}},
     'allOf': [{'if': {'additionalProperties': True,
                       'properties': {'commitments_secured': {'type': 'boolean',
                                                              'enum': [True]}}},
                'then': {'additionalProperties': True,
                         'required': ['channel_id', 'funding_outnum'],
                         'properties': {'commitments_secured': {},
                                        'channel_id': {'type': 'hash',
                                                       'description': ['The '
                                                                       'derived '
                                                                       'channel '
                                                                       'id.']},
                                        'close_to': {'type': 'hex',
                                                     'description': ['If a '
                                                                     '`close_to` '
                                                                     'address '
                                                                     'was '
                                                                     'provided '
                                                                     'to '
                                                                     '`openchannel_init` '
                                                                     'and '
                                                                     'the '
                                                                     'peer '
                                                                     'supports '
                                                                     '`option_upfront_shutdownscript`.']},
                                        'funding_outnum': {'type': 'u32',
                                                           'description': ['The '
                                                                           'index '
                                                                           'of '
                                                                           'the '
                                                                           'funding '
                                                                           'output '
                                                                           'for '
                                                                           'this '
                                                                           'channel '
                                                                           'in '
                                                                           'the '
                                                                           'funding '
                                                                           'transaction.']}}},
                'else': {'additionalProperties': False,
                         'properties': {'commitments_secured': {}}}}]}

On instance:
    {'channel_id': '2c383675809577b343f57acbea98d51dd913817874a3b621173f3fe2ea519c45',
     'psbt': 'cHNidP8BAgQCAAAAAQMEZgAAAAEEAQEBBQEBAQYBAwH7BAIAAAAAAQC0AgAAAAHeXUqJ+FMURF99QfNesChSzK29vAwv0ihuBf7QmaKCVQAAAAAA/f///wMw6MgpAQAAACJRIBgbpQcLvoxNWf3/x8OKAJYfeeIl3uZmfsd7Bc9w3HSjgIQeAAAAAAAiUSC5UNiwZgMpisf3FGL565UvuL4AQpOWN0jlcQ/ii1Nww4CEHgAAAAAAIlEgn6TSTp2kPFv4/A2XNtTkRSOKzXFNBoEW31Fl0Hkduh1lAAAAAQErgIQeAAAAAAAiUSCfpNJOnaQ8W/j8DZc21ORFI4rNcU0GgRbfUWXQeR26HQEOIPnY/JD6DVlLzXo7V7sgDxHVu4zCxZ3UBSP7ttjjASwoAQ8EAgAAAAEQBP3///8M/AlsaWdodG5pbmcBCD9OB5zUzdoUAAEDCMbqHAAAAAAAAQQiUSDLmLufQyk2EMedQ8Kz3wihNg/lGfQmqqD9Ce/mACuAugz8CWxpZ2h0bmluZwEIV5Xu3sckCyQA',
     'channel_type': {'bits': [12, 22],
                      'names': ['static_remotekey/even', 'anchors/even']},
     'commitments_secured': False,
     'funding_serial': 3014915220181719196,
     'requires_confirmed_inputs': False}


ERROR tests/test_opening.py::test_openchannel_wrong_psbt_doesnt_crash_peer - ValueError: 
Node errors:
 - lightningd-1: had BROKEN or That's weird messages
 - lightningd-1: had memleak messages
Global errors:
 - Node /tmp/ltests-v1hn5dn1/test_openchannel_wrong_psbt_doesnt_crash_peer_1/lightning-1/ has memory leaks: [
    {
        "subdaemon": "dualopend"
    }
]

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QABlockstream QA team have reproduced, or a test has been created! Look for the linked PR/Issue

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions