Skip to content

Conversation

@laanwj
Copy link
Member

@laanwj laanwj commented Oct 13, 2016

There are only a few uses of insecure_random outside the tests. This PR replaces uses of insecure_random (and its accompanying global state) in the core code with an FastRandomContext that is automatically seeded on creation.

This is meant to be used for inner loops. The FastRandomContext can be in the outer scope, or the class itself, then rand32() is used inside the loop. Useful e.g. for pushing addresses in CNode or the fee
rounding, or randomization for coin selection.

As a context is created per purpose, thus it gets rid of cross-thread unprotected shared usage of a single set of globals, this should also get rid of the potential race conditions.

  • I'd say TxMempool::check is not called enough to warrant using a special fast random context, this is switched to GetRand() (open for discussion...)
  • The use of insecure_rand in ConnectThroughProxy has been replaced by an atomic integer counter. The only goal here is to have a different credentials pair for each connection to go on a different Tor circuit, it does not need to be random nor unpredictable.
  • To avoid having a FastRandomContext on every CNode, the context is passed into PushAddress as appropriate.

There remains an insecure_random for test usage in test_random.h.

Replaces #8903. Intends to fix @JeremyRubin's concerns about race conditions.

TODO

  • Rename instances to insecure_rand i.s.o rand.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep the name at FastRandomContext insecure_rand, especially in the wallet code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Read the patch from the bottom up and went "huh? the whole reason we had this function was to use it in the subset sum solver!" doh. :)

Copy link
Member Author

@laanwj laanwj Oct 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, makes sense. It didn't become any less insecure, but at least there's no magic global state anymore.

@gmaxwell
Copy link
Contributor

Concept ACK.

src/random.h Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be nice to throw in a:

FastRandomContext() = delete;

just for clarify where the syntax

FastRandomContext rand;

is used.

Alternatively, because we know fDeterministic everywhere it is used, could also be made a template parameter to this class (which has the added benefit of a callee being able to specify what kind of insecure_rand they are getting...).

Copy link
Member Author

@laanwj laanwj Oct 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for clarify where the syntax

FastRandomContext rand;

If you want to find those, isn't removing the default argument =false enough (and maybe making the constructor explicit)?
I think the default (non-deterministic) makes sense though - only the tests have to override the parameter.

could also be made a template parameter to this class

The problem is that the tests switch from/to deterministic with the same object, so the determinism flag needs to be overwritable as part of the state.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think explicit constructors would be good. I think the current behavior (this is a change from prior specs) under c++11 is that the constructor is considered a converting constructor, meaning "FastRandomContext rand = 0" is valid I think?

Perhaps a more idiomatic version of this would be to make FastRandomContext always deterministic, and then add a "non_deterministic_reseed" method to it. This has the downside that the non-test use case always uses the non_det version, so maybe making it always non_det with a method to set a deterministic seed?

Ultimately, it's a minor nit I just think making it more clear how those objects are initialized is good.

src/netbase.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: technically, you can get away with

counter.fetch_add(1, std::memory_order_relaxed)

if it is any concern.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Though this is only called one time per new connection, so I don't think performance would be enough reason to make this more verbose. This could even just use a simple counter protected by a lock, but c++11 makes it so easy to use atomics :)

@JeremyRubin
Copy link
Contributor

Seems to address what I was concerned about and is cleaner than the global state, looks good!

Concept ACK.

@jonasschnelli
Copy link
Contributor

Concept ACK, agree with using FastRandomContext insecure_rand.

@laanwj laanwj force-pushed the 2016_10_kill_insecurerandom branch from 7d507ca to 1c8f590 Compare October 17, 2016 10:44
@laanwj
Copy link
Member Author

laanwj commented Oct 17, 2016

Ok:

  • renamed all instances to insecure_rand
  • FastRandomContext constructor is now explicit
  • And squashed

src/net.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rand -> insecure_rand for consistency?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gah did I forget one, good catch

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paveljanik there was another one in fees.h. Should have them all now (checked through grep)

There are only a few uses of `insecure_random` outside the tests.
This PR replaces uses of insecure_random (and its accompanying global
state) in the core code with an FastRandomContext that is automatically
seeded on creation.

This is meant to be used for inner loops. The FastRandomContext
can be in the outer scope, or the class itself, then rand32() is used
inside the loop. Useful e.g. for pushing addresses in CNode or the fee
rounding, or randomization for coin selection.

As a context is created per purpose, thus it gets rid of
cross-thread unprotected shared usage of a single set of globals, this
should also get rid of the potential race conditions.

- I'd say TxMempool::check is not called enough to warrant using a special
  fast random context, this is switched to GetRand() (open for
  discussion...)

