Uh oh!
There was an error while loading. Please reload this page.
Add EntropySource wrapper - #235
Conversation
dhardy
left a comment
There was a problem hiding this comment.
This actually makes NewSeeded redundant.
| } | ||
| impl EntropySource { | ||
| pub fn new() -> Result<Self, Error> { |
There was a problem hiding this comment.
I think it's worth making this infallible and delaying errors so that X::from_rng(EntropySource::new()) works. Since performance isn't very important here we could potentially just try all sources each call, though that's not optimal.
There was a problem hiding this comment.
JitterRng has a pretty high set-up cost, because it runs the timer for every initialization.
Do you mean to add something like a third variant to EntropySourceInner that none are available, with the Error?
There was a problem hiding this comment.
X::from_rng(EntropySource::new()) works really nice! It will take me until Wednesday or Thursday before I can update this PR.
| } | ||
| fn fill_bytes(&mut self, dest: &mut [u8]) { | ||
| self.try_fill_bytes(dest).unwrap(); |
There was a problem hiding this comment.
unwrap has to go — but sure, this is a quick implementation
There was a problem hiding this comment.
I was even thinking of just using unimplemented!() here. The situations where both OsRng and JitterRng fail should be extremely rare, so I didn't care much about the unwrap. What do suggest to replace it with?
| let mut rng2_result = JitterRng::new(); | ||
| if let Ok(mut rng2) = rng2_result { | ||
| result = rng2.try_fill_bytes(dest); // Can't fail | ||
| switch_rng = Some(EntropySourceInner::Jitter(rng2)); |
There was a problem hiding this comment.
Probably simpler to recurse here (i.e. call new_self.try_fill_bytes()).
There was a problem hiding this comment.
It took some thinking to get the logic right and the borrow checker happy. But I'll think about it!
dhardy
commented
Jan 14, 2018
Um, so did you come up with this idea independently or see my comment before I finished the review? Either way I like it, plus we can leave out It might be nice to have a global generator function like |
pitdicker
commented
Jan 14, 2018
I was surprised by you comment. We thought of the same thing at the same time 😄. |
pitdicker
commented
Jan 14, 2018
I am partial about the name. Do you want to pick between I feel that adding an |
fd7c131 to
e32b4c9Comparepitdicker
commented
Jan 14, 2018
(nothing changed yet, just a rebase to hopefully get the CI happy) |
dhardy
commented
Jan 15, 2018
To quote the OED:
More on topic, I prefer You are right that But having this as well, and making |
pitdicker
commented
Jan 15, 2018
Ah, thank you. I was impartial. Now I am starting to get partial to
Yes, I don't like the extra import. But there seems to be no way around it? Without the trait it is necessary to import What did you think of the idea to add a feature flag (in the future) that allows crates to provide a different source for |
dhardy
commented
Jan 15, 2018
Um... I think the extra import could be avoided if Anyway, this "entropy source" will be a full I don't think a feature flag can do that; at best it could enable support for setting another source at run time. |
pitdicker
commented
Jan 15, 2018
I also though of renaming If we make I just thought of an issue:
I was thinking of something like this (but have to learn a lot about FFI and linking first): #[cfg(feature = "extern_entropy_source")]extern{fnextern_fill_bytes(dest:*mutu8,length:usize) -> u32;}#[cfg(feature = "extern_entropy_source")]implRngforEntropySource{fntry_fill_bytes(&mutself,dest:&mut[u8]) -> Result<(),Error>{/* call extern_fill_bytes */}}Linking in a crate that provides a different source would have to be done by the build script of the final crate. |
dhardy
commented
Jan 15, 2018
I was playing the devil's advocate; I didn't mean putting You're right, linking like that should be possible, but it's not very "Rustic". It relies on |
pitdicker
commented
Jan 19, 2018
(I have been busy writing this comment for four days...)
One of the nicest ways to explore options 😄. What do you think of
Would this be more "Rustic"? Moving
Good point. We don't want an application that relies on a source like The second part of the puzzle I had in mind was to make Something like this had been proposed/tried before in #109, #133, #78. It is not optimal, no use of As argued in #109 (comment) this could help make crates to be available for |
If we go in that direction —
The above is quite a big redesign, but on first impressions it sounds good.
I was experimenting with making |
e32b4c9 to
7a07c36Comparepitdicker
commented
Jan 21, 2018
I have rebased on top of #233 again (basically recreated the branch...). The last commit renames The logic to select an entropy source now is something like this: Maybe I just made things to difficult, but couldn't quickly see a better way. Will you have another look? I would like to keep future directions for |
dhardy
commented
Jan 22, 2018
The logic in the comment above sounds reasonable to me. I didn't look at the commits themselves; the order seems to be mixed up with commits from #233? Can you do |
pitdicker
commented
Jan 22, 2018
I am not sure what is happening with the order of the commits, locally and on github (https://github.com/pitdicker/rand/commits/entropy_source) they aren't mixed. I did not change the commits you already reviewed, only added one extra. |
dhardy
commented
Jan 22, 2018
That's odd. Anyway, your new approach looks fine, although it doesn't check the error kind. If If |
pitdicker
commented
Jan 22, 2018
Good point about checking the error kind, I only thought about it partially. I am also not sure using a counter is best. The overhead of the extra system call is only 2%. Especially when doing larger reads with I just realized I will add a description of the fall-back strategy to the documentation of |
dhardy
commented
Jan 22, 2018
Performance isn't critical here, so using
|
Yes, that could work. And every time we retry, we get the reason for failing again from the OS, so we can reset the counter. Something like this? EntropySource::Jitter(ref mut rng) => {ifself.counter == 0{matchtry_os_new(dest){Ok(os_rng) => {
switch_rng = Some(EntropySource::Os(os_rng));}Err(e) => {if e.kind() == ErrorKind::Unavailable{self.counter = 8;// Wait 8 calls before retry}else{self.counter = 0;// Retry on next call}return rng.try_fill_bytes(dest);// use JitterRng}}}else{self.counter -= 1;return rng.try_fill_bytes(dest);// use JitterRng}} |
Yes. Although if we only wait 8 calls I wonder if it's worth using a counter at all; I was thinking a much higher count, but there's probably no reason to do so. I guess given how slow |
pitdicker
commented
Jan 22, 2018
I don't think using a counter or not matters much. If we set the counter to a high value, and If we set the counter to a low value, and I'll leave it to you: keep things as they are now, remove the counter, or increase it? |
dhardy
commented
Jan 23, 2018
Good argument. So I guess I'll let you decide, while I take another look at #233. |
dhardy
commented
Jan 23, 2018
Looks like this needs a rebase |
41fc616 to
b6339f5Comparepitdicker
commented
Jan 24, 2018
Rebased and removed the counter |
dhardy
commented
Jan 24, 2018
Okay, I made my own commit to replace usage of to: With that change I'm happy to merge this (although I did notice |
dhardy
commented
Jan 24, 2018
Thinking about it some more, the above messages are still not ideal: we never show errors from I keep wondering whether we want a single shared state for these RNGs (i.e. accessed via a function) or not; so far it doesn't appear necessary for |
dhardy
commented
Jan 27, 2018
I think you need something like a static I guess this brings us back to this discussion too. |
pitdicker
commented
Jan 31, 2018
I would like to make the changes to |
dhardy
commented
Jan 31, 2018
No, it shouldn't hold this up. Sorry, I'll try to get this merged. |
dhardy
commented
Jan 31, 2018
I tweaked this and merged with master, but it needs a bit more work really. Feel free to rebase, or I might try reworking this a bit more. I'm not sure about the error handling; e.g. if reseeding failed it might be permissible to continue without reseeding? |
pitdicker
commented
Jan 31, 2018
Thank you. I wanted to say no need to hurry, it is not as if I was able to do much last week.
Is there a way to see what changes you made? |
pitdicker
commented
Feb 1, 2018
dhardy
commented
Feb 1, 2018
Sorry, I've been using kdiff3 to do the merges, and apparently trusting it too much. |
pitdicker
commented
Feb 1, 2018
I found a nice way to reduce the size of |
dhardy
commented
Feb 1, 2018
Why did you close — are you going to start fresh with a new PR? |
pitdicker
commented
Feb 1, 2018
Yes, I will make a fresh PR. I did not realize re-using this one was even an option... |
dhardy
commented
Feb 1, 2018
You can force-push and re-open if you like — depends whether you want to keep these comments in the same thread really. |
b6339f5 to
69eee53CompareApologies, I understood things wrong and blamed you and merging. I rebased and reopened this PR. Also added an extra commit with logging for And it turned out reopening a PR after a force-push is difficult. |
dhardy
commented
Feb 5, 2018
I'm still not quite sure we've got this right, though re-reading the comment thread the design has evolved significantly since we started! The Since the current code tries to use The logging doesn't seem quite right; currently error details should be printed via Since the above issues are very minor and we've been waiting for this a while, I'll go ahead and merge, and leave #249 and #251 to follow up. |
This is just an idea I am trying. The PR is based on top of #233, only the last 3 commits are new.
I have added an
EntropySourcewrapper that usesOsRng, and if it errors falls back toJitterRng. I hope this will help in three situations:NewSeededcan also be used by user code.Reseedertrait, providing an RNG for reseeding is enough.EntropySourceuse an external RNG. This will make it andNewSeededavailable forno_stduses.