rippled
Loading...
Searching...
No Matches
AccountID.cpp
1#include <xrpl/basics/hardened_hash.h>
2#include <xrpl/basics/spinlock.h>
3#include <xrpl/beast/utility/Zero.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/protocol/AccountID.h>
6#include <xrpl/protocol/PublicKey.h>
7#include <xrpl/protocol/digest.h>
8#include <xrpl/protocol/tokens.h>
9
10#include <atomic>
11#include <cstdint>
12#include <cstring>
13#include <memory>
14#include <mutex>
15#include <optional>
16#include <string>
17#include <vector>
18
19namespace ripple {
20
21namespace detail {
22
25{
26private:
28 {
30 char encoding[40] = {0};
31 };
32
33 // The actual cache
35
36 // We use a hash function designed to resist algorithmic complexity attacks
38
39 // 64 spinlocks, packed into a single 64-bit value
41
42public:
44 {
45 // This is non-binding, but we try to avoid wasting memory that
46 // is caused by overallocation.
47 cache_.shrink_to_fit();
48 }
49
52 {
53 auto const index = hasher_(id) % cache_.size();
54
55 packed_spinlock sl(locks_, index % 64);
56
57 {
58 std::lock_guard lock(sl);
59
60 // The check against the first character of the encoding ensures
61 // that we don't mishandle the case of the all-zero account:
62 if (cache_[index].encoding[0] != 0 && cache_[index].id == id)
63 return cache_[index].encoding;
64 }
65
66 auto ret =
67 encodeBase58Token(TokenType::AccountID, id.data(), id.size());
68
69 XRPL_ASSERT(
70 ret.size() <= 38,
71 "ripple::detail::AccountIdCache : maximum result size");
72
73 {
74 std::lock_guard lock(sl);
75 cache_[index].id = id;
76 std::strcpy(cache_[index].encoding, ret.c_str());
77 }
78
79 return ret;
80 }
81};
82
83} // namespace detail
84
86
87void
93
96{
98 return accountIdCache->toBase58(v);
99
101}
102
103template <>
106{
107 auto const result = decodeBase58Token(s, TokenType::AccountID);
108 if (result.size() != AccountID::bytes)
109 return std::nullopt;
110 return AccountID{result};
111}
112
113//------------------------------------------------------------------------------
114/*
115 Calculation of the Account ID
116
117 The AccountID is a 160-bit identifier that uniquely
118 distinguishes an account. The account may or may not
119 exist in the ledger. Even for accounts that are not in
120 the ledger, cryptographic operations may be performed
121 which affect the ledger. For example, designating an
122 account not in the ledger as a regular key for an
123 account that is in the ledger.
124
125 Why did we use half of SHA512 for most things but then
126 SHA256 followed by RIPEMD160 for account IDs? Why didn't
127 we do SHA512 half then RIPEMD160? Or even SHA512 then RIPEMD160?
128 For that matter why RIPEMD160 at all why not just SHA512 and keep
129 only 160 bits?
130
131 Answer (David Schwartz):
132
133 The short answer is that we kept Bitcoin's behavior.
134 The longer answer was that:
135 1) Using a single hash could leave ripple
136 vulnerable to length extension attacks.
137 2) Only RIPEMD160 is generally considered safe at 160 bits.
138
139 Any of those schemes would have been acceptable. However,
140 the one chosen avoids any need to defend the scheme chosen.
141 (Against any criticism other than unnecessary complexity.)
142
143 "The historical reason was that in the very early days,
144 we wanted to give people as few ways to argue that we were
145 less secure than Bitcoin. So where there was no good reason
146 to change something, it was not changed."
147*/
150{
151 static_assert(AccountID::bytes == sizeof(ripesha_hasher::result_type));
152
153 ripesha_hasher rsh;
154 rsh(pk.data(), pk.size());
155 return AccountID{static_cast<ripesha_hasher::result_type>(rsh)};
156}
157
158AccountID const&
160{
161 static AccountID const account(beast::zero);
162 return account;
163}
164
165AccountID const&
167{
168 static AccountID const account(1);
169 return account;
170}
171
172bool
174{
175 if (issuer.parseHex(s))
176 return true;
177 auto const account = parseBase58<AccountID>(s);
178 if (!account)
179 return false;
180 issuer = *account;
181 return true;
182}
183
184} // namespace ripple
A public key.
Definition PublicKey.h:43
std::uint8_t const * data() const noexcept
Definition PublicKey.h:68
std::size_t size() const noexcept
Definition PublicKey.h:74
static std::size_t constexpr bytes
Definition base_uint.h:89
static constexpr std::size_t size()
Definition base_uint.h:507
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:484
Caches the base58 representations of AccountIDs.
Definition AccountID.cpp:25
std::string toBase58(AccountID const &id)
Definition AccountID.cpp:51
AccountIdCache(std::size_t count)
Definition AccountID.cpp:43
std::vector< CachedAccountID > cache_
Definition AccountID.cpp:34
std::atomic< std::uint64_t > locks_
Definition AccountID.cpp:40
Seed functor once per construction.
Classes to handle arrays of spinlocks packed into a single atomic integer:
Definition spinlock.h:76
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
AccountID const & noAccount()
A placeholder for empty accounts.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
AccountID const & xrpAccount()
Compute AccountID from public key.
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
static std::unique_ptr< detail::AccountIdCache > accountIdCache
Definition AccountID.cpp:85
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
Definition AccountID.cpp:88
std::string encodeBase58Token(TokenType type, void const *token, std::size_t size)
Encode data in Base58Check format using XRPL alphabet.
Definition tokens.cpp:181
AccountID calcAccountID(PublicKey const &pk)
std::string decodeBase58Token(std::string const &s, TokenType type)
Definition tokens.cpp:191
T strcpy(T... args)
Returns the RIPEMD-160 digest of the SHA256 hash of the message.
Definition digest.h:117
std::array< std::uint8_t, 20 > result_type
Definition digest.h:124