Move Zcash protobuf parsing to separate process (#21627)

* Move Zcash protobuf parsing to separate process
Introduces BraveWalletUtilsService that is able to provide ZCashDecoder
to convert protobufs to mojo structs and pass them to the mai.
Resolves https://github.com/brave/brave-browser/issues/34561
This commit is contained in:
cypt4
2024-01-30 03:26:41 +07:00
committed by GitHub
parent 224c58bb83
commit 5b8ea34b73
44 changed files with 976 additions and 185 deletions
+4
View File
@@ -898,6 +898,10 @@ Or change later at <ph name="SETTINGS_EXTENIONS_LINK">$2<ex>brave://settings/ext
<message name="IDS_BRAVE_IPFS_ALWAYS_START_INFOBAR_NO" desc="Ignore proposition">
Cancel
</message>
<!-- Brave Wallet -->
<message name="IDS_UTILITY_PROCESS_WALLET_UTILS_NAME" desc="The utility process running wallet utils">
Brave Wallet Utility Service
</message>
<!-- Brave Wayback Machine -->
<message name="IDS_BRAVE_WAYBACK_MACHINE_INFOBAR_PAGE_MISSING_TEXT" desc="The label for sorry message when page is not available on infobar">
+4 -5
View File
@@ -250,7 +250,6 @@ static_library("browser") {
":pref_names",
":transaction",
":utils",
":zcash_proto",
"//base",
"//brave/components/brave_component_updater/browser",
"//brave/components/brave_stats/browser",
@@ -267,6 +266,10 @@ static_library("browser") {
"//brave/components/json/rs:rust_lib",
"//brave/components/p3a_utils",
"//brave/components/resources:strings_grit",
"//brave/components/services/brave_wallet/public/cpp",
"//brave/components/services/brave_wallet/public/cpp/utils",
"//brave/components/services/brave_wallet/public/mojom",
"//brave/components/services/brave_wallet/public/proto:zcash_proto",
"//brave/third_party/argon2",
"//components/component_updater",
"//components/content_settings/core/browser",
@@ -490,10 +493,6 @@ generated_types("generated_swap_responses") {
]
}
proto_library("zcash_proto") {
sources = [ "zcash/protos/zcash_grpc_data.proto" ]
}
config("sardine_config") {
defines = [
"SARDINE_CLIENT_ID=\"$sardine_client_id\"",
@@ -135,6 +135,8 @@ source_set("brave_wallet_unit_tests") {
"//brave/components/ipfs",
"//brave/components/json/rs:rust_lib",
"//brave/components/resources:strings_grit",
"//brave/components/services/brave_wallet/public/cpp/utils",
"//brave/components/services/brave_wallet/public/mojom",
"//components/component_updater:test_support",
"//components/permissions",
"//components/prefs",
@@ -48,18 +48,18 @@ std::optional<uint32_t> ZCashBlockTracker::GetLatestHeight(
void ZCashBlockTracker::OnGetLatestBlockForHeight(
const std::string& chain_id,
base::expected<zcash::BlockID, std::string> latest_block) {
if (!latest_block.has_value()) {
base::expected<mojom::BlockIDPtr, std::string> latest_block) {
if (!latest_block.has_value() || !latest_block.value()) {
return;
}
auto cur_latest_height = GetLatestHeight(chain_id);
if (cur_latest_height &&
cur_latest_height.value() == latest_block->height()) {
cur_latest_height.value() == (*latest_block)->height) {
return;
}
latest_height_map_[chain_id] = latest_block->height();
latest_height_map_[chain_id] = (*latest_block)->height;
for (auto& observer : observers_) {
observer.OnLatestHeightUpdated(chain_id, latest_block->height());
observer.OnLatestHeightUpdated(chain_id, (*latest_block)->height);
}
}
@@ -15,7 +15,7 @@
#include "base/time/time.h"
#include "base/types/expected.h"
#include "brave/components/brave_wallet/browser/block_tracker.h"
#include "brave/components/brave_wallet/browser/zcash/protos/zcash_grpc_data.pb.h"
#include "brave/components/services/brave_wallet/public/mojom/zcash_decoder.mojom.h"
namespace brave_wallet {
@@ -44,7 +44,7 @@ class ZCashBlockTracker : public BlockTracker {
void GetBlockHeight(const std::string& chain_id);
void OnGetLatestBlockForHeight(
const std::string& chain_id,
base::expected<zcash::BlockID, std::string> latest_height);
base::expected<mojom::BlockIDPtr, std::string> latest_height);
// <chain_id, block_height>
std::map<std::string, uint32_t> latest_height_map_;
@@ -18,35 +18,6 @@ constexpr size_t kGrpcHeaderSize = 5;
constexpr char kNoCompression = 0;
} // namespace
std::string GetPrefixedProtobuf(const std::string& serialized_proto) {
std::string result(kGrpcHeaderSize, 0);
result[0] = kNoCompression;
base::WriteBigEndian<uint32_t>(&result[1], serialized_proto.size());
result.append(serialized_proto);
return result;
}
// Resolves serialized protobuf from length-prefixed string
std::optional<std::string> ResolveSerializedMessage(
const std::string& grpc_response_body) {
if (grpc_response_body.size() < kGrpcHeaderSize) {
return std::nullopt;
}
if (grpc_response_body[0] != kNoCompression) {
// Compression is not supported yet
return std::nullopt;
}
uint32_t size = 0;
base::ReadBigEndian(
reinterpret_cast<const uint8_t*>(&(grpc_response_body[1])), &size);
if (grpc_response_body.size() != size + kGrpcHeaderSize) {
return std::nullopt;
}
return grpc_response_body.substr(kGrpcHeaderSize);
}
GRrpcMessageStreamHandler::GRrpcMessageStreamHandler() = default;
GRrpcMessageStreamHandler::~GRrpcMessageStreamHandler() = default;
@@ -6,7 +6,6 @@
#ifndef BRAVE_COMPONENTS_BRAVE_WALLET_BROWSER_ZCASH_ZCASH_GRPC_UTILS_H_
#define BRAVE_COMPONENTS_BRAVE_WALLET_BROWSER_ZCASH_ZCASH_GRPC_UTILS_H_
#include <optional>
#include <string>
#include <string_view>
@@ -14,15 +13,6 @@
namespace brave_wallet {
// Resolves serialized protobuf from length-prefixed string
std::optional<std::string> ResolveSerializedMessage(
const std::string& grpc_response_body);
// Prefixes provided serialized protobuf with compression byte and 4 bytes of
// message size. See
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
std::string GetPrefixedProtobuf(const std::string& serialized_proto);
// Handles a stream of GRPC objects
class GRrpcMessageStreamHandler
: public network::SimpleURLLoaderStreamConsumer {
@@ -14,6 +14,7 @@
#include "base/functional/callback.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "brave/components/services/brave_wallet/public/cpp/utils/protobuf_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace brave_wallet {
@@ -8,6 +8,9 @@
#include "base/functional/bind.h"
#include "brave/components/brave_wallet/browser/brave_wallet_utils.h"
#include "brave/components/brave_wallet/common/brave_wallet.mojom.h"
#include "brave/components/services/brave_wallet/public/cpp/brave_wallet_utils_service.h"
#include "brave/components/services/brave_wallet/public/cpp/utils/protobuf_utils.h"
#include "brave/components/services/brave_wallet/public/proto/zcash_grpc_data.pb.h"
#include "components/grit/brave_components_strings.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
@@ -319,10 +322,9 @@ void ZCashRpc::GetTransaction(const std::string& chain_id,
5000);
}
void ZCashRpc::OnGetUtxosResponse(
ZCashRpc::GetUtxoListCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body) {
void ZCashRpc::OnGetUtxosResponse(ZCashRpc::GetUtxoListCallback callback,
UrlLoadersList::iterator it,
std::unique_ptr<std::string> response_body) {
auto current_loader = std::move(*it);
url_loaders_list_.erase(it);
if (current_loader->NetError()) {
@@ -337,35 +339,32 @@ void ZCashRpc::OnGetUtxosResponse(
return;
}
auto message = ResolveSerializedMessage(*response_body);
if (!message) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
GetDecoder()->ParseGetAddressUtxos(
*response_body,
base::BindOnce(
&ZCashRpc::OnParseResult<mojom::GetAddressUtxosResponsePtr>,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
template <typename T>
void ZCashRpc::OnParseResult(
base::OnceCallback<void(base::expected<T, std::string>)> callback,
T value) {
if (value) {
std::move(callback).Run(std::move(value));
return;
}
zcash::GetAddressUtxosResponse response;
if (!response.ParseFromString(message.value())) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
return;
}
std::vector<zcash::ZCashUtxo> result;
for (const auto& item : response.addressutxos()) {
result.push_back(item);
}
std::move(callback).Run(result);
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
}
void ZCashRpc::OnGetLatestBlockResponse(
ZCashRpc::GetLatestBlockCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body) {
std::unique_ptr<std::string> response_body) {
auto current_loader = std::move(*it);
url_loaders_list_.erase(it);
zcash::BlockID response;
if (current_loader->NetError()) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_INTERNAL_ERROR)));
@@ -378,29 +377,18 @@ void ZCashRpc::OnGetLatestBlockResponse(
return;
}
auto message = ResolveSerializedMessage(*response_body);
if (!message) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
return;
}
if (!response.ParseFromString(message.value())) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
return;
}
std::move(callback).Run(response);
GetDecoder()->ParseBlockID(
*response_body,
base::BindOnce(&ZCashRpc::OnParseResult<mojom::BlockIDPtr>,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void ZCashRpc::OnGetTransactionResponse(
ZCashRpc::GetTransactionCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body) {
std::unique_ptr<std::string> response_body) {
auto current_loader = std::move(*it);
url_loaders_list_.erase(it);
zcash::RawTransaction response;
if (current_loader->NetError()) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_INTERNAL_ERROR)));
@@ -413,20 +401,10 @@ void ZCashRpc::OnGetTransactionResponse(
return;
}
auto message = ResolveSerializedMessage(*response_body);
if (!message) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
return;
}
if (!response.ParseFromString(message.value())) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
return;
}
std::move(callback).Run(response);
GetDecoder()->ParseRawTransaction(
*response_body,
base::BindOnce(&ZCashRpc::OnParseResult<mojom::RawTransactionPtr>,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void ZCashRpc::SendTransaction(const std::string& chain_id,
@@ -488,10 +466,9 @@ void ZCashRpc::IsKnownAddress(const std::string& chain_id,
void ZCashRpc::OnSendTransactionResponse(
ZCashRpc::SendTransactionCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body) {
std::unique_ptr<std::string> response_body) {
auto current_loader = std::move(*it);
url_loaders_list_.erase(it);
zcash::SendResponse response;
if (current_loader->NetError()) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_INTERNAL_ERROR)));
@@ -504,20 +481,10 @@ void ZCashRpc::OnSendTransactionResponse(
return;
}
auto message = ResolveSerializedMessage(*response_body);
if (!message) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
return;
}
if (!response.ParseFromString(message.value())) {
std::move(callback).Run(
base::unexpected(l10n_util::GetStringUTF8(IDS_WALLET_PARSING_ERROR)));
return;
}
std::move(callback).Run(response);
GetDecoder()->ParseSendResponse(
*response_body,
base::BindOnce(&ZCashRpc::OnParseResult<mojom::SendResponsePtr>,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void ZCashRpc::OnGetAddressTxResponse(
@@ -540,4 +507,14 @@ void ZCashRpc::OnGetAddressTxResponse(
std::move(callback).Run(result.value());
}
mojo::AssociatedRemote<mojom::ZCashDecoder>& ZCashRpc::GetDecoder() {
if (zcash_decoder_.is_bound()) {
return zcash_decoder_;
}
BraveWalletUtilsService::GetInstance()->CreateZCashDecoder(
zcash_decoder_.BindNewEndpointAndPassReceiver());
zcash_decoder_.reset_on_disconnect();
return zcash_decoder_;
}
} // namespace brave_wallet
@@ -15,9 +15,12 @@
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/types/expected.h"
#include "brave/components/brave_wallet/browser/zcash/protos/zcash_grpc_data.pb.h"
#include "brave/components/brave_wallet/browser/zcash/zcash_grpc_utils.h"
#include "brave/components/services/brave_wallet/public/mojom/zcash_decoder.mojom.h"
#include "components/prefs/pref_service.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
@@ -28,15 +31,15 @@ namespace brave_wallet {
class ZCashRpc {
public:
using GetUtxoListCallback = base::OnceCallback<void(
base::expected<std::vector<zcash::ZCashUtxo>, std::string>)>;
base::expected<mojom::GetAddressUtxosResponsePtr, std::string>)>;
using GetLatestBlockCallback =
base::OnceCallback<void(base::expected<zcash::BlockID, std::string>)>;
base::OnceCallback<void(base::expected<mojom::BlockIDPtr, std::string>)>;
using GetTransactionCallback = base::OnceCallback<void(
base::expected<zcash::RawTransaction, std::string>)>;
base::expected<mojom::RawTransactionPtr, std::string>)>;
using SendTransactionCallback = base::OnceCallback<void(
base::expected<zcash::SendResponse, std::string>)>;
base::expected<mojom::SendResponsePtr, std::string>)>;
using GetTransactionsCallback = base::OnceCallback<void(
base::expected<zcash::SendResponse, std::string>)>;
base::expected<mojom::SendResponsePtr, std::string>)>;
using IsKnownAddressCallback =
base::OnceCallback<void(base::expected<bool, std::string>)>;
@@ -74,32 +77,38 @@ class ZCashRpc {
void OnGetUtxosResponse(ZCashRpc::GetUtxoListCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body);
std::unique_ptr<std::string> response_body);
void OnGetLatestBlockResponse(
ZCashRpc::GetLatestBlockCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body);
void OnGetLatestBlockResponse(ZCashRpc::GetLatestBlockCallback callback,
UrlLoadersList::iterator it,
std::unique_ptr<std::string> response_body);
void OnGetTransactionResponse(
ZCashRpc::GetTransactionCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body);
void OnGetTransactionResponse(ZCashRpc::GetTransactionCallback callback,
UrlLoadersList::iterator it,
std::unique_ptr<std::string> response_body);
void OnSendTransactionResponse(
ZCashRpc::SendTransactionCallback callback,
UrlLoadersList::iterator it,
const std::unique_ptr<std::string> response_body);
void OnSendTransactionResponse(ZCashRpc::SendTransactionCallback callback,
UrlLoadersList::iterator it,
std::unique_ptr<std::string> response_body);
void OnGetAddressTxResponse(ZCashRpc::IsKnownAddressCallback callback,
UrlLoadersList::iterator it,
StreamHandlersList::iterator handler_it,
base::expected<bool, std::string> result);
template <typename T>
void OnParseResult(base::OnceCallback<void(base::expected<T, std::string>)>,
T value);
mojo::AssociatedRemote<mojom::ZCashDecoder>& GetDecoder();
UrlLoadersList url_loaders_list_;
StreamHandlersList stream_handlers_list_;
raw_ptr<PrefService> prefs_ = nullptr;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_ = nullptr;
mojo::AssociatedRemote<mojom::ZCashDecoder> zcash_decoder_;
base::WeakPtrFactory<ZCashRpc> weak_ptr_factory_{this};
};
@@ -218,20 +218,20 @@ std::optional<ZCashTransaction::TxInput> ZCashTransaction::TxInput::FromValue(
// static
std::optional<ZCashTransaction::TxInput> ZCashTransaction::TxInput::FromRpcUtxo(
const std::string& address,
const zcash::ZCashUtxo& utxo) {
if (address != utxo.address()) {
const mojom::ZCashUtxo& utxo) {
if (address != utxo.address) {
return std::nullopt;
}
ZCashTransaction::TxInput result;
result.utxo_address = utxo.address();
result.utxo_address = utxo.address;
result.script_pub_key.insert(result.script_pub_key.begin(),
utxo.script().begin(), utxo.script().end());
if (utxo.txid().size() != 32) {
utxo.script.begin(), utxo.script.end());
if (utxo.tx_id.size() != 32) {
return std::nullopt;
}
std::copy_n(utxo.txid().begin(), 32, result.utxo_outpoint.txid.begin());
result.utxo_outpoint.index = utxo.index();
result.utxo_value = utxo.valuezat();
std::copy_n(utxo.tx_id.begin(), 32, result.utxo_outpoint.txid.begin());
result.utxo_outpoint.index = utxo.index;
result.utxo_value = utxo.value_zat;
return result;
}
@@ -12,8 +12,8 @@
#include <string>
#include <vector>
#include "brave/components/brave_wallet/browser/zcash/protos/zcash_grpc_data.pb.h"
#include "brave/components/brave_wallet/common/hash_utils.h"
#include "brave/components/services/brave_wallet/public/mojom/zcash_decoder.mojom.h"
namespace brave_wallet {
@@ -51,7 +51,7 @@ class ZCashTransaction {
static std::optional<TxInput> FromValue(const base::Value::Dict& value);
static std::optional<TxInput> FromRpcUtxo(const std::string& address,
const zcash::ZCashUtxo& utxo);
const mojom::ZCashUtxo& utxo);
std::string utxo_address;
Outpoint utxo_outpoint;
@@ -268,15 +268,15 @@ void ZCashWalletService::OnResolveLastBlockHeightForSendTransaction(
const mojom::AccountIdPtr& account_id,
ZCashTransaction zcash_transaction,
SignAndPostTransactionCallback callback,
base::expected<zcash::BlockID, std::string> result) {
if (!result.has_value()) {
base::expected<mojom::BlockIDPtr, std::string> result) {
if (!result.has_value() || !result.value()) {
std::move(callback).Run(
"", std::move(zcash_transaction),
l10n_util::GetStringUTF8(IDS_WALLET_INTERNAL_ERROR));
return;
}
zcash_transaction.set_expiry_height(result->height() +
zcash_transaction.set_expiry_height((*result)->height +
kDefaultBlockHeightDelta);
if (!SignTransactionInternal(zcash_transaction, account_id)) {
@@ -298,8 +298,8 @@ void ZCashWalletService::OnResolveLastBlockHeightForSendTransaction(
void ZCashWalletService::OnSendTransactionResult(
SignAndPostTransactionCallback callback,
ZCashTransaction tx,
base::expected<zcash::SendResponse, std::string> result) {
if (result.has_value() && result->errorcode() == 0) {
base::expected<mojom::SendResponsePtr, std::string> result) {
if (result.has_value() && result.value() && (*result)->error_code == 0) {
auto tx_id = ZCashSerializer::CalculateTxIdDigest(tx);
auto tx_id_hex = ToHex(tx_id);
CHECK(tx_id_hex.starts_with("0x"));
@@ -313,18 +313,18 @@ void ZCashWalletService::OnSendTransactionResult(
void ZCashWalletService::OnGetUtxos(
scoped_refptr<GetTransparentUtxosContext> context,
const std::string& address,
base::expected<std::vector<zcash::ZCashUtxo>, std::string> result) {
base::expected<mojom::GetAddressUtxosResponsePtr, std::string> result) {
DCHECK(context->addresses.contains(address));
DCHECK(!context->utxos.contains(address));
if (!result.has_value()) {
if (!result.has_value() || !result.value()) {
context->SetError(result.error());
WorkOnGetUtxos(std::move(context));
return;
}
context->addresses.erase(address);
context->utxos[address] = result.value();
context->utxos[address] = std::move(result.value()->address_utxos);
WorkOnGetUtxos(std::move(context));
}
@@ -350,7 +350,8 @@ void ZCashWalletService::OnDiscoveryDoneForBalance(
GetBalanceCallback callback,
RunDiscoveryResult discovery_result) {
if (!discovery_result.has_value()) {
std::move(callback).Run(nullptr, "Failed to fetch balance");
std::move(callback).Run(
nullptr, l10n_util::GetStringUTF8(IDS_WALLET_INTERNAL_ERROR));
return;
}
GetUtxos(chain_id, std::move(account_id),
@@ -371,7 +372,7 @@ void ZCashWalletService::OnUtxosResolvedForBalance(
for (const auto& by_addr : utxos.value()) {
uint64_t balance_by_addr = 0;
for (const auto& by_utxo : by_addr.second) {
balance_by_addr += by_utxo.valuezat();
balance_by_addr += by_utxo->value_zat;
}
result->total_balance += balance_by_addr;
result->balances[by_addr.first] = balance_by_addr;
@@ -415,13 +416,13 @@ void ZCashWalletService::GetTransactionStatus(
void ZCashWalletService::OnTransactionResolvedForStatus(
GetTransactionStatusCallback callback,
base::expected<zcash::RawTransaction, std::string> result) {
if (!result.has_value()) {
base::expected<mojom::RawTransactionPtr, std::string> result) {
if (!result.has_value() || !result.value()) {
std::move(callback).Run(base::unexpected(result.error()));
return;
}
std::move(callback).Run(result.value().height() > 0);
std::move(callback).Run((*result)->height > 0);
}
void ZCashWalletService::CreateTransactionTaskDone(
@@ -17,7 +17,6 @@
#include "base/types/expected.h"
#include "brave/components/brave_wallet/browser/keyring_service.h"
#include "brave/components/brave_wallet/browser/keyring_service_observer_base.h"
#include "brave/components/brave_wallet/browser/zcash/protos/zcash_grpc_data.pb.h"
#include "brave/components/brave_wallet/browser/zcash/zcash_rpc.h"
#include "brave/components/brave_wallet/browser/zcash/zcash_transaction.h"
#include "brave/components/brave_wallet/common/brave_wallet.mojom.h"
@@ -32,7 +31,7 @@ class ZCashWalletService : public KeyedService,
public mojom::ZCashWalletService,
KeyringServiceObserverBase {
public:
using UtxoMap = std::map<std::string, std::vector<zcash::ZCashUtxo>>;
using UtxoMap = std::map<std::string, std::vector<mojom::ZCashUtxoPtr>>;
using RunDiscoveryResult =
base::expected<std::vector<mojom::ZCashAddressPtr>, std::string>;
using GetUtxosCallback =
@@ -122,7 +121,7 @@ class ZCashWalletService : public KeyedService,
void OnGetUtxos(
scoped_refptr<GetTransparentUtxosContext> context,
const std::string& current_address,
base::expected<std::vector<zcash::ZCashUtxo>, std::string> result);
base::expected<mojom::GetAddressUtxosResponsePtr, std::string> result);
void WorkOnGetUtxos(scoped_refptr<GetTransparentUtxosContext> context);
void OnDiscoveryDoneForBalance(mojom::AccountIdPtr account_id,
@@ -133,19 +132,19 @@ class ZCashWalletService : public KeyedService,
base::expected<UtxoMap, std::string> result);
void OnTransactionResolvedForStatus(
GetTransactionStatusCallback callback,
base::expected<zcash::RawTransaction, std::string> result);
base::expected<mojom::RawTransactionPtr, std::string> result);
void OnResolveLastBlockHeightForSendTransaction(
const std::string& chain_id,
const mojom::AccountIdPtr& account_id,
ZCashTransaction zcash_transaction,
SignAndPostTransactionCallback callback,
base::expected<zcash::BlockID, std::string> result);
base::expected<mojom::BlockIDPtr, std::string> result);
void OnSendTransactionResult(
SignAndPostTransactionCallback callback,
ZCashTransaction zcash_transaction,
base::expected<zcash::SendResponse, std::string> result);
base::expected<mojom::SendResponsePtr, std::string> result);
void CreateTransactionTaskDone(CreateTransparentTransactionTask* task);
@@ -128,14 +128,14 @@ void DiscoverNextUnusedZCashAddressTask::WorkOnTask() {
}
void DiscoverNextUnusedZCashAddressTask::OnGetLastBlock(
base::expected<zcash::BlockID, std::string> result) {
if (!result.has_value()) {
base::expected<mojom::BlockIDPtr, std::string> result) {
if (!result.has_value() || !result.value()) {
error_ = result.error();
WorkOnTask();
return;
}
block_end_ = result.value().height();
block_end_ = (*result)->height;
WorkOnTask();
}
@@ -237,14 +237,14 @@ void CreateTransparentTransactionTask::WorkOnTask() {
}
void CreateTransparentTransactionTask::OnGetChainHeight(
base::expected<zcash::BlockID, std::string> result) {
if (!result.has_value()) {
base::expected<mojom::BlockIDPtr, std::string> result) {
if (!result.has_value() || !result.value()) {
SetError(std::move(result).error());
WorkOnTask();
return;
}
chain_height_ = result.value().height();
chain_height_ = (*result)->height;
WorkOnTask();
}
@@ -281,8 +281,12 @@ bool CreateTransparentTransactionTask::PickInputs() {
std::vector<ZCashTransaction::TxInput> all_inputs;
for (const auto& item : utxo_map_) {
for (const auto& utxo : item.second) {
if (!utxo) {
error_ = l10n_util::GetStringUTF8(IDS_WALLET_INTERNAL_ERROR);
return false;
}
if (auto input =
ZCashTransaction::TxInput::FromRpcUtxo(item.first, utxo)) {
ZCashTransaction::TxInput::FromRpcUtxo(item.first, *utxo)) {
all_inputs.emplace_back(std::move(*input));
}
}
@@ -54,7 +54,7 @@ class DiscoverNextUnusedZCashAddressTask
void WorkOnTask();
void OnGetIsKnownAddress(base::expected<bool, std::string> stats);
void OnGetLastBlock(base::expected<zcash::BlockID, std::string> result);
void OnGetLastBlock(base::expected<mojom::BlockIDPtr, std::string> result);
base::WeakPtr<ZCashWalletService> zcash_wallet_service_;
mojom::AccountIdPtr account_id_;
@@ -91,7 +91,7 @@ class CreateTransparentTransactionTask {
bool PickInputs();
bool PrepareOutputs();
void OnGetChainHeight(base::expected<zcash::BlockID, std::string> result);
void OnGetChainHeight(base::expected<mojom::BlockIDPtr, std::string> result);
void OnGetUtxos(
base::expected<ZCashWalletService::UtxoMap, std::string> utxo_map);
void OnGetChangeAddress(
@@ -25,6 +25,7 @@
#include "brave/components/brave_wallet/common/features.h"
#include "brave/components/brave_wallet/common/hex_utils.h"
#include "brave/components/brave_wallet/common/zcash_utils.h"
#include "brave/components/services/brave_wallet/public/mojom/zcash_decoder.mojom.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -179,8 +180,8 @@ TEST_F(ZCashWalletServiceUnitTest, SignAndPostTransaction) {
.WillByDefault(
::testing::Invoke([](const std::string& chain_id,
ZCashRpc::GetLatestBlockCallback callback) {
zcash::BlockID response;
response.set_height(2286687);
mojom::BlockIDPtr response = mojom::BlockID::New();
response->height = 2286687;
std::move(callback).Run(std::move(response));
}));
@@ -200,8 +201,8 @@ TEST_F(ZCashWalletServiceUnitTest, SignAndPostTransaction) {
.WillOnce([&](const std::string& chain_id, const std::string& data,
ZCashRpc::SendTransactionCallback callback) {
captured_data = data;
zcash::SendResponse response;
response.set_errorcode(0);
mojom::SendResponsePtr response = mojom::SendResponse::New();
response->error_code = 0;
std::move(callback).Run(std::move(response));
});
zcash_wallet_service_->SignAndPostTransaction(
@@ -232,8 +233,8 @@ TEST_F(ZCashWalletServiceUnitTest, AddressDiscovery) {
.WillByDefault(
::testing::Invoke([](const std::string& chain_id,
ZCashRpc::GetLatestBlockCallback callback) {
zcash::BlockID response;
response.set_height(2286687);
mojom::BlockIDPtr response = mojom::BlockID::New();
response->height = 2286687;
std::move(callback).Run(std::move(response));
}));
@@ -347,8 +348,8 @@ TEST_F(ZCashWalletServiceUnitTest, AddressDiscovery_FromPrefs) {
.WillByDefault(
::testing::Invoke([](const std::string& chain_id,
ZCashRpc::GetLatestBlockCallback callback) {
zcash::BlockID response;
response.set_height(2286687);
mojom::BlockIDPtr response = mojom::BlockID::New();
response->height = 2286687;
std::move(callback).Run(std::move(response));
}));
+22
View File
@@ -0,0 +1,22 @@
# Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
source_set("lib") {
visibility = [
"//brave/components/services/brave_wallet/public/cpp",
"//chrome/utility:*",
]
sources = [
"brave_wallet_utils_service_impl.cc",
"brave_wallet_utils_service_impl.h",
]
deps = [
"//brave/components/services/brave_wallet/public/mojom",
"//brave/components/services/brave_wallet/zcash:zcash_decoder",
"//mojo/public/cpp/system",
]
}
@@ -0,0 +1,30 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#include "brave/components/services/brave_wallet/brave_wallet_utils_service_impl.h"
#include <memory>
#include <utility>
#include "brave/components/services/brave_wallet/zcash/zcash_decoder.h"
namespace brave_wallet {
BraveWalletUtilsServiceImpl::BraveWalletUtilsServiceImpl(
mojo::PendingReceiver<mojom::BraveWalletUtilsService> receiver)
: receiver_(this, std::move(receiver)) {}
BraveWalletUtilsServiceImpl::~BraveWalletUtilsServiceImpl() = default;
void BraveWalletUtilsServiceImpl::CreateZCashDecoderService(
mojo::PendingAssociatedReceiver<mojom::ZCashDecoder>
zcash_decoder_receiver) {
if (!instance_) {
instance_ = mojo::MakeSelfOwnedAssociatedReceiver(
std::make_unique<ZCashDecoder>(), std::move(zcash_decoder_receiver));
}
}
} // namespace brave_wallet
@@ -0,0 +1,39 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_BRAVE_WALLET_UTILS_SERVICE_IMPL_H_
#define BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_BRAVE_WALLET_UTILS_SERVICE_IMPL_H_
#include "brave/components/services/brave_wallet/public/mojom/brave_wallet_utils_service.mojom.h"
#include "brave/components/services/brave_wallet/public/mojom/zcash_decoder.mojom.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
namespace brave_wallet {
class BraveWalletUtilsServiceImpl : public mojom::BraveWalletUtilsService {
public:
explicit BraveWalletUtilsServiceImpl(
mojo::PendingReceiver<mojom::BraveWalletUtilsService> receiver);
~BraveWalletUtilsServiceImpl() override;
BraveWalletUtilsServiceImpl(const BraveWalletUtilsServiceImpl&) = delete;
BraveWalletUtilsServiceImpl& operator=(const BraveWalletUtilsServiceImpl&) =
delete;
void CreateZCashDecoderService(
mojo::PendingAssociatedReceiver<mojom::ZCashDecoder>
zcash_decoder_receiver) override;
private:
mojo::Receiver<mojom::BraveWalletUtilsService> receiver_;
mojo::SelfOwnedAssociatedReceiverRef<mojom::ZCashDecoder> instance_;
};
} // namespace brave_wallet
#endif // BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_BRAVE_WALLET_UTILS_SERVICE_IMPL_H_
@@ -0,0 +1,20 @@
# Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
source_set("content") {
visibility = [ "//brave/components/services/brave_wallet/public/cpp" ]
sources = [
"brave_wallet_utils_service_launcher.cc",
"brave_wallet_utils_service_launcher.h",
]
deps = [
"//brave/app:brave_generated_resources_grit",
"//brave/components/services/brave_wallet/public/mojom",
"//content/public/browser",
"//mojo/public/cpp/bindings",
]
}
@@ -0,0 +1,4 @@
include_rules = [
"+content/public/browser",
]
@@ -0,0 +1,24 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#include "brave/components/services/brave_wallet/content/brave_wallet_utils_service_launcher.h"
#include <utility>
#include "brave/grit/brave_generated_resources.h"
#include "content/public/browser/service_process_host.h"
namespace brave_wallet {
void LaunchBraveWalletUtilsService(
mojo::PendingReceiver<mojom::BraveWalletUtilsService> receiver) {
content::ServiceProcessHost::Launch(
std::move(receiver),
content::ServiceProcessHost::Options()
.WithDisplayName(IDS_UTILITY_PROCESS_WALLET_UTILS_NAME)
.Pass());
}
} // namespace brave_wallet
@@ -0,0 +1,20 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_CONTENT_BRAVE_WALLET_UTILS_SERVICE_LAUNCHER_H_
#define BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_CONTENT_BRAVE_WALLET_UTILS_SERVICE_LAUNCHER_H_
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "brave/components/services/brave_wallet/public/mojom/brave_wallet_utils_service.mojom.h"
namespace brave_wallet {
void LaunchBraveWalletUtilsService(
mojo::PendingReceiver<mojom::BraveWalletUtilsService> receiver);
} // namespace brave_wallet
#endif // BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_CONTENT_BRAVE_WALLET_UTILS_SERVICE_LAUNCHER_H_
@@ -0,0 +1,29 @@
# Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
source_set("cpp") {
visibility = [
"//brave/components/brave_wallet/browser:*",
"//chrome/utility:*",
]
sources = [
"brave_wallet_utils_service.cc",
"brave_wallet_utils_service.h",
"brave_wallet_utils_service_in_process_launcher.cc",
"brave_wallet_utils_service_in_process_launcher.h",
]
deps = [
"//brave/components/services/brave_wallet:lib",
"//brave/components/services/brave_wallet/public/mojom",
"//brave/components/services/brave_wallet/zcash:zcash_decoder",
"//mojo/public/cpp/bindings",
]
if (!is_ios) {
deps += [ "//brave/components/services/brave_wallet/content" ]
}
}
@@ -0,0 +1,50 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#include "brave/components/services/brave_wallet/public/cpp/brave_wallet_utils_service.h"
#include <utility>
#include "base/no_destructor.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_IOS)
#include "brave/components/services/brave_wallet/public/cpp/brave_wallet_utils_service_in_process_launcher.h"
#else
#include "brave/components/services/brave_wallet/content/brave_wallet_utils_service_launcher.h"
#endif
namespace brave_wallet {
BraveWalletUtilsService::BraveWalletUtilsService() = default;
BraveWalletUtilsService::~BraveWalletUtilsService() = default;
// static
BraveWalletUtilsService* BraveWalletUtilsService::GetInstance() {
static base::NoDestructor<BraveWalletUtilsService> service;
return service.get();
}
void BraveWalletUtilsService::CreateZCashDecoder(
mojo::PendingAssociatedReceiver<mojom::ZCashDecoder> receiver) {
MaybeLaunchService();
brave_wallet_utils_service_->CreateZCashDecoderService(std::move(receiver));
}
void BraveWalletUtilsService::MaybeLaunchService() {
#if BUILDFLAG(IS_IOS)
LaunchInProcessBraveWalletUtilsService(
brave_wallet_utils_service_.BindNewPipeAndPassReceiver());
brave_wallet_utils_service_.reset_on_disconnect();
#else
LaunchBraveWalletUtilsService(
brave_wallet_utils_service_.BindNewPipeAndPassReceiver());
brave_wallet_utils_service_.reset_on_disconnect();
// 10 minutes is a default wallet lock time
brave_wallet_utils_service_.reset_on_idle_timeout(base::Minutes(10));
#endif
}
} // namespace brave_wallet
@@ -0,0 +1,41 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_BRAVE_WALLET_UTILS_SERVICE_H_
#define BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_BRAVE_WALLET_UTILS_SERVICE_H_
#include "brave/components/services/brave_wallet/public/mojom/brave_wallet_utils_service.mojom.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace brave_wallet {
/**
* Launches and communicates mojom::BraveWalletUtilsService in separate process.
*/
class BraveWalletUtilsService {
public:
BraveWalletUtilsService();
~BraveWalletUtilsService();
BraveWalletUtilsService(const BraveWalletUtilsService&) = delete;
BraveWalletUtilsService& operator=(const BraveWalletUtilsService&) = delete;
// Creates decoder in brave wallet utils process and provides handles.
void CreateZCashDecoder(
mojo::PendingAssociatedReceiver<mojom::ZCashDecoder> receiver);
static BraveWalletUtilsService* GetInstance();
private:
void MaybeLaunchService();
mojo::Remote<mojom::BraveWalletUtilsService> brave_wallet_utils_service_;
base::WeakPtrFactory<BraveWalletUtilsService> weak_ptr_factory_{this};
};
} // namespace brave_wallet
#endif // BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_BRAVE_WALLET_UTILS_SERVICE_H_
@@ -0,0 +1,29 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_CONTENT_BRAVE_WALLET_UTILS_SERVICE_LAUNCHER_H_
#define BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_CONTENT_BRAVE_WALLET_UTILS_SERVICE_LAUNCHER_H_
#include "brave/components/services/brave_wallet/public/cpp/brave_wallet_utils_service_in_process_launcher.h"
#include <memory>
#include <utility>
#include "brave/components/services/brave_wallet/brave_wallet_utils_service_impl.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
namespace brave_wallet {
void LaunchInProcessBraveWalletUtilsService(
mojo::PendingReceiver<mojom::BraveWalletUtilsService> receiver) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<BraveWalletUtilsServiceImpl>(
mojo::PendingReceiver<mojom::BraveWalletUtilsService>()),
std::move(receiver));
}
} // namespace brave_wallet
#endif // BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_CONTENT_BRAVE_WALLET_UTILS_SERVICE_LAUNCHER_H_
@@ -0,0 +1,19 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_BRAVE_WALLET_UTILS_SERVICE_IN_PROCESS_LAUNCHER_H_
#define BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_BRAVE_WALLET_UTILS_SERVICE_IN_PROCESS_LAUNCHER_H_
#include "brave/components/services/brave_wallet/public/mojom/brave_wallet_utils_service.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
namespace brave_wallet {
void LaunchInProcessBraveWalletUtilsService(
mojo::PendingReceiver<mojom::BraveWalletUtilsService> receiver);
} // namespace brave_wallet
#endif // BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_BRAVE_WALLET_UTILS_SERVICE_IN_PROCESS_LAUNCHER_H_
@@ -0,0 +1,13 @@
# Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
source_set("utils") {
sources = [
"protobuf_utils.cc",
"protobuf_utils.h",
]
deps = [ "//base" ]
}
@@ -0,0 +1,48 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#include "brave/components/services/brave_wallet/public/cpp/utils/protobuf_utils.h"
#include <utility>
#include "base/big_endian.h"
#include "base/functional/callback.h"
namespace brave_wallet {
namespace {
constexpr size_t kGrpcHeaderSize = 5;
constexpr char kNoCompression = 0;
} // namespace
std::string GetPrefixedProtobuf(const std::string& serialized_proto) {
std::string result(kGrpcHeaderSize, 0);
result[0] = kNoCompression;
base::WriteBigEndian<uint32_t>(&result[1], serialized_proto.size());
result.append(serialized_proto);
return result;
}
std::optional<std::string> ResolveSerializedMessage(
const std::string& grpc_response_body) {
if (grpc_response_body.size() < kGrpcHeaderSize) {
return std::nullopt;
}
if (grpc_response_body[0] != kNoCompression) {
// Compression is not supported yet
return std::nullopt;
}
uint32_t size = 0;
base::ReadBigEndian(
reinterpret_cast<const uint8_t*>(&(grpc_response_body[1])), &size);
if (grpc_response_body.size() != size + kGrpcHeaderSize) {
return std::nullopt;
}
return grpc_response_body.substr(kGrpcHeaderSize);
}
} // namespace brave_wallet
@@ -0,0 +1,25 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_UTILS_PROTOBUF_UTILS_H_
#define BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_UTILS_PROTOBUF_UTILS_H_
#include <optional>
#include <string>
namespace brave_wallet {
// Prefixes provided serialized protobuf with compression byte and 4 bytes of
// message size. See
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
std::string GetPrefixedProtobuf(const std::string& serialized_proto);
// Resolves serialized protobuf from length-prefixed string
std::optional<std::string> ResolveSerializedMessage(
const std::string& grpc_response_body);
} // namespace brave_wallet
#endif // BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_PUBLIC_CPP_UTILS_PROTOBUF_UTILS_H_
@@ -0,0 +1,17 @@
# Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [
"brave_wallet_utils_service.mojom",
"zcash_decoder.mojom",
]
public_deps = [ "//mojo/public/mojom/base" ]
deps = [ "//sandbox/policy/mojom" ]
}
@@ -0,0 +1,15 @@
// Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
module brave_wallet.mojom;
import "brave/components/services/brave_wallet/public/mojom/zcash_decoder.mojom";
import "sandbox/policy/mojom/sandbox.mojom";
[ServiceSandbox=sandbox.mojom.Sandbox.kService]
interface BraveWalletUtilsService {
CreateZCashDecoderService(
pending_associated_receiver<ZCashDecoder> zcash_decoder_receiver);
};
@@ -0,0 +1,42 @@
// Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
module brave_wallet.mojom;
struct ZCashUtxo {
string address;
array<uint8> tx_id;
int32 index;
array<uint8> script;
int64 value_zat;
uint64 height;
};
struct GetAddressUtxosResponse {
array<ZCashUtxo> address_utxos;
};
struct BlockID {
uint64 height;
array<uint8> hash;
};
struct SendResponse {
int32 error_code;
string error_message;
};
struct RawTransaction {
array<uint8> data;
uint64 height;
};
interface ZCashDecoder {
ParseBlockID(string data) => (BlockID? value);
ParseGetAddressUtxos(string data) => (GetAddressUtxosResponse? value);
ParseSendResponse(string data) => (SendResponse? value);
ParseRawTransaction(string adata) => (RawTransaction? tx);
};
@@ -0,0 +1,10 @@
# Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
import("//third_party/protobuf/proto_library.gni")
proto_library("zcash_proto") {
sources = [ "zcash_grpc_data.proto" ]
}
@@ -0,0 +1,38 @@
# Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/.
import("//mojo/public/tools/bindings/mojom.gni")
source_set("zcash_decoder") {
visibility = [ "//brave/components/services/brave_wallet/*" ]
sources = [
"zcash_decoder.cc",
"zcash_decoder.h",
]
deps = [
"//base",
"//brave/components/services/brave_wallet/public/cpp/utils",
"//brave/components/services/brave_wallet/public/mojom",
"//brave/components/services/brave_wallet/public/proto:zcash_proto",
]
}
source_set("zcash_decoder_unit_tests") {
testonly = true
sources = [
"//brave/components/services/brave_wallet/zcash/zcash_decoder_unittest.cc",
]
deps = [
"//base/test:test_support",
"//brave/components/brave_wallet/common:test_support",
"//brave/components/services/brave_wallet/public/cpp/utils",
"//brave/components/services/brave_wallet/public/proto:zcash_proto",
"//brave/components/services/brave_wallet/zcash:zcash_decoder",
"//testing/gtest",
]
}
@@ -0,0 +1,84 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#include "brave/components/services/brave_wallet/zcash/zcash_decoder.h"
#include <utility>
#include "base/big_endian.h"
#include "brave/components/services/brave_wallet/public/cpp/utils/protobuf_utils.h"
#include "brave/components/services/brave_wallet/public/proto/zcash_grpc_data.pb.h"
namespace brave_wallet {
ZCashDecoder::ZCashDecoder() = default;
ZCashDecoder::~ZCashDecoder() = default;
void ZCashDecoder::ParseRawTransaction(const std::string& data,
ParseRawTransactionCallback callback) {
zcash::RawTransaction result;
auto serialized_message = ResolveSerializedMessage(data);
if (!serialized_message ||
!result.ParseFromString(serialized_message.value())) {
std::move(callback).Run(nullptr);
return;
}
std::vector<uint8_t> tx_data(result.data().begin(), result.data().end());
std::move(callback).Run(
mojom::RawTransaction::New(std::move(tx_data), result.height()));
}
void ZCashDecoder::ParseBlockID(const std::string& data,
ParseBlockIDCallback callback) {
zcash::BlockID result;
auto serialized_message = ResolveSerializedMessage(data);
if (!serialized_message ||
!result.ParseFromString(serialized_message.value())) {
std::move(callback).Run(nullptr);
return;
}
std::vector<uint8_t> hash(result.hash().begin(), result.hash().end());
std::move(callback).Run(
mojom::BlockID::New(result.height(), std::move(hash)));
}
void ZCashDecoder::ParseGetAddressUtxos(const std::string& data,
ParseGetAddressUtxosCallback callback) {
zcash::GetAddressUtxosResponse result;
auto serialized_message = ResolveSerializedMessage(data);
if (!serialized_message ||
!result.ParseFromString(serialized_message.value())) {
std::move(callback).Run(nullptr);
return;
}
std::vector<mojom::ZCashUtxoPtr> utxos;
for (int i = 0; i < result.addressutxos_size(); i++) {
const zcash::ZCashUtxo& item = result.addressutxos(i);
std::vector<uint8_t> tx_id(item.txid().begin(), item.txid().end());
std::vector<uint8_t> script(item.script().begin(), item.script().end());
utxos.push_back(mojom::ZCashUtxo::New(item.address(), std::move(tx_id),
item.index(), std::move(script),
item.valuezat(), item.height()));
}
std::move(callback).Run(
mojom::GetAddressUtxosResponse::New(std::move(utxos)));
}
void ZCashDecoder::ParseSendResponse(const std::string& data,
ParseSendResponseCallback callback) {
zcash::SendResponse result;
auto serialized_message = ResolveSerializedMessage(data);
if (!serialized_message ||
!result.ParseFromString(serialized_message.value())) {
std::move(callback).Run(nullptr);
return;
}
std::move(callback).Run(
mojom::SendResponse::New(result.errorcode(), result.errormessage()));
}
} // namespace brave_wallet
@@ -0,0 +1,39 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_ZCASH_ZCASH_DECODER_H_
#define BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_ZCASH_ZCASH_DECODER_H_
#include "brave/components/services/brave_wallet/public/mojom/zcash_decoder.mojom.h"
#include <string>
#include <vector>
#include "mojo/public/cpp/bindings/receiver_set.h"
namespace brave_wallet {
// Parses Zcash protobuf objects and translates them to mojo.
class ZCashDecoder : public mojom::ZCashDecoder {
public:
ZCashDecoder();
~ZCashDecoder() override;
ZCashDecoder(const ZCashDecoder&) = delete;
ZCashDecoder& operator=(const ZCashDecoder&) = delete;
void ParseRawTransaction(const std::string& data,
ParseRawTransactionCallback callback) override;
void ParseBlockID(const std::string& data,
ParseBlockIDCallback callback) override;
void ParseGetAddressUtxos(const std::string& data,
ParseGetAddressUtxosCallback callback) override;
void ParseSendResponse(const std::string& data,
ParseSendResponseCallback) override;
};
} // namespace brave_wallet
#endif // BRAVE_COMPONENTS_SERVICES_BRAVE_WALLET_ZCASH_ZCASH_DECODER_H_
@@ -0,0 +1,160 @@
/* Copyright (c) 2024 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 https://mozilla.org/MPL/2.0/. */
#include "brave/components/services/brave_wallet/zcash/zcash_decoder.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/test/bind.h"
#include "base/test/mock_callback.h"
#include "brave/components/brave_wallet/common/test_utils.h"
#include "brave/components/services/brave_wallet/public/cpp/utils/protobuf_utils.h"
#include "brave/components/services/brave_wallet/public/proto/zcash_grpc_data.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace brave_wallet {
namespace {
std::vector<uint8_t> ToBytes(const std::string& str) {
return std::vector<uint8_t>(str.begin(), str.end());
}
} // namespace
class ZCashDecoderUnitTest : public testing::Test {
public:
ZCashDecoderUnitTest() = default;
ZCashDecoderUnitTest(const ZCashDecoderUnitTest&) = delete;
ZCashDecoderUnitTest& operator=(const ZCashDecoderUnitTest&) = delete;
~ZCashDecoderUnitTest() override = default;
void SetUp() override { decoder_ = std::make_unique<ZCashDecoder>(); }
void TearDown() override {}
ZCashDecoder* decoder() { return decoder_.get(); }
private:
std::unique_ptr<ZCashDecoder> decoder_;
};
TEST_F(ZCashDecoderUnitTest, ParseBlockID) {
// Correct
{
zcash::BlockID block_id;
block_id.set_height(64u);
block_id.set_hash("abcd");
mojom::BlockIDPtr result;
base::MockCallback<ZCashDecoder::ParseBlockIDCallback> callback;
EXPECT_CALL(callback,
Run(EqualsMojo(mojom::BlockID::New(64u, ToBytes("abcd")))));
decoder()->ParseBlockID(GetPrefixedProtobuf(block_id.SerializeAsString()),
callback.Get());
}
// Incorrect
{
mojom::BlockIDPtr result;
std::optional<std::string> error;
base::MockCallback<ZCashDecoder::ParseBlockIDCallback> callback;
EXPECT_CALL(callback, Run(EqualsMojo(mojom::BlockIDPtr())));
decoder()->ParseBlockID("123", callback.Get());
}
}
TEST_F(ZCashDecoderUnitTest, ParseGetAddressUtxos) {
// Correct
{
zcash::ZCashUtxo utxo1;
utxo1.set_address("addr1");
utxo1.set_txid("txid1");
utxo1.set_valuezat(1u);
zcash::ZCashUtxo utxo2;
utxo2.set_address("addr2");
utxo2.set_txid("txid2");
utxo2.set_valuezat(2u);
zcash::GetAddressUtxosResponse response;
*(response.add_addressutxos()) = utxo1;
*(response.add_addressutxos()) = utxo2;
base::MockCallback<ZCashDecoder::ParseGetAddressUtxosCallback> callback;
EXPECT_CALL(
callback,
Run(testing::Truly(
[&](const mojom::GetAddressUtxosResponsePtr& result) {
EXPECT_TRUE(result);
EXPECT_EQ(result->address_utxos[0]->address, "addr1");
EXPECT_EQ(result->address_utxos[0]->tx_id, ToBytes("txid1"));
EXPECT_EQ(result->address_utxos[0]->value_zat, 1u);
EXPECT_EQ(result->address_utxos[1]->address, "addr2");
EXPECT_EQ(result->address_utxos[1]->tx_id, ToBytes("txid2"));
EXPECT_EQ(result->address_utxos[1]->value_zat, 2u);
return true;
})));
decoder()->ParseGetAddressUtxos(
GetPrefixedProtobuf(response.SerializeAsString()), callback.Get());
}
// Incorrect
{
mojom::GetAddressUtxosResponsePtr result;
std::optional<std::string> error;
base::MockCallback<ZCashDecoder::ParseGetAddressUtxosCallback> callback;
EXPECT_CALL(callback, Run(EqualsMojo(mojom::GetAddressUtxosResponsePtr())));
decoder()->ParseGetAddressUtxos("123", callback.Get());
}
}
TEST_F(ZCashDecoderUnitTest, ParseSendResponse) {
// Correct
{
zcash::SendResponse response;
response.set_errorcode(1);
response.set_errormessage("123");
mojom::SendResponsePtr result;
base::MockCallback<ZCashDecoder::ParseSendResponseCallback> callback;
EXPECT_CALL(callback, Run(EqualsMojo(mojom::SendResponse::New(1, "123"))));
decoder()->ParseSendResponse(
GetPrefixedProtobuf(response.SerializeAsString()), callback.Get());
}
// Incorrect
{
mojom::SendResponsePtr result;
std::optional<std::string> error;
base::MockCallback<ZCashDecoder::ParseSendResponseCallback> callback;
EXPECT_CALL(callback, Run(EqualsMojo(mojom::SendResponsePtr())));
decoder()->ParseSendResponse("123", callback.Get());
}
}
TEST_F(ZCashDecoderUnitTest, ParseRawTransaction) {
// Correct
{
zcash::RawTransaction response;
response.set_height(2);
response.set_data("data");
mojom::RawTransactionPtr result;
base::MockCallback<ZCashDecoder::ParseRawTransactionCallback> callback;
EXPECT_CALL(
callback,
Run(EqualsMojo(mojom::RawTransaction::New(ToBytes("data"), 2u))));
decoder()->ParseRawTransaction(
GetPrefixedProtobuf(response.SerializeAsString()), callback.Get());
}
// Incorrect
{
mojom::RawTransactionPtr result;
std::optional<std::string> error;
base::MockCallback<ZCashDecoder::ParseRawTransactionCallback> callback;
EXPECT_CALL(callback, Run(EqualsMojo(mojom::RawTransactionPtr())));
decoder()->ParseRawTransaction("123", callback.Get());
}
}
} // namespace brave_wallet
+1
View File
@@ -257,6 +257,7 @@ test("brave_unit_tests") {
"//brave/components/resources:strings_grit",
"//brave/components/script_injector/renderer:unit_tests",
"//brave/components/search_engines:unit_tests",
"//brave/components/services/brave_wallet/zcash:zcash_decoder_unit_tests",
"//brave/components/services/ipfs/test:ipfs_service_unit_tests",
"//brave/components/sessions/content:unit_tests",
"//brave/components/signin/public/identity_manager:unit_tests",
+12
View File
@@ -30,6 +30,9 @@
#include "brave/components/services/tor/tor_launcher_impl.h"
#endif
#include "brave/components/services/brave_wallet/brave_wallet_utils_service_impl.h"
#include "brave/components/services/brave_wallet/public/mojom/brave_wallet_utils_service.mojom.h"
namespace {
#if !BUILDFLAG(IS_ANDROID)
@@ -63,6 +66,13 @@ auto RunBatAdsService(
return std::make_unique<bat_ads::BatAdsServiceImpl>(std::move(receiver));
}
auto RunBraveWalletUtilsService(
mojo::PendingReceiver<brave_wallet::mojom::BraveWalletUtilsService>
receiver) {
return std::make_unique<brave_wallet::BraveWalletUtilsServiceImpl>(
std::move(receiver));
}
} // namespace
BraveContentUtilityClient::BraveContentUtilityClient() = default;
@@ -86,5 +96,7 @@ void BraveContentUtilityClient::RegisterMainThreadServices(
services.Add(RunBatAdsService);
services.Add(RunBraveWalletUtilsService);
return ChromeContentUtilityClient::RegisterMainThreadServices(services);
}
+2
View File
@@ -27,6 +27,8 @@ brave_utility_deps = [
"//brave/components/services/bat_ads/public/interfaces",
"//brave/components/services/bat_rewards:lib",
"//brave/components/services/bat_rewards/public/interfaces",
"//brave/components/services/brave_wallet:lib",
"//brave/components/services/brave_wallet/public/mojom",
"//brave/components/tor/buildflags",
"//mojo/public/cpp/bindings",
]