Skip to content

Commit dae964b

Browse files
authored
Init actor VM method (#79)
Signed-off-by: turuslan <[email protected]>
1 parent add474f commit dae964b

22 files changed

+356
-120
lines changed

core/primitives/address/address.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "primitives/address/address.hpp"
77

88
#include "common/visitor.hpp"
9+
#include "crypto/blake2/blake2b160.hpp"
910

1011
OUTCOME_CPP_DEFINE_CATEGORY(fc::primitives::address, AddressError, e) {
1112
using fc::primitives::address::AddressError;
@@ -23,6 +24,7 @@ OUTCOME_CPP_DEFINE_CATEGORY(fc::primitives::address, AddressError, e) {
2324
}
2425

2526
namespace fc::primitives::address {
27+
using crypto::blake2b::blake2b_160;
2628

2729
bool Address::isKeyType() const {
2830
return visit_in_place(
@@ -47,6 +49,11 @@ namespace fc::primitives::address {
4749
return {TESTNET, id};
4850
}
4951

52+
Address Address::makeActorExecAddress(gsl::span<const uint8_t> data) {
53+
// TODO(turuslan): FIL-118 remove hardcoded TESTNET
54+
return {TESTNET, ActorExecHash{blake2b_160(data).value()}};
55+
}
56+
5057
bool operator==(const Address &lhs, const Address &rhs) {
5158
return lhs.network == rhs.network && lhs.getProtocol() == rhs.getProtocol()
5259
&& lhs.data == rhs.data;

core/primitives/address/address.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ namespace fc::primitives::address {
6868
/// id - number assigned to actors in a Filecoin Chain
6969
static Address makeFromId(uint64_t id);
7070

71+
static Address makeActorExecAddress(gsl::span<const uint8_t> data);
72+
7173
Network network;
7274
Payload data;
7375
};

core/vm/actor/actor_method.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ namespace fc::vm::actor {
2323
/// Actor methods exported by number
2424
using ActorExports = std::map<MethodNumber, ActorMethod>;
2525

26+
/// Reserved method number for constructor
27+
constexpr MethodNumber kConstructorMethodNumber{1};
28+
2629
constexpr VMExitCode DECODE_ACTOR_PARAMS_ERROR{1};
2730

2831
/// Decode actor params, raises appropriate error

core/vm/actor/cron_actor.cpp

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,19 @@
55

66
#include "vm/actor/cron_actor.hpp"
77

8-
namespace fc::vm::actor {
9-
10-
using vm::actor::MethodNumber;
11-
using vm::runtime::InvocationOutput;
12-
using vm::runtime::Runtime;
13-
14-
constexpr MethodNumber kEpochTickMethodNumber{2};
15-
16-
std::vector<CronTableEntry> CronActor::entries = {
17-
{kStoragePowerAddress, SpaMethods::CHECK_PROOF_SUBMISSIONS}};
18-
19-
outcome::result<InvocationOutput> CronActor::epochTick(
20-
const Actor &actor, Runtime &runtime, const MethodParams &params) {
21-
if ((runtime.getMessage()->from != kCronAddress)) {
22-
return WRONG_CALL;
8+
namespace fc::vm::actor::cron_actor {
9+
/**
10+
* Entries is a set of actors (and corresponding methods) to call during
11+
* EpochTick
12+
*/
13+
std::vector<CronTableEntry> entries = {
14+
{kStoragePowerAddress, {SpaMethods::CHECK_PROOF_SUBMISSIONS}}};
15+
16+
outcome::result<InvocationOutput> epochTick(const Actor &actor,
17+
Runtime &runtime,
18+
const MethodParams &params) {
19+
if ((runtime.getMessage().get().from != kCronAddress)) {
20+
return cron_actor::WRONG_CALL;
2321
}
2422

2523
for (const auto &entry : entries) {
@@ -28,7 +26,7 @@ namespace fc::vm::actor {
2826
return outcome::success();
2927
}
3028

31-
ActorExports CronActor::exports = {
32-
{kEpochTickMethodNumber, ActorMethod(CronActor::epochTick)},
29+
ActorExports exports = {
30+
{kEpochTickMethodNumber, ActorMethod(epochTick)},
3331
};
34-
} // namespace fc::vm::actor
32+
} // namespace fc::vm::actor::cron_actor

core/vm/actor/cron_actor.hpp

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,28 @@
99
#include "vm/actor/actor_method.hpp"
1010
#include "vm/actor/storage_power_actor.hpp"
1111

12-
namespace fc::vm::actor {
13-
14-
using runtime::InvocationOutput;
15-
using runtime::Runtime;
16-
12+
namespace fc::vm::actor::cron_actor {
1713
struct CronTableEntry {
1814
Address to_addr;
1915
MethodNumber method_num{};
2016
};
2117

22-
struct CronActor {
23-
static constexpr VMExitCode WRONG_CALL{1};
24-
25-
/**
26-
* Entries is a set of actors (and corresponding methods) to call during
27-
* EpochTick
28-
*/
29-
static std::vector<CronTableEntry> entries;
30-
31-
/**
32-
* @brief EpochTick executes built-in periodic actions, run at every Epoch.
33-
* @param actor from Lotus(doesn't use)
34-
* @param runtime is virtual machine context
35-
* @param params from Lotus(doesn't use)
36-
* @return success or error
37-
*/
38-
static outcome::result<InvocationOutput> epochTick(
39-
const Actor &actor, Runtime &runtime, const MethodParams &params);
40-
41-
static ActorExports exports;
42-
};
18+
constexpr MethodNumber kEpochTickMethodNumber{2};
19+
constexpr VMExitCode WRONG_CALL{1};
20+
21+
/**
22+
* @brief EpochTick executes built-in periodic actions, run at every Epoch.
23+
* @param actor from Lotus(doesn't use)
24+
* @param runtime is virtual machine context
25+
* @param params from Lotus(doesn't use)
26+
* @return success or error
27+
*/
28+
outcome::result<InvocationOutput> epochTick(const Actor &actor,
29+
Runtime &runtime,
30+
const MethodParams &params);
31+
32+
extern ActorExports exports;
4333

44-
} // namespace fc::vm::actor
34+
} // namespace fc::vm::actor::cron_actor
4535

4636
#endif // CPP_FILECOIN_CORE_VM_ACTOR_CRON_ACTOR_HPP

core/vm/actor/impl/invoker_impl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
#include "vm/actor/impl/invoker_impl.hpp"
77

88
#include "vm/actor/cron_actor.hpp"
9+
#include "vm/actor/init_actor.hpp"
910

1011
namespace fc::vm::actor {
1112

1213
using runtime::InvocationOutput;
1314

1415
InvokerImpl::InvokerImpl() {
15-
builtin_[actor::kCronCodeCid] = actor::CronActor::exports;
16+
builtin_[actor::kCronCodeCid] = actor::cron_actor::exports;
17+
builtin_[actor::kInitCodeCid] = actor::init_actor::exports;
1618
}
1719

1820
outcome::result<InvocationOutput> InvokerImpl::invoke(

core/vm/actor/init_actor.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
#include "primitives/address/address_codec.hpp"
99
#include "storage/hamt/hamt.hpp"
10+
#include "vm/runtime/gas_cost.hpp"
1011

11-
namespace fc::vm::actor {
12+
namespace fc::vm::actor::init_actor {
1213
outcome::result<Address> InitActorState::addActor(
1314
std::shared_ptr<IpfsDatastore> store, const Address &address) {
1415
storage::hamt::Hamt hamt(std::move(store), address_map);
@@ -19,4 +20,37 @@ namespace fc::vm::actor {
1920
++next_id;
2021
return Address::makeFromId(id);
2122
}
22-
} // namespace fc::vm::actor
23+
24+
outcome::result<InvocationOutput> exec(const Actor &actor,
25+
Runtime &runtime,
26+
const MethodParams &params) {
27+
OUTCOME_TRY(exec_params, decodeActorParams<ExecParams>(params));
28+
if (!isBuiltinActor(exec_params.code)) {
29+
return init_actor::NOT_BUILTIN_ACTOR;
30+
}
31+
if (isSingletonActor(exec_params.code)) {
32+
return init_actor::SINGLETON_ACTOR;
33+
}
34+
OUTCOME_TRY(runtime.chargeGas(runtime::kInitActorExecCost));
35+
auto &message = runtime.getMessage().get();
36+
auto actor_address{Address::makeActorExecAddress(
37+
Buffer{primitives::address::encode(message.from)}.putUint64(
38+
message.nonce))};
39+
auto store = runtime.getIpfsDatastore();
40+
OUTCOME_TRY(init_actor,
41+
store->getCbor<InitActorState>(runtime.getCurrentActorState()));
42+
OUTCOME_TRY(id_address, init_actor.addActor(store, actor_address));
43+
OUTCOME_TRY(runtime.createActor(
44+
id_address,
45+
Actor{exec_params.code, ActorSubstateCID{kEmptyObjectCid}, 0, 0}));
46+
OUTCOME_TRY(runtime.send(id_address,
47+
kConstructorMethodNumber,
48+
exec_params.params,
49+
message.value));
50+
OUTCOME_TRY(new_state, store->setCbor(init_actor));
51+
OUTCOME_TRY(runtime.commit(ActorSubstateCID{new_state}));
52+
return InvocationOutput{Buffer{primitives::address::encode(id_address)}};
53+
}
54+
55+
ActorExports exports{{kExecMethodNumber, ActorMethod(exec)}};
56+
} // namespace fc::vm::actor::init_actor

core/vm/actor/init_actor.hpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
#define CPP_FILECOIN_CORE_VM_ACTOR_INIT_ACTOR_HPP
88

99
#include "storage/ipfs/datastore.hpp"
10-
#include "vm/actor/actor.hpp"
10+
#include "vm/actor/actor_method.hpp"
1111

12-
namespace fc::vm::actor {
12+
namespace fc::vm::actor::init_actor {
1313
using storage::ipfs::IpfsDatastore;
1414

1515
/// Init actor state
@@ -36,6 +36,36 @@ namespace fc::vm::actor {
3636
s.list() >> state.address_map >> state.next_id;
3737
return s;
3838
}
39-
} // namespace fc::vm::actor
39+
40+
constexpr MethodNumber kExecMethodNumber{2};
41+
constexpr VMExitCode NOT_BUILTIN_ACTOR{1};
42+
constexpr VMExitCode SINGLETON_ACTOR{1};
43+
44+
struct ExecParams {
45+
CodeId code;
46+
MethodParams params;
47+
};
48+
49+
outcome::result<InvocationOutput> exec(const Actor &actor,
50+
Runtime &runtime,
51+
const MethodParams &params);
52+
53+
extern ActorExports exports;
54+
55+
template <class Stream,
56+
typename = std::enable_if_t<
57+
std::remove_reference_t<Stream>::is_cbor_encoder_stream>>
58+
Stream &operator<<(Stream &&s, const ExecParams &params) {
59+
return s << (s.list() << params.code << params.params);
60+
}
61+
62+
template <class Stream,
63+
typename = std::enable_if_t<
64+
std::remove_reference_t<Stream>::is_cbor_decoder_stream>>
65+
Stream &operator>>(Stream &&s, ExecParams &params) {
66+
s.list() >> params.code >> params.params;
67+
return s;
68+
}
69+
} // namespace fc::vm::actor::init_actor
4070

4171
#endif // CPP_FILECOIN_CORE_VM_ACTOR_INIT_ACTOR_HPP

core/vm/runtime/gas_cost.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ namespace fc::vm::runtime {
105105
*/
106106
inline static const BigInt kCommitGasCost{50};
107107

108+
inline static const BigInt kInitActorExecCost{100};
108109
} // namespace fc::vm::runtime
109110

110111
#endif // CPP_FILECOIN_CORE_VM_RUNTIME_GAS_COST_HPP

0 commit comments

Comments
 (0)