1
0
Commit Graph

17600 Commits

Author SHA1 Message Date
SomberNight
93f2e8a3ad interface: disable ssl.VERIFY_X509_STRICT for self-signed certs
The "ssl.VERIFY_X509_STRICT" flag for openssl verification has been enabled by default in python 3.13+ (it was disabled before that).
see https://github.com/python/cpython/issues/107361
and https://discuss.python.org/t/ssl-changing-the-default-sslcontext-verify-flags/30230/16

We explicitly disable it for self-signed certs, thereby restoring the pre-3.13 defaults,
as it seems to break lots of servers.

For example, using python 3.13 (or setting `sslc.verify_flags |= ssl.VERIFY_X509_STRICT`),
- I can connect to `btc.electroncash.dk:60002:s`
- but not to `electrum.emzy.de:50002:s`
despite both using self-signed certs.

We should investigate more why exactly "strict" verification fails for some self-signed certs and not for others,
and make sure that at least newly generated certs adhere to the stricter requirements (e.g. update guide in e-x?).
2024-10-20 15:11:08 +00:00
SomberNight
2efac4ee33 follow-up prev: fix tests 2024-10-20 15:09:43 +00:00
SomberNight
3a465593d3 lnpeer: maybe send update_fee right away after reestablish
I just had a channel force-closed over a fee-estimate-disagreement :(

Scenario:
1. started electrum, opened wallet
2. waited around 10 seconds, opened the lightning channels overview, saw that channels are open/ready
3. after around 10 more seconds, scanned bolt11 invoice and tried to pay
4. channel got force-closed

Before this commit, we only call maybe_update_fee via lnwatcher callbacks.
These callbacks trigger on events such as "adb_set_up_to_date", "blockchain_updated", "network_updated", "fee".
In my case there was a race that all these events triggered *before* the channel got reestablished
(in fact before the peer handshake finished). And also, by chance there were none of these events after
the reestablish but before I sent the HTLC.
When I sent the HTLC, the channel counterparty (eclair) sent back an "error" msg that the feerates are
too different, which led us to do a local-force-close.

I have other channels in this wallet (with other peers), which reestablished faster and got lucky with
timing: the lnwatcher callbacks came just in time to trigger update_fee for them.

```
20241017T222847.598163Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | handshake done for 03ecef675be448b615e6176424070673ef8284e0fd19d8be062a6cb5b130a0a0d1@lightning.electrum.org:9740
20241017T222847.602594Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending INIT
20241017T222847.641383Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received INIT
20241017T222847.655041Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending CHANNEL_REESTABLISH
20241017T222847.658355Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | channel_reestablish (<redacted_shortchanid>): sent channel_reestablish with (next_local_ctn=157, oldest_unrevoked_remote_ctn=156)
20241017T222847.659524Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.660491Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.661442Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.662768Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.669875Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received QUERY_CHANNEL_RANGE
20241017T222847.690318Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received GOSSIP_TIMESTAMP_FILTER
20241017T222847.705782Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received CHANNEL_REESTABLISH
20241017T222847.707932Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | channel_reestablish (<redacted_shortchanid>): received channel_reestablish with (their_next_local_ctn=157, their_oldest_unrevoked_remote_ctn=156)
20241017T222847.712504Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | channel_reestablish (<redacted_shortchanid>): replayed 0 unacked messages. []
20241017T222847.716096Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending CHANNEL_READY
20241017T222847.738709Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | saved remote channel_update gossip msg for chan <redacted_shortchanid>
20241017T222907.627447Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | lnpeer.pay len(route)=1
20241017T222907.628927Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] |   0: edge=<redacted_shortchanid> hop_data=<OnionHopsDataSingle. payload={<redacted>}. hmac=None>
20241017T222907.629184Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | adding trampoline onion to final payload
20241017T222907.629405Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | lnpeer.pay len(t_route)=2
20241017T222907.629653Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] |   0: t_node=03ecef675be448b615e6176424070673ef8284e0fd19d8be062a6cb5b130a0a0d1 hop_data=<OnionHopsDataSingle. payload={<redacted>}. hmac=<redacted>>
20241017T222907.629894Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] |   1: t_node=<redacted> hop_data=<OnionHopsDataSingle. payload={<redacted>}. hmac=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
20241017T222907.631495Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | starting payment. len(route)=1.
20241017T222907.633075Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | starting payment. htlc: UpdateAddHtlc(amount_msat=<redacted>, payment_hash=<redacted>, cltv_abs=<redacted>, timestamp=1729204147, htlc_id=66)
20241017T222907.633385Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending UPDATE_ADD_HTLC
20241017T222907.635118Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | send_commitment. chan <redacted_shortchanid>. ctn: 157.
20241017T222907.643229Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending COMMITMENT_SIGNED
20241017T222907.721929Z |    DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received ERROR
20241017T222907.722621Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | remote peer sent error [DO NOT TRUST THIS MESSAGE]: 'local/remote feerates are too different: remoteFeeratePerKw=<redacted_low_val> localFeeratePerKw=50125'. chan_id=<redacted>. is_known_chan_id=True
20241017T222907.734272Z |    DEBUG | lnchannel.Channel.[<redacted_shortchanid>] | Setting channel state: OPEN -> FORCE_CLOSING
20241017T222907.825540Z |     INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Disconnecting: GracefulDisconnect()
```
2024-10-20 15:09:32 +00:00
SomberNight
422ca01a0c exchange_rate: add historical rates for BitStamp 2024-10-20 15:09:06 +00:00
SomberNight
80bd03b7d0 exchange_rate: add BitFinex, which has historical rates for usd and eur
yay

Given how few providers have free historical APIs, each one is very much appreciated.
They are doing a public service. Thanks. Not that they ever read commit messages. :)
2024-10-20 15:08:00 +00:00
SomberNight
f0750139a8 exchange_rate: fix regenerating currencies.json
```
cannot find currencies.json. will regenerate it now.
Traceback (most recent call last):
  File "...\electrum\run_electrum", line 94, in <module>
    from electrum.logging import get_logger, configure_logging  # import logging submodule first
  File "...\electrum\electrum\__init__.py", line 27, in <module>
    from . import daemon
  File "...\electrum\electrum\daemon.py", line 55, in <module>
    from .exchange_rate import FxThread
  File "...\electrum\electrum\exchange_rate.py", line 539, in <module>
    CURRENCIES = get_exchanges_and_currencies()
  File "...\electrum\electrum\exchange_rate.py", line 529, in get_exchanges_and_currencies
    loop = util.get_asyncio_loop()
  File "...\electrum\electrum\util.py", line 1578, in get_asyncio_loop
    raise Exception("event loop not created yet")
Exception: event loop not created yet
```
2024-10-20 15:06:20 +00:00
SomberNight
c4fe279660 qt tx dlg: fix showing fee warnings
In qt, only the confirm_tx_dialog was showing the fee warnings, the transaction_dialog was not...

