ba124757c4 hashes: Default to no_std (Tobin C. Harding)
6a4e219c55 hashes: embedded: Remove unused import (Tobin C. Harding)
915c9627f6 Put feature gate attribute under test attribute (Tobin C. Harding)
Pull request description:
`hashes` is `no_std` ready, lets default to `no_std`.
Done as part of #2413
ACKs for top commit:
apoelstra:
ACK ba124757c419aef38019ee7825c32af540b9dcd0; successfully ran local tests
Tree-SHA512: 14a69d32c7e1fe8303d53944fa274acfe6a509407b8d69312d693102588a1f59a56a815370d6d4dfe15fa68678ef67faa1c313967a7caaba01db97065e634b7b
There is a range of different wordings used in the docs of constructor
type functions.
Change all to start with `Constructs a new` or `Constructs an empty`.
In functions that act like constructors there is a mixture of the usage
of `creates` and `constructs`.
Replace all occurrences of `creates` with `constructs` in the first line
of docs of constructor like functions.
We don't want a dependency on `internals` for `hashes` unless its really
needed.
Duplicated the `impl_from_infallible` macro into `hashes::error` and
use it to implement from infallible for `FromSliceError`.
Add a public `error` module and move the one error for the `hashes`
crate into it.
Re-export at the crate root.
Done in preparation for adding an additional error type.
81d8699b55 units: Put no_std up top (Tobin C. Harding)
3e332c3839 amount: Fix docs on FromStr (Tobin C. Harding)
5bec76aa51 amount: Fix rustdocs (Tobin C. Harding)
41c80cc476 amount: Improve docs on div by weight (Tobin C. Harding)
2b4a61739a Add type to debug output for Amount (Tobin C. Harding)
42e5043b33 Add from_int_btc group of functions (Tobin C. Harding)
Pull request description:
Improve the `amount` module by doing:
- Patch 1: Add/update `from_int_btc` and `from_int_btc_const` functions
- Patch 2: Add type to debug output for `Amount`
- Patch 3: Fix incorrect docs
- Patch 4: Make docs use correct style and be uniform across the two amount types
- Patch 5: Fix docs on `FromStr`
ACKs for top commit:
apoelstra:
ACK 81d8699b55dad570247cb14d2b3eea64270a83cf; successfully ran local tests
jamillambert:
ACK 81d8699b55
Tree-SHA512: ddd6e02b4cd9a9aa8cbdd2d2f7ae289a6bcca9eb002ef0c6d83a6eca950b2cd08f5918286bb33e814f321e3bfe83fdf75ae051cf8f91ee45d3e4abe76c1c2a4c
312718cd6e Update rust-bitcoin-maintainer-tools (Tobin C. Harding)
Pull request description:
Update to the latest commit hash of tip of master.
ACKs for top commit:
apoelstra:
ACK 312718cd6eae8ce71a331c2957381b71240888d7; successfully ran local tests
Tree-SHA512: 94fbe5fb7c8f0ead1f46435e3b0c13f61d907f1e06aaa3160d6e7dc9f86339eb5efcf5a00322be42ab236396ff8245dc5e526ceaaa6642588e0bcd82252538d7
The `no_std` attribute has significant ramifications, as opposed to the
clippy attributes etc.
Put the `no_std` attribute up top so it catches the eye. This is also
uniform with other crates in this repo.
The docs on `FromStr` say "string slice is zero" but actually mean to
document the behaviour when the value represented is zero.
Also the fact that `FromStr` returns an error if parsing fails is self
evident.
Fix the rustdocs on `Amount` and `SignedAmount` by doing:
- Make them uniform
- Use correct style (looks like `SignedAmount` got left behind when we
improved `Amount`)
6555143478 bitcoin: Re-format crate level re-exports (Tobin C. Harding)
Pull request description:
Is there any advantage trying to lay out the re-exports to give users an idea of the crate structure?
We have the explicit aim that users who depend on `bitcoin` do not ever need to reach directly into `primitives` (or `units`) however it is kind of nice to know where things come from, saves jumping to multiple files looking for them (for those of us that jump to files manually).
I do not know how all the re-exports interact with other folks IDEs, I personally open files manually and just remember where stuff is.
ACKs for top commit:
jamillambert:
ACK 6555143478
apoelstra:
ACK 6555143478dbd2306d0506a29b7d83433e7b33f5; successfully ran local tests; If Jamil and Tobin are happy then I am happy
Tree-SHA512: 15fc9bec6ba34114b59f9eeb8b5377f8bc2957f10b37e8b41772b26f3240fa2b41bb67dc33575f54e1a42d4c3cc44f148630e328674bc1c9e0e3a29c9e6efa06
9f60e1ae26 Copy crate level attributes to chacha20_poly1305 (Tobin C. Harding)
Pull request description:
No obvious reason not to; copy the crate level attributes that we have in all our other crates.
ACKs for top commit:
apoelstra:
ACK 9f60e1ae26d2ff29a53e90bccd5a580d7a0f2c84; successfully ran local tests
Tree-SHA512: 5b861fc3a7f05cb4bd24f714a47266616d462ffa67253249f214339d341f39d5f42e35d7e23269bdf40182041b6138e9b304f7883c644f9e522ec2a90be5cb99
The `Transaction` type was created way back when, and the field names
were named using singular (`input` and `output`). In hindsite plural
probably should have been used since its more idiomatic Rust but the
fields have been around so long now that re-naming them is going annoy a
whole bunch of people.
As a compromise add getters that use plural, immutable and mutable
versions, for both the `input` and `output` fields.
Close: #822
f3aedf5335 Automated update to Github CI to rustc nightly-2024-11-03 (Update Nightly Rustc Bot)
Pull request description:
Automated update to Github CI workflow `rust.yml` by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action
ACKs for top commit:
tcharding:
ACK f3aedf5335
Tree-SHA512: 49d27faea980f7aaacd9d0c15c4687f1157962a25e29849bd5916f134333dd85a967a23c804a0753c3551eef618bc782127cf5ed37d977385c90305e510798e6
Is there any advantage trying to lay out the re-exports to give users an
idea of the crate structure?
We have the explicit aim that users who depend on `bitcoin` do not ever
need to reach directly into `primitives` (or `units`) however it is kind
of nice to know where things come from, saves jumping to multiple files
looking for them (for those of us that jump to files manually).
I do not know how all the re-exports interact with other folks IDEs, I
personally open files manually and just remember where stuff is.
85942c355d Re-export block::Header as BlockHeader (Tobin C. Harding)
Pull request description:
For users who want to just grab stuff from the crate root it makes total sense for there to be a `BlockHeader`.
Another nice thing, in the HMTL docs it makes BlockHeader be in the struct list right along with `Block`, `BlockHash`, and `BlockHeight`.
Close: #3548
ACKs for top commit:
apoelstra:
ACK 85942c355dfdcf9ddf9a46202f4db56794dcc85d; successfully ran local tests
jamillambert:
ACK 85942c355d
Tree-SHA512: 6fbaf7936062323d31940179ffcbc62951b21f53955a42dca2e28476bda0cebeb041db0e1b4f1ceeac32e43d94fe5476ef055595ae88dc6cfc266d32082bdf4d
4431df18fe script: remove `unsafe` marker from slice-to-script conversions (Andrew Poelstra)
Pull request description:
The length of the slices is not a safety invariant.
Fixes#3531
ACKs for top commit:
tcharding:
ACK 4431df18fe
Tree-SHA512: 85f745058bc5bf68d312f75c53cef570ead986247ca3cb3fc54b5381dd0214e7df55c1fcb99f06e693b0b9478ec6a9785186cac56886f8007ab7b827d903bd01
90b2ac03e3 hashes: Introduce impl_bytelike_traits macro (Tobin C. Harding)
Pull request description:
We have a couple of problems:
1. There are two macros currently for fmt stuff that do similar things, `arr_newtype_fmt_impl` and `hex_fmt_impl` - the difference is not immediately obvious, its the way that the byte array is iterated.
2. Our hash types are missing `AsRef<[u8; len]>` and `Borrow<[u8; len]>`.
Introduce a new macro and remove a bunch of other macros. Include extensive docs but hide the macro from public docs because its not really for consumers of the library.
The macro requires `$crate::hex` to point to `hex-conservative`.
Note the macro is pretty generic (as in general purpose), `hashes` might not be the right home for it. Potentially a better place would be in `hex` itself?
ACKs for top commit:
apoelstra:
ACK 90b2ac03e3560b0e9f78f52b198c869773b5816e; successfully ran local tests
Tree-SHA512: 4d8778c572f29d965d353ab877631c24ce09c27c8f1269d2874fd9a97b3e8ba782d367aedcd501d9e7236ac653ed1f106ec9bf1759c5574f21a607856347f75d
32bc68d4dc primitives: Add rustdoc links back in (Tobin C. Harding)
Pull request description:
During move of code to `primitives` we removed a few links to types that were not yet moved, we can now put these back in.
Close: #2997
ACKs for top commit:
apoelstra:
ACK 32bc68d4dcbbb9a15694df56743ae550de0c805c; successfully ran local tests
jamillambert:
ACK 32bc68d4dc
Tree-SHA512: 952bd9c2e358aed4dc8b40f6f98d11ef2f52acb9366587a81033663a16745d2fb68003b043516b3ef3faf788742910cccb40ffa8b515bb3ad189131425f969bf
The length of the slices is not a safety invariant.
Fairly large diff because I had to remove a bunch of `unsafe` blocks
around calls to this function.
Fixes#3531
38b8c6f5ea units: Remove a bunch of feature gateing (Tobin C. Harding)
e347b50614 Use InputString in hex prefix error types (Tobin C. Harding)
ff20249bdc Remove unneeded feature gate (Tobin C. Harding)
88f6621e30 Split parse macros (Tobin C. Harding)
Pull request description:
Remove the feature gating from the modules in `units` - BOOM!
Close: #3213
ACKs for top commit:
apoelstra:
ACK 38b8c6f5ea2d997e08aae496ed333abeedab9406; successfully ran local tests; nice!
Tree-SHA512: 75c7e70e64c705fe0e32d92d9a0557cd77f5cd5d68a50f274be4a128331f5ae69259f6c6a9d483699478cbc2c40ebadcb83e1d419952287f74657906ca65caaf
Add/update the from_int group of functions to provide one that errors
and one that is const and panics (errors in const context are not useful
because one cannot call `unwrap` in const context).
During move of code to `primitives` we removed a few links to types that
were not yet moved, we can now put these back in.
Feature all rustdoc imports on `alloc` and `doc`.
Close: #2997
In an effort to reduce requirement for `alloc`; remove the `String` and
use `InputString` in the hex prefix related error types.
Tested with:
(Note in test code we have to use `"cafe".to_owned()` before this patch
is applied.)
rust```
#[test]
fn hex_prefix_errors() {
let err = hex_remove_prefix("cafe").unwrap_err();
std::println!("{}", err);
std::println!("{:?}", err);
let err = hex_check_unprefixed("0xcafe").unwrap_err();
std::println!("{}", err);
std::println!("{:?}", err);
}
```
Before:
hex string is missing a prefix (e.g. 0x): cafe
MissingPrefixError { hex: "cafe" }
hex string contains a prefix: 0xcafe
ContainsPrefixError { hex: "0xcafe" }
After:
failed to parse 'cafe' as hex because it is missing the '0x' prefix
MissingPrefixError { hex: InputString("cafe") }
failed to parse '0xcafe' as hex because it contains the '0x' prefix
ContainsPrefixError { hex: InputString("0xcafe") }
We have a couple of problems:
1. There are two macros currently for fmt stuff that do similar things,
`arr_newtype_fmt_impl` and `hex_fmt_impl` - the difference is not
immediately obvious, its the way that the byte array is iterated.
2. Our hash types are missing `AsRef<[u8; len]>` and `Borrow<[u8; len]>`.
Introduce a new macro and remove a bunch of other macros. Include
extensive docs but hide the macro from public docs because its not
really for consumers of the library.
The macro requires `$crate::hex` to point to `hex-conservative`.
Note the macro is pretty generic (as in general purpose), `hashes` might
not be the right home for it. Potentially a better place would be in
`hex` itself?
For users who want to just grab stuff from the crate root it makes total
sense for there to be a `BlockHeader`.
Another nice thing, in the HMTL docs it makes BlockHeader be in the
struct list right along with `Block`, `BlockHash`, and `BlockHeight`.
3f2e760d1f Replace String with InputString in ParseIntError (Tobin C. Harding)
aa5c78430c Replace invalidInteger with ParseIntError (Tobin C. Harding)
9b7a706bfd Remove From<ParseIntError> (Tobin C. Harding)
c90f4b6033 Fix bug in error output (Tobin C. Harding)
c986b2f620 internals: Move error.rs to error/mod.rs (Tobin C. Harding)
Pull request description:
This PR hopefully clears the way for removing many of the `alloc` feature gates in `units` and `primitives`
The three final patches were tested by adding the following test to `units::locktime::absolute`:
```rust
#[test]
pub fn debug_absolute_error_conversion_height() {
let invalid_height = LOCK_TIME_THRESHOLD + 1;
let err = Height::from_consensus(invalid_height).unwrap_err();
std::println!("{:?}", err);
std::println!("{}", err);
let invalid_time = LOCK_TIME_THRESHOLD - 1;
let err = Time::from_consensus(invalid_time).unwrap_err();
std::println!("{:?}", err);
std::println!("{}", err);
let invalid_height = std::format!("{:x}", LOCK_TIME_THRESHOLD + 1);
let err = Height::from_hex(&invalid_height).unwrap_err();
std::println!("{:?}", err);
std::println!("{}", err);
let invalid_time = std::format!("{:x}", LOCK_TIME_THRESHOLD - 1);
let err = Time::from_hex(&invalid_time).unwrap_err();
std::println!("{:?}", err);
std::println!("{}", err);
let err = Height::from_hex("somerandomshit").unwrap_err();
std::println!("{:?}", err);
std::println!("{}", err);
let err = Time::from_hex("somerandomshit").unwrap_err();
std::println!("{:?}", err);
std::println!("{}", err);
}
```
Gives the following output (the last four lines is the bit that changes, the rest just proves we don't break other variants)
On commit: `d47ff1c25 Remove From<ParseIntError>`
ConversionError { unit: Blocks, input: 500000001 }
invalid lock time value 500000001, expected lock-by-blockheight (must be < 500000000)
ConversionError { unit: Seconds, input: 499999999 }
invalid lock time value 499999999, expected lock-by-blocktime (must be >= 500000000)
ParseHeightError(Conversion(500000001))
block height 500000001 is above limit 499999999
ParseTimeError(Conversion(499999999))
block height 499999999 is below limit 500000000
ParseHeightError(InvalidInteger { source: ParseIntError { kind: InvalidDigit }, input: "somerandomshit" })
failed to parse somerandomshit as block height
ParseTimeError(InvalidInteger { source: ParseIntError { kind: InvalidDigit }, input: "somerandomshit" })
failed to parse somerandomshit as block time
On commit: `0155a0d9a Replace invalidInteger with ParseIntError`
ConversionError { unit: Blocks, input: 500000001 }
invalid lock time value 500000001, expected lock-by-blockheight (must be < 500000000)
ConversionError { unit: Seconds, input: 499999999 }
invalid lock time value 499999999, expected lock-by-blocktime (must be >= 500000000)
ParseHeightError(Conversion(500000001))
block height 500000001 is above limit 499999999
ParseTimeError(Conversion(499999999))
block height 499999999 is below limit 500000000
ParseHeightError(ParseInt(ParseIntError { input: "somerandomshit", bits: 32, is_signed: true, source: ParseIntError { kind: InvalidDigit } }))
failed to parse somerandomshit as block height
ParseTimeError(ParseInt(ParseIntError { input: "somerandomshit", bits: 32, is_signed: true, source: ParseIntError { kind: InvalidDigit } }))
failed to parse somerandomshit as block time
On Commit: `3f2e760d1 Replace String with InputString in ParseIntError`
ConversionError { unit: Blocks, input: 500000001 }
invalid lock time value 500000001, expected lock-by-blockheight (must be < 500000000)
ConversionError { unit: Seconds, input: 499999999 }
invalid lock time value 499999999, expected lock-by-blocktime (must be >= 500000000)
ParseHeightError(Conversion(500000001))
block height 500000001 is above limit 499999999
ParseTimeError(Conversion(499999999))
block time 499999999 is below limit 500000000
ParseHeightError(ParseInt(ParseIntError { input: InputString("somerandomshit"), bits: 32, is_signed: true, source: ParseIntError { kind: InvalidDigit } }))
failed to parse 'somerandomshit' as absolute Height/Time (block height)
ParseTimeError(ParseInt(ParseIntError { input: InputString("somerandomshit"), bits: 32, is_signed: true, source: ParseIntError { kind: InvalidDigit } }))
failed to parse 'somerandomshit' as absolute Height/Time (block time)
ACKs for top commit:
apoelstra:
ACK 3f2e760d1fef2951f93a2554cd53340b0d7a6e0b; successfully ran local tests; nice!
Tree-SHA512: f7fd55acfb83082419db22c24a6b375c20e2631263401e500410c5b5659463f06dc4bdb145621e475dc15d75e764668cdcbf8f88006a487248a05fdb237ad136
2b7cb04265 primitives: Add missing re-exports (Tobin C. Harding)
Pull request description:
Add re-exports of types from `taproot` and `merkle_tree`.
ACKs for top commit:
jamillambert:
ACK 2b7cb04265
apoelstra:
ACK 2b7cb04265cdb2d62c1bcc645e19d8bafa132b4b; successfully ran local tests
Tree-SHA512: e837c8e7bfda3e8c5510a15ba19b2b0b433e9e87c961ab9ab81d134288b70bc98364007e8e610e7066732e16f72ea990a782cade9ead6b71ddc9b843753fa0ee
6aa8c2b023 Remove needless_borrows_for_generic_args (Tobin C. Harding)
Pull request description:
This has been fixed and we use nightly to lint so we have access to the merged fix.
ACKs for top commit:
apoelstra:
ACK 6aa8c2b023619534437043e76ec4252f27295875; successfully ran local tests
Tree-SHA512: 011677b6c1a2dc6c63097cafd1682fab5d9bdd94133b872bdd49699a55c80a01a8e6e5e844ae1cfe1ca9da47a2ba2ed6b910719b1ccbb06e60e22ecb01ec0efc
80b5d8b7b3 hashes: Add changelog for release 0.15.0 (Tobin C. Harding)
Pull request description:
The version has already been bumped on `master`.
In preparation for releasing `hashes v0.15.0` add a changelog entry.
ACKs for top commit:
apoelstra:
ACK 80b5d8b7b36ea97007f062971a732ec8a512cfa5; successfully ran local tests; again lots of stuff!
Tree-SHA512: ab1bbdf7df819c587dc905e4cdcda2232ede2a495a0e395e5d6f6bd730a7c3c0675e05f8ab616e5e6dee0a87836ab486d025f80608e73b713007391711ef15ba
Currently the `ParseIntError` contains an owned copy of the input
string, this is causing us to have to use `alloc` everywhere.
We already have a alloc-friendly string replacement type, the
`InputString` - use it.
We have a special type for wrapping integer parsing errors, use it.
To test this I added the following tests:
#[test]
pub fn debug_absolute_error_conversion_height() {
let invalid_height = LOCK_TIME_THRESHOLD + 1;
let _ = Height::from_consensus(invalid_height).unwrap();
}
#[test]
pub fn debug_absolute_error_conversion_time() {
let invalid_time = LOCK_TIME_THRESHOLD - 1;
let _ = Time::from_consensus(invalid_time).unwrap();
}
#[test]
#[cfg(feature = "std")]
pub fn debug_absolute_error_conversion_height_string() {
let invalid_height = std::format!("{:x}", LOCK_TIME_THRESHOLD + 1);
let _ = Height::from_hex(&invalid_height).unwrap();
}
#[test]
#[cfg(feature = "std")]
pub fn debug_absolute_error_conversion_time_string() {
let invalid_time = std::format!("{:x}", LOCK_TIME_THRESHOLD - 1);
let _ = Time::from_hex(&invalid_time).unwrap();
}
#[test]
#[cfg(feature = "std")]
pub fn debug_absolute_error_height_invalid_hex_string() {
let _ = Height::from_hex("somerandomshit").unwrap();
}
#[test]
#[cfg(feature = "std")]
pub fn debug_absolute_error_time_invalid_hex_string() {
let _ = Time::from_hex("somerandomshit").unwrap();
}
Which resulted in the following output
Before:
---- locktime::absolute::tests::debug_absolute_error_conversion_height stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height' panicked at units/src/locktime/absolute.rs:431:56:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Blocks, input: 500000001 }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- locktime::absolute::tests::debug_absolute_error_conversion_height_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height_string' panicked at units/src/locktime/absolute.rs:444:51:
called `Result::unwrap()` on an `Err` value: ParseHeightError(Conversion(500000001))
---- locktime::absolute::tests::debug_absolute_error_conversion_time stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time' panicked at units/src/locktime/absolute.rs:437:52:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Seconds, input: 499999999 }
---- locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string' panicked at units/src/locktime/absolute.rs:457:52:
called `Result::unwrap()` on an `Err` value: ParseHeightError(InvalidInteger { source: ParseIntError { kind: InvalidDigit }, input: "somerandomshit" })
---- locktime::absolute::tests::debug_absolute_error_conversion_time_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time_string' panicked at units/src/locktime/absolute.rs:451:47:
called `Result::unwrap()` on an `Err` value: ParseTimeError(Conversion(499999999))
---- locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string' panicked at units/src/locktime/absolute.rs:464:50:
called `Result::unwrap()` on an `Err` value: ParseTimeError(InvalidInteger { source: ParseIntError { kind: InvalidDigit }, input: "somerandomshit" })
After:
---- locktime::absolute::tests::debug_absolute_error_conversion_height stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height' panicked at units/src/locktime/absolute.rs:432:56:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Blocks, input: 500000001 }
---- locktime::absolute::tests::debug_absolute_error_conversion_height_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_height_string' panicked at units/src/locktime/absolute.rs:445:51:
called `Result::unwrap()` on an `Err` value: ParseHeightError(Conversion(500000001))
---- locktime::absolute::tests::debug_absolute_error_conversion_time stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time' panicked at units/src/locktime/absolute.rs:438:52:
called `Result::unwrap()` on an `Err` value: ConversionError { unit: Seconds, input: 499999999 }
---- locktime::absolute::tests::debug_absolute_error_conversion_time_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_conversion_time_string' panicked at units/src/locktime/absolute.rs:452:47:
called `Result::unwrap()` on an `Err` value: ParseTimeError(Conversion(499999999))
---- locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_height_invalid_hex_string' panicked at units/src/locktime/absolute.rs:458:52:
called `Result::unwrap()` on an `Err` value: ParseHeightError(ParseInt(ParseIntError { input: "somerandomshit", bits: 32, is_signed: false, source: ParseIntError { kind: InvalidDigit } }))
---- locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string stdout ----
thread 'locktime::absolute::tests::debug_absolute_error_time_invalid_hex_string' panicked at units/src/locktime/absolute.rs:465:50:
called `Result::unwrap()` on an `Err` value: ParseTimeError(ParseInt(ParseIntError { input: "somerandomshit", bits: 32, is_signed: false, source: ParseIntError { kind: InvalidDigit } }))
The errors in `units::locktime::absolute` are complex, I'd like to make
them more simple so they are more understandable.
I have no clue why this is implemented - remove it.