Commit Graph

1220 Commits

Author SHA1 Message Date
Tobin Harding f3688ecf56 Use rand-std in key rustdoc examples
Seems there is a bug in cargo, the tests in `key.rs` run successfully
but AFAICT they should fail. Here is an example, running `cargo test
--features=rand` should make this test fail but it doesn't?
```
/// Secret 256-bit key used as `x` in an ECDSA signature.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #[cfg(all(feature = "rand", any(feature =  "alloc", feature = "std")))] {
/// use secp256k1::{rand, Secp256k1, SecretKey};
///
/// let secp = Secp256k1::new();
/// let secret_key = SecretKey::new(&mut rand::thread_rng());
/// # }
/// ```

Anywho, use the correct feature gate: `rand-std`.
2022-02-01 15:21:30 +11:00
Tobin Harding ae3e06f95b Fix lint warnings in test code
Various combinations of features trigger lint warnings for unused code,
all warnings are caused by incorrect feature gating.

Correct feature gating to remove Clippy warnings during testing.
2022-02-01 15:21:30 +11:00
Tobin Harding c01cd8f1f3 Enable running tests without default features
Currently various features fail to build when enabled without default
features. This is because many tests need feature gating.

Feature gating the import statements quickly turns into spaghetti when
trying to cover all combinations of two features correctly, instead just
allow unused imports on `tests` modules where needed.

Add correct feature requirements to the examples so they also can be run
without default features.

Improve the CI script by doing:

- Add `std` to the feature matrix.
- Add `--no-default-features` to test runs in the CI script.
2022-02-01 15:20:44 +11:00
Tobin Harding a79840eca2 Be explicit about example feature requirements
The examples depend on having the "std" feature [1]. In preparation for
being able to run tests with `--no-default-features` add the "std"
feature as a requirement for all three examples. While we are at it use
the correct rand feature requirement: `rand-std`.

[1] Technically we only need "alloc" but "alloc" is not working with
Rust 1.29 currently so just use "std".
2022-02-01 15:20:06 +11:00
Tobin Harding 433c350424 Add multiple implementations of Debug for secrets
The `Debug` implementation for secrets is feature gated on `std` because
it uses a hasher from `std`. If `bitcoin_hashes` is enabled we can use
it for hashing. If neither `std` nor `bitcoin_hashes` is enabled fall
back to outputting:

<secret requires std or bitcoin_hashes feature to display>

Remove the docs conditional since we now implement `Debug` always.
2022-02-01 14:51:40 +11:00
Vincent Liao 2732891359 Change rand to rand-std in lib.rs documentation 2022-01-27 23:45:56 +07:00
Tobin Harding 632ecc4530 Use fully qualified path for mem
When building with --no-default-features the compiler emits:

  warning: unused import: `mem`

The call site is feature gated so we either need to feature gate the
import or use a fully qualified path. Since 'core' is quite short elect
to use the fully qualified path.
2022-01-26 13:25:33 +11:00
Andrew Poelstra f7d637e6aa
Merge rust-bitcoin/rust-secp256k1#376: Add examples to `key` module
aa828f01a5 Improve documentation in the key module (Tobin Harding)
9e46d6f122 Add examples to types and methods in key module (Tobin Harding)
a7f3d9bcfd Improve key module docs (Tobin Harding)
6d23614467 Improve lib.rs rustdocs (Tobin Harding)
4c4268f1ad Improve docs on method generate_keypair (Tobin Harding)

Pull request description:

  This PR is an initial attempt to more thoroughly test our public API.

  Add examples to various types/methods/functions in the key module.

  I'm not entirely sure when is enough, do we want an example on every single public method, function, and type or is this overkill. In this PR I tried to find a balance by doing ever method/function that took an argument that is a custom type from this lib. I think this should be extended to include return values too though ...

  Thanks to @thomaseizinger for the idea!

  First 2 patches are docs improvements to `lib.rs`.

ACKs for top commit:
  apoelstra:
    ACK aa828f01a5

Tree-SHA512: 9383ad263469f98ce7e988d47edc1482a09a0ce82f43d3991bd80aabdf621430f4a3c86be4debf33232dcb1d60d3e81f2c6d930ea7de7aa0e34b037accd7bc98
2022-01-25 12:34:45 +00:00
Andrew Poelstra 6b515755ab
Merge rust-bitcoin/rust-secp256k1#369: Trivial doc: Warn that serde differs from consensus encoding
52560a9205 Warn that serde differs from consensus encoding (Martin Habovstiak)

