def test_encode_decode_msg__missing_optional_field_will_not_appear_in_decoded_dict( self): # "channel_update": optional field "htlc_maximum_msat" missing -> does not get put into dict self.assertEqual( bfh("01020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000000d43100006f00025e6ed0830100009000000000000000c8000001f400000023" ), encode_msg( "channel_update", short_channel_id=ShortChannelID.from_components(54321, 111, 2), channel_flags=b'\x00', message_flags=b'\x01', cltv_expiry_delta=144, htlc_minimum_msat=200, fee_base_msat=500, fee_proportional_millionths=35, chain_hash=constants.net.rev_genesis_bytes(), timestamp=1584320643, )) self.assertEqual( ('channel_update', { 'chain_hash': b'CI\x7f\xd7\xf8&\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 144, 'fee_base_msat': 500, 'fee_proportional_millionths': 35, 'htlc_minimum_msat': 200, 'message_flags': b'\x01', 'short_channel_id': b'\x00\xd41\x00\x00o\x00\x02', 'signature': bytes(64), 'timestamp': 1584320643 }), decode_msg( bfh("01020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000000d43100006f00025e6ed0830100009000000000000000c8000001f400000023" )))
def test_encode_decode_msg__ints_can_be_passed_as_bytes(self): self.assertEqual( bfh("01020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000000d43100006f00025e6ed0830100009000000000000000c8000001f400000023000000003b9aca00" ), encode_msg( "channel_update", short_channel_id=ShortChannelID.from_components(54321, 111, 2), channel_flags=b'\x00', message_flags=b'\x01', cltv_expiry_delta=int.to_bytes(144, length=2, byteorder="big", signed=False), htlc_minimum_msat=int.to_bytes(200, length=8, byteorder="big", signed=False), htlc_maximum_msat=int.to_bytes(1_000_000_000, length=8, byteorder="big", signed=False), fee_base_msat=int.to_bytes(500, length=4, byteorder="big", signed=False), fee_proportional_millionths=int.to_bytes(35, length=4, byteorder="big", signed=False), chain_hash=constants.net.rev_genesis_bytes(), timestamp=int.to_bytes(1584320643, length=4, byteorder="big", signed=False), ))
def test_encode_decode_msg__missing_mandatory_field_gets_set_to_zeroes(self): # "channel_update": "signature" missing -> gets set to zeroes self.assertEqual(bfh(frombtc("01020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000000d43100006f00025e6ed0830100009000000000000000c8000001f400000023000000003b9aca00")), encode_msg( "channel_update", short_channel_id=ShortChannelID.from_components(54321, 111, 2), channel_flags=b'\x00', message_flags=b'\x01', cltv_expiry_delta=144, htlc_minimum_msat=200, htlc_maximum_msat=1_000_000_000, fee_base_msat=500, fee_proportional_millionths=35, chain_hash=constants.net.rev_genesis_bytes(), timestamp=1584320643, ))
def test_liquidity_hints(self): liquidity_hints = LiquidityHintMgr() node_from = bytes(0) node_to = bytes(1) channel_id = ShortChannelID.from_components(0, 0, 0) amount_to_send = 1_000_000 # check default penalty self.assertEqual( fee_for_edge_msat(amount_to_send, DEFAULT_PENALTY_BASE_MSAT, DEFAULT_PENALTY_PROPORTIONAL_MILLIONTH), liquidity_hints.penalty(node_from, node_to, channel_id, amount_to_send)) liquidity_hints.update_can_send(node_from, node_to, channel_id, 1_000_000) liquidity_hints.update_cannot_send(node_from, node_to, channel_id, 2_000_000) hint = liquidity_hints.get_hint(channel_id) self.assertEqual(1_000_000, hint.can_send(node_from < node_to)) self.assertEqual(None, hint.cannot_send(node_to < node_from)) self.assertEqual(2_000_000, hint.cannot_send(node_from < node_to)) # the can_send backward hint is set automatically self.assertEqual(2_000_000, hint.can_send(node_to < node_from)) # check penalties self.assertEqual( 0., liquidity_hints.penalty(node_from, node_to, channel_id, 1_000_000)) self.assertEqual( 650, liquidity_hints.penalty(node_from, node_to, channel_id, 1_500_000)) self.assertEqual( inf, liquidity_hints.penalty(node_from, node_to, channel_id, 2_000_000)) # test that we don't overwrite significant info with less significant info liquidity_hints.update_can_send(node_from, node_to, channel_id, 500_000) hint = liquidity_hints.get_hint(channel_id) self.assertEqual(1_000_000, hint.can_send(node_from < node_to)) # test case when can_send > cannot_send liquidity_hints.update_can_send(node_from, node_to, channel_id, 3_000_000) hint = liquidity_hints.get_hint(channel_id) self.assertEqual(3_000_000, hint.can_send(node_from < node_to)) self.assertEqual(None, hint.cannot_send(node_from < node_to))
def test_read_tlv_stream_tests2(self): # from https://github.com/lightningnetwork/lightning-rfc/blob/452a0eb916fedf4c954137b4fd0b61b5002b34ad/01-messaging.md#tlv-decoding-successes lnser = LNSerializer() for tlv_stream_name in ("n1", "n2"): with self.subTest(tlv_stream_name=tlv_stream_name): self.assertEqual({}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("")), tlv_stream_name=tlv_stream_name)) self.assertEqual({}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("2100")), tlv_stream_name=tlv_stream_name)) self.assertEqual({}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("fd020100")), tlv_stream_name=tlv_stream_name)) self.assertEqual({}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("fd00fd00")), tlv_stream_name=tlv_stream_name)) self.assertEqual({}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("fd00ff00")), tlv_stream_name=tlv_stream_name)) self.assertEqual({}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("fe0200000100")), tlv_stream_name=tlv_stream_name)) self.assertEqual({}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("ff020000000000000100")), tlv_stream_name=tlv_stream_name)) self.assertEqual({"tlv1": {"amount_msat": 0}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("0100")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 1}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("010101")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 256}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("01020100")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 65536}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("0103010000")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 16777216}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("010401000000")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 4294967296}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("01050100000000")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 1099511627776}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("0106010000000000")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 281474976710656}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("010701000000000000")), tlv_stream_name="n1")) self.assertEqual({"tlv1": {"amount_msat": 72057594037927936}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("01080100000000000000")), tlv_stream_name="n1")) self.assertEqual({"tlv2": {"scid": ShortChannelID.from_components(0, 0, 550)}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("02080000000000000226")), tlv_stream_name="n1")) self.assertEqual({"tlv3": {"node_id": bfh("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb"), "amount_msat_1": 1, "amount_msat_2": 2}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("0331023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002")), tlv_stream_name="n1")) self.assertEqual({"tlv4": {"cltv_delta": 550}}, lnser.read_tlv_stream(fd=io.BytesIO(bfh("fd00fe020226")), tlv_stream_name="n1"))
'fee_proportional_millionths': 35, 'htlc_maximum_msat': 1000000000, 'htlc_minimum_msat': 200, 'message_flags': b'\x01', 'short_channel_id': b'\x00\xd41\x00\x00o\x00\x02', 'signature': bytes(64), 'timestamp': 1584320643 }), decode_msg( bfh("01020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000000d43100006f00025e6ed0830100009000000000000000c8000001f400000023000000003b9aca00" ))) # "htlc_minimum_msat" is passed as bytes but with incorrect length with self.assertRaises(UnexpectedFieldSizeForEncoder): encode_msg( "channel_update", short_channel_id=ShortChannelID.from_components(54321, 111, 2), channel_flags=b'\x00', message_flags=b'\x01', cltv_expiry_delta=int.to_bytes(144, length=2, byteorder="big", signed=False), htlc_minimum_msat=int.to_bytes(200, length=4, byteorder="big", signed=False), htlc_maximum_msat=int.to_bytes(1_000_000_000, length=8, byteorder="big", signed=False), fee_base_msat=int.to_bytes(500,
def channel(number: int) -> ShortChannelID: return ShortChannelID(bfh(format(number, '016x')))