regression from bc3946d2f4
2024-10-20 15:05:37 +00:00
Sander van Grieken
fa27ccc261 trustedcoin: fix check in 2fa wallet setup, when not continuing a unfinished wallet (fixes #9253) 2024-10-16 23:14:16 +02:00
SomberNight
31702c63e7 android: update p4a ref
- to include 0ab0d872e6
  > recipes: add patches for python3 recipes, for reproducible .pyc generation
  This should fix build repro of the apk.
4.5.6
2024-10-15 23:45:17 +00:00
SomberNight
3d5a9083cf update release notes: add date 2024-10-14 20:44:29 +00:00
SomberNight
84ded43ced prepare release 4.5.6 2024-10-14 19:26:23 +00:00
SomberNight
f8b1da1b3c update release notes for version 4.5.6 2024-10-14 19:25:55 +00:00
ThomasV
3ce5d95b0d send tab: catch exception raised if swap server is unreachable,
show error to the user.
(similar to main_window.run_swap_dialog)
2024-10-14 17:30:33 +00:00
SomberNight
d4765c5edc update block header checkpoints 2024-10-14 16:39:14 +00:00
ThomasV
38f9e6bf39 normal swaps message: put TLDR at the beginning! 2024-10-14 16:10:23 +00:00
SomberNight
a486d01640 qt: tray icon: don't show "network" if --offline 2024-10-14 16:09:38 +00:00
SomberNight
719292f818 hw plugins: ledger: bump pinned lib to 0.3.0, raise max_lib to <0.4
closes https://github.com/spesmilo/electrum/issues/9035
2024-10-14 16:09:12 +00:00
SomberNight
85940e7e3d hw plugins: cmdline: fix offline commands for encrypted hw wallets
```
$ ./run_electrum --testnet signmessage -w /home/user/.electrum/testnet/wallets/test_trezor_white_bip84 tb1q5pguna9y2g9y2gsu8r8gmxeye2cefvyly8dg02 heyheyhey -o
  0.84 | W | plugins.jade.jadepy.jade | No module named 'electrum.plugins.jade.jadepy.jade_ble'
  0.84 | W | plugins.jade.jadepy.jade | BLE scanning/connectivity will not be available
  3.73 | E | __main__ | error running command (without daemon)
Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 151, in get_xpub
    node = trezorlib.btc.get_public_node(self.client, address_n).node
  File "/home/user/.local/lib/python3.10/site-packages/trezorlib/tools.py", line 274, in wrapped_f
    ret = f(*args, **kwargs)
  File "/home/user/.local/lib/python3.10/site-packages/trezorlib/btc.py", line 125, in get_public_node
    return client.call(
  File "/home/user/.local/lib/python3.10/site-packages/trezorlib/tools.py", line 297, in wrapped_f
    return f(client, *args, **kwargs)
  File "/home/user/.local/lib/python3.10/site-packages/trezorlib/client.py", line 260, in call
    resp = self._callback_pin(resp)
  File "/home/user/.local/lib/python3.10/site-packages/trezorlib/client.py", line 186, in _callback_pin
    pin = self.ui.get_pin(msg.type)
  File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 308, in get_pin
    pin = self.handler.get_pin(msg.format(self.device), show_strength=show_strength)
AttributeError: 'NoneType' object has no attribute 'get_pin'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/user/wspace/electrum/./run_electrum", line 540, in handle_cmd
    result = fut.result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 458, in result
    return self.__get_result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File "/home/user/wspace/electrum/./run_electrum", line 227, in run_offline_command
    password = get_password_for_hw_device_encrypted_storage(plugins)
  File "/home/user/wspace/electrum/./run_electrum", line 212, in get_password_for_hw_device_encrypted_storage
    return client.get_password_for_storage_encryption()
  File "/home/user/wspace/electrum/electrum/plugin.py", line 523, in wrapper
    return run_in_hwd_thread(partial(func, *args, **kwargs))
  File "/home/user/wspace/electrum/electrum/plugin.py", line 516, in run_in_hwd_thread
    return fut.result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 458, in result
    return self.__get_result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/user/wspace/electrum/electrum/plugins/hw_wallet/plugin.py", line 260, in get_password_for_storage_encryption
    xpub = self.get_xpub(derivation, "standard")
  File "/home/user/wspace/electrum/electrum/plugin.py", line 523, in wrapper
    return run_in_hwd_thread(partial(func, *args, **kwargs))
  File "/home/user/wspace/electrum/electrum/plugin.py", line 513, in run_in_hwd_thread
    return func()
  File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 150, in get_xpub
    with self.run_flow(creating_wallet=creating):
  File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 89, in __exit__
    self.end_flow()
  File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 82, in end_flow
    self.handler.finished()
AttributeError: 'NoneType' object has no attribute 'finished'
```
2024-10-14 16:08:52 +00:00
SomberNight
ef62fcdd2f hw plugins: cmdline: support numpad for trezor one PIN codes 2024-10-14 16:08:38 +00:00
SomberNight
af18df10f6 android: update p4a ref
- to include d4432ec8d0
    see https://github.com/spesmilo/electrum/issues/9215#issuecomment-2403072217
- and add a fixme to revisit apkdiff re horrors beyond my comprehension
2024-10-14 16:07:55 +00:00
Sander van Grieken
5da46e9087 cli: require password for close_channel, request_force_close, export_channel_backup, reverse_swap, rebalance_channels 2024-10-14 16:06:34 +00:00
Sander van Grieken
84aa3eec54 commands: require wallet password for lnpay, get_channel_ctx commands 2024-10-14 16:06:11 +00:00
SomberNight
a1cf979928 commands: check password already in decorator
Previously it was only the actual commands that directly or indirectly verified
the password. This adds a check that runs for any command requiring a password.

related https://github.com/spesmilo/electrum/pull/9238
2024-10-14 16:05:51 +00:00
SomberNight
fa8595b1af set stricter UNIX permissions for log files
Looks like stdlib was creating them with 0o664 :/
2024-10-14 16:05:13 +00:00
SomberNight
70c70eec35 contrib/release_www.sh: put android versionCode in "version" file
This can be used by the F-Droid buildserver to detect new versions
and release updates automatically.

ref:
https://github.com/spesmilo/electrum/pull/9221#issuecomment-2386549086
https://f-droid.org/en/docs/Build_Metadata_Reference/#UpdateCheckMode
2024-10-14 16:05:02 +00:00
SomberNight
def89a90bc contrib/release_www.sh: minor clean-up 2024-10-14 16:04:38 +00:00
SomberNight
0d4e8f62ba android build: exclude fastlane/ from apk
related:
7fb7ac919c
https://github.com/spesmilo/electrum/issues/9215#issuecomment-2395249194
2024-10-14 16:04:23 +00:00
SomberNight
28bfa56577 (trivial) contrib/make_packages.sh: print success msg when done 2024-10-14 16:00:57 +00:00
SomberNight
4dc2eb9469 android build: use spesmilo/ fork of p4a and buildozer
- fdroid maintainers asked that releases use fixed forks of p4a and buildozer,
  so now we use the newly created forks in the spesmilo org. I plan to keep using
  my existing contributor-specific repos for development, but whatever we push
  to electrum master, should use the new spesmilo/ forks.
  see https://gitlab.com/fdroid/fdroiddata/-/merge_requests/15858#note_2136345746
  - Also, I added branch protection rules for branches named "electrum_*", so if
    we name the branches that are actually used in releases as such, we won't
    accidentally force-push them. (ref https://github.com/spesmilo/electrum/issues/8162)
    I think we can just create a new branch whenever we would want to force-push
    the existing one.
- also factored out some parameters so that it is easier to programmatically
  access them from the fdroid build script.
  see https://gitlab.com/fdroid/fdroiddata/-/merge_requests/15858#note_2136094409
2024-10-14 16:00:44 +00:00
SomberNight
4773815830 android readme: extend "access datadir on Android from desktop"
- add commands to restrict unix permissions for pushed files
- add notes for "multiple user profiles" case
2024-10-14 16:00:16 +00:00
ThomasV
fa1eb9f286 update hash for winehq.key
Looks like upstream key file changed. Still the same crypto key, just updated expiration date.

```
$ sha256sum winehq_20*
78b185fabdb323971d13bd329fefc8038e08559aa51c4996de18db0639a51df6 *winehq_2019.key
d965d646defe94b3dfba6d5b4406900ac6c81065428bf9d9303ad7a72ee8d1b8 *winehq_2024.key

$ gpg winehq_2019.key
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
pub   rsa3072 2018-12-10 [SC]
      D43F640145369C51D786DDEA76F1A20FF987672F
uid           WineHQ packages <wine-devel@winehq.org>
sub   rsa3072 2018-12-10 [E] [expired: 2020-12-09]

$ gpg winehq_2024.key
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
pub   rsa3072 2018-12-10 [SC]
      D43F640145369C51D786DDEA76F1A20FF987672F
uid           WineHQ packages <wine-devel@winehq.org>
sub   rsa3072 2018-12-10 [E]
```

Co-authored-by: SomberNight <somber.night@protonmail.com>
2024-10-14 15:59:16 +00:00
SomberNight
d415d2ab89 android build: add own logic to calculate versionCode
Use our own logic to go from ELECTRUM_VERSION to numeric android versionCode,
instead of using the default conversion done by python-for-android.

Even before this, we were already patching p4a to modify their logic (see [0]).
This commit changes that logic again, and moves it into a separate script in our repo.
- calculation change is due to the f-droid maintainers asking for the
  arch code to be in the least significant digits (instead of most sig digits) (see [1])

I have pushed and changed to a new p4a branch, which is just a copy of the previous one
with 3 commits related to versionCode calc squashed.

[0]: edb7e4fe6d
[1]: https://github.com/spesmilo/electrum/issues/9210#issuecomment-2380559324
2024-10-14 15:53:40 +00:00
SomberNight
e72b7ca25c version.py: rm APK_VERSION
related: https://github.com/spesmilo/electrum/issues/9210#issuecomment-2376572832
2024-10-14 15:53:19 +00:00
thecockatiel
a3786a4f85 chore: add fastlane metadata for f-droid (#9211)
* chore: add fastlane metadata for f-droid

* chore: add short description

* chore: use the correct short description
2024-10-14 15:53:01 +00:00
SomberNight
6ebdbf0401 android: update p4a ref
to have 58d21ad89b
> reproducible apks: strip file path prefix from .pyc files

related: https://github.com/spesmilo/electrum/issues/9215
2024-10-14 15:52:32 +00:00
SomberNight
08127a608b android build: bump python version (3.8.18->3.10.14)
cffi also had to be updated for this, and corresponding commit backported from upstream p4a
2024-10-14 15:52:00 +00:00
SomberNight
b79ee9b0ef android: update p4a ref
to have 04e80084eb
> recipe: libsecp256k1: enable modules for schnorr sigs
2024-10-14 15:51:19 +00:00
SomberNight
2917fde598 android: set target_sdk_version to 34
To comply with new google play store requirement:

> Starting August 31 2024:
> - New apps and app updates must target Android 14 (API level 34) or higher to be submitted to Google Play

AFAICS, we do not need to adapt to any of the changes.
https://developer.android.com/about/versions/14/behavior-changes-14
2024-10-14 15:39:17 +00:00
SomberNight
7b1d088d32 android: add comment that OS push notifications are broken 2024-10-14 15:38:58 +00:00
SomberNight
3ec16a08e5 build: include tests/ in tarballs
closes https://github.com/spesmilo/electrum/issues/9207
2024-10-14 15:38:31 +00:00
ThomasV
1c9d31b938 qml: do not display success if swap failed.. 2024-10-14 15:38:18 +00:00
Soren Stoutner
32c97145ef revealer plugin: move font initialisation to earlier
Co-authored-by: SomberNight <somber.night@protonmail.com>
2024-10-14 15:37:23 +00:00
Soren Stoutner
c187f64508 Update Source Sans Pro font to the current Source Sans 3. 2024-10-14 15:37:15 +00:00
SomberNight
b55c486f1f build: update pinned qdarkstyle (partial rerun freeze_packages)
related https://github.com/spesmilo/electrum/pull/9189
(version 3.2 added support for qt6, so this version supports both qt5 and qt6)
2024-10-14 15:34:53 +00:00
SomberNight
7cc8666061 follow-up testnet4 stuff: trivial clean-up
re https://github.com/spesmilo/electrum/pull/9197

localhost in servers list should only be for regtest-like networks
2024-10-14 15:34:24 +00:00
wakiyamap
213be4f617 remove BOLT11_HRP_INV_DICT 2024-10-14 15:29:51 +00:00
wakiyamap
de4c1b65fe Add suport testnet4 2024-10-14 15:29:29 +00:00
SomberNight
1c4bca7dc5 sdist README: document differences between sourceonly and normal tar.gz 2024-10-14 15:28:16 +00:00
SomberNight
4ff13f598d build: appimage: dl xcb-util as debian src pkg instead of upstream git
The upstream git repo has been unreachable for at least days.
2024-10-14 15:26:55 +00:00
SomberNight
aeb0a168b5 qt gui: use QGuiApplication.setApplicationName
I noticed that when running from source on macOS, the OS menubar has an "About Python" menu item,
instead of an "About Electrum" menu item. I tried to fix that by this, but actually it is not working :P

Nevertheless, this looks useful at least on Linux and Windows. E.g. when instantiating a new dialog
without an explicit title, the qt application name is used as default.

The application name, without this change AFAICS was already "Electrum" when running any of the binaries.
However when running from source, it was in some cases "python" or "run_electrum" or even "electrum-4"
(depending on OS and how the main script is started).
Now it is consistent -- except on macOS it still is not, as there it really wants to look for a .plist...
2024-10-14 15:26:32 +00:00