Skip to content

Commit 3e39915

Browse files
Feature/storage power actor (#95)
Signed-off-by: Alexey-N-Chernyshov <[email protected]>
1 parent 0adcb72 commit 3e39915

27 files changed

+587
-235
lines changed

core/power/CMakeLists.txt

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
add_library(power_table
5-
impl/power_table_impl.cpp
6-
impl/power_table_error.cpp
7-
)
5+
impl/power_table_impl.cpp
6+
impl/power_table_error.cpp
7+
)
88
target_link_libraries(power_table
9-
outcome
10-
address
11-
)
9+
address
10+
outcome
11+
)
12+
13+
add_library(power_table_hamt
14+
impl/power_table_hamt.cpp
15+
impl/power_table_error.cpp
16+
)
17+
target_link_libraries(power_table_hamt
18+
address
19+
outcome
20+
hamt
21+
)

core/power/impl/power_table_hamt.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "power/impl/power_table_hamt.hpp"
7+
8+
#include "power/power_table_error.hpp"
9+
#include "primitives/address/address_codec.hpp"
10+
11+
using fc::power::Power;
12+
using fc::power::PowerTableError;
13+
using fc::power::PowerTableHamt;
14+
using fc::primitives::address::Address;
15+
using fc::primitives::address::decodeFromByteString;
16+
using fc::primitives::address::encodeToByteString;
17+
using fc::storage::hamt::HamtError;
18+
using fc::storage::hamt::Value;
19+
20+
PowerTableHamt::PowerTableHamt(Hamt hamt) : power_table_{std::move(hamt)} {}
21+
22+
fc::outcome::result<Power> PowerTableHamt::getMinerPower(
23+
const Address &address) const {
24+
auto result = power_table_.getCbor<Power>(encodeToByteString(address));
25+
if (!result && result.error() == HamtError::NOT_FOUND) {
26+
return outcome::failure(PowerTableError::NO_SUCH_MINER);
27+
}
28+
return result;
29+
}
30+
31+
fc::outcome::result<void> PowerTableHamt::setMinerPower(const Address &address,
32+
Power power_amount) {
33+
if (power_amount < 0) return PowerTableError::NEGATIVE_POWER;
34+
return power_table_.setCbor(encodeToByteString(address), power_amount);
35+
}
36+
37+
fc::outcome::result<void> PowerTableHamt::removeMiner(const Address &address) {
38+
auto result = power_table_.remove(encodeToByteString(address));
39+
if (!result && result.error() == HamtError::NOT_FOUND) {
40+
return outcome::failure(PowerTableError::NO_SUCH_MINER);
41+
}
42+
return result;
43+
}
44+
45+
fc::outcome::result<size_t> PowerTableHamt::getSize() const {
46+
size_t n = 0;
47+
Hamt::Visitor counter{[&n](auto k, auto v) {
48+
++n;
49+
return fc::outcome::success();
50+
}};
51+
OUTCOME_TRY(power_table_.visit(counter));
52+
return n;
53+
}
54+
55+
fc::outcome::result<Power> PowerTableHamt::getMaxPower() const {
56+
Power max = 0;
57+
Hamt::Visitor max_visitor{
58+
[&max](auto k, auto v) -> fc::outcome::result<void> {
59+
OUTCOME_TRY(power, codec::cbor::decode<Power>(v));
60+
if (max < power) max = power;
61+
return fc::outcome::success();
62+
}};
63+
OUTCOME_TRY(power_table_.visit(max_visitor));
64+
return max;
65+
}
66+
67+
fc::outcome::result<std::vector<Address>> PowerTableHamt::getMiners() const {
68+
std::vector<Address> miners;
69+
Hamt::Visitor max_visitor{
70+
[&miners](auto k, auto v) -> fc::outcome::result<void> {
71+
OUTCOME_TRY(address, decodeFromByteString(k));
72+
miners.push_back(address);
73+
return fc::outcome::success();
74+
}};
75+
OUTCOME_TRY(power_table_.visit(max_visitor));
76+
return miners;
77+
}