- The use of `insecure_rand` in ConnectThroughProxy has been replaced by
  an atomic integer counter. The only goal here is to have a different
  credentials pair for each connection to go on a different Tor circuit,
  it does not need to be random nor unpredictable.

- To avoid having a FastRandomContext on every CNode, the context is
  passed into PushAddress as appropriate.

There remains an insecure_random for test usage in `test_random.h`.
@laanwj laanwj force-pushed the 2016_10_kill_insecurerandom branch from 1c8f590 to 5eaaa83 Compare October 17, 2016 11:08
Copy link
Contributor

@paveljanik paveljanik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 5eaaa83

boost::mutex counterMutex[10];
int counter[10] = { 0 };
boost::random::mt19937 rng(insecure_rand());
boost::random::mt19937 rng(42);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good choice. Chosen by a fair dice roll, I assume?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah. It's the result of a certain long-running computation to answer a question that I can't quite remember anymore but seemed ultimately important.

@laanwj laanwj merged commit 5eaaa83 into bitcoin:master Oct 18, 2016
laanwj added a commit that referenced this pull request Oct 18, 2016
5eaaa83 Kill insecure_random and associated global state (Wladimir J. van der Laan)
codablock pushed a commit to codablock/dash that referenced this pull request Jan 12, 2018
5eaaa83 Kill insecure_random and associated global state (Wladimir J. van der Laan)
andvgal pushed a commit to energicryptocurrency/gen2-energi that referenced this pull request Jan 6, 2019
5eaaa83 Kill insecure_random and associated global state (Wladimir J. van der Laan)
zkbot added a commit to zcash/zcash that referenced this pull request Jan 24, 2020
Micro-benchmarking framework part 1

Cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#6733
- bitcoin/bitcoin#6770
- bitcoin/bitcoin#6892
  - Excluding changes to `src/policy/policy.h` which we don't have yet.
- bitcoin/bitcoin#7934
  - Just the benchmark, not the performance improvements.
- bitcoin/bitcoin#8039
- bitcoin/bitcoin#8107
- bitcoin/bitcoin#8115
- bitcoin/bitcoin#8914
  - Required resolving several merge conflicts in code that had been refactored upstream. The changes were simple enough that I decided it was okay to impose merge conflicts on pulling in those refactors later.
- bitcoin/bitcoin#9200
- bitcoin/bitcoin#9202
  - Adds support for measuring CPU cycles, which is later removed in an upstream PR after the refactor. I am including it to reduce future merge conflicts.
- bitcoin/bitcoin#9281
  - Only changes to `src/bench/bench.cpp`
- bitcoin/bitcoin#9498
- bitcoin/bitcoin#9712
- bitcoin/bitcoin#9547
- bitcoin/bitcoin#9505
  - Just the benchmark, not the performance improvements.
- bitcoin/bitcoin#9792
  - Just the benchmark, not the performance improvements.
- bitcoin/bitcoin#10272
- bitcoin/bitcoin#10395
  - Only changes to `src/bench/`
- bitcoin/bitcoin#10735
  - Only changes to `src/bench/base58.cpp`
- bitcoin/bitcoin#10963
- bitcoin/bitcoin#11303
  - Only the benchmark backend change.
- bitcoin/bitcoin#11562
- bitcoin/bitcoin#11646
- bitcoin/bitcoin#11654

This pulls in all changes to the micro-benchmark framework prior to December 2017, when it was rewritten. The rewrite depends on other upstream PRs we have not pulled in yet.

This does not pull in all benchmarks prior to December 2017. It leaves out benchmarks that either test code we do not have yet (except for the `FastRandomContext` refactor, which I decided to pull in), or would require rewrites to work with our changes to the codebase.
furszy added a commit to PIVX-Project/PIVX that referenced this pull request Jan 25, 2021
b886a4c Fix header guards using reserved identifiers (Dan Raviv)
b389b3f speed up Unserialize_impl for prevector (Akio Nakamura)
13d2102 Minimal fix to slow prevector tests as stopgap measure (Jeremy Rubin)

Pull request description:

  Backports bitcoin#12324.
  The `DeserializeAndCheckBlock` benchmark (introduced in #2146) shows a speedup of about 4% (not as much as the upstream PR, due to the optimizations already included in #2083).

  Cherry-picks also
  - bitcoin#8671 (with minimal changes to the random context, due to bitcoin#8914 and bitcoin#9792 being already ported out of order).
  - bitcoin#11151

ACKs for top commit:
  Fuzzbawls:
    utACK b886a4c
  furszy:
    utACK b886a4c and merging..

Tree-SHA512: f5de40e5acfb0b875d413d8995d71dd90489730fe4853f0be03d76a1c44ec95eaeb28c0c40d8e91906f23529ad26501bda4f9779ce466cd8603ed97f1662ca98
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants