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 xrpl {
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 = encodeBase58Token(TokenType::AccountID, id.data(), id.size());
67
68 XRPL_ASSERT(ret.size() <= 38, "xrpl::detail::AccountIdCache : maximum result size");
69
70 {
71 std::lock_guard lock(sl);
72 cache_[index].id = id;
73 std::strcpy(cache_[index].encoding, ret.c_str());
74 }
75
76 return ret;
77 }
78};
79
80} // namespace detail
81
83
84void
90
93{
95 return accountIdCache->toBase58(v);
96
98}
99
100template <>
103{
104 auto const result = decodeBase58Token(s, TokenType::AccountID);
105 if (result.size() != AccountID::bytes)
106 return std::nullopt;
107 return AccountID{result};
108}
109
110//------------------------------------------------------------------------------
111/*
112 Calculation of the Account ID
113
114 The AccountID is a 160-bit identifier that uniquely
115 distinguishes an account. The account may or may not
116 exist in the ledger. Even for accounts that are not in
117 the ledger, cryptographic operations may be performed
118 which affect the ledger. For example, designating an
119 account not in the ledger as a regular key for an
120 account that is in the ledger.
121
122 Why did we use half of SHA512 for most things but then
123 SHA256 followed by RIPEMD160 for account IDs? Why didn't
124 we do SHA512 half then RIPEMD160? Or even SHA512 then RIPEMD160?
125 For that matter why RIPEMD160 at all why not just SHA512 and keep
126 only 160 bits?
127
128 Answer (David Schwartz):
129
130 The short answer is that we kept Bitcoin's behavior.
131 The longer answer was that:
132 1) Using a single hash could leave ripple
133 vulnerable to length extension attacks.
134 2) Only RIPEMD160 is generally considered safe at 160 bits.
135
136 Any of those schemes would have been acceptable. However,
137 the one chosen avoids any need to defend the scheme chosen.
138 (Against any criticism other than unnecessary complexity.)
139
140 "The historical reason was that in the very early days,
141 we wanted to give people as few ways to argue that we were
142 less secure than Bitcoin. So where there was no good reason
143 to change something, it was not changed."
144*/
147{
148 static_assert(AccountID::bytes == sizeof(ripesha_hasher::result_type));
149
150 ripesha_hasher rsh;
151 rsh(pk.data(), pk.size());
152 return AccountID{static_cast<ripesha_hasher::result_type>(rsh)};
153}
154
155AccountID const&
157{
158 static AccountID const account(beast::zero);
159 return account;
160}
161
162AccountID const&
164{
165 static AccountID const account(1);
166 return account;
167}
168
169bool
171{
172 if (issuer.parseHex(s))
173 return true;
174 auto const account = parseBase58<AccountID>(s);
175 if (!account)
176 return false;
177 issuer = *account;
178 return true;
179}
180
181} // namespace xrpl
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
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:472
pointer data()
Definition base_uint.h:102
static std::size_t constexpr bytes
Definition base_uint.h:85
static constexpr std::size_t size()
Definition base_uint.h:495
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
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
static std::unique_ptr< detail::AccountIdCache > accountIdCache
Definition AccountID.cpp:82
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:92
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
Definition AccountID.cpp:85
AccountID calcAccountID(PublicKey const &pk)
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
AccountID const & noAccount()
A placeholder for empty accounts.
AccountID const & xrpAccount()
Compute AccountID from public key.
std::string encodeBase58Token(TokenType type, void const *token, std::size_t size)
Encode data in Base58Check format using XRPL alphabet.
Definition tokens.cpp:176
std::string decodeBase58Token(std::string const &s, TokenType type)
Definition tokens.cpp:186
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