Pull request description:

  Addresses https://github.com/rust-bitcoin/rust-bitcoin/pull/756#discussion_r780844146

ACKs for top commit:
  apoelstra:
    ACK 52560a9205

Tree-SHA512: ee56c13dcb0493318f5b59306d6375adb202a5812c4673f0b9abe71fb809b927a74c3fd61aa20fe28fd2176c67f495214bf4da546380dfe9c83b933b02835fff
2022-01-24 15:58:21 +00:00
Andrew Poelstra d44646b80b
Merge rust-bitcoin/rust-secp256k1#382: Fix the mess around Parity
6fad20ef0c Fix the mess around Parity (Tobin Harding)

Pull request description:

  Recently we made a wee mess with the `Parity` opaque type. Let's fix it
  up by doing:

  - Use an enum with variants `Even` and `Odd`.
  - Add explicit conversion methods to/from u8 and i32
  - Implement `BitXor`

  This PR attempts to follow the plan laid out in the issue but:
  - I don't get why`to_u8` is requested, I added it anyways.
  - `to_i32` is not mentioned but we need it if we are going to pass the parity back to FFI code after receiving it _without_ having to care about the value. And that is the whole point of this `Parity` type in the first place.
  - I don't get why `from_xxx` is fallible, when is an integer not even or odd?

  Please note: This patch is an API breaking change that does _not_ follow the deprecation guidelines. Rust does not allow deprecating `From` impl blocks AFAICT.

  Fixes: #370

ACKs for top commit:
  apoelstra:
    ACK 6fad20ef0c

Tree-SHA512: 810d5028f02fa608eab48721d32dca58be472080fcbac7a0ee79b5211b229112a756c48233e8597fb6c137690b2565431f410e9e97d6940ed389a4501bb015a0
2022-01-24 14:03:19 +00:00
Tobin Harding aa828f01a5 Improve documentation in the key module
We recently patched much of the docs in the `key` module, lets attempt
to attain perfection.

Improve docs by doing:

- Use full stops
- Use 100 character column width
- Use plural third person tense
- Use plural for section headings
- Fix any grammar mistakes
- Use code ticks and links as appropriate
2022-01-24 14:48:46 +11:00
Tobin Harding 9e46d6f122 Add examples to types and methods in key module
Done in an effort to better test our public API.

Add tests in the `Examples` section as is idiomatic in the Rust
ecosystem.

Make other minor improvements to any rusdocs we touch:
- Use full stops
- Use 100 character column width
- Use plural third person tense
- Use plural for section headings
2022-01-24 14:48:46 +11:00
Tobin Harding a7f3d9bcfd Improve key module docs
Use 'standard' stlye, standard is defined as
- No markdown heading
- Full sentence (capital first letter and full stop)
- Trailing empty comment line
2022-01-24 14:43:44 +11:00
Tobin Harding 6d23614467 Improve lib.rs rustdocs
Improve the main docs by doing:

- Remove unneeded `self` from use statement
- Add code ticks to `bitcoin_hashes`
2022-01-24 14:43:44 +11:00
Tobin Harding 4c4268f1ad Improve docs on method generate_keypair
Improve method docs by doing:

- Remove 'batch' comment
- Remove mention of required features, docs already show this
- Use links to types as well as ticks
2022-01-24 14:43:44 +11:00
Tobin Harding 6fad20ef0c Fix the mess around Parity
Recently we made a wee mess with the `Parity` opaque type. Let's fix it
up by doing:

- Use an enum with variants `Even` and `Odd`.
- Add explicit conversion methods to/from u8 and i32
- Implement `BitXor`

Note: This patch is an API breaking change that does _not_ follow the
deprecation guidelines. Rust does not allow deprecating `From` impl
blocks AFAICT.
2022-01-23 10:33:51 +11:00
Andrew Poelstra da3c24c56e
Merge rust-bitcoin/rust-secp256k1#383: Add a disabled rustfmt.toml
20fe3a14dc Add a disabled rustfmt.toml (Tobin Harding)

