Skip to content

Commit f09caec

Browse files
authored
Refactor address_codec to render Address serialization consistent with Lotus (#55)
* Refactor address_codec to render Address serialization consistent with Lotus (#55) Signed-off-by: Eugene Kovalev <[email protected]>
1 parent 526f736 commit f09caec

File tree

7 files changed

+140
-229
lines changed

7 files changed

+140
-229
lines changed

core/primitives/address/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ target_link_libraries(address
1212
blake2
1313
blob
1414
bls_provider
15+
cbor
1516
outcome
1617
p2p::p2p_secp256k1_provider
1718
)

core/primitives/address/address_codec.cpp

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ namespace fc::primitives::address {
2323
using base32 = cppcodec::base32_rfc4648;
2424
using UVarint = libp2p::multi::UVarint;
2525

26-
std::vector<uint8_t> encode(const Address &address) {
26+
std::vector<uint8_t> encode(const Address &address) noexcept {
2727
std::vector<uint8_t> res{};
28-
res.push_back(address.network);
2928
res.push_back(address.getProtocol());
3029
std::vector<uint8_t> payload = visit_in_place(
3130
address.data,
@@ -38,16 +37,13 @@ namespace fc::primitives::address {
3837
}
3938

4039
outcome::result<Address> decode(const std::vector<uint8_t> &v) {
41-
if (v.size() < 3) return outcome::failure(AddressError::INVALID_PAYLOAD);
42-
auto pos = v.begin();
40+
if (v.size() < 2) return outcome::failure(AddressError::INVALID_PAYLOAD);
4341

44-
auto net = static_cast<Network>(*(pos++));
45-
if (!(net == Network::TESTNET || net == Network::MAINNET)) {
46-
return outcome::failure(AddressError::UNKNOWN_NETWORK);
47-
}
42+
// TODO(ekovalev): [FIL-118] make network configurable; hardcoded for now
43+
Network net{Network::TESTNET};
4844

49-
auto p = static_cast<Protocol>(*(pos++));
50-
std::vector<uint8_t> payload(pos, v.end());
45+
auto p = static_cast<Protocol>(v[0]);
46+
std::vector<uint8_t> payload(std::next(v.begin()), v.end());
5147
switch (p) {
5248
case Protocol::ID: {
5349
boost::optional<UVarint> value = UVarint::create(payload);
@@ -94,8 +90,7 @@ namespace fc::primitives::address {
9490
std::string encodeToString(const Address &address) {
9591
std::string res{};
9692

97-
char networkPrefix = 'f';
98-
if (address.network == Network::TESTNET) networkPrefix = 't';
93+
char networkPrefix = address.network == Network::TESTNET ? 't' : 'f';
9994
res.push_back(networkPrefix);
10095

10196
Protocol p = address.getProtocol();
@@ -137,17 +132,11 @@ namespace fc::primitives::address {
137132
outcome::result<Address> decodeFromString(const std::string &s) {
138133
if (s.size() < 3) return outcome::failure(AddressError::INVALID_PAYLOAD);
139134

140-
std::vector<uint8_t> buffer{};
141-
Network net{Network::MAINNET};
142-
143135
if (s[0] != 'f' && s[0] != 't')
144136
return outcome::failure(AddressError::UNKNOWN_NETWORK);
145-
if (s[0] == 'f')
146-
buffer.push_back(static_cast<uint8_t>(Network::MAINNET));
147-
else {
148-
buffer.push_back(static_cast<uint8_t>(Network::TESTNET));
149-
net = Network::TESTNET;
150-
}
137+
138+
std::vector<uint8_t> buffer{};
139+
Network net = s[0] == 't' ? Network::TESTNET : Network::MAINNET;
151140

152141
int protocol = int(s[1]) - int('0');
153142
if (protocol < Protocol::ID || protocol > Protocol::BLS)
@@ -190,7 +179,9 @@ namespace fc::primitives::address {
190179
std::make_move_iterator(payload.begin()),
191180
std::make_move_iterator(payload.end()) - 4);
192181

193-
return decode(buffer);
182+
OUTCOME_TRY(address, decode(buffer));
183+
address.network = net;
184+
return address;
194185
}
195186

196187
std::vector<uint8_t> checksum(const Address &address) {
@@ -208,13 +199,12 @@ namespace fc::primitives::address {
208199

209200
ingest.push_back(p);
210201

211-
ingest = visit_in_place(
212-
address.data,
213-
[&ingest](uint64_t v) { return ingest; },
214-
[&ingest](const auto &v) {
215-
ingest.insert(ingest.end(), v.begin(), v.end());
216-
return ingest;
217-
});
202+
ingest = visit_in_place(address.data,
203+
[&ingest](uint64_t v) { return ingest; },
204+
[&ingest](const auto &v) {
205+
ingest.insert(ingest.end(), v.begin(), v.end());
206+
return ingest;
207+
});
218208

219209
size_t outlen = 4;
220210
blake2b(res.data(), outlen, nullptr, 0, ingest.data(), ingest.size());
@@ -227,4 +217,4 @@ namespace fc::primitives::address {
227217
return digest == expect;
228218
}
229219

230-
}; // namespace fc::primitives
220+
}; // namespace fc::primitives::address

core/primitives/address/address_codec.hpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
#include <string>
1010
#include <vector>
1111

12-
#include "common/outcome.hpp"
1312
#include "address.hpp"
13+
#include "codec/cbor/cbor.hpp"
14+
#include "common/outcome.hpp"
15+
#include "common/outcome_throw.hpp"
1416

1517
namespace fc::primitives::address {
1618

1719
/**
1820
* @brief Encodes an Address to an array of bytes
1921
*/
20-
std::vector<uint8_t> encode(const Address &address);
22+
std::vector<uint8_t> encode(const Address &address) noexcept;
2123

2224
/**
2325
* @brief Decodes an Address from an array of bytes
@@ -34,6 +36,27 @@ namespace fc::primitives::address {
3436
*/
3537
outcome::result<Address> decodeFromString(const std::string &s);
3638

39+
template <class Stream,
40+
typename = std::enable_if_t<
41+
std::remove_reference<Stream>::type::is_cbor_encoder_stream>>
42+
Stream &operator<<(Stream &&s, const Address &address) noexcept {
43+
return s << encode(address);
44+
}
45+
46+
template <class Stream,
47+
typename = std::enable_if_t<
48+
std::remove_reference<Stream>::type::is_cbor_decoder_stream>>
49+
Stream &operator>>(Stream &&s, Address &address) {
50+
std::vector<uint8_t> data{};
51+
s >> data;
52+
auto res = decode(data);
53+
if (res.has_error()) {
54+
outcome::raise(AddressError::INVALID_PAYLOAD);
55+
}
56+
address = std::move(res.value());
57+
return s;
58+
}
59+
3760
/**
3861
* @brief A helper function that calculates a checksum of an Address protocol
3962
* + payload
@@ -46,6 +69,6 @@ namespace fc::primitives::address {
4669
bool validateChecksum(const Address &address,
4770
const std::vector<uint8_t> &expect);
4871

49-
}; // namespace fc::primitives
72+
}; // namespace fc::primitives::address
5073

5174
#endif // CPP_FILECOIN_CORE_PRIMITIVES_ADDRESS_CODEC_HPP

core/primitives/address/impl/address_builder_impl.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,21 @@ namespace fc::primitives::address {
1414
using Sec256k1PublicKey = libp2p::crypto::secp256k1::PublicKey;
1515
using BlsPublicKey = crypto::bls::PublicKey;
1616
using crypto::blake2b::blake2b_160;
17-
using primitives::address::decode;
18-
using primitives::address::encode;
17+
using primitives::address::BLSPublicKeyHash;
1918
using primitives::address::Protocol;
19+
using primitives::address::Secp256k1PublicKeyHash;
2020

2121
outcome::result<Address> AddressBuilderImpl::makeFromSecp256k1PublicKey(
2222
Network network, const Sec256k1PublicKey &public_key) noexcept {
2323
OUTCOME_TRY(hash, blake2b_160(public_key));
24-
std::vector<uint8_t> sec256k1_bytes{network, Protocol::SECP256K1};
25-
sec256k1_bytes.insert(sec256k1_bytes.end(), hash.begin(), hash.end());
26-
return decode(sec256k1_bytes);
24+
Secp256k1PublicKeyHash secp256k1Hash{hash};
25+
return Address{network, secp256k1Hash};
2726
}
2827

2928
outcome::result<Address> AddressBuilderImpl::makeFromBlsPublicKey(
3029
Network network, const BlsPublicKey &public_key) noexcept {
31-
std::vector<uint8_t> bls_bytes{network, Protocol::BLS};
32-
bls_bytes.insert(bls_bytes.end(), public_key.begin(), public_key.end());
33-
return decode(bls_bytes);
30+
BLSPublicKeyHash blsHash{public_key};
31+
return Address{network, blsHash};
3432
}
3533

3634
} // namespace fc::primitives::address

0 commit comments

Comments
 (0)