core/power/impl/power_table_hamt.hpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef CPP_FILECOIN_POWER_POWER_TABLE_HAMT_HPP
7+
#define CPP_FILECOIN_POWER_POWER_TABLE_HAMT_HPP
8+
9+
#include "power/power_table.hpp"
10+
#include "storage/hamt/hamt.hpp"
11+
12+
namespace fc::power {
13+
14+
using storage::hamt::Hamt;
15+
16+
/**
17+
* @class PowerTableHamt - HAMT-based implementation of PowerTable
18+
*/
19+
class PowerTableHamt : public PowerTable {
20+
public:
21+
/**
22+
* Construct HAMT-based power table
23+
* @param store - ipfs datastore
24+
* @param root - hamt root cid
25+
*/
26+
explicit PowerTableHamt(Hamt hamt);
27+
28+
/** @copydoc PowerTable::getMinerPower() */
29+
outcome::result<Power> getMinerPower(const Address &address) const override;
30+
31+
/** @copydoc PowerTable::setMinerPower() */
32+
outcome::result<void> setMinerPower(const Address &address,
33+
Power power_amount) override;
34+
35+
/** @copydoc PowerTable::removeMiner() */
36+
outcome::result<void> removeMiner(const Address &address) override;
37+
38+
/** @copydoc PowerTable::getSize() */
39+
fc::outcome::result<size_t> getSize() const override;
40+
41+
/** @copydoc PowerTable::getMaxPower() */
42+
fc::outcome::result<Power> getMaxPower() const override;
43+
44+
/** @copydoc PowerTable::getMiners() */
45+
outcome::result<std::vector<Address>> getMiners() const override;
46+
47+
private:
48+
/**
49+
* TODO (a.chernyshov) HAMT getter is not constant due to it uses cache.
50+
* It is a common example to use mutable field in HAMT.
51+
* In order to save semantic constant regarless of syntax constant
52+
* correctness the power_table_ field is marked as mutable.
53+
*
54+
* Remove mutable keyword after HAMT getter has const qualifier.
55+
*/
56+
mutable Hamt power_table_;
57+
};
58+
59+
} // namespace fc::power
60+
61+
#endif // CPP_FILECOIN_POWER_POWER_TABLE_HAMT_HPP

core/power/impl/power_table_impl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ namespace fc::power {
3636
return outcome::success();
3737
}
3838