Pull request description:

  We do not currently use `rustfmt`, this is a nuisance for devs who routinely work on code bases that do use rustfmt who often have their editors set to format on save. We can make the life of such devs much better by explicitly disabling formatting using `rustfmt.toml`.

  ref: https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting

ACKs for top commit:
  apoelstra:
    ACK 20fe3a14dc

Tree-SHA512: 63a7f9c64886cf85e15748c28137a9e642de74890c0b5194fafe3b6c0f9243662b9b7c19c04fbf56e9dd4b14449b07cefd163f69ccfa7e4ffe7dbc3df60b34ff
2022-01-21 16:18:32 +00:00
Tobin Harding 20fe3a14dc Add a disabled rustfmt.toml
We do not currently use `rustfmt`, this is a nuisance for devs who
routinely work on code bases that do use rustfmt who often have their
editors set to format on save. We can make the life of such devs much
better by explicitly disabling formatting using `rustfmt.toml`.

ref: https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting
2022-01-21 10:04:46 +11:00
Andrew Poelstra a9f0ec2258
Merge rust-bitcoin/rust-secp256k1#381: Fix typo in documentation
47411ce73d Fix typo in documentation (Tobin Harding)

Pull request description:

  Docs reference a function name but there is a typo.

  'grund' -> 'grind'.

ACKs for top commit:
  apoelstra:
    ACK 47411ce73d

Tree-SHA512: e6724f1c7972625d59be0ae9de358295c9280e2e126e7322d706cbdca342c1189552b2fdeef9370ff4f85ea8ef185ef4447f6693979d5e8548fcfa2df41a491e
2022-01-19 18:48:04 +00:00
Andrew Poelstra 5445bc37b7
Merge rust-bitcoin/rust-secp256k1#379: Add serde impl for KeyPair
1877e4db33 Add serde impl for KeyPair (elsirion)

Pull request description:

  The impl is added as a module instead of being a direct implementation since it uses the global context and users should be aware that.

ACKs for top commit:
  apoelstra:
    ACK 1877e4db33
  elichai:
    ACK 1877e4db33

Tree-SHA512: decb593a3b047631d08763a13ae10979d07c73bc2547d8f7ea541287f162461e0608992f43a81d819aaf201fc9feed7edc2ef918bdb2d82a39205cb2c77852f3
2022-01-19 18:17:48 +00:00
Tobin Harding 47411ce73d Fix typo in documentation
Docs reference a function name but there is a typo.

'grund' -> 'grind'.
2022-01-19 15:22:37 +11:00
elsirion 1877e4db33
Add serde impl for KeyPair
The impl is added as a module instead of being a direct implementation
since it uses the global context and users should be aware that.
2022-01-18 20:10:11 +01:00
Andrew Poelstra 045896dae7
Merge rust-bitcoin/rust-secp256k1#377: Use the new recover_ecdsa in bench function
c7a8bbb772 Use the new recover_ecdsa in bench function (Tobin Harding)

Pull request description:

  We recently deprecated `recover` in favour of `recover_ecdsa` but missed
  one call site in benches.

ACKs for top commit:
  apoelstra:
    ACK c7a8bbb772

Tree-SHA512: c57625ff50aea6c3985f7c7d52bf47ba6a48e93d3c60408edb6ab9ddc6e014171f8691dab954472b02ac745fcefa95c9206000560ef1ba64308b521b36563bfa
2022-01-14 19:36:34 +00:00
Tobin Harding c7a8bbb772 Use the new recover_ecdsa in bench function
We recently deprecated `recover` in favour of `recover_ecdsa` but missed
one call site in benches.
2022-01-14 13:19:36 +11:00
Andrew Poelstra 7b8392057c
Merge rust-bitcoin/rust-secp256k1#374: Do trivial Clippy fixes
72f5e0441e Do not use deprecated functions (Tobin Harding)
3840ce914b Add Debug/Copy/Clone derives (Tobin Harding)
63ae716e6f Add clippy.toml (Tobin Harding)

Pull request description:

  Add `clippy.toml` and fix a few trivial Clippy warnings.

ACKs for top commit:
  elichai:
    ACK 72f5e04
  apoelstra:
    ACK 72f5e0441e

