xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
libxrpl
protocol
AccountID.cpp
1
#include <xrpl/protocol/AccountID.h>
2
3
#include <xrpl/basics/hardened_hash.h>
4
#include <xrpl/basics/spinlock.h>
5
#include <xrpl/beast/utility/Zero.h>
6
#include <xrpl/beast/utility/instrumentation.h>
7
#include <xrpl/protocol/PublicKey.h>
8
#include <xrpl/protocol/digest.h>
9
#include <xrpl/protocol/tokens.h>
10
11
#include <
atomic
>
12
#include <
cstdint
>
13
#include <
cstring
>
14
#include <
memory
>
15
#include <
mutex
>
16
#include <
optional
>
17
#include <
string
>
18
#include <
vector
>
19
20
namespace
xrpl
{
21
22
namespace
detail
{
23
27
class
AccountIdCache
28
{
29
private
:
30
struct
CachedAccountID
31
{
32
AccountID
id
;
33
char
encoding
[40] = {0};
34
};
35
36
// The actual cache
37
std::vector<CachedAccountID>
cache_
;
38
39
// We use a hash function designed to resist algorithmic complexity attacks
40
HardenedHash<>
hasher_
;
41
42
// 64 spinlocks, packed into a single 64-bit value
43
std::atomic<std::uint64_t>
locks_
= 0;
44
45
public
:
46
AccountIdCache
(
std::size_t
count) :
cache_
(count)
47
{
48
// This is non-binding, but we try to avoid wasting memory that
49
// is caused by overallocation.
50
cache_
.shrink_to_fit();
51
}
52
53
std::string
54
toBase58
(
AccountID
const
&
id
)
55
{
56
auto
const
index =
hasher_
(
id
) %
cache_
.size();
57
58
PackedSpinlock
sl(
locks_
, index % 64);
59
60
{
61
std::scoped_lock
const
lock(sl);
62
63
// The check against the first character of the encoding ensures
64
// that we don't mishandle the case of the all-zero account:
65
if
(
cache_
[index].encoding[0] != 0 &&
cache_
[index].
id
==
id
)
66
return
cache_
[index].encoding;
67
}
68
69
auto
ret =
encodeBase58Token
(
TokenType::AccountID
,
id
.data(),
id
.size());
70
71
XRPL_ASSERT(ret.size() <= 38,
"xrpl::detail::AccountIdCache : maximum result size"
);
72
73
{
74
std::scoped_lock
const
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
85
static
std::unique_ptr<detail::AccountIdCache>
gAccountIdCache
;
86
87
void
88
initAccountIdCache
(
std::size_t
count)
89
{
90
if
(!
gAccountIdCache
&& count != 0)
91
gAccountIdCache
=
std::make_unique<detail::AccountIdCache>
(count);
92
}
93
94
std::string
95
toBase58
(
AccountID
const
& v)
96
{
97
if
(
gAccountIdCache
)
98
return
gAccountIdCache
->toBase58(v);
99
100
return
encodeBase58Token
(
TokenType::AccountID
, v.
data
(), v.
size
());
101
}
102
103
template
<>
104
std::optional<AccountID>
105
parseBase58
(
std::string
const
& s)
106
{
107
auto
const
result =
decodeBase58Token
(s,
TokenType::AccountID
);
108
if
(result.size() !=
AccountID::kBytes
)
109
return
std::nullopt;
110
return
AccountID::fromRaw
(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
*/
148
AccountID
149
calcAccountID
(
PublicKey
const
& pk)
150
{
151
static_assert
(
AccountID::kBytes
==
sizeof
(
RipeshaHasher::result_type
));
152
153
RipeshaHasher
rsh;
154
rsh(pk.
data
(), pk.
size
());
155
return
AccountID::fromRaw
(
static_cast<
RipeshaHasher::result_type
>
(rsh));
156
}
157
158
AccountID
const
&
159
xrpAccount
()
160
{
161
static
AccountID
const
kAccount(
beast::kZero
);
162
return
kAccount;
163
}
164
165
AccountID
const
&
166
noAccount
()
167
{
168
static
AccountID
const
kAccount(1);
169
return
kAccount;
170
}
171
172
bool
173
toIssuer
(
AccountID
& issuer,
std::string
const
& s)
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 xrpl
atomic
std::string
xrpl::BaseUInt< 160, detail::AccountIDTag >::fromRaw
static BaseUInt fromRaw(Container const &c)
Definition
base_uint.h:302
xrpl::BaseUInt::data
pointer data()
Definition
base_uint.h:117
xrpl::BaseUInt< 160, detail::AccountIDTag >::kBytes
static constexpr std::size_t kBytes
Definition
base_uint.h:100
xrpl::BaseUInt::size
static constexpr std::size_t size()
Definition
base_uint.h:548
xrpl::BaseUInt::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition
base_uint.h:525
xrpl::HardenedHash
Seed functor once per construction.
Definition
hardened_hash.h:72
xrpl::PackedSpinlock
Classes to handle arrays of spinlocks packed into a single atomic integer:
Definition
spinlock.h:78
xrpl::PublicKey
A public key.
Definition
PublicKey.h:53
xrpl::PublicKey::data
std::uint8_t const * data() const noexcept
Definition
PublicKey.h:79
xrpl::PublicKey::size
static std::size_t size() noexcept
Definition
PublicKey.h:85
xrpl::detail::AccountIdCache::toBase58
std::string toBase58(AccountID const &id)
Definition
AccountID.cpp:54
xrpl::detail::AccountIdCache::AccountIdCache
AccountIdCache(std::size_t count)
Definition
AccountID.cpp:46
xrpl::detail::AccountIdCache::hasher_
HardenedHash hasher_
Definition
AccountID.cpp:40
xrpl::detail::AccountIdCache::cache_
std::vector< CachedAccountID > cache_
Definition
AccountID.cpp:37
xrpl::detail::AccountIdCache::locks_
std::atomic< std::uint64_t > locks_
Definition
AccountID.cpp:43
cstdint
cstring
std::make_unique
T make_unique(T... args)
memory
mutex
beast::kZero
constexpr Zero kZero
Definition
Zero.h:30
xrpl::detail
Definition
base_uint.h:37
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::gAccountIdCache
static std::unique_ptr< detail::AccountIdCache > gAccountIdCache
Definition
AccountID.cpp:85
xrpl::parseBase58
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
Definition
AccountID.cpp:105
xrpl::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition
AccountID.cpp:95
xrpl::initAccountIdCache
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
Definition
AccountID.cpp:88
xrpl::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition
AccountID.cpp:149
xrpl::TokenType::AccountID
@ AccountID
Definition
tokens.h:23
xrpl::AccountID
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition
AccountID.h:34
xrpl::noAccount
AccountID const & noAccount()
A placeholder for empty accounts.
Definition
AccountID.cpp:166
xrpl::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition
AccountID.cpp:159
xrpl::encodeBase58Token
std::string encodeBase58Token(TokenType type, void const *token, std::size_t size)
Encode data in Base58Check format using XRPL alphabet.
Definition
tokens.cpp:181
xrpl::decodeBase58Token
std::string decodeBase58Token(std::string const &s, TokenType type)
Definition
tokens.cpp:191
xrpl::toIssuer
bool toIssuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition
AccountID.cpp:173
optional
std::scoped_lock
std::size_t
std::strcpy
T strcpy(T... args)
string
xrpl::RipeshaHasher
Returns the RIPEMD-160 digest of the SHA256 hash of the message.
Definition
digest.h:124
xrpl::RipeshaHasher::result_type
std::array< std::uint8_t, 20 > result_type
Definition
digest.h:131
xrpl::detail::AccountIdCache::CachedAccountID
Definition
AccountID.cpp:31
xrpl::detail::AccountIdCache::CachedAccountID::id
AccountID id
Definition
AccountID.cpp:32
xrpl::detail::AccountIdCache::CachedAccountID::encoding
char encoding[40]
Definition
AccountID.cpp:33
std::unique_ptr
vector
Generated by
1.17.0