Skip to content

Commit

Permalink
Merge pull request #2446 from brave/riastradh-4435-exponrate
Browse files Browse the repository at this point in the history
Implement and use exponentially/geometrically distributed delays.
  • Loading branch information
riastradh-brave authored May 31, 2019
2 parents bbdbfc2 + 653f132 commit 90b3163
Show file tree
Hide file tree
Showing 18 changed files with 431 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
Expand Down
2 changes: 2 additions & 0 deletions test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ test("brave_unit_tests") {
"//brave/components/omnibox/browser/topsites_provider_unittest.cc",
"//brave/components/rappor/log_uploader_unittest.cc",
"//brave/third_party/libaddressinput/chromium/chrome_metadata_source_unittest.cc",
"//brave/vendor/brave_base/random_unittest.cc",
"//chrome/common/importer/mock_importer_bridge.cc",
"//chrome/common/importer/mock_importer_bridge.h",
"../browser/importer/chrome_profile_lock_unittest.cc",
Expand Down Expand Up @@ -189,6 +190,7 @@ test("brave_unit_tests") {
"//brave/components/brave_ads/browser:testutil",
"//brave/components/brave_sync:testutil",
"//brave/vendor/bat-native-rapidjson",
"//brave/vendor/brave_base",
"//chrome:browser_dependencies",
"//chrome:child_dependencies",
"//chrome/test:test_support",
Expand Down
1 change: 1 addition & 0 deletions vendor/bat-native-ads/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,6 @@ source_set("ads") {
"//url",
rebase_path("bat-native-usermodel", dep_base),
rebase_path("bat-native-rapidjson", dep_base),
rebase_path("brave_base", dep_base),
]
}
16 changes: 10 additions & 6 deletions vendor/bat-native-ads/src/bat/ads/internal/ads_serve.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include "bat/ads/internal/bundle.h"
#include "bat/ads/internal/logging.h"

#include "base/rand_util.h"
#include "base/time/time.h"
#include "brave_base/random.h"

using std::placeholders::_1;
using std::placeholders::_2;
Expand Down Expand Up @@ -125,9 +125,13 @@ void AdsServe::UpdateNextCatalogCheck() {
ping = bundle_->GetCatalogPing();
}

// Add randomized delay so that the Ad server can't correlate users by timing
auto rand_delay = base::RandInt(0, ping / 10);
next_catalog_check_timestamp_in_seconds = ping + rand_delay;
// Choose a geometrically distributed number of seconds so that from
// the server's perspective, at any given time, every client has the
// same distribution on when its next check will be, so knowing
// which client made the last one when reveals nothing about which
// client will make the next one.
auto rand_delay = brave_base::random::Geometric(ping);
next_catalog_check_timestamp_in_seconds = rand_delay;

ads_->StartCollectingActivity(next_catalog_check_timestamp_in_seconds);
}
Expand Down Expand Up @@ -204,8 +208,8 @@ void AdsServe::RetryDownloadingCatalog() {
next_retry_start_timer_in_ *= 2;
}

auto rand_delay = base::RandInt(0, next_retry_start_timer_in_ / 10);
next_retry_start_timer_in_ += rand_delay;
auto rand_delay = brave_base::random::Geometric(next_retry_start_timer_in_);
next_retry_start_timer_in_ = rand_delay;