Tree-SHA512: 5310832d9a4d864a118fef41e275304b912d1c8997060e1eaba95e12700a0b551e846309f9765e10a9a886a03f65b90fcda31d6bf92188791b3c73f97a14e18d
2022-01-12 18:29:23 +00:00
Andrew Poelstra 83e3372edb
Merge rust-bitcoin/rust-secp256k1#372: Deprecate generate_schnorrsig_keypair method
97524b2da7 Deprecate generate_schnorrsig_keypair (Tobin Harding)
389abddcc7 Add method KeyPair::public_key (Tobin Harding)

Pull request description:

  Recently we deprecated a bunch of functions/methods that used the term `schnorrsig`. Seems we left `generate_schnorrsig_keypair` in there, along with some stale docs on it.

  - Patch 1: Adds method `KeyPair::public_key` that calls through to `XOnlyPublicKey::from_keypair`.
  - Patch 2: Deprecates `generate_schnorrsig_keypair` and uses the newly defined `pk.public_key()` everywhere.

  ### Note to reviewers

  Please note, this PR has been totally re-written using the suggestions below by @apoelstra.

ACKs for top commit:
  apoelstra:
    ACK 97524b2da7

Tree-SHA512: a10255d04b86c0031d5cfe4b6357224bc7bcd31c7e278d28af414a34ba4f158dd05d712c4878dfdc327ff8cb42b4421cc0a4b2605c6781691a3158b237fda2d3
2022-01-12 18:14:07 +00:00
Tobin Harding 72f5e0441e Do not use deprecated functions
Recently we deprecated a bunch of methods/functions. We are still
calling them in test code. Found by Clippy.

Use the shiny new methods/functions instead of the deprecated ones.
2022-01-12 18:56:08 +11:00
Tobin Harding 3840ce914b Add Debug/Copy/Clone derives
Clear Clippy warnings by adding derives to `GlobalContext`.
2022-01-12 18:55:06 +11:00
Tobin Harding 63ae716e6f Add clippy.toml
Inform Clippy that our MSRV is 1.29
2022-01-12 18:54:30 +11:00
Tobin Harding 97524b2da7 Deprecate generate_schnorrsig_keypair
We have deprecated all other functions that use the identifier
'schnorrsig' but we missed `generate_schnorrsig_keypair`.

This function is purely a helper function and serves no real purpose
other than to reduce two lines of code to a single line. Downstream
users can write this function themselves if they need it.

Also, we recently added a new public method to `KeyPair` to get the
public key in a slightly more ergonomic fashion. Use `kp.public_key()`
when replacing usage of now deprecated `generate_schnorrsig_keypair`
function.
2022-01-12 18:23:40 +11:00
Tobin Harding 389abddcc7 Add method KeyPair::public_key
Currently to get the `XOnlyPublicKey` from a `KeyPair` users must do
`XOnlyPublicKey::from_keypair(&kp)`. While this does the job we can make
the lib more ergonomic by providing a method directly on `KeyPair` that
calls through to `XOnlyPublicKey::from_keypair`.

Add method `KeyPair::public_key(&self)`.
2022-01-12 18:14:19 +11:00
Andrew Poelstra a9cf6785cc
Merge rust-bitcoin/rust-secp256k1#373: Use hyperlinks
f6a19290fc Use hyperlinks (Tobin Harding)

Pull request description:

  Clippy emits two warnings of type:

   warning: this URL is not a hyperlink

  As suggested, add pointy brackets to the links.

  Docs built and links verified to be:

  a) Not links as Clippy said before this patch is applied
  b) Both are valid links with this patch applied

ACKs for top commit:
  apoelstra:
    ACK f6a19290fc

Tree-SHA512: 702807fee7922ff7755a43fc84333b8fb477c9700199eee2c2ee7c8c8238fcd3d2915ef256efd933f8934600c85bd64914dfe0c092d0bb356ce12a53b4469637
2022-01-11 14:56:51 +00:00
Tobin Harding f6a19290fc Use hyperlinks
Clippy emits two warnings of type:

 warning: this URL is not a hyperlink

