Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFT pinning optimisation #17742

Merged
merged 4 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,15 @@ void BraveWalletAutoPinService::OnTaskFinished(bool result,
}

void BraveWalletAutoPinService::OnValidateTaskFinished(
bool result,
mojom::PinErrorPtr error) {
if (!result) {
AddOrExecute(std::make_unique<IntentData>(current_->token, Operation::kAdd,
current_->service));
mojom::TokenValidationResult result) {
if (result == mojom::TokenValidationResult::kValidationError) {
PostRetry(std::move(current_));
}
auto current = std::move(current_);
if (result == mojom::TokenValidationResult::kValidationFailed) {
AddOrExecute(std::make_unique<IntentData>(current->token, Operation::kAdd,
current->service));
}
current_.reset();
CheckQueue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class BraveWalletAutoPinService
void UnpinToken(const std::unique_ptr<IntentData>& data);

void OnTaskFinished(bool result, mojom::PinErrorPtr error);
void OnValidateTaskFinished(bool result, mojom::PinErrorPtr error);
void OnValidateTaskFinished(mojom::TokenValidationResult result);

mojo::Receiver<brave_wallet::mojom::BraveWalletServiceTokenObserver>
token_observer_{this};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ TEST_F(BraveWalletAutoPinServiceTest, ValidateOldTokens_WhenRestore) {
[](BlockchainTokenPtr token,
const absl::optional<std::string>& service,
BraveWalletPinService::ValidateCallback callback) {
std::move(callback).Run(true, nullptr);
std::move(callback).Run(
mojom::TokenValidationResult::kValidationPassed);
}));

EXPECT_CALL(*GetBraveWalletPinService(),
Expand Down
118 changes: 42 additions & 76 deletions components/brave_wallet/browser/brave_wallet_pin_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const char kValidateTimestamp[] = "validate_timestamp";
const char kError[] = "error";
const char kErrorCode[] = "error_code";
const char kErrorMessage[] = "error_message";
const char kAssetUrlListKey[] = "cids";
const char kAssetUrlListKey[] = "urls";

namespace {
// Solana NFTs don't have token_id
Expand Down Expand Up @@ -106,28 +106,6 @@ absl::optional<std::string> ExtractIpfsUrl(const std::string& url) {
return source.value().spec();
}

absl::optional<std::string> ExtractCID(const std::string& url) {
GURL gurl = GURL(ExtractIpfsUrl(url).value_or(""));

if (!gurl.is_valid()) {
return absl::nullopt;
}

std::vector<std::string> result = base::SplitString(
gurl.path(), "/", base::WhitespaceHandling::KEEP_WHITESPACE,
base::SplitResult::SPLIT_WANT_NONEMPTY);

if (result.size() == 0) {
return absl::nullopt;
}

if (!ipfs::IsValidCID(result.at(0))) {
return absl::nullopt;
}

return result.at(0);
}

} // namespace

// static
Expand Down Expand Up @@ -434,45 +412,43 @@ absl::optional<std::string> BraveWalletPinService::ServiceFromPrefPath(
void BraveWalletPinService::Validate(mojom::BlockchainTokenPtr token,
const absl::optional<std::string>& service,
ValidateCallback callback) {
auto path = GetTokenPrefPath(absl::nullopt, token);
if (!path) {
std::move(callback).Run(mojom::TokenValidationResult::kValidationIgnored);
return;
}

mojom::TokenPinStatusPtr status = GetTokenStatus(service, token);
if (!status) {
std::move(callback).Run(false, nullptr);
std::move(callback).Run(mojom::TokenValidationResult::kValidationIgnored);
return;
}

if (status->code != mojom::TokenPinStatusCode::STATUS_PINNED) {
std::move(callback).Run(false, nullptr);
std::move(callback).Run(mojom::TokenValidationResult::kValidationIgnored);
return;
}

absl::optional<std::vector<std::string>> cids =
absl::optional<std::vector<std::string>> ipfs_urls =
ResolvePinItems(service, token);

if (!cids) {
if (!ipfs_urls) {
SetTokenStatus(service, std::move(token),
mojom::TokenPinStatusCode::STATUS_PINNING_IN_PROGRESS,
nullptr);
std::move(callback).Run(true, nullptr);
return;
}

auto path = GetTokenPrefPath(absl::nullopt, token);
if (!path) {
std::move(callback).Run(
false,
mojom::PinError::New(mojom::WalletPinServiceErrorCode::ERR_WRONG_TOKEN,
"Wrong token data"));
std::move(callback).Run(mojom::TokenValidationResult::kValidationFailed);
return;
}

if (!service) {
local_pin_service_->ValidatePins(
path.value(), cids.value(),
path.value(), ipfs_urls.value(),
base::BindOnce(&BraveWalletPinService::OnTokenValidated,
weak_ptr_factory_.GetWeakPtr(), service,
std::move(callback), std::move(token)));
} else {
// Remote pinning not implemented yet
std::move(callback).Run(false, nullptr);
std::move(callback).Run(mojom::TokenValidationResult::kValidationIgnored);
}
}

Expand Down Expand Up @@ -652,8 +628,8 @@ void BraveWalletPinService::ProcessTokenMetadata(
const std::string& token_url,
const std::string& result,
AddPinCallback callback) {
auto metadata_cid = ExtractCID(token_url);
if (!metadata_cid) {
auto metadata_ipfs_url = ExtractIpfsUrl(token_url);
if (!metadata_ipfs_url) {
auto pin_error = mojom::PinError::New(
mojom::WalletPinServiceErrorCode::ERR_NON_IPFS_TOKEN_URL,
"Metadata has non-ipfs url");
Expand All @@ -677,10 +653,10 @@ void BraveWalletPinService::ProcessTokenMetadata(
}

auto* image_url = parsed_result->FindStringKey("image");
auto image_cid =
image_url != nullptr ? ExtractCID(*image_url) : absl::nullopt;
auto image_ipfs_url =
image_url != nullptr ? ExtractIpfsUrl(*image_url) : absl::nullopt;

if (!image_cid) {
if (!image_ipfs_url) {
auto pin_error = mojom::PinError::New(
mojom::WalletPinServiceErrorCode::ERR_NON_IPFS_TOKEN_URL,
"Can't find proper image field");
Expand All @@ -690,32 +666,21 @@ void BraveWalletPinService::ProcessTokenMetadata(
return;
}

std::vector<std::string> cids;
cids.push_back(metadata_cid.value());
cids.push_back(image_cid.value());

auto ipfs_image_url = ExtractIpfsUrl(*image_url);
if (!ipfs_image_url) {
auto pin_error = mojom::PinError::New(
mojom::WalletPinServiceErrorCode::ERR_NON_IPFS_TOKEN_URL,
"Can't find proper image field");
SetTokenStatus(service, token,
mojom::TokenPinStatusCode::STATUS_PINNING_FAILED, pin_error);
std::move(callback).Run(false, std::move(pin_error));
return;
}
std::vector<std::string> ipfs_urls;
ipfs_urls.push_back(metadata_ipfs_url.value());
ipfs_urls.push_back(image_ipfs_url.value());

content_type_checker_->CheckContentTypeSupported(
ipfs_image_url.value(),
image_ipfs_url.value(),
base::BindOnce(&BraveWalletPinService::OnContentTypeChecked,
weak_ptr_factory_.GetWeakPtr(), service, token.Clone(),
std::move(cids), std::move(callback)));
std::move(ipfs_urls), std::move(callback)));
}

void BraveWalletPinService::OnContentTypeChecked(
absl::optional<std::string> service,
mojom::BlockchainTokenPtr token,
std::vector<std::string> cids,
std::vector<std::string> ipfs_urls,
AddPinCallback callback,
absl::optional<bool> result) {
if (!result.has_value()) {
Expand Down Expand Up @@ -749,14 +714,14 @@ void BraveWalletPinService::OnContentTypeChecked(
return;
}

AddToken(service, token, cids);
AddToken(service, token, ipfs_urls);
SetTokenStatus(service, token,
mojom::TokenPinStatusCode::STATUS_PINNING_IN_PROGRESS,
nullptr);

if (!service) {
local_pin_service_->AddPins(
path.value(), cids,
path.value(), ipfs_urls,
base::BindOnce(&BraveWalletPinService::OnTokenPinned,
weak_ptr_factory_.GetWeakPtr(), absl::nullopt,
std::move(callback), std::move(token)));
Expand Down Expand Up @@ -789,26 +754,27 @@ void BraveWalletPinService::OnTokenValidated(
mojom::BlockchainTokenPtr token,
absl::optional<bool> result) {
if (!result.has_value()) {
std::move(callback).Run(false, nullptr);
std::move(callback).Run(mojom::TokenValidationResult::kValidationError);
return;
}

if (!result.value()) {
SetTokenStatus(service, token,
mojom::TokenPinStatusCode::STATUS_PINNING_IN_PROGRESS,
nullptr);
std::move(callback).Run(mojom::TokenValidationResult::kValidationFailed);
} else {
// Also updates verification timestamp
SetTokenStatus(service, token, mojom::TokenPinStatusCode::STATUS_PINNED,
nullptr);
std::move(callback).Run(mojom::TokenValidationResult::kValidationPassed);
}

std::move(callback).Run(true, nullptr);
}

bool BraveWalletPinService::AddToken(const absl::optional<std::string>& service,
const mojom::BlockchainTokenPtr& token,
const std::vector<std::string>& cids) {
bool BraveWalletPinService::AddToken(
const absl::optional<std::string>& service,
const mojom::BlockchainTokenPtr& token,
const std::vector<std::string>& ipfs_urls) {
auto path = GetTokenPrefPath(service, token);
if (!path) {
return false;
Expand All @@ -819,13 +785,13 @@ bool BraveWalletPinService::AddToken(const absl::optional<std::string>& service,
base::Value::Dict& update_dict = update.Get();

base::Value::Dict token_data;
base::Value::List cids_list;
base::Value::List ipfs_urls_list;

for (const auto& cid : cids) {
cids_list.Append(cid);
for (const auto& ipfs_url : ipfs_urls) {
ipfs_urls_list.Append(ipfs_url);
}

token_data.Set(kAssetUrlListKey, std::move(cids_list));
token_data.Set(kAssetUrlListKey, std::move(ipfs_urls_list));
token_data.Set(
kAssetStatus,
StatusToString(mojom::TokenPinStatusCode::STATUS_NOT_PINNED));
Expand Down Expand Up @@ -912,13 +878,13 @@ absl::optional<std::vector<std::string>> BraveWalletPinService::ResolvePinItems(
return absl::nullopt;
}

auto* cids = token_data_as_dict->FindList(kAssetUrlListKey);
if (!cids) {
auto* ipfs_urls = token_data_as_dict->FindList(kAssetUrlListKey);
if (!ipfs_urls) {
return absl::nullopt;
}

std::vector<std::string> result;
for (const base::Value& item : *cids) {
for (const base::Value& item : *ipfs_urls) {
result.push_back(item.GetString());
}

Expand Down
Loading