diff --git a/browser/ui/webui/brave_wallet/android/android_wallet_page_ui.cc b/browser/ui/webui/brave_wallet/android/android_wallet_page_ui.cc index 3f015b2cbd55..e78134e2f531 100644 --- a/browser/ui/webui/brave_wallet/android/android_wallet_page_ui.cc +++ b/browser/ui/webui/brave_wallet/android/android_wallet_page_ui.cc @@ -52,11 +52,9 @@ AndroidWalletPageUI::AndroidWalletPageUI(content::WebUI* web_ui, // Add required resources. if (url.host() == kWalletPageHost) { - webui::SetupWebUIDataSource( - source, - UNSAFE_TODO(base::make_span(kBraveWalletPageGenerated, - kBraveWalletPageGeneratedSize)), - IDR_WALLET_PAGE_HTML); + webui::SetupWebUIDataSource(source, + base::make_span(kBraveWalletPageGenerated), + IDR_WALLET_PAGE_HTML); } else { NOTREACHED_IN_MIGRATION() << "Failed to find page resources for:" << url.path(); diff --git a/browser/ui/webui/brave_wallet/ledger/ledger_ui.cc b/browser/ui/webui/brave_wallet/ledger/ledger_ui.cc index d5f245d96bf2..0aeb91799024 100644 --- a/browser/ui/webui/brave_wallet/ledger/ledger_ui.cc +++ b/browser/ui/webui/brave_wallet/ledger/ledger_ui.cc @@ -21,8 +21,7 @@ UntrustedLedgerUI::UntrustedLedgerUI(content::WebUI* web_ui) auto* untrusted_source = content::WebUIDataSource::CreateAndAdd( web_ui->GetWebContents()->GetBrowserContext(), kUntrustedLedgerURL); untrusted_source->SetDefaultResource(IDR_BRAVE_WALLET_LEDGER_BRIDGE_HTML); - untrusted_source->AddResourcePaths(UNSAFE_TODO( - base::make_span(kLedgerBridgeGenerated, kLedgerBridgeGeneratedSize))); + untrusted_source->AddResourcePaths(base::make_span(kLedgerBridgeGenerated)); untrusted_source->AddFrameAncestor(GURL(kBraveUIWalletPageURL)); untrusted_source->AddFrameAncestor(GURL(kBraveUIWalletPanelURL)); untrusted_source->OverrideContentSecurityPolicy( diff --git a/browser/ui/webui/brave_wallet/trezor/trezor_ui.cc b/browser/ui/webui/brave_wallet/trezor/trezor_ui.cc index 9e97e7c2a3b4..da0b17a1add0 100644 --- a/browser/ui/webui/brave_wallet/trezor/trezor_ui.cc +++ b/browser/ui/webui/brave_wallet/trezor/trezor_ui.cc @@ -25,8 +25,7 @@ UntrustedTrezorUI::UntrustedTrezorUI(content::WebUI* web_ui) auto* untrusted_source = content::WebUIDataSource::CreateAndAdd( web_ui->GetWebContents()->GetBrowserContext(), kUntrustedTrezorURL); untrusted_source->SetDefaultResource(IDR_BRAVE_WALLET_TREZOR_BRIDGE_HTML); - untrusted_source->AddResourcePaths(UNSAFE_TODO( - base::make_span(kTrezorBridgeGenerated, kTrezorBridgeGeneratedSize))); + untrusted_source->AddResourcePaths(base::make_span(kTrezorBridgeGenerated)); untrusted_source->AddFrameAncestor(GURL(kBraveUIWalletPageURL)); untrusted_source->AddFrameAncestor(GURL(kBraveUIWalletPanelURL)); untrusted_source->OverrideContentSecurityPolicy( diff --git a/browser/ui/webui/brave_wallet/wallet_page_ui.cc b/browser/ui/webui/brave_wallet/wallet_page_ui.cc index f69bd17d30af..d660e09e9d56 100644 --- a/browser/ui/webui/brave_wallet/wallet_page_ui.cc +++ b/browser/ui/webui/brave_wallet/wallet_page_ui.cc @@ -64,10 +64,7 @@ WalletPageUI::WalletPageUI(content::WebUI* web_ui) web_ui->AddMessageHandler(std::move(plural_string_handler)); NavigationBarDataProvider::Initialize(source, profile); webui::SetupWebUIDataSource( - source, - UNSAFE_TODO(base::make_span(kBraveWalletPageGenerated, - kBraveWalletPageGeneratedSize)), - IDR_WALLET_PAGE_HTML); + source, base::make_span(kBraveWalletPageGenerated), IDR_WALLET_PAGE_HTML); source->AddString("braveWalletLedgerBridgeUrl", kUntrustedLedgerURL); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ImgSrc, diff --git a/browser/ui/webui/brave_wallet/wallet_panel_ui.cc b/browser/ui/webui/brave_wallet/wallet_panel_ui.cc index 2116b243aa46..b7f32b926a36 100644 --- a/browser/ui/webui/brave_wallet/wallet_panel_ui.cc +++ b/browser/ui/webui/brave_wallet/wallet_panel_ui.cc @@ -66,11 +66,9 @@ WalletPanelUI::WalletPanelUI(content::WebUI* web_ui) plural_string_handler->AddLocalizedString( "braveWalletPendingTransactions", IDS_BRAVE_WALLET_PENDING_TRANSACTIONS); web_ui->AddMessageHandler(std::move(plural_string_handler)); - webui::SetupWebUIDataSource( - source, - UNSAFE_TODO(base::make_span(kBraveWalletPanelGenerated, - kBraveWalletPanelGeneratedSize)), - IDR_WALLET_PANEL_HTML); + webui::SetupWebUIDataSource(source, + base::make_span(kBraveWalletPanelGenerated), + IDR_WALLET_PANEL_HTML); source->AddString("braveWalletLedgerBridgeUrl", kUntrustedLedgerURL); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::FrameSrc, diff --git a/components/brave_wallet/browser/eip1559_transaction.cc b/components/brave_wallet/browser/eip1559_transaction.cc index 9541436c8e2d..5414cf63897a 100644 --- a/components/brave_wallet/browser/eip1559_transaction.cc +++ b/components/brave_wallet/browser/eip1559_transaction.cc @@ -9,6 +9,7 @@ #include #include +#include "base/containers/extend.h" #include "base/values.h" #include "brave/components/brave_wallet/browser/rlp_encode.h" #include "brave/components/brave_wallet/common/hash_utils.h" @@ -270,11 +271,9 @@ std::optional Eip1559Transaction::FromValue( return tx; } -std::vector Eip1559Transaction::GetMessageToSign(uint256_t chain_id, - bool hash) const { +std::vector Eip1559Transaction::GetMessageToSign( + uint256_t chain_id) const { DCHECK(nonce_); - std::vector result; - result.push_back(type_); base::Value::List list; list.Append(RLPUint256ToBlob(chain_id_)); @@ -287,9 +286,10 @@ std::vector Eip1559Transaction::GetMessageToSign(uint256_t chain_id, list.Append(base::Value(data_)); list.Append(base::Value(AccessListToValue(access_list_))); - const std::string rlp_msg = RLPEncode(base::Value(std::move(list))); - result.insert(result.end(), rlp_msg.begin(), rlp_msg.end()); - return hash ? KeccakHash(result) : result; + std::vector result; + result.push_back(type_); + base::Extend(result, RLPEncode(list)); + return result; } std::string Eip1559Transaction::GetSignedTransaction() const { @@ -361,10 +361,7 @@ std::vector Eip1559Transaction::Serialize() const { std::vector result; result.push_back(type_); - - const std::string rlp_msg = RLPEncode(base::Value(std::move(list))); - result.insert(result.end(), rlp_msg.begin(), rlp_msg.end()); - + base::Extend(result, RLPEncode(list)); return result; } diff --git a/components/brave_wallet/browser/eip1559_transaction.h b/components/brave_wallet/browser/eip1559_transaction.h index a58c6d3b2fd7..1d098c9cea9f 100644 --- a/components/brave_wallet/browser/eip1559_transaction.h +++ b/components/brave_wallet/browser/eip1559_transaction.h @@ -63,10 +63,9 @@ class Eip1559Transaction : public Eip2930Transaction { gas_estimation_ = estimation; } - // keccak256(0x02 || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, - // gasLimit, destination, value, data, access_list])) - std::vector GetMessageToSign(uint256_t chain_id = 0, - bool hash = true) const override; + // 0x02 || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, + // gasLimit, destination, value, data, access_list]) + std::vector GetMessageToSign(uint256_t chain_id) const override; // 0x02 || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, // destination, value, data, accessList, signatureYParity, signatureR, diff --git a/components/brave_wallet/browser/eip1559_transaction_unittest.cc b/components/brave_wallet/browser/eip1559_transaction_unittest.cc index 43c10e3d57ab..1742cf7e57cd 100644 --- a/components/brave_wallet/browser/eip1559_transaction_unittest.cc +++ b/components/brave_wallet/browser/eip1559_transaction_unittest.cc @@ -49,7 +49,7 @@ TEST(Eip1559TransactionUnitTest, GetMessageToSign) { access_list->push_back(item); - EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx.GetMessageToSign())), + EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx.GetHashedMessageToSign(0))), "fa81814f7dd57bad435657a05eabdba2815f41e3f15ddd6139027e7db56b0dea"); } @@ -143,7 +143,7 @@ TEST(Eip1559TransactionUnitTest, GetSignedTransactionAndHash) { int recid; const std::vector signature = - key.SignCompact(tx.GetMessageToSign(), &recid); + key.SignCompact(tx.GetHashedMessageToSign(0), &recid); tx.ProcessSignature(signature, recid); EXPECT_EQ(tx.GetSignedTransaction(), entry.signed_tx); EXPECT_EQ(tx.GetTransactionHash(), entry.hash); diff --git a/components/brave_wallet/browser/eip2930_transaction.cc b/components/brave_wallet/browser/eip2930_transaction.cc index e3b4e6440691..a39707e40a5a 100644 --- a/components/brave_wallet/browser/eip2930_transaction.cc +++ b/components/brave_wallet/browser/eip2930_transaction.cc @@ -8,6 +8,7 @@ #include #include +#include "base/containers/extend.h" #include "base/values.h" #include "brave/components/brave_wallet/browser/rlp_encode.h" #include "brave/components/brave_wallet/common/eth_address.h" @@ -161,11 +162,9 @@ Eip2930Transaction::ValueToAccessList(const base::Value::List& value) { return access_list; } -std::vector Eip2930Transaction::GetMessageToSign(uint256_t chain_id, - bool hash) const { +std::vector Eip2930Transaction::GetMessageToSign( + uint256_t chain_id) const { DCHECK(nonce_); - std::vector result; - result.push_back(type_); base::Value::List list; list.Append(RLPUint256ToBlob(chain_id_)); @@ -177,9 +176,10 @@ std::vector Eip2930Transaction::GetMessageToSign(uint256_t chain_id, list.Append(base::Value(data_)); list.Append(base::Value(AccessListToValue(access_list_))); - const std::string rlp_msg = RLPEncode(base::Value(std::move(list))); - result.insert(result.end(), rlp_msg.begin(), rlp_msg.end()); - return hash ? KeccakHash(result) : result; + std::vector result; + result.push_back(type_); + base::Extend(result, RLPEncode(list)); + return result; } std::string Eip2930Transaction::GetSignedTransaction() const { @@ -241,10 +241,7 @@ std::vector Eip2930Transaction::Serialize() const { std::vector result; result.push_back(type_); - - const std::string rlp_msg = RLPEncode(base::Value(std::move(list))); - result.insert(result.end(), rlp_msg.begin(), rlp_msg.end()); - + base::Extend(result, RLPEncode(list)); return result; } diff --git a/components/brave_wallet/browser/eip2930_transaction.h b/components/brave_wallet/browser/eip2930_transaction.h index e02fadb5998f..6c605bfa40e2 100644 --- a/components/brave_wallet/browser/eip2930_transaction.h +++ b/components/brave_wallet/browser/eip2930_transaction.h @@ -50,10 +50,9 @@ class Eip2930Transaction : public EthTransaction { const AccessList* access_list() const { return &access_list_; } AccessList* access_list() { return &access_list_; } - // keccak256(0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, - // accessList])) - std::vector GetMessageToSign(uint256_t chain_id = 0, - bool hash = true) const override; + // 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, + // accessList]) + std::vector GetMessageToSign(uint256_t chain_id) const override; // 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, // accessList, signatureYParity, signatureR, signatureS]) diff --git a/components/brave_wallet/browser/eip2930_transaction_unittest.cc b/components/brave_wallet/browser/eip2930_transaction_unittest.cc index a7a18700007b..d5a8e082b480 100644 --- a/components/brave_wallet/browser/eip2930_transaction_unittest.cc +++ b/components/brave_wallet/browser/eip2930_transaction_unittest.cc @@ -93,7 +93,7 @@ TEST(Eip2930TransactionUnitTest, GetMessageToSign) { access_list->push_back(item); - EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx.GetMessageToSign())), + EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx.GetHashedMessageToSign(0))), "78528e2724aa359c58c13e43a7c467eb721ce8d410c2a12ee62943a3aaefb60b"); } @@ -126,7 +126,7 @@ TEST(Eip2930TransactionUnitTest, GetSignedTransactionAndHash) { key.SetPrivateKey(private_key); int recid; const std::vector signature = - key.SignCompact(tx.GetMessageToSign(), &recid); + key.SignCompact(tx.GetHashedMessageToSign(0), &recid); ASSERT_FALSE(tx.IsSigned()); tx.ProcessSignature(signature, recid); diff --git a/components/brave_wallet/browser/ens_resolver_task.cc b/components/brave_wallet/browser/ens_resolver_task.cc index 90db35f05925..da1d19cb5b7d 100644 --- a/components/brave_wallet/browser/ens_resolver_task.cc +++ b/components/brave_wallet/browser/ens_resolver_task.cc @@ -167,7 +167,7 @@ std::optional OffchainLookupData::ExtractFromEthAbiPayload( auto sender = eth_abi::ExtractAddressFromTuple(args, 0); auto urls = eth_abi::ExtractStringArrayFromTuple(args, 1); auto call_data = eth_abi::ExtractBytesFromTuple(args, 2); - auto callback_function = eth_abi::ExtractFixedBytesFromTuple(args, 4, 3); + auto callback_function = eth_abi::ExtractFixedBytesFromTuple<4>(args, 3); auto extra_data = eth_abi::ExtractBytesFromTuple(args, 4); if (!sender.IsValid() || !urls || !call_data || !callback_function || @@ -543,14 +543,12 @@ void EnsResolverTask::OnFetchOffchainDone(APIRequestResult api_request_result) { offchain_lookup_attemps_left_--; DCHECK_GE(offchain_lookup_attemps_left_, 0); - DCHECK_EQ(offchain_lookup_data_->callback_function.size(), 4u); - UNSAFE_TODO(eth_abi::Span4 callback_selector( - offchain_lookup_data_->callback_function.begin(), 4u)); - - offchain_callback_call_ = eth_abi::TupleEncoder() - .AddBytes(*bytes_result) - .AddBytes(offchain_lookup_data_->extra_data) - .EncodeWithSelector(callback_selector); + + offchain_callback_call_ = + eth_abi::TupleEncoder() + .AddBytes(*bytes_result) + .AddBytes(offchain_lookup_data_->extra_data) + .EncodeWithSelector(offchain_lookup_data_->callback_function); offchain_lookup_data_.reset(); } diff --git a/components/brave_wallet/browser/ens_resolver_task.h b/components/brave_wallet/browser/ens_resolver_task.h index 1c0e399f870b..8284a34f62bc 100644 --- a/components/brave_wallet/browser/ens_resolver_task.h +++ b/components/brave_wallet/browser/ens_resolver_task.h @@ -55,7 +55,7 @@ struct OffchainLookupData { EthAddress sender; std::vector urls; std::vector call_data; - std::vector callback_function; + eth_abi::Bytes4 callback_function; std::vector extra_data; }; diff --git a/components/brave_wallet/browser/eth_allowance_manager.cc b/components/brave_wallet/browser/eth_allowance_manager.cc index 78693c31b7fb..daf63274055a 100644 --- a/components/brave_wallet/browser/eth_allowance_manager.cc +++ b/components/brave_wallet/browser/eth_allowance_manager.cc @@ -8,6 +8,7 @@ #include #include +#include "base/containers/span.h" #include "base/no_destructor.h" #include "brave/components/brave_wallet/browser/blockchain_registry.h" #include "brave/components/brave_wallet/browser/json_rpc_service.h" @@ -164,7 +165,8 @@ void EthAllowanceManager::OnGetCurrentBlock( return; } - const auto approval_topic_hash = KeccakHash(kApprovalTopicFunctionSignature); + const auto approval_topic_hash = ToHex(KeccakHash( + base::byte_span_from_cstring(kApprovalTopicFunctionSignature))); for (const auto& account_address : account_addresses) { std::string account_address_hex; if (!PadHexEncodedParameter(account_address, &account_address_hex)) { diff --git a/components/brave_wallet/browser/eth_data_builder_unittest.cc b/components/brave_wallet/browser/eth_data_builder_unittest.cc index f5ae41214cc4..19f592bf14ce 100644 --- a/components/brave_wallet/browser/eth_data_builder_unittest.cc +++ b/components/brave_wallet/browser/eth_data_builder_unittest.cc @@ -253,7 +253,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_ETH) { ASSERT_TRUE(keys_array); EXPECT_THAT(*keys_array, ElementsAreArray({"crypto.ETH.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -272,7 +272,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_ETH) { ElementsAreArray({"crypto.USDT.version.BEP20.address", "crypto.USDT.address", "crypto.ETH.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -290,7 +290,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_ETH) { EXPECT_THAT(*keys_array, ElementsAreArray({"crypto.QWEQWE.address", "crypto.ETH.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -309,7 +309,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_SOL) { ASSERT_TRUE(keys_array); EXPECT_THAT(*keys_array, ElementsAreArray({"crypto.SOL.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -325,7 +325,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_SOL) { ASSERT_TRUE(keys_array); EXPECT_THAT(*keys_array, ElementsAreArray({"crypto.SOL.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -344,7 +344,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_SOL) { ElementsAreArray({"crypto.QWEQWE.version.SOLANA.address", "crypto.SOL.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -363,7 +363,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_FIL) { ASSERT_TRUE(keys_array); EXPECT_THAT(*keys_array, ElementsAreArray({"crypto.FIL.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -379,7 +379,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_FIL) { ASSERT_TRUE(keys_array); EXPECT_THAT(*keys_array, ElementsAreArray({"crypto.FIL.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } @@ -396,7 +396,7 @@ TEST(EthCallDataBuilderTest, GetWalletAddr_FIL) { ASSERT_TRUE(keys_array); EXPECT_THAT(*keys_array, ElementsAreArray({"crypto.FIL.address"})); - auto name_hash = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto name_hash = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); ASSERT_TRUE(name_hash); EXPECT_TRUE(base::ranges::equal(*name_hash, Namehash("test.crypto"))); } diff --git a/components/brave_wallet/browser/eth_topics_builder.cc b/components/brave_wallet/browser/eth_topics_builder.cc index eb39c88ac80e..df22a1bff346 100644 --- a/components/brave_wallet/browser/eth_topics_builder.cc +++ b/components/brave_wallet/browser/eth_topics_builder.cc @@ -7,6 +7,7 @@ #include +#include "base/containers/span.h" #include "brave/components/brave_wallet/browser/brave_wallet_utils.h" #include "brave/components/brave_wallet/common/hash_utils.h" #include "brave/components/brave_wallet/common/hex_utils.h" @@ -17,7 +18,8 @@ bool MakeAssetDiscoveryTopics( const std::vector& to_account_addresses, base::Value::List* topics) { // First topic matches full keccak hash of the erc20::Transfer event signature - topics->Append(brave_wallet::KeccakHash("Transfer(address,address,uint256)")); + topics->Append(ToHex(KeccakHash( + base::byte_span_from_cstring("Transfer(address,address,uint256)")))); // Second topic matches everything (any from_address) topics->Append(base::Value()); diff --git a/components/brave_wallet/browser/eth_transaction.cc b/components/brave_wallet/browser/eth_transaction.cc index 5c23c6de2b8d..46ad2953f9f4 100644 --- a/components/brave_wallet/browser/eth_transaction.cc +++ b/components/brave_wallet/browser/eth_transaction.cc @@ -9,6 +9,7 @@ #include #include "base/base64.h" +#include "base/containers/extend.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" @@ -171,8 +172,8 @@ std::optional EthTransaction::FromValue( return tx; } -std::vector EthTransaction::GetMessageToSign(uint256_t chain_id, - bool hash) const { +std::vector EthTransaction::GetMessageToSign( + uint256_t chain_id) const { DCHECK(nonce_); base::Value::List list; list.Append(RLPUint256ToBlob(nonce_.value())); @@ -187,9 +188,14 @@ std::vector EthTransaction::GetMessageToSign(uint256_t chain_id, list.Append(RLPUint256ToBlob(0)); } - const std::string message = RLPEncode(base::Value(std::move(list))); - auto result = std::vector(message.begin(), message.end()); - return hash ? KeccakHash(result) : result; + std::vector result; + base::Extend(result, RLPEncode(list)); + return result; +} + +KeccakHashArray EthTransaction::GetHashedMessageToSign( + uint256_t chain_id) const { + return KeccakHash(GetMessageToSign(chain_id)); } std::string EthTransaction::GetSignedTransaction() const { @@ -202,7 +208,7 @@ std::string EthTransaction::GetTransactionHash() const { DCHECK(IsSigned()); DCHECK(nonce_); - return KeccakHash(RLPEncode(Serialize())); + return ToHex(KeccakHash(RLPEncode(Serialize()))); } bool EthTransaction::ProcessVRS(const std::vector& v, diff --git a/components/brave_wallet/browser/eth_transaction.h b/components/brave_wallet/browser/eth_transaction.h index 126e8d2b435c..57961add0158 100644 --- a/components/brave_wallet/browser/eth_transaction.h +++ b/components/brave_wallet/browser/eth_transaction.h @@ -14,6 +14,7 @@ #include "brave/components/brave_wallet/common/brave_wallet.mojom.h" #include "brave/components/brave_wallet/common/brave_wallet_types.h" #include "brave/components/brave_wallet/common/eth_address.h" +#include "brave/components/brave_wallet/common/hash_utils.h" namespace base { class Value; @@ -69,13 +70,12 @@ class EthTransaction { bool IsToCreationAddress() const { return to_.IsEmpty(); } // return - // if hash == true: - // keccack(rlp([nonce, gasPrice, gasLimit, to, value, data, chainID, 0, 0])) - // else: // rlp([nonce, gasPrice, gasLimit, to, value, data, chainID, 0, 0]) // Support EIP-155 chain id - virtual std::vector GetMessageToSign(uint256_t chain_id, - bool hash = true) const; + virtual std::vector GetMessageToSign(uint256_t chain_id) const; + + // keccak(GetMessageToSign(chain_id)) + KeccakHashArray GetHashedMessageToSign(uint256_t chain_id) const; // return rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s]) virtual std::string GetSignedTransaction() const; diff --git a/components/brave_wallet/browser/eth_transaction_unittest.cc b/components/brave_wallet/browser/eth_transaction_unittest.cc index 2426e2d61636..aa0413b81c04 100644 --- a/components/brave_wallet/browser/eth_transaction_unittest.cc +++ b/components/brave_wallet/browser/eth_transaction_unittest.cc @@ -40,11 +40,12 @@ TEST(EthTransactionUnitTest, GetMessageToSign) { "0xbe862ad9abfe6f22bcb087716c7d89a26051f74c", "0x016345785d8a0000", data, false, std::nullopt)); - EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx1.GetMessageToSign(0))), + EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx1.GetHashedMessageToSign(0))), "61e1ec33764304dddb55348e7883d4437426f44ab3ef65e6da1e025734c03ff0"); - EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx1.GetMessageToSign(1337))), - "9ad82175b6921c5525fc52ebc08b97118cc9709952a16b2249a3f42d44614721"); + EXPECT_EQ( + base::ToLowerASCII(base::HexEncode(tx1.GetHashedMessageToSign(1337))), + "9ad82175b6921c5525fc52ebc08b97118cc9709952a16b2249a3f42d44614721"); data.clear(); EthTransaction tx2 = *EthTransaction::FromTxData( @@ -53,11 +54,11 @@ TEST(EthTransactionUnitTest, GetMessageToSign) { "0x2386f26fc10000", data, false, std::nullopt)); // with chain id (mainnet) - EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx2.GetMessageToSign(1))), + EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx2.GetHashedMessageToSign(1))), "f97c73fdca079da7652dbc61a46cd5aeef804008e057be3e712c43eac389aaf0"); EXPECT_EQ( - base::ToLowerASCII(base::HexEncode(tx2.GetMessageToSign(1, false))), + base::ToLowerASCII(base::HexEncode(tx2.GetMessageToSign(1))), "eb0b85051f4d5c0082520894656e929d6fc0cac52d3d9526d288fe02dcd56fbd872386f" "26fc1000080018080"); @@ -107,7 +108,7 @@ TEST(EthTransactionUnitTest, GetMessageToSign) { entry.nonce, entry.gas_price, entry.gas_limit, entry.to, entry.value, std::vector(), false, std::nullopt)); // with chain id (mainnet) - EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx.GetMessageToSign(1))), + EXPECT_EQ(base::ToLowerASCII(base::HexEncode(tx.GetHashedMessageToSign(1))), entry.hash); } } @@ -125,7 +126,7 @@ TEST(EthTransactionUnitTest, GetSignedTransactionAndHash) { "0x3535353535353535353535353535353535353535", "0x0de0b6b3a7640000", std::vector(), false, std::nullopt)); - const std::vector message = tx.GetMessageToSign(1); + auto message = tx.GetHashedMessageToSign(1); EXPECT_EQ(base::ToLowerASCII(base::HexEncode(message)), "daf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53"); @@ -165,7 +166,7 @@ TEST(EthTransactionUnitTest, GetSignedTransactionAndHash) { "67CBE9D8997F761AECB703304B3800CCF555C9F3DC64214B297FB1966A3B6D83"); // Bigger chain_id - const std::vector message1337 = tx.GetMessageToSign(1337); + auto message1337 = tx.GetHashedMessageToSign(1337); EXPECT_EQ(base::ToLowerASCII(base::HexEncode(message1337)), "9df81edc908cd622cbbab86525a4588fdcbaf6c88757f39b42b1f8f58fd617c2"); recid = 0; diff --git a/components/brave_wallet/browser/eth_tx_manager.cc b/components/brave_wallet/browser/eth_tx_manager.cc index 561cf41360a4..b166c42dd8f1 100644 --- a/components/brave_wallet/browser/eth_tx_manager.cc +++ b/components/brave_wallet/browser/eth_tx_manager.cc @@ -454,7 +454,7 @@ void EthTxManager::GetEthTransactionMessageToSign( return; } std::move(callback).Run(base::ToLowerASCII( - base::HexEncode(meta->tx()->GetMessageToSign(chain_id, false)))); + base::HexEncode(meta->tx()->GetMessageToSign(chain_id)))); } mojom::CoinType EthTxManager::GetCoinType() const { diff --git a/components/brave_wallet/browser/ethereum_keyring.cc b/components/brave_wallet/browser/ethereum_keyring.cc index def6cd757fb0..c4c004c0e91a 100644 --- a/components/brave_wallet/browser/ethereum_keyring.cc +++ b/components/brave_wallet/browser/ethereum_keyring.cc @@ -8,6 +8,7 @@ #include #include "base/base64.h" +#include "base/containers/extend.h" #include "base/containers/span.h" #include "base/strings/string_number_conversions.h" #include "brave/components/brave_wallet/browser/eth_transaction.h" @@ -19,13 +20,14 @@ namespace brave_wallet { namespace { // Get the 32 byte message hash -std::vector GetMessageHash(base::span message) { - std::string prefix("\x19"); - prefix += std::string("Ethereum Signed Message:\n" + - base::NumberToString(message.size())); +KeccakHashArray GetMessageHash(base::span message) { + std::string prefix = + "\x19" + "Ethereum Signed Message:\n" + + base::NumberToString(message.size()); std::vector hash_input(prefix.begin(), prefix.end()); - hash_input.insert(hash_input.end(), message.begin(), message.end()); - return brave_wallet::KeccakHash(hash_input); + base::Extend(hash_input, message); + return KeccakHash(hash_input); } } // namespace @@ -53,7 +55,7 @@ std::optional EthereumKeyring::RecoverAddress( // So recid = v - 27 when chain_id is 0 uint8_t recid = v - 27; signature_only.pop_back(); - std::vector hash = GetMessageHash(message); + auto hash = GetMessageHash(message); // Public keys (in scripts) are given as 04 where x and y are 32 // byte big-endian integers representing the coordinates of a point on the @@ -88,20 +90,20 @@ std::vector EthereumKeyring::SignMessage( return std::vector(); } - std::vector hash; + std::array hashed_message; if (!is_eip712) { - hash = GetMessageHash(message); + hashed_message = GetMessageHash(message); } else { // eip712 hash is Keccak if (message.size() != 32) { return std::vector(); } - hash.assign(message.begin(), message.end()); + base::span(hashed_message).copy_from(message); } int recid; - std::vector signature = hd_key->SignCompact(hash, &recid); + std::vector signature = hd_key->SignCompact(hashed_message, &recid); uint8_t v = static_cast(chain_id ? recid + chain_id * 2 + 35 : recid + 27); signature.push_back(v); @@ -117,9 +119,9 @@ void EthereumKeyring::SignTransaction(const std::string& address, return; } - const std::vector message = tx->GetMessageToSign(chain_id); - int recid; - const std::vector signature = hd_key->SignCompact(message, &recid); + int recid = 0; + const std::vector signature = + hd_key->SignCompact(tx->GetHashedMessageToSign(chain_id), &recid); tx->ProcessSignature(signature, recid, chain_id); } diff --git a/components/brave_wallet/browser/ethereum_provider_impl.cc b/components/brave_wallet/browser/ethereum_provider_impl.cc index 0914413fc575..c151be9d3076 100644 --- a/components/brave_wallet/browser/ethereum_provider_impl.cc +++ b/components/brave_wallet/browser/ethereum_provider_impl.cc @@ -684,9 +684,10 @@ void EthereumProviderImpl::SignTypedMessage( mojom::SignDataUnionPtr sign_data = mojom::SignDataUnion::NewEthSignTypedData(std::move(eth_sign_typed_data)); - SignMessageInternal(account_id, std::move(sign_data), - std::move(message_to_sign), std::move(callback), - std::move(id)); + SignMessageInternal( + account_id, std::move(sign_data), + std::vector(message_to_sign->begin(), message_to_sign->end()), + std::move(callback), std::move(id)); } void EthereumProviderImpl::SignMessageInternal( diff --git a/components/brave_wallet/browser/internal/hd_key.cc b/components/brave_wallet/browser/internal/hd_key.cc index 57887b9bd336..df400c8651b8 100644 --- a/components/brave_wallet/browser/internal/hd_key.cc +++ b/components/brave_wallet/browser/internal/hd_key.cc @@ -77,8 +77,8 @@ bool UTCPasswordVerification(const std::string& derived_key, mac_verification_input.insert(mac_verification_input.end(), ciphertext.begin(), ciphertext.end()); // verify password - std::vector mac_verification(KeccakHash(mac_verification_input)); - if (base::ToLowerASCII(base::HexEncode(mac_verification)) != mac) { + if (base::ToLowerASCII( + base::HexEncode(KeccakHash(mac_verification_input))) != mac) { VLOG(0) << __func__ << ": password does not match"; return false; } @@ -671,13 +671,10 @@ std::unique_ptr HDKey::DeriveChildFromPath(const std::string& path) { return hd_key; } -std::vector HDKey::SignCompact(base::span msg, - int* recid) { +std::vector HDKey::SignCompact( + base::span msg, + int* recid) { std::vector sig(kCompactSignatureSize); - if (msg.size() != 32) { - LOG(ERROR) << __func__ << ": message length should be 32"; - return sig; - } if (!recid) { secp256k1_ecdsa_signature ecdsa_sig; if (!secp256k1_ecdsa_sign(GetSecp256k1Ctx(), &ecdsa_sig, msg.data(), @@ -712,7 +709,7 @@ std::vector HDKey::SignCompact(base::span msg, } std::optional> HDKey::SignDer( - base::span msg) { + base::span msg) { unsigned char extra_entropy[32] = {0}; secp256k1_ecdsa_signature ecdsa_sig; if (!secp256k1_ecdsa_sign(GetSecp256k1Ctx(), &ecdsa_sig, msg.data(), @@ -787,13 +784,14 @@ bool HDKey::VerifyForTesting(base::span msg, return true; } -std::vector HDKey::RecoverCompact(bool compressed, - base::span msg, - base::span sig, - int recid) { +std::vector HDKey::RecoverCompact( + bool compressed, + base::span msg, + base::span sig, + int recid) { size_t public_key_len = compressed ? 33 : 65; std::vector public_key(public_key_len); - if (msg.size() != 32 || sig.size() != kCompactSignatureSize) { + if (sig.size() != kCompactSignatureSize) { LOG(ERROR) << __func__ << ": message or signature length is invalid"; return public_key; } diff --git a/components/brave_wallet/browser/internal/hd_key.h b/components/brave_wallet/browser/internal/hd_key.h index 47013a4c9a34..7f2d78f275dd 100644 --- a/components/brave_wallet/browser/internal/hd_key.h +++ b/components/brave_wallet/browser/internal/hd_key.h @@ -13,12 +13,14 @@ #include "base/containers/span.h" #include "base/gtest_prod_util.h" +#include "brave/components/brave_wallet/common/hash_utils.h" #include "brave/components/brave_wallet/common/mem_utils.h" namespace brave_wallet { inline constexpr size_t kCompactSignatureSize = 64; inline constexpr size_t kSecp256k1PubkeySize = 33; +inline constexpr size_t kSecp256k1MsgSize = 32; using SecureVector = std::vector>; @@ -99,11 +101,13 @@ class HDKey { // Sign the message using private key. The msg has to be exactly 32 bytes // Return 64 bytes ECDSA signature when succeed, otherwise empty vector // if recid is not null, recovery id will be filled. - std::vector SignCompact(base::span msg, int* recid); + std::vector SignCompact( + base::span msg, + int* recid); // Sign the message using private key and return it in DER format. std::optional> SignDer( - base::span msg); + base::span msg); // Verify the ECDSA signature using public key. The msg has to be exactly 32 // bytes and the sig has to be 64 bytes. @@ -114,10 +118,11 @@ class HDKey { // Recover public key from signature and message. The msg has to be exactly 32 // bytes and the sig has to be 64 bytes. // Return valid public key when succeed, all zero vector otherwise - std::vector RecoverCompact(bool compressed, - base::span msg, - base::span sig, - int recid); + std::vector RecoverCompact( + bool compressed, + base::span msg, + base::span sig, + int recid); private: FRIEND_TEST_ALL_PREFIXES(Eip1559TransactionUnitTest, diff --git a/components/brave_wallet/browser/internal/hd_key_unittest.cc b/components/brave_wallet/browser/internal/hd_key_unittest.cc index f155f8ef76e4..951780344362 100644 --- a/components/brave_wallet/browser/internal/hd_key_unittest.cc +++ b/components/brave_wallet/browser/internal/hd_key_unittest.cc @@ -362,8 +362,9 @@ TEST(HDKeyUnitTest, GenerateFromPrivateKey) { std::unique_ptr key = HDKey::GenerateFromPrivateKey(private_key); EXPECT_NE(key, nullptr); EXPECT_EQ(key->GetPath(), ""); - const std::vector msg_a(32, 0x00); - const std::vector msg_b(32, 0x08); + std::array msg_a = {}; + std::array msg_b = {}; + msg_b.fill(0x08); int recid_a = -1; int recid_b = -1; const std::vector sig_a = key->SignCompact(msg_a, &recid_a); @@ -389,8 +390,9 @@ TEST(HDKeyUnitTest, SignAndVerifyAndRecover) { "GfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"); auto* key = parsed_xprv->hdkey.get(); - const std::vector msg_a(32, 0x00); - const std::vector msg_b(32, 0x08); + std::array msg_a = {}; + std::array msg_b = {}; + msg_b.fill(0x08); int recid_a = -1; int recid_b = -1; const std::vector sig_a = key->SignCompact(msg_a, &recid_a); @@ -431,10 +433,6 @@ TEST(HDKeyUnitTest, SignAndVerifyAndRecover) { EXPECT_FALSE(key->VerifyForTesting(msg_a, std::vector(63))); EXPECT_FALSE(key->VerifyForTesting(msg_a, std::vector(65))); - EXPECT_TRUE(IsPublicKeyEmpty( - key->RecoverCompact(true, std::vector(31), sig_a, recid_a))); - EXPECT_TRUE(IsPublicKeyEmpty( - key->RecoverCompact(true, std::vector(33), sig_a, recid_a))); EXPECT_TRUE(IsPublicKeyEmpty( key->RecoverCompact(true, msg_a, std::vector(31), recid_a))); EXPECT_TRUE(IsPublicKeyEmpty( diff --git a/components/brave_wallet/browser/json_rpc_service_unittest.cc b/components/brave_wallet/browser/json_rpc_service_unittest.cc index a6c27e92d174..60c0cc989dc9 100644 --- a/components/brave_wallet/browser/json_rpc_service_unittest.cc +++ b/components/brave_wallet/browser/json_rpc_service_unittest.cc @@ -3157,7 +3157,7 @@ class UDGetManyCallHandler : public EthCallHandler { std::optional HandleEthCall(eth_abi::Span call_data) override { auto [_, args] = eth_abi::ExtractFunctionSelectorAndArgsFromCall(call_data); auto keys_array = eth_abi::ExtractStringArrayFromTuple(args, 0); - auto namehash_bytes = eth_abi::ExtractFixedBytesFromTuple(args, 32, 1); + auto namehash_bytes = eth_abi::ExtractFixedBytesFromTuple<32>(args, 1); EXPECT_TRUE(keys_array); EXPECT_TRUE(namehash_bytes); @@ -5492,7 +5492,7 @@ class EnsGetResolverHandler : public EthCallHandler { std::optional HandleEthCall(eth_abi::Span call_data) override { auto [_, args] = eth_abi::ExtractFunctionSelectorAndArgsFromCall(call_data); - auto namehash_bytes = eth_abi::ExtractFixedBytesFromTuple(args, 32, 0); + auto namehash_bytes = eth_abi::ExtractFixedBytesFromTuple<32>(args, 0); EXPECT_TRUE(namehash_bytes); if (!base::ranges::equal(*namehash_bytes, Namehash(host_name_))) { @@ -5519,7 +5519,7 @@ class Ensip10SupportHandler : public EthCallHandler { std::optional HandleEthCall(eth_abi::Span call_data) override { auto [_, args] = eth_abi::ExtractFunctionSelectorAndArgsFromCall(call_data); - auto arg_selector = eth_abi::ExtractFixedBytesFromTuple(args, 4, 0); + auto arg_selector = eth_abi::ExtractFixedBytesFromTuple<4>(args, 0); EXPECT_TRUE(arg_selector); EXPECT_TRUE(base::ranges::equal(*arg_selector, kResolveBytesBytesSelector)); @@ -5571,7 +5571,7 @@ class EnsGetRecordHandler : public EthCallHandler { auto [selector, args] = eth_abi::ExtractFunctionSelectorAndArgsFromCall(call_data); - auto namehash_bytes = eth_abi::ExtractFixedBytesFromTuple(args, 32, 0); + auto namehash_bytes = eth_abi::ExtractFixedBytesFromTuple<32>(args, 0); EXPECT_TRUE(namehash_bytes); bool host_matches = base::ranges::equal(*namehash_bytes, Namehash(host_name_)); @@ -5729,7 +5729,7 @@ class OffchainGatewayHandler { eth_abi::ExtractFunctionSelectorAndArgsFromCall(*encoded_call); auto domain_namehash = - eth_abi::ExtractFixedBytesFromTuple(enconed_call_args, 32, 0); + eth_abi::ExtractFixedBytesFromTuple<32>(enconed_call_args, 0); EXPECT_TRUE(domain_namehash); std::vector data_value; diff --git a/components/brave_wallet/browser/rlp_encode.cc b/components/brave_wallet/browser/rlp_encode.cc index de87835cc539..3f902d6ca023 100644 --- a/components/brave_wallet/browser/rlp_encode.cc +++ b/components/brave_wallet/browser/rlp_encode.cc @@ -8,28 +8,34 @@ #include #include +#include "base/containers/extend.h" + +namespace { + namespace { +constexpr uint8_t kStringOffset = 0x80; +constexpr uint8_t kListOffset = 0xc0; +constexpr uint8_t kSingleByteLengthLimit = 55; +} // namespace -std::string RLPToBinary(size_t x) { +std::vector RLPToBinary(size_t x) { if (x == 0) { - return ""; + return {}; } - std::string ret = RLPToBinary(x / 256); + std::vector ret = RLPToBinary(x / 256); ret.push_back(x % 256); return ret; } -std::string RLPEncodeLength(size_t length, size_t offset) { - char sz[2] = {0}; - if (length < 56) { - sz[0] = length + offset; - return sz; +std::vector RLPEncodeLength(size_t length, uint8_t offset) { + if (length <= kSingleByteLengthLimit) { + return std::vector(1, length + offset); } - std::string BL = RLPToBinary(length); - sz[0] = BL.length() + offset + 55; - std::string ret(sz); - ret.append(BL); - return ret; + std::vector length_encoded = RLPToBinary(length); + std::vector result(length_encoded.size() + 1); + result[0] = length_encoded.size() + offset + kSingleByteLengthLimit; + base::span(result).subspan(1).copy_from(length_encoded); + return result; } } // namespace @@ -48,28 +54,41 @@ base::Value::BlobStorage RLPUint256ToBlob(uint256_t input) { return output; } -std::string RLPEncode(base::Value val) { +std::vector RLPEncode(const base::Value& val) { if (val.is_int()) { int i = val.GetInt(); return RLPEncode(base::Value(RLPUint256ToBlob((uint256_t)i))); - } else if (val.is_blob()) { + } + + if (val.is_blob()) { base::Value::BlobStorage blob = val.GetBlob(); - std::string s(blob.begin(), blob.end()); - if (blob.size() == 1 && static_cast(blob[0]) < 0x80) { - return s; - } - return RLPEncodeLength(blob.size(), 0x80) + s; - } else if (val.is_string()) { - std::string s = val.GetString(); - return RLPEncode(base::Value(base::Value::BlobStorage(s.begin(), s.end()))); - } else if (val.is_list()) { - std::string output; - for (auto& item : val.GetList()) { - output += RLPEncode(std::move(item)); + if (blob.size() == 1 && blob[0] < kStringOffset) { + return blob; } - return RLPEncodeLength(output.length(), 0xc0) + output; + auto result = RLPEncodeLength(blob.size(), kStringOffset); + base::Extend(result, blob); + return result; + } + + if (val.is_string()) { + return RLPEncode(base::Value(base::as_byte_span(val.GetString()))); + } + + if (val.is_list()) { + return RLPEncode(val.GetList()); + } + + return {}; +} + +std::vector RLPEncode(const base::Value::List& val) { + std::vector items_encoded; + for (auto& item : val) { + base::Extend(items_encoded, RLPEncode(item)); } - return ""; + auto result = RLPEncodeLength(items_encoded.size(), kListOffset); + base::Extend(result, items_encoded); + return result; } } // namespace brave_wallet diff --git a/components/brave_wallet/browser/rlp_encode.h b/components/brave_wallet/browser/rlp_encode.h index 0c1d16ae18ae..9a956695d488 100644 --- a/components/brave_wallet/browser/rlp_encode.h +++ b/components/brave_wallet/browser/rlp_encode.h @@ -18,7 +18,8 @@ base::Value::BlobStorage RLPUint256ToBlob(uint256_t input); // Recursive Length Prefix (RLP) encoding of base::Values consisting of string, // blob, or int data -std::string RLPEncode(base::Value val); +std::vector RLPEncode(const base::Value& val); +std::vector RLPEncode(const base::Value::List& val); } // namespace brave_wallet diff --git a/components/brave_wallet/browser/rlp_encode_unittest.cc b/components/brave_wallet/browser/rlp_encode_unittest.cc index e11bc6554086..aa35530606c2 100644 --- a/components/brave_wallet/browser/rlp_encode_unittest.cc +++ b/components/brave_wallet/browser/rlp_encode_unittest.cc @@ -9,11 +9,13 @@ #pragma allow_unsafe_buffers #endif +#include "brave/components/brave_wallet/browser/rlp_encode.h" + #include + #include #include -#include "brave/components/brave_wallet/browser/rlp_encode.h" #include "brave/components/brave_wallet/common/hex_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -89,22 +91,22 @@ base::Value RLPTestStringToValue(const std::string& s) { namespace brave_wallet { TEST(RLPEncodeTest, EmptyString) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("''")); + auto v = RLPEncode(RLPTestStringToValue("''")); ASSERT_EQ(ToHex(v), "0x80"); } TEST(RLPEncodeTest, SingleChar) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("'d'")); + auto v = RLPEncode(RLPTestStringToValue("'d'")); ASSERT_EQ(ToHex(v), "0x64"); } TEST(RLPEncodeTest, ShortString) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("'dog'")); + auto v = RLPEncode(RLPTestStringToValue("'dog'")); ASSERT_EQ(ToHex(v), "0x83646f67"); } TEST(RLPEncodeTest, ShortString2) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue( + auto v = RLPEncode(RLPTestStringToValue( "'Lorem ipsum dolor sit amet, consectetur adipisicing eli'")); ASSERT_EQ(ToHex(v), "0xb74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e" @@ -112,7 +114,7 @@ TEST(RLPEncodeTest, ShortString2) { } TEST(RLPEncodeTest, LongString) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue( + auto v = RLPEncode(RLPTestStringToValue( "'Lorem ipsum dolor sit amet, consectetur adipisicing elit'")); ASSERT_EQ(ToHex(v), "0xb8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f" @@ -120,7 +122,7 @@ TEST(RLPEncodeTest, LongString) { } TEST(RLPEncodeTest, LongString2) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue( + auto v = RLPEncode(RLPTestStringToValue( "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur " "mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin " "suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique " @@ -170,48 +172,48 @@ TEST(RLPEncodeTest, LongString2) { } TEST(RLPEncodeTest, Zero) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("0")); + auto v = RLPEncode(RLPTestStringToValue("0")); ASSERT_EQ(ToHex(v), "0x80"); } TEST(RLPEncodeTest, SmallInt1) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("1")); + auto v = RLPEncode(RLPTestStringToValue("1")); ASSERT_EQ(ToHex(v), "0x01"); } TEST(RLPEncodeTest, SmallInt2) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("16")); + auto v = RLPEncode(RLPTestStringToValue("16")); ASSERT_EQ(ToHex(v), "0x10"); } TEST(RLPEncodeTest, SmallInt3) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("79")); + auto v = RLPEncode(RLPTestStringToValue("79")); ASSERT_EQ(ToHex(v), "0x4f"); } TEST(RLPEncodeTest, SmallInt4) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("127")); + auto v = RLPEncode(RLPTestStringToValue("127")); ASSERT_EQ(ToHex(v), "0x7f"); } TEST(RLPEncodeTest, MediumInt1) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("128")); + auto v = RLPEncode(RLPTestStringToValue("128")); ASSERT_EQ(ToHex(v), "0x8180"); } TEST(RLPEncodeTest, MediumInt2) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("1000")); + auto v = RLPEncode(RLPTestStringToValue("1000")); ASSERT_EQ(ToHex(v), "0x8203e8"); } TEST(RLPEncodeTest, MediumInt3) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("100000")); + auto v = RLPEncode(RLPTestStringToValue("100000")); ASSERT_EQ(ToHex(v), "0x830186a0"); } TEST(RLPEncodeTest, BlobStorage) { base::Value::BlobStorage input{0, 255, 33, 127, 0, 128}; - std::string v = brave_wallet::RLPEncode(base::Value(input)); + auto v = RLPEncode(base::Value(input)); ASSERT_EQ(ToHex(v), "0x8600ff217f0080"); } @@ -225,7 +227,7 @@ TEST(RLPEncodeTest, MediumInt4) { input += static_cast(9681528633); input *= ten_billion; input += static_cast(1701780722); - std::string v = brave_wallet::RLPEncode(base::Value(RLPUint256ToBlob(input))); + auto v = RLPEncode(base::Value(RLPUint256ToBlob(input))); ASSERT_EQ(ToHex(v), "0x8f102030405060708090a0b0c0d0e0f2"); } @@ -245,7 +247,7 @@ TEST(RLPEncodeTest, MediumInt5) { input += static_cast(6297482234); input *= ten_billion; input += static_cast(7068935681); - std::string v = brave_wallet::RLPEncode(base::Value(RLPUint256ToBlob(input))); + auto v = RLPEncode(base::Value(RLPUint256ToBlob(input))); ASSERT_EQ(ToHex(v), "0x9c0100020003000400050006000700080009000a000b000c000d000e01"); } @@ -268,7 +270,7 @@ TEST(RLPEncodeTest, BigInt) { input += static_cast(5758400791); input *= ten_billion; input += static_cast(3129639935); - std::string v = brave_wallet::RLPEncode(base::Value(RLPUint256ToBlob(input))); + auto v = RLPEncode(base::Value(RLPUint256ToBlob(input))); ASSERT_EQ( ToHex(v), "0xa0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); @@ -276,35 +278,34 @@ TEST(RLPEncodeTest, BigInt) { TEST(RLPEncodeTest, ByteString00) { std::string bytestring = {0}; - std::string v = brave_wallet::RLPEncode(base::Value(bytestring)); + auto v = RLPEncode(base::Value(bytestring)); ASSERT_EQ(ToHex(v), "0x00"); } TEST(RLPEncodeTest, ByteString01) { std::string bytestring = {1}; - std::string v = brave_wallet::RLPEncode(base::Value(bytestring)); + auto v = RLPEncode(base::Value(bytestring)); ASSERT_EQ(ToHex(v), "0x01"); } TEST(RLPEncodeTest, ByteString7f) { std::string bytestring = {0x7f}; - std::string v = brave_wallet::RLPEncode(base::Value(bytestring)); + auto v = RLPEncode(base::Value(bytestring)); ASSERT_EQ(ToHex(v), "0x7f"); } TEST(RLPEncodeTest, EmptyList) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue("[]")); + auto v = RLPEncode(RLPTestStringToValue("[]")); ASSERT_EQ(ToHex(v), "0xc0"); } TEST(RLPEncodeTest, StringList) { - std::string v = - brave_wallet::RLPEncode(RLPTestStringToValue("['dog', 'god', 'cat']")); + auto v = RLPEncode(RLPTestStringToValue("['dog', 'god', 'cat']")); ASSERT_EQ(ToHex(v), "0xcc83646f6783676f6483636174"); } TEST(RLPEncodeTest, ShortListMax1) { - std::string v = brave_wallet::RLPEncode( + auto v = RLPEncode( RLPTestStringToValue("['asdf', 'qwer', 'zxcv', 'asdf', 'qwer', 'zxcv', " "'asdf', 'qwer', 'zxcv', 'asdf', 'qwer']")); ASSERT_EQ(ToHex(v), @@ -313,7 +314,7 @@ TEST(RLPEncodeTest, ShortListMax1) { } TEST(RLPEncodeTest, LongList1) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue( + auto v = RLPEncode(RLPTestStringToValue( "[['asdf', 'qwer', 'zxcv'], ['asdf', 'qwer', 'zxcv'], ['asdf', 'qwer', " "'zxcv'], ['asdf', 'qwer', 'zxcv']]")); ASSERT_EQ( @@ -323,7 +324,7 @@ TEST(RLPEncodeTest, LongList1) { } TEST(RLPEncodeTest, LongList2) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue( + auto v = RLPEncode(RLPTestStringToValue( "[['asdf', 'qwer', 'zxcv'], ['asdf', 'qwer', 'zxcv'], ['asdf', 'qwer', " "'zxcv'], ['asdf', 'qwer', 'zxcv'], ['asdf', 'qwer', 'zxcv'], ['asdf', " "'qwer', 'zxcv'], ['asdf', 'qwer', 'zxcv'], ['asdf', 'qwer', 'zxcv'], " @@ -356,25 +357,22 @@ TEST(RLPEncodeTest, LongList2) { } TEST(RLPEncodeTest, Multilist) { - std::string v = - brave_wallet::RLPEncode(RLPTestStringToValue("['zw', [4], 1]")); + auto v = RLPEncode(RLPTestStringToValue("['zw', [4], 1]")); ASSERT_EQ(ToHex(v), "0xc6827a77c10401"); } TEST(RLPEncodeTest, ListOfLists) { - std::string v = - brave_wallet::RLPEncode(RLPTestStringToValue("[[[], []], []]")); + auto v = RLPEncode(RLPTestStringToValue("[[[], []], []]")); ASSERT_EQ(ToHex(v), "0xc4c2c0c0c0"); } TEST(RLPEncodeTest, ListOfLists2) { - std::string v = - brave_wallet::RLPEncode(RLPTestStringToValue("[[], [[]], [[], [[]]]]")); + auto v = RLPEncode(RLPTestStringToValue("[[], [[]], [[], [[]]]]")); ASSERT_EQ(ToHex(v), "0xc7c0c1c0c3c0c1c0"); } TEST(RLPEncodeTest, DictTest1) { - std::string v = brave_wallet::RLPEncode( + auto v = RLPEncode( RLPTestStringToValue("[['key1', 'val1'], ['key2', 'val2'], ['key3', " "'val3'], ['key4', 'val4']]")); ASSERT_EQ(ToHex(v), @@ -383,7 +381,7 @@ TEST(RLPEncodeTest, DictTest1) { } TEST(RLPEncodeTest, ComplexStructure) { - std::string v = brave_wallet::RLPEncode(RLPTestStringToValue( + auto v = RLPEncode(RLPTestStringToValue( "['cat',['puppy', 'cow'], 'horse', [[]], 'pig', [''], 'sheep']")); ASSERT_EQ(ToHex(v), "0xe383636174ca85707570707983636f7785686f727365c1c083706967c1808573" @@ -393,7 +391,7 @@ TEST(RLPEncodeTest, ComplexStructure) { TEST(RLPEncodeTest, DictionaryValueNotSupported) { base::Value::Dict d; d.Set("test", true); - ASSERT_TRUE(brave_wallet::RLPEncode(base::Value(std::move(d))).empty()); + ASSERT_TRUE(RLPEncode(base::Value(std::move(d))).empty()); } } // namespace brave_wallet diff --git a/components/brave_wallet/browser/wallet_data_files_installer.cc b/components/brave_wallet/browser/wallet_data_files_installer.cc index 96b73cf43284..2b8b86ebe64d 100644 --- a/components/brave_wallet/browser/wallet_data_files_installer.cc +++ b/components/brave_wallet/browser/wallet_data_files_installer.cc @@ -122,9 +122,8 @@ base::FilePath WalletDataFilesInstallerPolicy::GetRelativeInstallDir() const { } void WalletDataFilesInstallerPolicy::GetHash(std::vector* hash) const { - UNSAFE_TODO(hash->assign( - kWalletDataFilesSha2Hash, - kWalletDataFilesSha2Hash + std::size(kWalletDataFilesSha2Hash))); + hash->assign(std::begin(kWalletDataFilesSha2Hash), + std::end(kWalletDataFilesSha2Hash)); } std::string WalletDataFilesInstallerPolicy::GetName() const { diff --git a/components/brave_wallet/common/btc_like_serializer_stream.cc b/components/brave_wallet/common/btc_like_serializer_stream.cc index 003e8f60befa..7d5f0622a638 100644 --- a/components/brave_wallet/common/btc_like_serializer_stream.cc +++ b/components/brave_wallet/common/btc_like_serializer_stream.cc @@ -5,31 +5,24 @@ #include "brave/components/brave_wallet/common/btc_like_serializer_stream.h" -#include "base/compiler_specific.h" #include "base/containers/span.h" -#include "base/numerics/byte_conversions.h" namespace brave_wallet { void BtcLikeSerializerStream::Push8AsLE(uint8_t i) { - UNSAFE_TODO(base::span data_to_insert(reinterpret_cast(&i), - sizeof(i))); - PushBytes(data_to_insert); + PushBytes(base::byte_span_from_ref(i)); } void BtcLikeSerializerStream::Push16AsLE(uint16_t i) { - PushBytes(base::byte_span_from_ref( - base::numerics::U16FromLittleEndian(base::byte_span_from_ref(i)))); + PushBytes(base::byte_span_from_ref(i)); } void BtcLikeSerializerStream::Push32AsLE(uint32_t i) { - PushBytes(base::byte_span_from_ref( - base::numerics::U32FromLittleEndian(base::byte_span_from_ref(i)))); + PushBytes(base::byte_span_from_ref(i)); } void BtcLikeSerializerStream::Push64AsLE(uint64_t i) { - PushBytes(base::byte_span_from_ref( - base::numerics::U64FromLittleEndian(base::byte_span_from_ref(i)))); + PushBytes(base::byte_span_from_ref(i)); } // https://developer.bitcoin.org/reference/transactions.html#compactsize-unsigned-integers diff --git a/components/brave_wallet/common/btc_like_serializer_stream.h b/components/brave_wallet/common/btc_like_serializer_stream.h index 04a1afcb08d5..371e4b421d00 100644 --- a/components/brave_wallet/common/btc_like_serializer_stream.h +++ b/components/brave_wallet/common/btc_like_serializer_stream.h @@ -9,7 +9,7 @@ #include #include "base/containers/span.h" -#include "base/memory/raw_ref.h" +#include "base/memory/raw_ptr.h" namespace brave_wallet { diff --git a/components/brave_wallet/common/eth_abi_utils.cc b/components/brave_wallet/common/eth_abi_utils.cc index 88bfcaba36f5..31e72af5effe 100644 --- a/components/brave_wallet/common/eth_abi_utils.cc +++ b/components/brave_wallet/common/eth_abi_utils.cc @@ -67,7 +67,7 @@ std::optional ToSpan32(Span data) { return std::nullopt; } - return UNSAFE_TODO(Span32(data.data(), kRowLength)); + return Span32(data.first(kRowLength)); } Span ExtractRows(Span data, size_t row, size_t row_count) { @@ -107,6 +107,28 @@ EthAddress ExtractAddress(Span32 address_encoded) { } // namespace +namespace internal { + +std::optional ExtractFixedBytesRowFromTuple(Span data, + size_t fixed_size, + size_t tuple_pos) { + CHECK(fixed_size > 0 && fixed_size <= 32); + + // Head contains bytes itself. + auto head = ExtractHeadFromTuple(data, tuple_pos); + if (!head) { + return std::nullopt; + } + + if (!CheckPadding(head->subspan(0), fixed_size)) { + return std::nullopt; + } + + return head; +} + +} // namespace internal + std::pair ExtractFunctionSelectorAndArgsFromCall(Span data) { if (data.size() < 4) { return {}; @@ -358,33 +380,11 @@ std::optional> ExtractBytesFromTuple(Span data, return ExtractBytes(bytes); } -std::optional> -ExtractFixedBytesFromTuple(Span data, size_t fixed_size, size_t tuple_pos) { - if (fixed_size == 0 || fixed_size > 32) { - NOTREACHED_IN_MIGRATION(); - return std::nullopt; - } - - // Head contains bytes itself. - auto head = ExtractHeadFromTuple(data, tuple_pos); - if (!head) { - return std::nullopt; - } - - if (!CheckPadding(head->subspan(0), fixed_size)) { - return std::nullopt; - } - - return std::vector{head->begin(), head->begin() + fixed_size}; -} - -// NOLINTNEXTLINE(runtime/references) size_t AppendEmptyRow(std::vector& destination) { destination.resize(destination.size() + kRowLength, 0); return kRowLength; } -// NOLINTNEXTLINE(runtime/references) size_t AppendRow(std::vector& destination, uint256_t value) { // Append 32 bytes. destination.resize(destination.size() + kRowLength, 0); @@ -393,7 +393,6 @@ size_t AppendRow(std::vector& destination, uint256_t value) { return kRowLength; } -// NOLINTNEXTLINE(runtime/references) size_t AppendRow(std::vector& destination, Span32 value) { DCHECK_EQ(value.size(), kRowLength); // Append 32 bytes. @@ -404,7 +403,6 @@ size_t AppendRow(std::vector& destination, Span32 value) { return kRowLength; } -// NOLINTNEXTLINE(runtime/references) size_t AppendBytesWithPadding(std::vector& destination, Span bytes) { auto padded_size = PaddedSize(bytes.size()); destination.resize(destination.size() + padded_size); @@ -413,7 +411,6 @@ size_t AppendBytesWithPadding(std::vector& destination, Span bytes) { return padded_size; } -// NOLINTNEXTLINE(runtime/references) size_t AppendBytes(std::vector& destination, Span bytes) { size_t total_added_bytes = 0; total_added_bytes += AppendRow(destination, bytes.size()); @@ -421,7 +418,6 @@ size_t AppendBytes(std::vector& destination, Span bytes) { return total_added_bytes; } -// NOLINTNEXTLINE(runtime/references) void EncodeTuple(std::vector& destination, Span bytes_0, Span bytes_1) { diff --git a/components/brave_wallet/common/eth_abi_utils.h b/components/brave_wallet/common/eth_abi_utils.h index 0696f5598ef1..1e74ea16abb0 100644 --- a/components/brave_wallet/common/eth_abi_utils.h +++ b/components/brave_wallet/common/eth_abi_utils.h @@ -17,6 +17,7 @@ #include "brave/components/brave_wallet/common/eth_address.h" namespace brave_wallet::eth_abi { + constexpr size_t kRowLength = 32; constexpr size_t kSelectorLength = 4; @@ -26,6 +27,14 @@ using Span32 = base::span; using Bytes4 = std::array; using Bytes32 = std::array; +namespace internal { + +std::optional ExtractFixedBytesRowFromTuple(Span data, + size_t fixed_size, + size_t tuple_pos); + +} + std::pair ExtractFunctionSelectorAndArgsFromCall(Span data); EthAddress ExtractAddress(Span address_encoded); @@ -47,8 +56,22 @@ ExtractBoolBytesArray(Span string_array); std::optional>>> ExtractBoolBytesArrayFromTuple(Span data, size_t tuple_pos); -std::optional> -ExtractFixedBytesFromTuple(Span data, size_t fixed_size, size_t tuple_pos); +template +std::optional> ExtractFixedBytesFromTuple( + Span data, + size_t tuple_pos) + requires(N > 0 && N <= 32) +{ + auto head = internal::ExtractFixedBytesRowFromTuple(data, N, tuple_pos); + if (!head) { + return std::nullopt; + } + + std::array result; + base::span(result).copy_from(head->first(N)); + + return result; +} class TupleEncoder { public: diff --git a/components/brave_wallet/common/eth_abi_utils_unittest.cc b/components/brave_wallet/common/eth_abi_utils_unittest.cc index a255e74f4676..e3b21aa764b7 100644 --- a/components/brave_wallet/common/eth_abi_utils_unittest.cc +++ b/components/brave_wallet/common/eth_abi_utils_unittest.cc @@ -97,7 +97,7 @@ TEST(EthAbiUtilsTest, OffchainLookup) { "3b3b57de42041b0018edd29d7c17154b0c671acc0502ea0b3693cafbeadf58e6be" "aaa16c00000000000000000000000000000000000000000000000000000000"); - EXPECT_EQ(ToHex(*ExtractFixedBytesFromTuple(args, 4, 3)), "0xf4d4d2f8"); + EXPECT_EQ(ToHex(*ExtractFixedBytesFromTuple<4>(args, 3)), "0xf4d4d2f8"); EXPECT_EQ(ToHex(*ExtractBytesFromTuple(args, 4)), "0x9061b92300000000000000000000000000000000000000000000000000000000" @@ -123,7 +123,7 @@ TEST(EthAbiUtilsTest, OffchainLookupBy1Test) { ExtractAddressFromTuple(args, 0); ExtractStringArrayFromTuple(args, 1); ExtractBytesFromTuple(args, 2); - ExtractFixedBytesFromTuple(args, 4, 3); + ExtractFixedBytesFromTuple<4>(args, 3); ExtractBytesFromTuple(args, 4); } } @@ -695,21 +695,21 @@ TEST(EthAbiUtilsTest, ExtractFixedBytesFromTuple) { auto [_, args] = ExtractFunctionSelectorAndArgsFromCall(bytes); - EXPECT_EQ(ToHex(*ExtractFixedBytesFromTuple(args, 4, 3)), "0xf4d4d2f8"); + EXPECT_EQ(ToHex(*ExtractFixedBytesFromTuple<4>(args, 3)), "0xf4d4d2f8"); // Bad tuple pos. - EXPECT_FALSE(ExtractFixedBytesFromTuple(args, 4, 0)); - EXPECT_FALSE(ExtractFixedBytesFromTuple(args, 4, 1000)); + EXPECT_FALSE(ExtractFixedBytesFromTuple<4>(args, 0)); + EXPECT_FALSE(ExtractFixedBytesFromTuple<4>(args, 1000)); // Empty data. - EXPECT_FALSE(ExtractFixedBytesFromTuple({}, 4, 0)); + EXPECT_FALSE(ExtractFixedBytesFromTuple<4>({}, 0)); bytes[101] = 0; - EXPECT_EQ(ToHex(*ExtractFixedBytesFromTuple(args, 4, 3)), "0xf400d2f8"); + EXPECT_EQ(ToHex(*ExtractFixedBytesFromTuple<4>(args, 3)), "0xf400d2f8"); // Bad padding. bytes[111] = 1; - EXPECT_FALSE(ExtractFixedBytesFromTuple(args, 4, 3)); + EXPECT_FALSE(ExtractFixedBytesFromTuple<4>(args, 3)); } TEST(EthAbiTupleEncoderTest, EncodeCall) { diff --git a/components/brave_wallet/common/eth_address.cc b/components/brave_wallet/common/eth_address.cc index 5eaa17a41729..2c7e515cdfe3 100644 --- a/components/brave_wallet/common/eth_address.cc +++ b/components/brave_wallet/common/eth_address.cc @@ -14,6 +14,7 @@ #include #include "base/check_op.h" +#include "base/containers/span.h" #include "base/logging.h" #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" @@ -45,12 +46,8 @@ EthAddress EthAddress::FromPublicKey(const std::vector& public_key) { return EthAddress(); } - std::vector hash = KeccakHash(public_key); - std::vector result(hash.end() - kEthAddressLength, hash.end()); - - DCHECK_EQ(result.size(), kEthAddressLength); - - return EthAddress(std::move(result)); + return EthAddress( + base::as_byte_span(KeccakHash(public_key)).last(kEthAddressLength)); } // static @@ -95,8 +92,7 @@ bool EthAddress::IsValidAddress(const std::string& input) { } std::string EthAddress::ToHex() const { - const std::string input(bytes_.begin(), bytes_.end()); - return ::brave_wallet::ToHex(input); + return ::brave_wallet::ToHex(bytes_); } // static @@ -121,21 +117,20 @@ std::optional EthAddress::ToEip1191ChecksumAddress( std::string EthAddress::ToChecksumAddress(uint256_t eip1191_chaincode) const { std::string result = "0x"; - std::string input; + std::string prefix; if (eip1191_chaincode == static_cast(30) || eip1191_chaincode == static_cast(31)) { // TODO(jocelyn): We will need to revise this if there are supported chains // with ID larger than uint64_t. - input += + prefix = base::NumberToString(static_cast(eip1191_chaincode)) + "0x"; } - input += std::string(ToHex().data() + 2); - - const std::string hash_str(KeccakHash(input).data() + 2); const std::string address_str = base::ToLowerASCII(base::HexEncode(bytes_.data(), bytes_.size())); + const std::string hash_str = + base::HexEncode(KeccakHash(base::as_byte_span(prefix + address_str))); for (size_t i = 0; i < address_str.length(); ++i) { if (isdigit(address_str[i])) { diff --git a/components/brave_wallet/common/eth_request_helper.cc b/components/brave_wallet/common/eth_request_helper.cc index d192655e782a..514e36e8f4c5 100644 --- a/components/brave_wallet/common/eth_request_helper.cc +++ b/components/brave_wallet/common/eth_request_helper.cc @@ -5,6 +5,7 @@ #include "brave/components/brave_wallet/common/eth_request_helper.h" +#include #include #include #include @@ -12,6 +13,7 @@ #include "base/base64.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/ranges/algorithm.h" @@ -408,8 +410,9 @@ bool ParseEthDecryptParams(const std::string& json, } // IsValidHexString guarantees at least 2 bytes and starts with 0x - if (!UNSAFE_TODO(base::HexStringToString(untrusted_hex_json_str->data() + 2, - &untrusted_json))) { + if (!base::HexStringToString( + base::as_string_view(*untrusted_hex_json_str).substr(2), + &untrusted_json)) { return false; } diff --git a/components/brave_wallet/common/eth_sign_typed_data_helper.cc b/components/brave_wallet/common/eth_sign_typed_data_helper.cc index aee765cb75f3..1a4747c8ab6c 100644 --- a/components/brave_wallet/common/eth_sign_typed_data_helper.cc +++ b/components/brave_wallet/common/eth_sign_typed_data_helper.cc @@ -132,14 +132,12 @@ std::string EthSignTypedDataHelper::EncodeTypes( return result; } -std::vector EthSignTypedDataHelper::GetTypeHash( +KeccakHashArray EthSignTypedDataHelper::GetTypeHash( const std::string& primary_type_name) const { - const std::string type_hash = - KeccakHash(EncodeTypes(primary_type_name), false); - return std::vector(type_hash.begin(), type_hash.end()); + return KeccakHash(base::as_byte_span(EncodeTypes(primary_type_name))); } -std::optional, base::Value::Dict>> +std::optional> EthSignTypedDataHelper::HashStruct(const std::string& primary_type_name, const base::Value::Dict& data) const { auto encoded_data = EncodeData(primary_type_name, data); @@ -161,8 +159,7 @@ EthSignTypedDataHelper::EncodeData(const std::string& primary_type_name, } std::vector result; - const std::vector type_hash = GetTypeHash(primary_type_name); - result.insert(result.end(), type_hash.begin(), type_hash.end()); + base::Extend(result, GetTypeHash(primary_type_name)); base::Value::Dict sanitized_data; @@ -179,13 +176,11 @@ EthSignTypedDataHelper::EncodeData(const std::string& primary_type_name, if (!encoded_field) { return std::nullopt; } - result.insert(result.end(), encoded_field->begin(), encoded_field->end()); + base::Extend(result, *encoded_field); sanitized_data.Set(*name_str, value->Clone()); } else { if (version_ == Version::kV4) { - for (size_t i = 0; i < 32; ++i) { - result.push_back(0); - } + result.insert(result.end(), 32, 0); } } } @@ -194,12 +189,11 @@ EthSignTypedDataHelper::EncodeData(const std::string& primary_type_name, // Encode each field of a custom type, if a field is also a custom type it // will call EncodeData recursively until it reaches an atomic type -std::optional> EthSignTypedDataHelper::EncodeField( +std::optional EthSignTypedDataHelper::EncodeField( const std::string& type, const base::Value& value) const { // ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER constexpr double kMaxSafeInteger = static_cast(kMaxSafeIntegerUint64); - std::vector result; if (base::EndsWith(type, "]")) { if (version_ != Version::kV4) { @@ -221,22 +215,20 @@ std::optional> EthSignTypedDataHelper::EncodeField( if (!encoded_item) { return std::nullopt; } - array_result.insert(array_result.end(), encoded_item->begin(), - encoded_item->end()); + base::Extend(array_result, *encoded_item); } - auto array_hash = KeccakHash(array_result); - result.insert(result.end(), array_hash.begin(), array_hash.end()); - } else if (type == "string") { + return KeccakHash(array_result); + } + + if (type == "string") { const std::string* value_str = value.GetIfString(); if (!value_str) { return std::nullopt; } - const std::string encoded_value = KeccakHash(*value_str, false); - const std::vector encoded_value_bytes(encoded_value.begin(), - encoded_value.end()); - result.insert(result.end(), encoded_value_bytes.begin(), - encoded_value_bytes.end()); - } else if (type == "bytes") { + return KeccakHash(base::as_byte_span(*value_str)); + } + + if (type == "bytes") { const std::string* value_str = value.GetIfString(); if (!value_str || (!value_str->empty() && !IsValidHexString(*value_str))) { return std::nullopt; @@ -245,19 +237,21 @@ std::optional> EthSignTypedDataHelper::EncodeField( if (!value_str->empty()) { CHECK(PrefixedHexStringToBytes(*value_str, &bytes)); } - const std::vector encoded_value = KeccakHash(bytes); - result.insert(result.end(), encoded_value.begin(), encoded_value.end()); - } else if (type == "bool") { + return KeccakHash(bytes); + } + + if (type == "bool") { std::optional value_bool = value.GetIfBool(); if (!value_bool) { return std::nullopt; } - uint256_t encoded_value = (uint256_t)*value_bool; - // Append the encoded value to byte array result in big endian order - for (int i = 256 - 8; i >= 0; i -= 8) { - result.push_back(static_cast((encoded_value >> i) & 0xFF)); - } - } else if (type == "address") { + + KeccakHashArray result = {}; + result.back() = value_bool.value() ? 1 : 0; + return result; + } + + if (type == "address") { const std::string* value_str = value.GetIfString(); if (!value_str || !IsValidHexString(*value_str)) { return std::nullopt; @@ -267,11 +261,13 @@ std::optional> EthSignTypedDataHelper::EncodeField( if (address.size() != 20u) { return std::nullopt; } - for (size_t i = 0; i < 256 - 160; i += 8) { - result.push_back(0); - } - result.insert(result.end(), address.begin(), address.end()); - } else if (base::StartsWith(type, "bytes", base::CompareCase::SENSITIVE)) { + + KeccakHashArray result = {}; + base::as_writable_byte_span(result).last(20u).copy_from(address); + return result; + } + + if (base::StartsWith(type, "bytes", base::CompareCase::SENSITIVE)) { unsigned num_bits; if (!base::StringToUint(type.data() + 5, &num_bits) || num_bits > 32) { return std::nullopt; @@ -285,11 +281,12 @@ std::optional> EthSignTypedDataHelper::EncodeField( if (bytes.size() > 32) { return std::nullopt; } - result.insert(result.end(), bytes.begin(), bytes.end()); - for (size_t i = 0; i < 32u - bytes.size(); ++i) { - result.push_back(0); - } - } else if (base::StartsWith(type, "uint", base::CompareCase::SENSITIVE)) { + KeccakHashArray result = {}; + base::as_writable_byte_span(result).copy_prefix_from(bytes); + return result; + } + + if (base::StartsWith(type, "uint", base::CompareCase::SENSITIVE)) { // uint8 to uint256 in steps of 8 unsigned num_bits; if (!base::StringToUint(type.data() + 4, &num_bits) || @@ -324,11 +321,17 @@ std::optional> EthSignTypedDataHelper::EncodeField( return std::nullopt; } - // Append the encoded value to byte array result in big endian order - for (int i = 256 - 8; i >= 0; i -= 8) { - result.push_back(static_cast((encoded_value >> i) & 0xFF)); + KeccakHashArray result = {}; + auto encoded_value_span = base::byte_span_from_ref(encoded_value); + CHECK(result.size() == encoded_value_span.size()); + for (size_t i = 0; i < 32; ++i) { + result[i] = encoded_value_span[32 - i - 1]; } - } else if (base::StartsWith(type, "int", base::CompareCase::SENSITIVE)) { + + return result; + } + + if (base::StartsWith(type, "int", base::CompareCase::SENSITIVE)) { // int8 to int256 in steps of 8 unsigned num_bits; if (!base::StringToUint(type.data() + 3, &num_bits) || @@ -364,32 +367,33 @@ std::optional> EthSignTypedDataHelper::EncodeField( return std::nullopt; } - // Append the encoded value to byte array result in big endian order - for (int i = 256 - 8; i >= 0; i -= 8) { - result.push_back(static_cast((encoded_value >> i) & 0xFF)); - } - } else { - if (!value.is_dict()) { - return std::nullopt; - } - auto encoded_data = EncodeData(type, value.GetDict()); - if (!encoded_data) { - return std::nullopt; + KeccakHashArray result = {}; + auto encoded_value_span = base::byte_span_from_ref(encoded_value); + CHECK(result.size() == encoded_value_span.size()); + for (size_t i = 0; i < 32; ++i) { + result[i] = encoded_value_span[32 - i - 1]; } - std::vector encoded_value = KeccakHash(encoded_data->first); - result.insert(result.end(), encoded_value.begin(), encoded_value.end()); + return result; } - return result; + + if (!value.is_dict()) { + return std::nullopt; + } + auto encoded_data = EncodeData(type, value.GetDict()); + if (!encoded_data) { + return std::nullopt; + } + return KeccakHash(encoded_data->first); } -std::optional, base::Value::Dict>> +std::optional> EthSignTypedDataHelper::GetTypedDataDomainHash( const base::Value::Dict& domain) const { return HashStruct("EIP712Domain", domain); } -std::optional, base::Value::Dict>> +std::optional> EthSignTypedDataHelper::GetTypedDataPrimaryHash( const std::string& primary_type_name, const base::Value::Dict& message) const { @@ -397,7 +401,8 @@ EthSignTypedDataHelper::GetTypedDataPrimaryHash( } // static -std::vector EthSignTypedDataHelper::GetTypedDataMessageToSign( +std::optional +EthSignTypedDataHelper::GetTypedDataMessageToSign( base::span domain_hash, base::span primary_hash) { DCHECK(!domain_hash.empty()); diff --git a/components/brave_wallet/common/eth_sign_typed_data_helper.h b/components/brave_wallet/common/eth_sign_typed_data_helper.h index f4655c33328d..da0937296651 100644 --- a/components/brave_wallet/common/eth_sign_typed_data_helper.h +++ b/components/brave_wallet/common/eth_sign_typed_data_helper.h @@ -16,6 +16,7 @@ #include "base/containers/span.h" #include "base/gtest_prod_util.h" #include "base/values.h" +#include "brave/components/brave_wallet/common/hash_utils.h" namespace brave_wallet { @@ -34,20 +35,20 @@ class EthSignTypedDataHelper { void SetTypes(base::Value::Dict types); void SetVersion(Version version); - std::vector GetTypeHash(const std::string& primary_type_name) const; - std::optional, base::Value::Dict>> HashStruct( + KeccakHashArray GetTypeHash(const std::string& primary_type_name) const; + std::optional> HashStruct( const std::string& primary_type_name, const base::Value::Dict& data) const; std::optional, base::Value::Dict>> EncodeData( const std::string& primary_type_name, const base::Value::Dict& data) const; - static std::vector GetTypedDataMessageToSign( + static KeccakHashArray GetTypedDataMessageToSign( base::span domain_hash, base::span primary_hash); - std::optional, base::Value::Dict>> + std::optional> GetTypedDataPrimaryHash(const std::string& primary_type_name, const base::Value::Dict& message) const; - std::optional, base::Value::Dict>> + std::optional> GetTypedDataDomainHash(const base::Value::Dict& domain) const; private: @@ -66,9 +67,8 @@ class EthSignTypedDataHelper { const std::string& type_name) const; std::string EncodeTypes(const std::string& primary_type_name) const; - std::optional> EncodeField( - const std::string& type, - const base::Value& value) const; + std::optional EncodeField(const std::string& type, + const base::Value& value) const; base::Value::Dict types_; Version version_; diff --git a/components/brave_wallet/common/hash_utils.cc b/components/brave_wallet/common/hash_utils.cc index f66a178c0cc1..90582a473d5d 100644 --- a/components/brave_wallet/common/hash_utils.cc +++ b/components/brave_wallet/common/hash_utils.cc @@ -31,33 +31,22 @@ std::array ConcatArrays(const std::array& arr1, } } // namespace -std::string KeccakHash(const std::string& input, bool to_hex) { - std::vector bytes(input.begin(), input.end()); - std::vector result = KeccakHash(bytes); - std::string result_str(result.begin(), result.end()); - return to_hex ? ToHex(result_str) : result_str; -} - -std::vector KeccakHash(const std::vector& input) { - auto hash = ethash_keccak256(input.data(), input.size()); - return UNSAFE_TODO(std::vector(hash.bytes, hash.bytes + 32)); -} - -eth_abi::Bytes32 KeccakHashBytes32(base::span input) { +KeccakHashArray KeccakHash(base::span input) { auto hash = ethash_keccak256(input.data(), input.size()); - eth_abi::Bytes32 result; + KeccakHashArray result; static_assert(sizeof(result) == sizeof(hash.bytes)); base::ranges::copy(hash.bytes, result.begin()); return result; } std::string GetFunctionHash(const std::string& input) { - std::string result = KeccakHash(input); - return result.substr(0, std::min(static_cast(10), result.length())); + auto hex_hash = ToHex(KeccakHash(base::as_byte_span(input))); + CHECK_EQ(hex_hash.size(), 66u); + return hex_hash.substr(0, 10); } eth_abi::Bytes4 GetFunctionHashBytes4(const std::string& input) { - auto full_hash = KeccakHashBytes32(base::as_bytes(base::make_span(input))); + auto full_hash = KeccakHash(base::as_bytes(base::make_span(input))); eth_abi::Bytes4 bytes_result; base::ranges::copy(base::make_span(full_hash).first<4>(), bytes_result.begin()); @@ -70,8 +59,8 @@ eth_abi::Bytes32 Namehash(const std::string& name) { SplitString(name, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); for (const auto& label : base::Reversed(labels)) { - auto label_hash = KeccakHashBytes32(base::as_bytes(base::make_span(label))); - hash = KeccakHashBytes32(ConcatArrays(hash, label_hash)); + auto label_hash = KeccakHash(base::as_byte_span(label)); + hash = KeccakHash(ConcatArrays(hash, label_hash)); } return hash; } diff --git a/components/brave_wallet/common/hash_utils.h b/components/brave_wallet/common/hash_utils.h index 63d093548b10..34919e4baf7e 100644 --- a/components/brave_wallet/common/hash_utils.h +++ b/components/brave_wallet/common/hash_utils.h @@ -15,10 +15,10 @@ namespace brave_wallet { -// Equivalent to web3.utils.keccak256(string) -std::string KeccakHash(const std::string& input, bool to_hex = true); -std::vector KeccakHash(const std::vector& input); -eth_abi::Bytes32 KeccakHashBytes32(base::span input); +static const size_t kKeccakHashLength = 32; +using KeccakHashArray = std::array; + +KeccakHashArray KeccakHash(base::span input); // Returns the hex encoding of the first 4 bytes of the hash. // For example: keccak('balanceOf(address)') diff --git a/components/brave_wallet/common/hash_utils_unittest.cc b/components/brave_wallet/common/hash_utils_unittest.cc index 55da6011d88c..587b4740a162 100644 --- a/components/brave_wallet/common/hash_utils_unittest.cc +++ b/components/brave_wallet/common/hash_utils_unittest.cc @@ -7,6 +7,7 @@ #include +#include "base/containers/span.h" #include "brave/components/brave_wallet/common/hex_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -14,10 +15,10 @@ namespace brave_wallet { TEST(HashUtilsUnitTest, KeccakHash) { ASSERT_EQ( - KeccakHash(""), + ToHex(KeccakHash({})), "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); ASSERT_EQ( - KeccakHash("hello world"), + ToHex(KeccakHash(base::byte_span_from_cstring("hello world"))), "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"); } diff --git a/components/brave_wallet/common/hex_utils.cc b/components/brave_wallet/common/hex_utils.cc index 4d74d2ae0fe3..dc7a8fbd8fe4 100644 --- a/components/brave_wallet/common/hex_utils.cc +++ b/components/brave_wallet/common/hex_utils.cc @@ -8,7 +8,9 @@ #include #include -#include "base/compiler_specific.h" +#include "base/containers/adapters.h" +#include "base/containers/span.h" +#include "base/debug/crash_logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -152,18 +154,32 @@ bool HexValueToInt256(const std::string& hex_input, int256_t* out) { std::string Uint256ValueToHex(uint256_t input) { std::string result; - result.reserve(32); - - static constexpr char kHexChars[] = "0123456789abcdef"; - while (input) { - uint8_t i = static_cast(input & static_cast(0x0F)); - UNSAFE_TODO(result.insert(result.begin(), kHexChars[i])); - input >>= 4; + result.reserve(34); + result.append("0x"); + + auto input_span = base::byte_span_from_ref(input); + bool skipping_zeros = true; + for (auto& byte : base::Reversed(input_span)) { + if (skipping_zeros && !byte) { + continue; + } + if (skipping_zeros && byte) { + skipping_zeros = false; + if (byte <= 0xf) { + std::string one_char_byte; + base::AppendHexEncodedByte(byte, one_char_byte, false); + result += one_char_byte[1]; + continue; + } + } + base::AppendHexEncodedByte(byte, result, false); } - if (result.empty()) { - return "0x0"; + + if (result.size() == 2) { + return result += '0'; // 0x0 case } - return "0x" + result; + + return result; } bool PrefixedHexStringToBytes(const std::string& input, diff --git a/components/brave_wallet/renderer/js_solana_provider.cc b/components/brave_wallet/renderer/js_solana_provider.cc index 3f7854d81980..1a5882f37c09 100644 --- a/components/brave_wallet/renderer/js_solana_provider.cc +++ b/components/brave_wallet/renderer/js_solana_provider.cc @@ -93,39 +93,12 @@ JSSolanaProvider::JSSolanaProvider(content::RenderFrame* render_frame) : RenderFrameObserver(render_frame), v8_value_converter_(content::V8ValueConverter::Create()) { EnsureConnected(); - v8_value_converter_->SetStrategy(&strategy_); } JSSolanaProvider::~JSSolanaProvider() = default; gin::WrapperInfo JSSolanaProvider::kWrapperInfo = {gin::kEmbedderNativeGin}; -// Convert Uint8Array to blob base::Value -bool JSSolanaProvider::V8ConverterStrategy::FromV8ArrayBuffer( - v8::Local value, - std::unique_ptr* out, - v8::Isolate* isolate) { - if (!value->IsTypedArray()) { - return false; - } - std::vector bytes; - char* data = nullptr; - size_t data_length = 0; - gin::ArrayBufferView view; - if (gin::ConvertFromV8(isolate, value.As(), &view)) { - data = reinterpret_cast(view.bytes()); - data_length = view.num_bytes(); - UNSAFE_TODO(bytes.assign(data, data + data_length)); - } - if (!bytes.size()) { - return false; - } - std::unique_ptr new_value = std::make_unique(bytes); - *out = std::move(new_value); - - return true; -} - // static void JSSolanaProvider::Install(bool allow_overwrite_window_solana, content::RenderFrame* render_frame) { diff --git a/components/brave_wallet/renderer/js_solana_provider.h b/components/brave_wallet/renderer/js_solana_provider.h index 7d2f0ae857f6..76cffb138b4f 100644 --- a/components/brave_wallet/renderer/js_solana_provider.h +++ b/components/brave_wallet/renderer/js_solana_provider.h @@ -32,16 +32,6 @@ class JSSolanaProvider final : public gin::Wrappable, static gin::WrapperInfo kWrapperInfo; - class V8ConverterStrategy : public content::V8ValueConverter::Strategy { - public: - V8ConverterStrategy() = default; - ~V8ConverterStrategy() override = default; - - bool FromV8ArrayBuffer(v8::Local value, - std::unique_ptr* out, - v8::Isolate* isolate) override; - }; - static void Install(bool allow_overwrite_window_solana, content::RenderFrame* render_frame); @@ -195,7 +185,7 @@ class JSSolanaProvider final : public gin::Wrappable, bool wallet_standard_loaded_ = false; v8::Global solana_web3_module_; std::unique_ptr v8_value_converter_; - V8ConverterStrategy strategy_; + // V8ConverterStrategy strategy_; mojo::Remote solana_provider_; mojo::Receiver receiver_{this}; };