As suggested, add pointy brackets to the links.
2022-01-11 17:41:11 +11:00
Martin Habovstiak 52560a9205 Warn that serde differs from consensus encoding
Addresses https://github.com/rust-bitcoin/rust-bitcoin/pull/756#discussion_r780844146
2022-01-10 00:20:06 +01:00
Andrew Poelstra d068fd7d41
Merge rust-bitcoin/rust-secp256k1#365: Fixed docs(rs)
314e8755df Clarify `global-context` feature (Martin Habovstiak)
d52ab85dd5 Added missing features to docs.rs config (Martin Habovstiak)

Pull request description:

  Sadly, I missed two details in #353: features missing in docs.rs configuration and `global-context` being a bit confusing.
  This PR fixes those, see commit messages for details.

ACKs for top commit:
  apoelstra:
    ACK 314e8755df

Tree-SHA512: 01bed8ae2f30adcbdd436b514f08a084492d7f4e1a739ca62e6d8b8547e379c01faeda3522733c27ab615acbb4c6cff60e13906cc88a0d2b90e439e7da517466
2022-01-07 17:31:42 +00:00
Andrew Poelstra fe76cada92
Merge rust-bitcoin/rust-secp256k1#366: Remove capital letter in middle of docs sentence
656f19407b Remove capital letter in middle of docs sentence (Tobin Harding)

Pull request description:

  (Candidate for most trivial patch of all time.)

  Seems to be a typo, change the 'L' to an 'l'.

ACKs for top commit:
  real-or-random:
    ACK 656f19407b

Tree-SHA512: 06a4712868c3195a8465b9cf7bd39e55a30e37574086ca27cb032e0109a8fe053411426a15bcb354642bf78e6420b6fa2789ca487c6cc499f741a11220d5dc22
2022-01-07 17:28:19 +00:00
Andrew Poelstra db11cf93cc
Merge rust-bitcoin/rust-secp256k1#364: Add lints to catch missing traits
69f44d9301 Manually implement Debug for SerializedSignature (Tobin Harding)
26921a31b8 Add lints to catch missing traits (Tobin Harding)
35556e22f2 Remove useless call to format (Tobin Harding)
0ad414a982 Remove unneeded return statements (Tobin Harding)