39-
size_t PowerTableImpl::getSize() const {
39+
fc::outcome::result<size_t> PowerTableImpl::getSize() const {
4040
return power_table_.size();
4141
}
4242

43-
Power PowerTableImpl::getMaxPower() const {
43+
fc::outcome::result<Power> PowerTableImpl::getMaxPower() const {
4444
if (power_table_.empty()) return 0;
4545

4646
auto res = std::max(power_table_.cbegin(),
@@ -54,7 +54,8 @@ namespace fc::power {
5454

5555
outcome::result<std::vector<primitives::address::Address>>
5656
PowerTableImpl::getMiners() const {
57-
std::vector<primitives::address::Address> result = {};
57+
std::vector<primitives::address::Address> result;
58+
result.reserve(power_table_.size());
5859
for (auto &elem : power_table_) {
5960
OUTCOME_TRY(miner_addr,
6061
primitives::address::decodeFromString(elem.first));

core/power/impl/power_table_impl.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ namespace fc::power {
2222
outcome::result<void> removeMiner(
2323
const primitives::address::Address &address) override;
2424

25-
size_t getSize() const override;
25+
fc::outcome::result<size_t> getSize() const override;
2626

27-
Power getMaxPower() const override;
27+
fc::outcome::result<Power> getMaxPower() const override;
2828

2929
outcome::result<std::vector<primitives::address::Address>> getMiners()
3030
const override;

core/power/power_table.hpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
namespace fc::power {
1414

15-
using Power = primitives::BigInt;
15+
using primitives::address::Address;
16+
using Power = primitives::UBigInt;
1617

1718
/**
1819
* @interface Provides an interface to the power table
@@ -27,43 +28,41 @@ namespace fc::power {
2728
* @return power of the miner or No such miner error
2829
*/
2930
virtual outcome::result<Power> getMinerPower(
30-
const primitives::address::Address &address) const = 0;
31+
const Address &address) const = 0;
3132

3233
/**
3334
* @brief Set the power of a particular miner
3435
* @param address of the miner
3536
* @param power_amount - amount of power
3637
* @return success or Negative power error if amount less than 0
3738
*/
38-
virtual outcome::result<void> setMinerPower(
39-
const primitives::address::Address &address, Power power_amount) = 0;
39+
virtual outcome::result<void> setMinerPower(const Address &address,
40+
Power power_amount) = 0;
4041

4142
/**
4243
* @brief Remove a miner from power table
4344
* @param address of the miner
4445
* @return success or No such miner error
4546
*/
46-
virtual outcome::result<void> removeMiner(
47-
const primitives::address::Address &address) = 0;
47+
virtual outcome::result<void> removeMiner(const Address &address) = 0;
4848

4949
/**
5050
* @brief Get size of table
5151
* @return number of miners
5252
*/
53-
virtual size_t getSize() const = 0;
53+
virtual fc::outcome::result<size_t> getSize() const = 0;
5454

5555
/**
5656
* @brief Get Max power from table
5757
* @return max power from all miners
5858
*/
59-
virtual Power getMaxPower() const = 0;
59+
virtual fc::outcome::result<Power> getMaxPower() const = 0;
6060

6161
/**
6262
* @brief Get list of all miners from table
6363
* @return list of miners
6464
*/
65-
virtual outcome::result<std::vector<primitives::address::Address>>
66-
getMiners() const = 0;
65+
virtual outcome::result<std::vector<Address>> getMiners() const = 0;
6766
};
6867
} // namespace fc::power
6968
#endif // FILECOIN_CORE_POWER_TABLE_HPP

core/primitives/address/address_codec.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ namespace fc::primitives::address {
184184
return std::move(address);
185185
}
186186

187+
std::string encodeToByteString(const Address &address) {
188+
auto encoded = fc::primitives::address::encode(address);
189+
return std::string(encoded.begin(), encoded.end());
190+
}
191+
192+
fc::outcome::result<Address> decodeFromByteString(
193+
const std::string &encoded) {
194+
return fc::primitives::address::decode(
195+
std::vector<uint8_t>(encoded.begin(), encoded.end()));
196+
}
197+
187198
std::vector<uint8_t> checksum(const Address &address) {
188199
std::vector<uint8_t> res{};
189200

@@ -199,12 +210,13 @@ namespace fc::primitives::address {
199210

200211
ingest.push_back(p);
201212

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-
});
213+
ingest = visit_in_place(
214+
address.data,
215+
[&ingest](uint64_t v) { return ingest; },
216+
[&ingest](const auto &v) {
217+
ingest.insert(ingest.end(), v.begin(), v.end());
218+
return ingest;
219+
});
208220

209221
size_t outlen = 4;
210222
blake2b(res.data(), outlen, nullptr, 0, ingest.data(), ingest.size());

core/primitives/address/address_codec.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ namespace fc::primitives::address {
3636
*/
3737
outcome::result<Address> decodeFromString(const std::string &s);
3838

39+
/**
40+
* @brief Encodes an Address to an array of bytes with string representation
41+
*/
42+
43+
std::string encodeToByteString(const Address &address);
44+
/**
45+
* @brief Decodes Address from an array of bytes with string representation
46+
*/
47+
outcome::result<Address> decodeFromByteString(const std::string &s);
48+
3949
template <class Stream,
4050
typename = std::enable_if_t<
4151
std::remove_reference<Stream>::type::is_cbor_encoder_stream>>

0 commit comments

Comments
 (0)