ads_->StartCollectingActivity(next_retry_start_timer_in_);
}
Expand Down
1 change: 1 addition & 0 deletions vendor/bat-native-confirmations/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ source_set("bat-native-confirmations") {
rebase_path("bat-native-ledger:headers", dep_base),
rebase_path("bat-native-tweetnacl:tweetnacl", dep_base),
rebase_path("challenge_bypass_ristretto_ffi", dep_base),
rebase_path("brave_base", dep_base),
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
#include "bat/confirmations/internal/unblinded_tokens.h"
#include "bat/confirmations/internal/time.h"

#include "base/rand_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/time/time.h"
#include "brave_base/random.h"

#include "third_party/re2/src/re2/re2.h"

Expand Down Expand Up @@ -967,13 +967,13 @@ uint64_t ConfirmationsImpl::CalculateTokenRedemptionTimeInSeconds() {
uint64_t start_timer_in;
if (now_in_seconds >= next_token_redemption_date_in_seconds_) {
// Browser was launched after the token redemption date
start_timer_in = base::RandInt(0, 1 * base::Time::kSecondsPerMinute);
start_timer_in = 1 * base::Time::kSecondsPerMinute;
} else {
start_timer_in = next_token_redemption_date_in_seconds_ - now_in_seconds;
}

auto rand_delay = base::RandInt(0, start_timer_in / 10);
start_timer_in += rand_delay;
auto rand_delay = brave_base::random::Geometric(start_timer_in);
start_timer_in = rand_delay;

return start_timer_in;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
#include "bat/confirmations/internal/confirmations_impl.h"
#include "bat/confirmations/internal/unblinded_tokens.h"
#include "bat/confirmations/internal/redeem_payment_tokens_request.h"

#include "base/rand_util.h"
#include "brave_base/random.h"

using std::placeholders::_1;
using std::placeholders::_2;
Expand All @@ -23,6 +22,7 @@ PayoutTokens::PayoutTokens(
ConfirmationsClient* confirmations_client,
UnblindedTokens* unblinded_payment_tokens) :
next_retry_start_timer_in_(0),
backoff_count_(0),
confirmations_(confirmations),
confirmations_client_(confirmations_client),
unblinded_payment_tokens_(unblinded_payment_tokens) {
Expand All @@ -39,6 +39,8 @@ void PayoutTokens::Payout(const WalletInfo& wallet_info) {

BLOG(INFO) << "Payout";

backoff_count_ = 0; // reset exponential backoff

wallet_info_ = WalletInfo(wallet_info);

RedeemPaymentTokens();
Expand Down Expand Up @@ -137,14 +139,14 @@ void PayoutTokens::ScheduleNextPayout() const {
void PayoutTokens::RetryNextPayout() {
BLOG(INFO) << "Retry next payout";

if (next_retry_start_timer_in_ == 0) {
next_retry_start_timer_in_ = 2 * base::Time::kSecondsPerMinute;
} else {
next_retry_start_timer_in_ *= 2;
}
next_retry_start_timer_in_ = 2 * base::Time::kSecondsPerMinute;
// Overflow happens only if we have already backed off so many times
// our expected waiting time is longer than the lifetime of the
// universe.
next_retry_start_timer_in_ <<= backoff_count_++;

auto rand_delay = base::RandInt(0, next_retry_start_timer_in_ / 10);
next_retry_start_timer_in_ += rand_delay;
auto rand_delay = brave_base::random::Geometric(next_retry_start_timer_in_);
next_retry_start_timer_in_ = rand_delay;

confirmations_->StartPayingOutRedeemedTokens(next_retry_start_timer_in_);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class PayoutTokens {

void ScheduleNextPayout() const;
uint64_t next_retry_start_timer_in_;
unsigned backoff_count_;
void RetryNextPayout();

ConfirmationsImpl* confirmations_; // NOT OWNED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
#include "base/logging.h"
#include "base/guid.h"
#include "base/json/json_reader.h"
#include "base/rand_util.h"
#include "base/values.h"
#include "brave_base/random.h"

using std::placeholders::_1;
using std::placeholders::_2;
Expand Down Expand Up @@ -444,8 +444,8 @@ void RedeemToken::ScheduleNextRetryForFailedConfirmations() const {

uint64_t RedeemToken::CalculateTimerForNextRetryForFailedConfirmations() const {
auto start_timer_in = kRetryFailedConfirmationsAfterSeconds;
auto rand_delay = base::RandInt(0, start_timer_in / 10);
start_timer_in += rand_delay;
auto rand_delay = brave_base::random::Geometric(start_timer_in);
start_timer_in = rand_delay;

return start_timer_in;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "bat/confirmations/internal/get_signed_tokens_request.h"

#include "base/logging.h"
#include "base/rand_util.h"
#include "base/json/json_reader.h"

using std::placeholders::_1;
Expand Down
1 change: 1 addition & 0 deletions vendor/bat-native-ledger/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ source_set("ledger") {
rebase_path("bip39wally-core-native:bip39wally-core", dep_base),
rebase_path("bat-native-tweetnacl:tweetnacl", dep_base),
rebase_path("bat-native-rapidjson", dep_base),
rebase_path("brave_base", dep_base),
]

public_deps = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "bat/ledger/internal/ledger_impl.h"
#include "bat/ledger/internal/rapidjson_bat_helper.h"
#include "net/http/http_status_code.h"
#include "brave_base/random.h"

using std::placeholders::_1;
using std::placeholders::_2;
Expand Down Expand Up @@ -1603,7 +1604,7 @@ void BatContribution::SetReconcileTimer() {

void BatContribution::SetTimer(uint32_t* timer_id, uint64_t start_timer_in) {
if (start_timer_in == 0) {
start_timer_in = braveledger_bat_helper::getRandomValue(10, 60);
start_timer_in = brave_base::random::Geometric(45);
}

BLOG(ledger_, ledger::LogLevel::LOG_INFO) <<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2642,15 +2642,6 @@ uint8_t niceware_mnemonic_to_bytes(
return 0;
}

uint64_t getRandomValue(uint8_t min, uint8_t max) {
std::random_device seeder;
const auto seed = seeder.entropy() ? seeder() : time(nullptr);
std::mt19937 eng(static_cast<std::mt19937::result_type> (seed));
std::uniform_int_distribution <> dist(min, max);

return dist(eng);
}

void saveToJson(JsonWriter* writer, const ledger::VisitData& visitData) {
writer->StartObject();

Expand Down
2 changes: 0 additions & 2 deletions vendor/bat-native-ledger/src/bat/ledger/internal/bat_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,6 @@ uint8_t niceware_mnemonic_to_bytes(
size_t* written,
std::vector<std::string> wordDictionary);

uint64_t getRandomValue(uint8_t min, uint8_t max);

bool HasSameDomainAndPath(
const std::string& url,
const std::string& to_match,
Expand Down
22 changes: 22 additions & 0 deletions vendor/brave_base/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

config("external_config") {
include_dirs = [ ".." ]
}

source_set("brave_base") {
public_configs = [ ":external_config" ]
configs += [ ":external_config" ]

sources = [
"random.cc",
"random.h",
]

deps = [
"//base",
"//crypto",
]
}
125 changes: 125 additions & 0 deletions vendor/brave_base/random.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* Copyright (c) 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "brave_base/random.h"

#include <cmath>

#include "base/bits.h"
#include "crypto/random.h"

namespace brave_base {
namespace random {

uint64_t Uniform64() {
uint64_t x;

crypto::RandBytes(&x, sizeof x);

return x;
}

// Correct floating-point uniform [0,1] sampler which gives exactly
// the correct weight to every floating-point number in [0,1],
// i.e. the Lebesgue measure of the set of real numbers that is
// rounded to it.
//
// In principle this algorithm could return any floating-point number
// in [0,1], but in practice it cannot return 0 because the
// probability is 2^-1075; consequently you can reliably pass the
// result to, e.g., log, and be guaranteed to get a finite result.
//
// In contrast, if we simply divided a uniform random 53-bit or 64-bit
// integer by 2^53 or 2^64, the result would _not_ be guaranteed to be
// nonzero, _and_ it would exclude the result 1, which it should
// return with probability 2^-54.
double Uniform_01() {
uint64_t e, x, u;

// Draw an exponent with geometric distribution.
e = 0;
do {
if ((x = Uniform64()) != 0)
break;
e += 64;
} while (e < 1088);

// Count the remaining leading zero bits to finish up the geometric
// draw.
//
// If we stopped at e >= 1088, this means our RNG is broken. In
// that case, we could just as well abort the process. But it is
// also safe to call CountLeadingZeroBits at this point; it will
// just return 64, and the exponent will be even more improbably
// larger.
e += base::bits::CountLeadingZeroBits(x);

u = Uniform64();

return deterministic::Uniform_01(e, u);
}

// Nondeterministic distribution samplers. These should call
// Uniform64 and Uniform_01 only, and pass them on to a deterministic
// transform in order to facilitate automatic testing.

double Exponential(double rate) {
uint64_t s = Uniform64();
double p0 = Uniform_01();
return deterministic::Exponential(s, p0, rate);
}

uint64_t Geometric(double period) {
uint64_t s = Uniform64();
double p0 = Uniform_01();
return deterministic::Geometric(s, p0, period);
}

namespace deterministic {

double StdExponential(uint64_t s, double p0) {
// We want to evaluate log(p) for p near 0, and log1p(-p) for p near
// 1. We will decide which half of the interval we're lying in by a
// coin toss, and then scale p0 appropriately.
p0 *= 0.5;
return ((s & 1) == 0) ? -log(p0) : -log1p(-p0);
}

double Exponential(uint64_t s, double p0, double rate) {
return StdExponential(s, p0)/rate;
}

uint64_t Geometric(uint64_t s, double p0, double period) {
return floor(StdExponential(s, p0)*period);
}

// If e has geometric distribution and u has uniform distribution,
// Uniform_01(e, u) has uniform distribution in [0, 1].
double Uniform_01(uint64_t e, uint64_t u) {
double s;

// Pick a normalized odd significand in (2^63, 2^64). Choosing an
// odd significand breaks ties, which occur with Lebesgue measure
// zero in the reals but with nonzero probability in any finite
// truncation of the binary expansion.
u |= 0x8000000000000001ULL;

// Round to double in [2^63, 2^64].
s = static_cast<double>(u);

// Scale into [1/2, 1].
s *= ldexp(1, -64);

// Apply the exponent. This is a separate step, and done with
// multiplication, because some platforms have broken ldexp.
s *= ldexp(1, -e);

return s;
}

} // namespace deterministic

} // namespace random
} // namespace brave_base
Loading

0 comments on commit 90b3163

Please sign in to comment.