Pull request description:

  We can use the linters to help us catch type definitions that are missing 'standard' derives. 'standard' is project defined to be

  - Copy
  - Clone
  - Debug
  - PartialEq and Eq
  - PartialOrd and Ord
  - Hash

  (I've assumed this to be true based on the code and an open [PR](https://github.com/rust-bitcoin/rust-bitcoin/pull/587) in rust-bitcoin.)

  While neither Rustc nor Clippy can find all of these, Rustc can warn for missing `Copy` and `Debug` implementations and these warnings can assist us find types that may need additional derives.

  First two patches are trivial Clippy fixes in preparation for using the linter to improve type definitions crate wide.

  Patch 3 adds
  ```
  #![warn(missing_copy_implementations)]
  #![warn(missing_debug_implementations)]
  ```
  and fixes newly emitted warnings.

ACKs for top commit:
  thomaseizinger:
    ACK 69f44d9301
  apoelstra:
    ACK 69f44d9301

Tree-SHA512: 18f2c52d207f962ef7d6749a57a35e48eb18a18fac82d4df4ff3dce549b69661cb27f66c4cae516ae5477f5b919d9197f70a5c924955605c73f8545f430c3b42
2022-01-07 17:26:43 +00:00
Tobin Harding 656f19407b Remove capital letter in middle of docs sentence
Seems to be a typo, change the 'L' to an 'l'.
2022-01-07 15:05:00 +11:00
Martin Habovstiak 314e8755df Clarify `global-context` feature
Previously only `global-context-less-secure` was shown in the doc even
though `global-context` may also work. This was strictly correct because
`global-context` implies `global-context-less-secure` which is also
documented but people could miss it or forget about it and then worry
about security or worse, enable less secure feature.

Calling out both fetures seems useful, even important and thankfully
doesn't seem to cause too much noise in the docs.
2022-01-07 01:17:52 +01:00
Martin Habovstiak d52ab85dd5 Added missing features to docs.rs config
These features were previously forgotten and without them the docs.rs
doc is not that great. :(
2022-01-07 01:12:41 +01:00
Tobin Harding 69f44d9301 Manually implement Debug for SerializedSignature
Currently we have an implementation of `Debug` (also used by `Display`)
for `Signature` that first converts the sig to a `SerializedSignature`
then prints it as hex.

We would like to have an implementation of `Debug` for
`SerializedSignature`, this cannot be derived because of the `data: [u8;
field]`. We can manually implement `Debug` for `SerializedSignature`
exactly as it is currently done for `Signature` and call this new
implementation from `Signature::fmt()`.

This code path is already tested in `lib.rs` in the test function
`signature_display`.
2022-01-07 10:42:34 +11:00
Tobin Harding 26921a31b8 Add lints to catch missing traits
Rustc can warn us when we forget to add `Copy` and `Deubg` trait
implementations to types.

Add lint directives to enable warnings for missing `Copy` and `Debug`
implementations. Use the newly emitted warnings to find types that do
not implement our 'standard' traits. These 'standard' traits are defined
as the set of attributes that it has been found beneficial to
opportunistically add to all types, these are

- Copy
- Clone
- Debug
- PartialEq and Eq
- PartialOrd and Ord
- Hash
2022-01-07 10:28:10 +11:00
Tobin Harding 35556e22f2 Remove useless call to format
Clippy emits:

 warning: useless use of `format!`

As suggested, remove the useless call to `format!`.
2022-01-07 10:18:49 +11:00
Tobin Harding 0ad414a982 Remove unneeded return statements
Clippy emits a few warnings:

 warning: unneeded `return` statement

As suggested, remove the unneeded return statements.
2022-01-07 10:18:49 +11:00
Andrew Poelstra 691173410a
Merge rust-bitcoin/rust-secp256k1#361: Add basic derives for Parity
1671dfc2ed Release 0.21.2 (sanket1729)
837be22e09 Basic derives for Parity (sanket1729)
7059192de9 Wildcard export from key module (sanket1729)

Pull request description:

  Sorry for getting another point release. This time I have tested against this branch for rust-bitcoin https://github.com/rust-bitcoin/rust-bitcoin/pull/755. Hopefully, this is the last release.

  Next release, we should have a Release Candidate for a couple of days before publishing a release.

ACKs for top commit:
  apoelstra:
    ACK 1671dfc2ed

Tree-SHA512: 263ad027da3da764bd76f719200382c47ba21a976caefc23ebef45d1c4be35ddfc80ce619b57326310aaab22bbf75ca7f1db80b45e95ec076584805efb791f3f
2022-01-06 22:52:34 +00:00
sanket1729 1671dfc2ed Release 0.21.2 2022-01-06 23:57:28 +05:30
sanket1729 837be22e09 Basic derives for Parity 2022-01-06 23:57:26 +05:30
sanket1729 7059192de9 Wildcard export from key module 2022-01-06 23:08:01 +05:30
Andrew Poelstra 74e8fc7699
Merge rust-bitcoin/rust-secp256k1#360: Re-export Parity struct
e595b39510 Re-export Parity struct (sanket1729)

Pull request description:

  pub struct Parity is under a private module key and not re-exported in lib.rs . It is therefore not
  possible to use it downstream.

ACKs for top commit:
  elichai:
    ACK e595b39510
  apoelstra:
    ACK e595b39510

Tree-SHA512: 2573689f9a08505c8dfe8f79cd921d5a2742a2a2f4f92cf4066fe6557c765c756531d13560fa4fe6461f094b0c11a52aca30b44542eb77eda7dd1ebd24d3b155
2022-01-06 15:46:18 +00:00
Andrew Poelstra 88f6baee73
Merge rust-bitcoin/rust-secp256k1#353: Documented features
18f74d5242 Clarify what does "less security" mean (Martin Habovstiak)
94c55b4d09 Fixed typos/grammar mistakes (Martin Habovštiak)
1bf05523f0 Documented features (Martin Habovstiak)

Pull request description:

  This documents the Cargo features making sure docs.rs shows warning for
  feature-gated items. They are also explicitly spelled out in the crate
  documentation.

  The PR is similar in spirit to https://github.com/rust-bitcoin/rust-bitcoin/pull/633

ACKs for top commit:
  apoelstra:
    ACK 18f74d5242

Tree-SHA512: 8aac3fc5fd8ee887d6b13606d66b3d11ce44662afb92228c4f8da6169e3f70ac6a005b328f427a91d307f8d36d091dcf24bfe4d17dfc034d02b578258719a90a
2022-01-06 15:42:32 +00:00