From 16f90ba80f7997cd99563017f6d4d872a1844c7c Mon Sep 17 00:00:00 2001 From: Terry Mancey Date: Thu, 14 Mar 2019 03:41:32 +0000 Subject: [PATCH] Tokens that fail to redeem due to network errors should be added to a queue and retried --- vendor/bat-native-ads/BUILD.gn | 1 + .../include/bat/ads/confirmation_type.h | 40 +- .../src/bat/ads/confirmation_type.cc | 69 ++++ .../src/bat/ads/internal/ads_impl.cc | 29 +- .../src/bat/ads/notification_info.cc | 40 +- vendor/bat-native-confirmations/BUILD.gn | 4 + .../bat/confirmations/confirmation_type.h | 40 +- .../bat/confirmations/confirmation_type.cc | 69 ++++ .../internal/confirmation_info.cc | 30 ++ .../internal/confirmation_info.h | 37 ++ .../internal/confirmations_impl.cc | 373 +++++++++++++++--- .../internal/confirmations_impl.h | 24 +- .../internal/create_confirmation_request.cc | 29 +- .../confirmations/internal/redeem_token.cc | 262 +++++++----- .../bat/confirmations/internal/redeem_token.h | 28 +- .../confirmations/internal/security_helper.cc | 5 +- .../confirmations/internal/static_values.h | 3 + .../internal/unblinded_tokens.cc | 6 +- .../src/bat/ledger/internal/ledger_impl.cc | 3 +- 19 files changed, 792 insertions(+), 300 deletions(-) create mode 100644 vendor/bat-native-ads/src/bat/ads/confirmation_type.cc create mode 100644 vendor/bat-native-confirmations/src/bat/confirmations/confirmation_type.cc create mode 100644 vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.cc create mode 100644 vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.h diff --git a/vendor/bat-native-ads/BUILD.gn b/vendor/bat-native-ads/BUILD.gn index a23bd61785d6..fe37ab993dbc 100644 --- a/vendor/bat-native-ads/BUILD.gn +++ b/vendor/bat-native-ads/BUILD.gn @@ -83,6 +83,7 @@ source_set("ads") { "src/bat/ads/bundle_state.cc", "src/bat/ads/client_info.cc", "src/bat/ads/issuer_info.cc", + "src/bat/ads/confirmation_type.cc", "src/bat/ads/issuers_info.cc", "src/bat/ads/notification_info.cc", "src/bat/ads/internal/ads_impl.cc", diff --git a/vendor/bat-native-ads/include/bat/ads/confirmation_type.h b/vendor/bat-native-ads/include/bat/ads/confirmation_type.h index d59834388877..46c18faf47e5 100644 --- a/vendor/bat-native-ads/include/bat/ads/confirmation_type.h +++ b/vendor/bat-native-ads/include/bat/ads/confirmation_type.h @@ -6,19 +6,37 @@ #ifndef BAT_ADS_CONFIRMATION_TYPE_H_ #define BAT_ADS_CONFIRMATION_TYPE_H_ +#include + namespace ads { -static char kConfirmationTypeClick[] = "click"; -static char kConfirmationTypeDismiss[] = "dismiss"; -static char kConfirmationTypeView[] = "view"; -static char kConfirmationTypeLanded[] = "landed"; - -enum class ConfirmationType { - UNKNOWN, - CLICK, - DISMISS, - VIEW, - LANDED +class ConfirmationType { + public: + enum Value : int { + UNKNOWN, + CLICK, + DISMISS, + VIEW, + LANDED + }; + + ConfirmationType() = default; + + // Allow implicit conversion of the enum value to this wrapper + constexpr ConfirmationType(const Value& value) : value_(value) {} // NOLINT + + explicit ConfirmationType(const std::string& value); + + bool IsSupported() const; + + int value() const; + operator std::string() const; + + bool operator==(ConfirmationType type) const; + bool operator!=(ConfirmationType type) const; + + private: + Value value_; }; } // namespace ads diff --git a/vendor/bat-native-ads/src/bat/ads/confirmation_type.cc b/vendor/bat-native-ads/src/bat/ads/confirmation_type.cc new file mode 100644 index 000000000000..33cf42b56df1 --- /dev/null +++ b/vendor/bat-native-ads/src/bat/ads/confirmation_type.cc @@ -0,0 +1,69 @@ +/* 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 "bat/ads/confirmation_type.h" + +namespace ads { + +static const char kConfirmationTypeClick[] = "click"; +static const char kConfirmationTypeDismiss[] = "dismiss"; +static const char kConfirmationTypeView[] = "view"; +static const char kConfirmationTypeLanded[] = "landed"; + +ConfirmationType::ConfirmationType(const std::string& value) { + if (value == kConfirmationTypeClick) { + value_ = CLICK; + } else if (value == kConfirmationTypeDismiss) { + value_ = DISMISS; + } else if (value == kConfirmationTypeView) { + value_ = VIEW; + } else if (value == kConfirmationTypeLanded) { + value_ = LANDED; + } else { + value_ = UNKNOWN; + } +} + +bool ConfirmationType::IsSupported() const { + return value_ != UNKNOWN; +} + +int ConfirmationType::value() const { + return value_; +} + +ConfirmationType::operator std::string() const { + switch (value_) { + case UNKNOWN: { + return ""; + } + + case CLICK: { + return kConfirmationTypeClick; + } + + case DISMISS: { + return kConfirmationTypeDismiss; + } + + case VIEW: { + return kConfirmationTypeView; + } + + case LANDED: { + return kConfirmationTypeLanded; + } + } +} + +bool ConfirmationType::operator==(ConfirmationType type) const { + return value_ == type.value_; +} + +bool ConfirmationType::operator!=(ConfirmationType type) const { + return value_ != type.value_; +} + +} // namespace ads diff --git a/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc b/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc index 673c859f4bea..8b513f7fd7e5 100644 --- a/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc +++ b/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc @@ -1289,35 +1289,8 @@ void AdsImpl::GenerateAdReportingConfirmationEvent( writer.String("notificationId"); writer.String(info.uuid.c_str()); - std::string type; - switch (info.type) { - case ConfirmationType::UNKNOWN: { - DCHECK(false) << "Invalid confirmation type"; - break; - } - - case ConfirmationType::CLICK: { - type = kConfirmationTypeClick; - break; - } - - case ConfirmationType::DISMISS: { - type = kConfirmationTypeDismiss; - break; - } - - case ConfirmationType::VIEW: { - type = kConfirmationTypeView; - break; - } - - case ConfirmationType::LANDED: { - type = kConfirmationTypeLanded; - break; - } - } - writer.String("notificationType"); + auto type = std::string(info.type); writer.String(type.c_str()); writer.EndObject(); diff --git a/vendor/bat-native-ads/src/bat/ads/notification_info.cc b/vendor/bat-native-ads/src/bat/ads/notification_info.cc index 31b485cc5c2f..c2b2559e94b7 100644 --- a/vendor/bat-native-ads/src/bat/ads/notification_info.cc +++ b/vendor/bat-native-ads/src/bat/ads/notification_info.cc @@ -78,17 +78,7 @@ Result NotificationInfo::FromJson( if (document.HasMember("confirmation_type")) { std::string confirmation_type = document["confirmation_type"].GetString(); - if (confirmation_type == kConfirmationTypeClick) { - type = ConfirmationType::CLICK; - } else if (confirmation_type == kConfirmationTypeDismiss) { - type = ConfirmationType::DISMISS; - } else if (confirmation_type == kConfirmationTypeView) { - type = ConfirmationType::VIEW; - } else if (confirmation_type == kConfirmationTypeLanded) { - type = ConfirmationType::LANDED; - } else { - type = ConfirmationType::UNKNOWN; - } + type = ConfirmationType(confirmation_type); } return SUCCESS; @@ -116,32 +106,8 @@ void SaveToJson(JsonWriter* writer, const NotificationInfo& info) { writer->String(info.uuid.c_str()); writer->String("confirmation_type"); - switch (info.type) { - case ConfirmationType::UNKNOWN: { - writer->String(""); - break; - } - - case ConfirmationType::CLICK: { - writer->String(kConfirmationTypeClick); - break; - } - - case ConfirmationType::DISMISS: { - writer->String(kConfirmationTypeDismiss); - break; - } - - case ConfirmationType::VIEW: { - writer->String(kConfirmationTypeView); - break; - } - - case ConfirmationType::LANDED: { - writer->String(kConfirmationTypeLanded); - break; - } - } + auto type = std::string(info.type); + writer->String(type.c_str()); writer->EndObject(); } diff --git a/vendor/bat-native-confirmations/BUILD.gn b/vendor/bat-native-confirmations/BUILD.gn index 4e6a570c044a..c3509f74c7ba 100644 --- a/vendor/bat-native-confirmations/BUILD.gn +++ b/vendor/bat-native-confirmations/BUILD.gn @@ -37,6 +37,7 @@ source_set("bat-native-confirmations") { ] sources = [ + "include/bat/confirmations/confirmation_type.h", "include/bat/confirmations/confirmations_client.h", "include/bat/confirmations/confirmations.h", "include/bat/confirmations/export.h", @@ -44,6 +45,7 @@ source_set("bat-native-confirmations") { "include/bat/confirmations/issuers_info.h", "include/bat/confirmations/notification_info.h", "include/bat/confirmations/wallet_info.h", + "src/bat/confirmations/confirmation_type.cc", "src/bat/confirmations/confirmations.cc", "src/bat/confirmations/issuer_info.cc", "src/bat/confirmations/issuers_info.cc", @@ -51,6 +53,8 @@ source_set("bat-native-confirmations") { "src/bat/confirmations/wallet_info.cc", "src/bat/confirmations/internal/ads_serve_helper.cc", "src/bat/confirmations/internal/ads_serve_helper.h", + "src/bat/confirmations/internal/confirmation_info.cc", + "src/bat/confirmations/internal/confirmation_info.h", "src/bat/confirmations/internal/confirmations_impl.cc", "src/bat/confirmations/internal/confirmations_impl.h", "src/bat/confirmations/internal/create_confirmation_request.cc", diff --git a/vendor/bat-native-confirmations/include/bat/confirmations/confirmation_type.h b/vendor/bat-native-confirmations/include/bat/confirmations/confirmation_type.h index 0bdf524e0e1f..317bd2ebf482 100644 --- a/vendor/bat-native-confirmations/include/bat/confirmations/confirmation_type.h +++ b/vendor/bat-native-confirmations/include/bat/confirmations/confirmation_type.h @@ -6,19 +6,37 @@ #ifndef BAT_CONFIRMATIONS_CONFIRMATION_TYPE_H_ #define BAT_CONFIRMATIONS_CONFIRMATION_TYPE_H_ +#include + namespace confirmations { -static char kConfirmationTypeClick[] = "click"; -static char kConfirmationTypeDismiss[] = "dismiss"; -static char kConfirmationTypeView[] = "view"; -static char kConfirmationTypeLanded[] = "landed"; - -enum class ConfirmationType { - UNKNOWN, - CLICK, - DISMISS, - VIEW, - LANDED +class ConfirmationType { + public: + enum Value : int { + UNKNOWN, + CLICK, + DISMISS, + VIEW, + LANDED + }; + + ConfirmationType() = default; + + // Allow implicit conversion of the enum value to this wrapper + constexpr ConfirmationType(const Value& value) : value_(value) {} // NOLINT + + explicit ConfirmationType(const std::string& value); + + bool IsSupported() const; + + int value() const; + operator std::string() const; + + bool operator==(ConfirmationType type) const; + bool operator!=(ConfirmationType type) const; + + private: + Value value_; }; } // namespace confirmations diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/confirmation_type.cc b/vendor/bat-native-confirmations/src/bat/confirmations/confirmation_type.cc new file mode 100644 index 000000000000..eba081133836 --- /dev/null +++ b/vendor/bat-native-confirmations/src/bat/confirmations/confirmation_type.cc @@ -0,0 +1,69 @@ +/* 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 "bat/confirmations/confirmation_type.h" + +namespace confirmations { + +static const char kConfirmationTypeClick[] = "click"; +static const char kConfirmationTypeDismiss[] = "dismiss"; +static const char kConfirmationTypeView[] = "view"; +static const char kConfirmationTypeLanded[] = "landed"; + +ConfirmationType::ConfirmationType(const std::string& value) { + if (value == kConfirmationTypeClick) { + value_ = CLICK; + } else if (value == kConfirmationTypeDismiss) { + value_ = DISMISS; + } else if (value == kConfirmationTypeView) { + value_ = VIEW; + } else if (value == kConfirmationTypeLanded) { + value_ = LANDED; + } else { + value_ = UNKNOWN; + } +} + +bool ConfirmationType::IsSupported() const { + return value_ != UNKNOWN; +} + +int ConfirmationType::value() const { + return value_; +} + +ConfirmationType::operator std::string() const { + switch (value_) { + case UNKNOWN: { + return ""; + } + + case CLICK: { + return kConfirmationTypeClick; + } + + case DISMISS: { + return kConfirmationTypeDismiss; + } + + case VIEW: { + return kConfirmationTypeView; + } + + case LANDED: { + return kConfirmationTypeLanded; + } + } +} + +bool ConfirmationType::operator==(ConfirmationType type) const { + return value_ == type.value_; +} + +bool ConfirmationType::operator!=(ConfirmationType type) const { + return value_ != type.value_; +} + +} // namespace confirmations diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.cc b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.cc new file mode 100644 index 000000000000..3db4ff19f731 --- /dev/null +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.cc @@ -0,0 +1,30 @@ +/* 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 "bat/confirmations/internal/confirmation_info.h" + +namespace confirmations { + +ConfirmationInfo::ConfirmationInfo() : + id(""), + creative_instance_id(""), + type(ConfirmationType::UNKNOWN), + token_info(TokenInfo()), + payment_token(nullptr), + blinded_payment_token(nullptr), + credential("") {} + +ConfirmationInfo::ConfirmationInfo(const ConfirmationInfo& info) : + id(info.id), + creative_instance_id(info.creative_instance_id), + type(info.type), + token_info(info.token_info), + payment_token(info.payment_token), + blinded_payment_token(info.blinded_payment_token), + credential(info.credential) {} + +ConfirmationInfo::~ConfirmationInfo() {} + +} // namespace confirmations diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.h b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.h new file mode 100644 index 000000000000..00df164845e5 --- /dev/null +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmation_info.h @@ -0,0 +1,37 @@ +/* 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/. */ + +#ifndef BAT_CONFIRMATIONS_INTERNAL_CONFIRMATION_INFO_H_ +#define BAT_CONFIRMATIONS_INTERNAL_CONFIRMATION_INFO_H_ + +#include + +#include "bat/confirmations/confirmation_type.h" +#include "bat/confirmations/internal/token_info.h" + +#include "wrapper.hpp" // NOLINT + +using challenge_bypass_ristretto::Token; +using challenge_bypass_ristretto::BlindedToken; + +namespace confirmations { + +struct ConfirmationInfo { + ConfirmationInfo(); + explicit ConfirmationInfo(const ConfirmationInfo& info); + ~ConfirmationInfo(); + + std::string id; + std::string creative_instance_id; + ConfirmationType type; + TokenInfo token_info; + Token payment_token; + BlindedToken blinded_payment_token; + std::string credential; +}; + +} // namespace confirmations + +#endif // BAT_CONFIRMATIONS_INTERNAL_CONFIRMATION_INFO_H_ diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.cc b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.cc index 7b268a473bba..c01abba395dc 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.cc +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.cc @@ -31,6 +31,7 @@ namespace confirmations { ConfirmationsImpl::ConfirmationsImpl( ConfirmationsClient* confirmations_client) : is_initialized_(false), + retry_failed_confirmations_timer_id_(0), unblinded_tokens_(std::make_unique(this)), unblinded_payment_tokens_(std::make_unique(this)), retry_getting_signed_tokens_timer_id_(0), @@ -50,6 +51,7 @@ ConfirmationsImpl::~ConfirmationsImpl() { BLOG(INFO) << "Deinitializing Confirmations"; StopRetryingToGetRefillSignedTokens(); + StopRetryingFailedConfirmations(); StopPayingOutRedeemedTokens(); } @@ -82,6 +84,8 @@ void ConfirmationsImpl::CheckReady() { auto start_timer_in = CalculateTokenRedemptionTimeInSeconds(); StartPayingOutRedeemedTokens(start_timer_in); + RetryFailedConfirmations(); + RefillTokensIfNecessary(); } @@ -102,6 +106,10 @@ std::string ConfirmationsImpl::ToJSON() const { dictionary.SetKey("next_token_redemption_date_in_seconds", base::Value( std::to_string(next_token_redemption_date_in_seconds_))); + // Confirmations + auto confirmations = GetConfirmationsAsDictionary(confirmations_); + dictionary.SetKey("confirmations", base::Value(std::move(confirmations))); + // Transaction history auto transaction_history = GetTransactionHistoryAsDictionary(transaction_history_); @@ -146,6 +154,52 @@ base::Value ConfirmationsImpl::GetCatalogIssuersAsDictionary( return dictionary; } +base::Value ConfirmationsImpl::GetConfirmationsAsDictionary( + const std::vector& confirmations) const { + base::Value dictionary(base::Value::Type::DICTIONARY); + + base::Value list(base::Value::Type::LIST); + for (const auto& confirmation : confirmations) { + base::Value confirmation_dictionary(base::Value::Type::DICTIONARY); + + confirmation_dictionary.SetKey("id", base::Value(confirmation.id)); + + confirmation_dictionary.SetKey("creative_instance_id", + base::Value(confirmation.creative_instance_id)); + + std::string type = std::string(confirmation.type); + confirmation_dictionary.SetKey("type", base::Value(type)); + + base::Value token_info_dictionary(base::Value::Type::DICTIONARY); + auto unblinded_token_base64 = + confirmation.token_info.unblinded_token.encode_base64(); + token_info_dictionary.SetKey("unblinded_token", + base::Value(unblinded_token_base64)); + auto public_key = confirmation.token_info.public_key; + token_info_dictionary.SetKey("public_key", base::Value(public_key)); + confirmation_dictionary.SetKey("token_info", + base::Value(std::move(token_info_dictionary))); + + auto payment_token_base64 = confirmation.payment_token.encode_base64(); + confirmation_dictionary.SetKey("payment_token", + base::Value(payment_token_base64)); + + auto blinded_payment_token_base64 = + confirmation.blinded_payment_token.encode_base64(); + confirmation_dictionary.SetKey("blinded_payment_token", + base::Value(blinded_payment_token_base64)); + + confirmation_dictionary.SetKey("credential", + base::Value(confirmation.credential)); + + list.GetList().push_back(std::move(confirmation_dictionary)); + } + + dictionary.SetKey("failed_confirmations", base::Value(std::move(list))); + + return dictionary; +} + base::Value ConfirmationsImpl::GetTransactionHistoryAsDictionary( const std::vector& transaction_history) const { base::Value dictionary(base::Value::Type::DICTIONARY); @@ -194,6 +248,10 @@ bool ConfirmationsImpl::FromJSON(const std::string& json) { << json; } + if (!GetConfirmationsFromJSON(dictionary)) { + BLOG(WARNING) << "Failed to get confirmations from JSON: " << json; + } + if (!GetTransactionHistoryFromJSON(dictionary)) { BLOG(WARNING) << "Failed to get transaction history from JSON: " << json; } @@ -298,6 +356,170 @@ bool ConfirmationsImpl::GetNextTokenRedemptionDateInSecondsFromJSON( return true; } +bool ConfirmationsImpl::GetConfirmationsFromJSON( + base::DictionaryValue* dictionary) { + auto* confirmations_value = dictionary->FindKey("confirmations"); + if (!confirmations_value) { + return false; + } + + base::DictionaryValue* confirmations_dictionary; + if (!confirmations_value->GetAsDictionary( + &confirmations_dictionary)) { + return false; + } + + std::vector confirmations; + if (!GetConfirmationsFromDictionary(confirmations_dictionary, + &confirmations)) { + return false; + } + + confirmations_ = confirmations; + + return true; +} + +bool ConfirmationsImpl::GetConfirmationsFromDictionary( + base::DictionaryValue* dictionary, + std::vector* confirmations) { + DCHECK(dictionary); + DCHECK(confirmations); + + // Confirmations + auto* confirmations_value = dictionary->FindKey("failed_confirmations"); + if (!confirmations_value) { + DCHECK(false) << "Confirmations dictionary missing confirmations"; + return false; + } + + confirmations->clear(); + base::ListValue confirmations_list_value(confirmations_value->GetList()); + for (auto& confirmation_value : confirmations_list_value) { + base::DictionaryValue* confirmation_dictionary; + if (!confirmation_value.GetAsDictionary(&confirmation_dictionary)) { + DCHECK(false) << "Confirmation should be a dictionary"; + continue; + } + + ConfirmationInfo confirmation_info; + + // Id + auto* id_value = confirmation_dictionary->FindKey("id"); + if (id_value) { + confirmation_info.id = id_value->GetString(); + } else { + // Id missing, skip confirmation + DCHECK(false) << "Confirmation missing id"; + continue; + } + + // Creative instance id + auto* creative_instance_id_value = + confirmation_dictionary->FindKey("creative_instance_id"); + if (creative_instance_id_value) { + confirmation_info.creative_instance_id = + creative_instance_id_value->GetString(); + } else { + // Creative instance id missing, skip confirmation + DCHECK(false) << "Confirmation missing creative_instance_id"; + continue; + } + + // Type + auto* type_value = confirmation_dictionary->FindKey("type"); + if (type_value) { + ConfirmationType type(type_value->GetString()); + if (!type.IsSupported()) { + // Unsupported type, skip confirmation + DCHECK(false) << "Unsupported confirmation type: " << std::string(type); + continue; + } + + confirmation_info.type = type; + } else { + // Type missing, skip confirmation + DCHECK(false) << "Confirmation missing type"; + continue; + } + + // Token info + auto* token_info_value = confirmation_dictionary->FindKey("token_info"); + if (!token_info_value) { + DCHECK(false) << "Confirmation missing token_info"; + continue; + } + + base::DictionaryValue* token_info_dictionary; + if (!token_info_value->GetAsDictionary(&token_info_dictionary)) { + DCHECK(false) << "Token info should be a dictionary"; + continue; + } + + auto* unblinded_token_value = + token_info_dictionary->FindKey("unblinded_token"); + if (unblinded_token_value) { + auto unblinded_token_base64 = unblinded_token_value->GetString(); + confirmation_info.token_info.unblinded_token = + UnblindedToken::decode_base64(unblinded_token_base64); + } else { + // Unblinded token missing, skip confirmation + DCHECK(false) << "Token info missing unblinded_token"; + continue; + } + + auto* public_key_value = token_info_dictionary->FindKey("public_key"); + if (public_key_value) { + confirmation_info.token_info.public_key = public_key_value->GetString(); + } else { + // Public key missing, skip confirmation + DCHECK(false) << "Token info missing public_key"; + continue; + } + + // Payment token + auto* payment_token_value = + confirmation_dictionary->FindKey("payment_token"); + if (payment_token_value) { + auto payment_token_base64 = payment_token_value->GetString(); + confirmation_info.payment_token = + Token::decode_base64(payment_token_base64); + } else { + // Payment token missing, skip confirmation + DCHECK(false) << "Confirmation missing payment_token"; + continue; + } + + // Blinded payment token + auto* blinded_payment_token_value = + confirmation_dictionary->FindKey("blinded_payment_token"); + if (blinded_payment_token_value) { + auto blinded_payment_token_base64 = + blinded_payment_token_value->GetString(); + confirmation_info.blinded_payment_token = + BlindedToken::decode_base64(blinded_payment_token_base64); + } else { + // Blinded payment token missing, skip confirmation + DCHECK(false) << "Confirmation missing blinded_payment_token"; + continue; + } + + // Credential + auto* credential_value = confirmation_dictionary->FindKey("credential"); + if (credential_value) { + confirmation_info.credential = credential_value->GetString(); + } else { + // Credential missing, skip confirmation + DCHECK(false) << "Confirmation missing credential"; + continue; + } + + confirmations->push_back(confirmation_info); + } + + return true; +} + bool ConfirmationsImpl::GetTransactionHistoryFromJSON( base::DictionaryValue* dictionary) { auto* transaction_history_value = dictionary->FindKey("transaction_history"); @@ -375,7 +597,8 @@ bool ConfirmationsImpl::GetTransactionHistoryFromDictionary( info.confirmation_type = confirmation_type_value->GetString(); } else { // confirmation type missing, fallback to default - info.confirmation_type = kConfirmationTypeView; + ConfirmationType type(ConfirmationType::VIEW); + info.confirmation_type = std::string(type); } transaction_history->push_back(info); @@ -536,6 +759,37 @@ bool ConfirmationsImpl::IsValidPublicKeyForCatalogIssuers( return true; } +void ConfirmationsImpl::AppendConfirmationToQueue( + const ConfirmationInfo& confirmation_info) { + confirmations_.push_back(confirmation_info); + + SaveState(); +} + +bool ConfirmationsImpl::RemoveConfirmationFromQueue( + const ConfirmationInfo& confirmation_info) { + auto id = confirmation_info.id; + + auto it = std::find_if(confirmations_.begin(), confirmations_.end(), + [=](const ConfirmationInfo& info) { + return (info.id == id); + }); + + if (it == confirmations_.end()) { + return false; + } + + BLOG(INFO) << "Removed " << confirmation_info.creative_instance_id + << " creative instance id for " << std::string(confirmation_info.type) + << " from the confirmation queue"; + + confirmations_.erase(it); + + SaveState(); + + return true; +} + void ConfirmationsImpl::GetTransactionHistory( const uint64_t from_timestamp_in_seconds, const uint64_t to_timestamp_in_seconds, @@ -575,39 +829,13 @@ double ConfirmationsImpl::GetEstimatedRedemptionValue( return estimated_redemption_value; } -void ConfirmationsImpl::AppendTransactionToTransactionHistory( +void ConfirmationsImpl::AppendTransactionToHistory( const double estimated_redemption_value, const ConfirmationType confirmation_type) { TransactionInfo info; info.timestamp_in_seconds = Time::NowInSeconds(); info.estimated_redemption_value = estimated_redemption_value; - - switch (confirmation_type) { - case ConfirmationType::UNKNOWN: { - DCHECK(false) << "Invalid confirmation type"; - break; - } - - case ConfirmationType::CLICK: { - info.confirmation_type = kConfirmationTypeClick; - break; - } - - case ConfirmationType::DISMISS: { - info.confirmation_type = kConfirmationTypeDismiss; - break; - } - - case ConfirmationType::VIEW: { - info.confirmation_type = kConfirmationTypeView; - break; - } - - case ConfirmationType::LANDED: { - info.confirmation_type = kConfirmationTypeLanded; - break; - } - } + info.confirmation_type = std::string(confirmation_type); transaction_history_.push_back(info); @@ -618,38 +846,13 @@ void ConfirmationsImpl::AppendTransactionToTransactionHistory( void ConfirmationsImpl::ConfirmAd(std::unique_ptr info) { BLOG(INFO) << "ConfirmAd:"; - BLOG(INFO) << " creativeSetId: " << info->creative_set_id; + BLOG(INFO) << " creative_set_id: " << info->creative_set_id; BLOG(INFO) << " category: " << info->category; - BLOG(INFO) << " notificationUrl: " << info->url; - BLOG(INFO) << " notificationText: " << info->text; + BLOG(INFO) << " url: " << info->url; + BLOG(INFO) << " text: " << info->text; BLOG(INFO) << " advertiser: " << info->advertiser; BLOG(INFO) << " uuid: " << info->uuid; - switch (info->type) { - case ConfirmationType::UNKNOWN: { - DCHECK(false) << "Invalid confirmation type"; - break; - } - - case ConfirmationType::CLICK: { - BLOG(INFO) << " confirmationType: click"; - break; - } - - case ConfirmationType::DISMISS: { - BLOG(INFO) << " confirmationType: dismiss"; - break; - } - - case ConfirmationType::VIEW: { - BLOG(INFO) << " confirmationType: view"; - break; - } - - case ConfirmationType::LANDED: { - BLOG(INFO) << " confirmationType: landed"; - break; - } - } + BLOG(INFO) << " type: " << std::string(info->type); redeem_token_->Redeem(info->uuid, info->type); } @@ -666,6 +869,9 @@ bool ConfirmationsImpl::OnTimer(const uint32_t timer_id) { if (timer_id == retry_getting_signed_tokens_timer_id_) { RetryGettingRefillSignedTokens(); return true; + } else if (timer_id == retry_failed_confirmations_timer_id_) { + RetryFailedConfirmations(); + return true; } else if (timer_id == payout_redeemed_tokens_timer_id_) { PayoutRedeemedTokens(); return true; @@ -721,6 +927,57 @@ void ConfirmationsImpl::UpdateNextTokenRedemptionDate() { } } +void ConfirmationsImpl::StartRetryingFailedConfirmations( + const uint64_t start_timer_in) { + if (confirmations_.size() == 0) { + BLOG(INFO) << "No failed confirmations to retry"; + return; + } + + StopRetryingFailedConfirmations(); + + confirmations_client_->SetTimer(start_timer_in, + &retry_failed_confirmations_timer_id_); + if (retry_failed_confirmations_timer_id_ == 0) { + BLOG(ERROR) << "Failed to start retrying failed confirmations " + << "due to an invalid timer"; + + return; + } + + BLOG(INFO) << "Start retrying failed confirmations in " << start_timer_in + << " seconds"; +} + +void ConfirmationsImpl::RetryFailedConfirmations() const { + if (confirmations_.size() == 0) { + BLOG(INFO) << "No failed confirmations to retry"; + return; + } + + ConfirmationInfo confirmation_info(confirmations_.front()); + redeem_token_->Redeem(confirmation_info); +} + +void ConfirmationsImpl::StopRetryingFailedConfirmations() { + if (!IsRetryingFailedConfirmations()) { + return; + } + + BLOG(INFO) << "Stopped retrying failed confirmations"; + + confirmations_client_->KillTimer(retry_failed_confirmations_timer_id_); + retry_failed_confirmations_timer_id_ = 0; +} + +bool ConfirmationsImpl::IsRetryingFailedConfirmations() const { + if (retry_failed_confirmations_timer_id_ == 0) { + return false; + } + + return true; +} + void ConfirmationsImpl::StartPayingOutRedeemedTokens( const uint64_t start_timer_in) { StopPayingOutRedeemedTokens(); diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.h b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.h index d045597f8dcf..fb89f38d675c 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.h +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/confirmations_impl.h @@ -16,6 +16,7 @@ #include "bat/confirmations/confirmations_client.h" #include "bat/confirmations/notification_info.h" #include "bat/confirmations/issuers_info.h" +#include "bat/confirmations/internal/confirmation_info.h" #include "base/values.h" @@ -42,12 +43,17 @@ class ConfirmationsImpl : public Confirmations { bool IsValidPublicKeyForCatalogIssuers(const std::string& public_key) const; double GetEstimatedRedemptionValue(const std::string& public_key) const; + // Confirmations + void AppendConfirmationToQueue(const ConfirmationInfo& confirmation_info); + bool RemoveConfirmationFromQueue(const ConfirmationInfo& confirmation_info); + void StartRetryingFailedConfirmations(const uint64_t start_timer_in); + // Transaction history void GetTransactionHistory( const uint64_t from_timestamp_in_seconds, const uint64_t to_timestamp_in_seconds, OnGetTransactionHistoryCallback callback) override; - void AppendTransactionToTransactionHistory( + void AppendTransactionToHistory( const double estimated_redemption_value, const ConfirmationType confirmation_type); @@ -80,6 +86,13 @@ class ConfirmationsImpl : public Confirmations { // Catalog issuers std::map catalog_issuers_; + // Confirmations + uint32_t retry_failed_confirmations_timer_id_; + void RetryFailedConfirmations() const; + void StopRetryingFailedConfirmations(); + bool IsRetryingFailedConfirmations() const; + std::vector confirmations_; + // Transaction history std::vector transaction_history_; @@ -123,6 +136,9 @@ class ConfirmationsImpl : public Confirmations { const std::string& public_key, const std::map& issuers) const; + base::Value GetConfirmationsAsDictionary( + const std::vector& confirmations) const; + base::Value GetTransactionHistoryAsDictionary( const std::vector& transaction_history) const; @@ -138,6 +154,12 @@ class ConfirmationsImpl : public Confirmations { bool GetNextTokenRedemptionDateInSecondsFromJSON( base::DictionaryValue* dictionary); + bool GetConfirmationsFromJSON( + base::DictionaryValue* dictionary); + bool GetConfirmationsFromDictionary( + base::DictionaryValue* dictionary, + std::vector* confirmations); + bool GetTransactionHistoryFromJSON( base::DictionaryValue* dictionary); bool GetTransactionHistoryFromDictionary( diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/create_confirmation_request.cc b/vendor/bat-native-confirmations/src/bat/confirmations/internal/create_confirmation_request.cc index 73fb49e8d88d..c11e1309528d 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/create_confirmation_request.cc +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/create_confirmation_request.cc @@ -78,34 +78,7 @@ std::string CreateConfirmationRequest::CreateConfirmationRequestDTO( auto token_base64 = token.encode_base64(); payload.SetKey("blindedPaymentToken", base::Value(token_base64)); - std::string type; - switch (confirmation_type) { - case ConfirmationType::UNKNOWN: { - DCHECK(false) << "Invalid confirmation type"; - break; - } - - case ConfirmationType::CLICK: { - type = kConfirmationTypeClick; - break; - } - - case ConfirmationType::DISMISS: { - type = kConfirmationTypeDismiss; - break; - } - - case ConfirmationType::VIEW: { - type = kConfirmationTypeView; - break; - } - - case ConfirmationType::LANDED: { - type = kConfirmationTypeLanded; - break; - } - } - + auto type = std::string(confirmation_type); payload.SetKey("type", base::Value(type)); std::string json; diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.cc b/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.cc index 5ac4c4b195a8..4985ae224046 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.cc +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.cc @@ -9,6 +9,7 @@ #include "bat/confirmations/internal/logging.h" #include "bat/confirmations/internal/ads_serve_helper.h" #include "bat/confirmations/internal/security_helper.h" +#include "bat/confirmations/internal/static_values.h" #include "bat/confirmations/internal/confirmations_impl.h" #include "bat/confirmations/internal/unblinded_tokens.h" #include "bat/confirmations/internal/create_confirmation_request.h" @@ -17,6 +18,7 @@ #include "base/logging.h" #include "base/guid.h" #include "base/json/json_reader.h" +#include "base/rand_util.h" #include "base/values.h" using std::placeholders::_1; @@ -61,48 +63,34 @@ void RedeemToken::Redeem( CreateConfirmation(creative_instance_id, token_info, confirmation_type); } +void RedeemToken::Redeem( + const ConfirmationInfo& confirmation_info) { + CreateConfirmation(confirmation_info); +} + /////////////////////////////////////////////////////////////////////////////// void RedeemToken::CreateConfirmation( - const std::string& creative_instance_id, - const TokenInfo& token_info, - const ConfirmationType confirmation_type) { - DCHECK(!creative_instance_id.empty()); - + const ConfirmationInfo& confirmation_info) { BLOG(INFO) << "CreateConfirmation"; - if (!unblinded_tokens_->TokenExists(token_info)) { - BLOG(ERROR) << "Failed to redeem token " - << token_info.unblinded_token.encode_base64() - << " as unblinded token could not be found"; - OnRedeem(FAILED, token_info); - return; - } - BLOG(INFO) << "POST /v1/confirmation/{confirmation_id}/{credential}"; CreateConfirmationRequest request; - auto payment_tokens = helper::Security::GenerateTokens(1); - auto payment_token = payment_tokens.front(); - - auto blinded_payment_tokens = helper::Security::BlindTokens(payment_tokens); - auto blinded_payment_token = blinded_payment_tokens.front(); - - auto confirmation_id = base::GenerateGUID(); - - auto payload = request.CreateConfirmationRequestDTO(creative_instance_id, - blinded_payment_token, confirmation_type); - - auto credential = request.CreateCredential(token_info, payload); - BLOG(INFO) << "URL Request:"; - auto url = request.BuildUrl(confirmation_id, credential); + auto url = request.BuildUrl(confirmation_info.id, + confirmation_info.credential); BLOG(INFO) << " URL: " << url; auto method = request.GetMethod(); - auto body = request.BuildBody(payload); + auto confirmation_request_dto = request.CreateConfirmationRequestDTO( + confirmation_info.creative_instance_id, + confirmation_info.blinded_payment_token, + confirmation_info.type); + + auto body = request.BuildBody(confirmation_request_dto); BLOG(INFO) << " Body: " << body; auto headers = request.BuildHeaders(); @@ -115,24 +103,55 @@ void RedeemToken::CreateConfirmation( BLOG(INFO) << " Content_type: " << content_type; auto callback = std::bind(&RedeemToken::OnCreateConfirmation, - this, url, _1, _2, _3, confirmation_type, confirmation_id, payment_token, - blinded_payment_token, token_info); + this, url, _1, _2, _3, confirmation_info); confirmations_client_->LoadURL(url, headers, body, content_type, method, callback); } +void RedeemToken::CreateConfirmation( + const std::string& creative_instance_id, + const TokenInfo& token_info, + const ConfirmationType confirmation_type) { + DCHECK(!creative_instance_id.empty()); + DCHECK(unblinded_tokens_->TokenExists(token_info)); + + ConfirmationInfo confirmation_info; + + confirmation_info.id = base::GenerateGUID(); + + confirmation_info.creative_instance_id = creative_instance_id; + + confirmation_info.type = confirmation_type; + + confirmation_info.token_info = token_info; + + auto payment_tokens = helper::Security::GenerateTokens(1); + confirmation_info.payment_token = payment_tokens.front(); + + auto blinded_payment_tokens = helper::Security::BlindTokens(payment_tokens); + auto blinded_payment_token = blinded_payment_tokens.front(); + confirmation_info.blinded_payment_token = blinded_payment_token; + + CreateConfirmationRequest request; + + auto confirmation_request_dto = + request.CreateConfirmationRequestDTO(creative_instance_id, + blinded_payment_token, confirmation_type); + + confirmation_info.credential = + request.CreateCredential(token_info, confirmation_request_dto); + + CreateConfirmation(confirmation_info); +} + void RedeemToken::OnCreateConfirmation( const std::string& url, const int response_status_code, const std::string& response, const std::map& headers, - const ConfirmationType confirmation_type, - const std::string& confirmation_id, - const Token& payment_token, - const BlindedToken& blinded_payment_token, - const TokenInfo& token_info) { - DCHECK(!confirmation_id.empty()); + const ConfirmationInfo& confirmation_info) { + DCHECK(!confirmation_info.id.empty()); BLOG(INFO) << "OnCreateConfirmation"; @@ -145,50 +164,46 @@ void RedeemToken::OnCreateConfirmation( BLOG(INFO) << " " << header.first << ": " << header.second; } - if (response_status_code != 201) { + if (response_status_code != 201 && response_status_code != 400) { BLOG(ERROR) << "Failed to create confirmation"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } - // Parse JSON response - base::Optional dictionary = base::JSONReader::Read(response); - if (!dictionary || !dictionary->is_dict()) { - BLOG(ERROR) << "Failed to parse response: " << response; - OnRedeem(FAILED, token_info); - return; - } + if (response_status_code != 400) { + // Parse JSON response + base::Optional dictionary = base::JSONReader::Read(response); + if (!dictionary || !dictionary->is_dict()) { + BLOG(ERROR) << "Failed to parse response: " << response; + OnRedeem(FAILED, confirmation_info); + return; + } - // Get id - auto* id_value = dictionary->FindKey("id"); - if (!id_value) { - BLOG(ERROR) << "Response missing id"; - OnRedeem(FAILED, token_info); - return; - } + // Get id + auto* id_value = dictionary->FindKey("id"); + if (!id_value) { + BLOG(ERROR) << "Response missing id"; + OnRedeem(FAILED, confirmation_info); + return; + } - auto id = id_value->GetString(); + auto id = id_value->GetString(); - // Validate id - if (id != confirmation_id) { - BLOG(ERROR) << "Response id: " << id << " does not match confirmation id: " - << confirmation_id; - OnRedeem(FAILED, token_info); - return; + // Validate id + if (id != confirmation_info.id) { + BLOG(ERROR) << "Response id: " << id + << " does not match confirmation id: " << confirmation_info.id; + OnRedeem(FAILED, confirmation_info); + return; + } } // Fetch payment token - FetchPaymentToken(confirmation_type, confirmation_id, payment_token, - blinded_payment_token, token_info); + FetchPaymentToken(confirmation_info); } -void RedeemToken::FetchPaymentToken( - const ConfirmationType confirmation_type, - const std::string& confirmation_id, - const Token& payment_token, - const BlindedToken& blinded_payment_token, - const TokenInfo& token_info) { - DCHECK(!confirmation_id.empty()); +void RedeemToken::FetchPaymentToken(const ConfirmationInfo& confirmation_info) { + DCHECK(!confirmation_info.id.empty()); BLOG(INFO) << "FetchPaymentToken"; @@ -197,14 +212,13 @@ void RedeemToken::FetchPaymentToken( BLOG(INFO) << "URL Request:"; - auto url = request.BuildUrl(confirmation_id); + auto url = request.BuildUrl(confirmation_info.id); BLOG(INFO) << " URL: " << url; auto method = request.GetMethod(); auto callback = std::bind(&RedeemToken::OnFetchPaymentToken, - this, url, _1, _2, _3, confirmation_type, payment_token, - blinded_payment_token, token_info); + this, url, _1, _2, _3, confirmation_info); confirmations_client_->LoadURL(url, {}, "", "", method, callback); } @@ -214,10 +228,7 @@ void RedeemToken::OnFetchPaymentToken( const int response_status_code, const std::string& response, const std::map& headers, - const ConfirmationType confirmation_type, - const Token& payment_token, - const BlindedToken& blinded_payment_token, - const TokenInfo& token_info) { + const ConfirmationInfo& confirmation_info) { BLOG(INFO) << "OnFetchPaymentToken"; BLOG(INFO) << "URL Request Response:"; @@ -231,7 +242,7 @@ void RedeemToken::OnFetchPaymentToken( if (response_status_code != 200) { BLOG(ERROR) << "Failed to fetch payment token"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -239,7 +250,7 @@ void RedeemToken::OnFetchPaymentToken( base::Optional dictionary = base::JSONReader::Read(response); if (!dictionary || !dictionary->is_dict()) { BLOG(ERROR) << "Failed to parse response: " << response; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -247,7 +258,7 @@ void RedeemToken::OnFetchPaymentToken( auto* id_value = dictionary->FindKey("id"); if (!id_value) { BLOG(ERROR) << "Response missing id"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -257,7 +268,7 @@ void RedeemToken::OnFetchPaymentToken( auto* payment_token_value = dictionary->FindKey("paymentToken"); if (!payment_token_value) { BLOG(ERROR) << "Response missing paymentToken"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -265,7 +276,7 @@ void RedeemToken::OnFetchPaymentToken( base::DictionaryValue* payment_token_dictionary; if (!payment_token_value->GetAsDictionary(&payment_token_dictionary)) { BLOG(ERROR) << "Response missing paymentToken dictionary"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -273,7 +284,7 @@ void RedeemToken::OnFetchPaymentToken( auto* public_key_value = payment_token_dictionary->FindKey("publicKey"); if (!public_key_value) { BLOG(ERROR) << "Response missing publicKey in paymentToken dictionary"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } auto public_key_base64 = public_key_value->GetString(); @@ -283,7 +294,7 @@ void RedeemToken::OnFetchPaymentToken( if (!confirmations_->IsValidPublicKeyForCatalogIssuers(public_key_base64)) { BLOG(ERROR) << "Response public_key: " << public_key_base64 << " was not found in the catalog issuers"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -291,7 +302,7 @@ void RedeemToken::OnFetchPaymentToken( auto* batch_proof_value = payment_token_dictionary->FindKey("batchProof"); if (!batch_proof_value) { BLOG(ERROR) << "Response missing batchProof in paymentToken dictionary"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -302,14 +313,14 @@ void RedeemToken::OnFetchPaymentToken( auto* signed_tokens_value = payment_token_dictionary->FindKey("signedTokens"); if (!signed_tokens_value) { BLOG(ERROR) << "Response missing signedTokens in paymentToken dictionary"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } base::ListValue signed_token_base64_values(signed_tokens_value->GetList()); if (signed_token_base64_values.GetSize() != 1) { BLOG(ERROR) << "Too many signedTokens"; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } @@ -321,8 +332,8 @@ void RedeemToken::OnFetchPaymentToken( } // Verify and unblind payment token - auto payment_tokens = {payment_token}; - auto blinded_payment_tokens = {blinded_payment_token}; + auto payment_tokens = {confirmation_info.payment_token}; + auto blinded_payment_tokens = {confirmation_info.blinded_payment_token}; auto unblinded_payment_tokens = batch_proof.verify_and_unblind( payment_tokens, blinded_payment_tokens, signed_tokens, public_key); @@ -333,12 +344,13 @@ void RedeemToken::OnFetchPaymentToken( BLOG(ERROR) << " Batch proof: " << batch_proof_base64; BLOG(ERROR) << " Payment tokens (" << payment_tokens.size() << "):"; - auto payment_token_base64 = payment_token.encode_base64(); + auto payment_token_base64 = confirmation_info.payment_token.encode_base64(); BLOG(ERROR) << " " << payment_token_base64; BLOG(ERROR) << " Blinded payment tokens (" << blinded_payment_tokens.size() << "):"; - auto blinded_payment_token_base64 = blinded_payment_token.encode_base64(); + auto blinded_payment_token_base64 = + confirmation_info.blinded_payment_token.encode_base64(); BLOG(ERROR) << " " << blinded_payment_token_base64; BLOG(ERROR) << " Signed tokens (" << signed_tokens.size() << "):"; @@ -349,16 +361,21 @@ void RedeemToken::OnFetchPaymentToken( BLOG(ERROR) << " Public key: " << public_key_base64; - OnRedeem(FAILED, token_info); + OnRedeem(FAILED, confirmation_info); return; } // Add unblinded payment token TokenInfo unblinded_payment_token_info; - unblinded_payment_token_info.unblinded_token = - unblinded_payment_tokens.front(); + unblinded_payment_token_info.unblinded_token + = unblinded_payment_tokens.front(); unblinded_payment_token_info.public_key = public_key_base64; + if (unblinded_payment_tokens_->TokenExists(unblinded_payment_token_info)) { + OnRedeem(FAILED, confirmation_info, false); + return; + } + std::vector tokens = {unblinded_payment_token_info}; unblinded_payment_tokens_->AddTokens(tokens); @@ -372,31 +389,68 @@ void RedeemToken::OnFetchPaymentToken( << " " << estimated_redemption_value << " BAT, you now have " << unblinded_payment_tokens_->Count() << " unblinded payment tokens"; - confirmations_->AppendTransactionToTransactionHistory( - estimated_redemption_value, confirmation_type); + confirmations_->AppendTransactionToHistory( + estimated_redemption_value, confirmation_info.type); - OnRedeem(SUCCESS, token_info); + OnRedeem(SUCCESS, confirmation_info); } void RedeemToken::OnRedeem( const Result result, - const TokenInfo& token_info) { + const ConfirmationInfo& confirmation_info, + const bool should_retry) { + auto was_removed = + confirmations_->RemoveConfirmationFromQueue(confirmation_info); + if (result != SUCCESS) { - BLOG(ERROR) << "Failed to redeem token"; + BLOG(WARNING) << "Failed to redeem token with " + << confirmation_info.creative_instance_id + << " creative instance id for " + << std::string(confirmation_info.type); + + if (should_retry) { + if (was_removed) { + BLOG(INFO) << "Moved " << confirmation_info.creative_instance_id + << " creative instance id for " + << std::string(confirmation_info.type) + << " to the back of the confirmations queue"; + } else { + BLOG(INFO) << "Added " << confirmation_info.creative_instance_id + << " creative instance id for " + << std::string(confirmation_info.type) + << " to the confirmations queue"; + } + + confirmations_->AppendConfirmationToQueue(confirmation_info); + } } else { - BLOG(INFO) << "Successfully redeemed token"; + BLOG(INFO) << "Successfully redeemed token with " + << confirmation_info.creative_instance_id + << " creative instance id for " << std::string(confirmation_info.type); } - if (!unblinded_tokens_->RemoveToken(token_info)) { - BLOG(ERROR) << "Failed to remove unblinded token " - << token_info.unblinded_token.encode_base64() - << " as unblinded token could not be found"; - } else { - BLOG(INFO) << "Removed " << token_info.unblinded_token.encode_base64() + if (unblinded_tokens_->RemoveToken(confirmation_info.token_info)) { + BLOG(INFO) << "Removed " << + confirmation_info.token_info.unblinded_token.encode_base64() << " unblinded token"; } + ScheduleNextRetryForFailedConfirmations(); + confirmations_->RefillTokensIfNecessary(); } +void RedeemToken::ScheduleNextRetryForFailedConfirmations() const { + auto start_timer_in = CalculateTimerForNextRetryForFailedConfirmations(); + confirmations_->StartRetryingFailedConfirmations(start_timer_in); +} + +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; + + return start_timer_in; +} + } // namespace confirmations diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.h b/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.h index 3f03fd5772fa..4daf284b5053 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.h +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/redeem_token.h @@ -12,6 +12,7 @@ #include "bat/confirmations/confirmations_client.h" #include "bat/confirmations/internal/token_info.h" +#include "bat/confirmations/internal/confirmation_info.h" #include "bat/confirmations/confirmation_type.h" #include "wrapper.hpp" // NOLINT @@ -37,8 +38,12 @@ class RedeemToken { void Redeem( const std::string& creative_instance_id, const ConfirmationType confirmation_type); + void Redeem( + const ConfirmationInfo& confirmation_info); private: + void CreateConfirmation( + const ConfirmationInfo& confirmation_info); void CreateConfirmation( const std::string& creative_instance_id, const TokenInfo& token_info, @@ -48,31 +53,24 @@ class RedeemToken { const int response_status_code, const std::string& response, const std::map& headers, - const ConfirmationType confirmation_type, - const std::string& confirmation_id, - const Token& payment_token, - const BlindedToken& blinded_payment_token, - const TokenInfo& token_info); + const ConfirmationInfo& confirmation_info); void FetchPaymentToken( - const ConfirmationType confirmation_type, - const std::string& confirmation_id, - const Token& payment_token, - const BlindedToken& blinded_payment_token, - const TokenInfo& token_info); + const ConfirmationInfo& confirmation_info); void OnFetchPaymentToken( const std::string& url, const int response_status_code, const std::string& response, const std::map& headers, - const ConfirmationType confirmation_type, - const Token& payment_token, - const BlindedToken& blinded_payment_token, - const TokenInfo& token_info); + const ConfirmationInfo& confirmation_info); void OnRedeem( const Result result, - const TokenInfo& token_info); + const ConfirmationInfo& confirmation_info, + const bool should_retry = true); + + void ScheduleNextRetryForFailedConfirmations() const; + uint64_t CalculateTimerForNextRetryForFailedConfirmations() const; ConfirmationsImpl* confirmations_; // NOT OWNED ConfirmationsClient* confirmations_client_; // NOT OWNED diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/security_helper.cc b/vendor/bat-native-confirmations/src/bat/confirmations/internal/security_helper.cc index 78c98d48478a..3e5a0abcf2ea 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/security_helper.cc +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/security_helper.cc @@ -45,7 +45,8 @@ std::string Security::Sign( std::vector signed_message(crypto_sign_BYTES + concatenated_message.length()); - unsigned long long signed_message_size = 0; + // Resolving the following linter error breaks the build on Windows + unsigned long long signed_message_size = 0; // NOLINT crypto_sign(&signed_message.front(), &signed_message_size, reinterpret_cast(concatenated_message.c_str()), concatenated_message.length(), &public_key.front()); @@ -60,7 +61,7 @@ std::string Security::Sign( } std::vector Security::GenerateTokens(const int count) { - DCHECK_NE(count, 0); + DCHECK_GT(count, 0); std::vector tokens; diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/static_values.h b/vendor/bat-native-confirmations/src/bat/confirmations/internal/static_values.h index 3508f7e22d28..a39185f25579 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/static_values.h +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/static_values.h @@ -26,6 +26,9 @@ static const uint64_t kNextTokenRedemptionAfterSeconds = static const uint64_t kDebugNextTokenRedemptionAfterSeconds = 25 * base::Time::kSecondsPerMinute; +static const uint64_t kRetryFailedConfirmationsAfterSeconds = + 5 * base::Time::kSecondsPerMinute; + } // namespace confirmations #endif // BAT_CONFIRMATIONS_INTERNAL_STATIC_VALUES_H_ diff --git a/vendor/bat-native-confirmations/src/bat/confirmations/internal/unblinded_tokens.cc b/vendor/bat-native-confirmations/src/bat/confirmations/internal/unblinded_tokens.cc index ad208e506d6e..741e412f7c04 100644 --- a/vendor/bat-native-confirmations/src/bat/confirmations/internal/unblinded_tokens.cc +++ b/vendor/bat-native-confirmations/src/bat/confirmations/internal/unblinded_tokens.cc @@ -114,8 +114,7 @@ bool UnblindedTokens::RemoveToken(const TokenInfo& token) { auto it = std::find_if(tokens_.begin(), tokens_.end(), [=](const TokenInfo& info) { - return (info.unblinded_token == unblinded_token && - info.public_key == public_key); + return (info.unblinded_token == unblinded_token); }); if (it == tokens_.end()) { @@ -141,8 +140,7 @@ bool UnblindedTokens::TokenExists(const TokenInfo& token) { auto it = std::find_if(tokens_.begin(), tokens_.end(), [=](const TokenInfo& info) { - return (info.unblinded_token == unblinded_token && - info.public_key == public_key); + return (info.unblinded_token == unblinded_token); }); if (it == tokens_.end()) { diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc index 13d212d159a5..2d9fc7497f32 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc @@ -1331,7 +1331,8 @@ void LedgerImpl::ConfirmAd(const std::string& info) { notification_info->text = notification_info_ads.text; notification_info->url = notification_info_ads.url; notification_info->uuid = notification_info_ads.uuid; - switch (notification_info_ads.type) { + + switch (notification_info_ads.type.value()) { case ads::ConfirmationType::UNKNOWN: { notification_info->type = confirmations::ConfirmationType::UNKNOWN; break;