21
21
#include " node/pubsub_gate.hpp"
22
22
#include " primitives/tipset/chain.hpp"
23
23
#include " proofs/impl/proof_engine_impl.hpp"
24
+ #include " storage/car/car.hpp"
24
25
#include " storage/hamt/hamt.hpp"
25
26
#include " vm/actor/builtin/states/account/account_actor_state.hpp"
26
27
#include " vm/actor/builtin/states/init/init_actor_state.hpp"
35
36
#include " vm/actor/builtin/v0/market/market_actor.hpp"
36
37
#include " vm/actor/builtin/v5/market/validate.hpp"
37
38
#include " vm/actor/builtin/v5/miner/monies.hpp"
39
+ #include " vm/actor/builtin/v5/miner/state.hpp"
38
40
#include " vm/interpreter/interpreter.hpp"
39
41
#include " vm/message/impl/message_signer_impl.hpp"
40
42
#include " vm/message/message.hpp"
@@ -163,6 +165,7 @@ namespace fc::api {
163
165
};
164
166
165
167
outcome::result<std::vector<SectorInfo>> getSectorsForWinningPoSt (
168
+ NetworkVersion network,
166
169
const Address &miner,
167
170
const MinerActorStatePtr &state,
168
171
const Randomness &post_rand,
@@ -174,6 +177,11 @@ namespace fc::api {
174
177
OUTCOME_TRY (deadline, deadline_cid.get ());
175
178
OUTCOME_TRY (deadline->partitions .visit ([&](auto , auto &part) {
176
179
for (auto sector : part->sectors ) {
180
+ if (network >= NetworkVersion::kVersion7 ) {
181
+ if (part->terminated .has (sector) || part->unproven .has (sector)) {
182
+ continue ;
183
+ }
184
+ }
177
185
if (!part->faults .has (sector)) {
178
186
sectors_bitset.insert (sector);
179
187
}
@@ -205,6 +213,7 @@ namespace fc::api {
205
213
std::shared_ptr<FullNodeApi> makeImpl (
206
214
std::shared_ptr<FullNodeApi> api,
207
215
std::shared_ptr<ChainStore> chain_store,
216
+ IpldPtr markets_ipld,
208
217
const std::string &network_name,
209
218
std::shared_ptr<WeightCalculator> weight_calculator,
210
219
const EnvironmentContext &env_context,
@@ -357,6 +366,43 @@ namespace fc::api {
357
366
return weight_calculator->calculateWeight (*tipset);
358
367
}};
359
368
369
+ auto retrievalQuery{[=](const Address &miner,
370
+ const CID &root,
371
+ const boost::optional<CID> &piece,
372
+ auto cb) {
373
+ OUTCOME_CB (auto minfo, api->StateMinerInfo (miner, {}));
374
+ RetrievalPeer peer;
375
+ peer.address = miner;
376
+ OUTCOME_CB (peer.peer_id , PeerId::fromBytes (minfo.peer_id ));
377
+ retrieval_market_client->query (peer, {root, {piece}}, [=](auto _res) {
378
+ OUTCOME_CB (auto res, _res);
379
+ std::string error;
380
+ switch (res.response_status ) {
381
+ case markets::retrieval::QueryResponseStatus::kQueryResponseAvailable :
382
+ break ;
383
+ case markets::retrieval::QueryResponseStatus::
384
+ kQueryResponseUnavailable :
385
+ error = " retrieval query offer was unavailable: " + res.message ;
386
+ break ;
387
+ case markets::retrieval::QueryResponseStatus::kQueryResponseError :
388
+ error = " retrieval query offer errored: " + res.message ;
389
+ break ;
390
+ }
391
+ cb (QueryOffer{
392
+ error,
393
+ root,
394
+ piece,
395
+ res.item_size ,
396
+ res.unseal_price + res.min_price_per_byte * res.item_size ,
397
+ res.unseal_price ,
398
+ res.payment_interval ,
399
+ res.interval_increase ,
400
+ res.payment_address ,
401
+ peer,
402
+ });
403
+ });
404
+ }};
405
+
360
406
api->ClientFindData = waitCb<std::vector<QueryOffer>>(
361
407
[=](auto &&root_cid, auto &&piece_cid, auto &&cb) {
362
408
OUTCOME_CB (auto peers, market_discovery->getPeers (root_cid));
@@ -371,71 +417,40 @@ namespace fc::api {
371
417
}
372
418
373
419
auto waiter = std::make_shared<
374
- AsyncWaiter<RetrievalPeer, outcome::result<QueryResponse >>>(
420
+ AsyncWaiter<RetrievalPeer, outcome::result<QueryOffer >>>(
375
421
peers.size (), [=](auto all_calls) {
376
422
std::vector<QueryOffer> result;
377
423
for (const auto &[peer, maybe_response] : all_calls) {
378
424
if (maybe_response.has_error ()) {
379
425
logger->error (" Error when query peer {}" ,
380
426
maybe_response.error ().message ());
381
427
} else {
382
- auto response{maybe_response.value ()};
383
- std::string error_message;
384
- switch (response.response_status ) {
385
- case markets::retrieval::QueryResponseStatus::
386
- kQueryResponseAvailable :
387
- break ;
388
- case markets::retrieval::QueryResponseStatus::
389
- kQueryResponseUnavailable :
390
- error_message =
391
- " retrieval query offer was unavailable: "
392
- + response.message ;
393
- break ;
394
- case markets::retrieval::QueryResponseStatus::
395
- kQueryResponseError :
396
- error_message = " retrieval query offer errored: "
397
- + response.message ;
398
- break ;
399
- }
400
-
401
- result.emplace_back (QueryOffer{
402
- error_message,
403
- root_cid,
404
- piece_cid,
405
- response.item_size ,
406
- response.unseal_price
407
- + response.min_price_per_byte * response.item_size ,
408
- response.unseal_price ,
409
- response.payment_interval ,
410
- response.interval_increase ,
411
- response.payment_address ,
412
- peer});
428
+ result.emplace_back (maybe_response.value ());
413
429
}
414
430
}
415
431
cb (result);
416
432
});
417
433
for (const auto &peer : peers) {
418
- OUTCOME_CB1 (retrieval_market_client->query (
419
- peer, {root_cid, {piece_cid}}, waiter->on (peer)));
434
+ retrievalQuery (peer.address , root_cid, piece_cid, waiter->on (peer));
420
435
}
421
436
});
422
437
423
438
// TODO(turuslan): FIL-165 implement method
424
439
api->ClientHasLocal = {};
425
- // TODO(turuslan): FIL-165 implement method
426
- api->ClientImport = {};
427
- // TODO(turuslan): FIL-165 implement method
428
- api->ClientListImports = {};
440
+ api->ClientMinerQueryOffer = waitCb<QueryOffer>(retrievalQuery);
429
441
// TODO(turuslan): FIL-165 implement method
430
442
api->ClientQueryAsk = {};
431
443
432
444
/* *
433
445
* Initiates the retrieval deal of a file in retrieval market.
434
446
*/
435
- api->ClientRetrieve = waitCb<None>(
436
- [retrieval_market_client](auto &&order, auto &&file_ref, auto &&cb) {
447
+ api->ClientRetrieve =
448
+ waitCb<None>([=](auto order, auto &&file_ref, auto &&cb) {
449
+ if (!file_ref.is_car ) {
450
+ return cb (ERROR_TEXT (" ClientRetrieve unixfs not implemented" ));
451
+ }
437
452
if (order.size == 0 ) {
438
- cb (ERROR_TEXT (" Cannot make retrieval deal for zero bytes" ));
453
+ return cb (ERROR_TEXT (" Cannot make retrieval deal for zero bytes" ));
439
454
}
440
455
auto price_per_byte = bigdiv (order.total , order.size );
441
456
DealProposalParams params{
@@ -445,22 +460,28 @@ namespace fc::api {
445
460
.payment_interval = order.payment_interval ,
446
461
.payment_interval_increase = order.payment_interval_increase ,
447
462
.unseal_price = order.unseal_price };
463
+ if (!order.peer ) {
464
+ OUTCOME_CB (auto info, api->StateMinerInfo (order.miner , {}));
465
+ OUTCOME_CB (auto id, PeerId::fromBytes (info.peer_id ));
466
+ order.peer = RetrievalPeer{order.miner , std::move (id), {}};
467
+ }
448
468
OUTCOME_CB1 (retrieval_market_client->retrieve (
449
469
order.root ,
450
470
params,
451
471
order.total ,
452
- order.peer ,
472
+ * order.peer ,
453
473
order.client ,
454
474
order.miner ,
455
- [cb{std::move (cb)}](outcome::result<void > res) {
475
+ [=, cb{std::move (cb)}](outcome::result<void > res) {
456
476
if (res.has_error ()) {
457
477
logger->error (" Error in ClientRetrieve {}" ,
458
478
res.error ().message ());
459
- cb (res.error ());
460
- } else {
461
- logger->info (" retrieval deal proposed" );
462
- cb (outcome::success ());
479
+ return cb (res.error ());
463
480
}
481
+ logger->info (" retrieval deal done" );
482
+ OUTCOME_CB1 (storage::car::makeSelectiveCar (
483
+ *markets_ipld, {{order.root , {}}}, file_ref.path ));
484
+ cb (outcome::success ());
464
485
}));
465
486
});
466
487
@@ -472,12 +493,18 @@ namespace fc::api {
472
493
api->GasEstimateGasPremium = {[=](auto max_blocks, auto &, auto , auto &) {
473
494
return mpool->estimateGasPremium (max_blocks);
474
495
}};
475
- api->GasEstimateMessageGas = {
476
- [=](auto msg, auto &spec, auto &) -> outcome::result<UnsignedMessage> {
477
- OUTCOME_TRY (mpool->estimate (
478
- msg, spec ? spec->max_fee : storage::mpool::kDefaultMaxFee ));
479
- return msg;
480
- }};
496
+ api->GasEstimateMessageGas = [=](auto msg, auto &spec, auto &tsk)
497
+ -> outcome::result<UnsignedMessage> {
498
+ if (msg.from .isId ()) {
499
+ OUTCOME_TRY (context, tipsetContext (tsk));
500
+ OUTCOME_TRYA (msg.from ,
501
+ vm::runtime::resolveKey (
502
+ context.state_tree , context, msg.from , false ));
503
+ }
504
+ OUTCOME_TRY (mpool->estimate (
505
+ msg, spec ? spec->max_fee : storage::mpool::kDefaultMaxFee ));
506
+ return msg;
507
+ };
481
508
482
509
api->MarketReserveFunds = {[=](const Address &wallet,
483
510
const Address &address,
@@ -573,7 +600,11 @@ namespace fc::api {
573
600
seed)};
574
601
OUTCOME_CB (info.sectors ,
575
602
getSectorsForWinningPoSt (
576
- miner, miner_state, post_rand, lookback));
603
+ getNetworkVersion (context.tipset ->epoch ()),
604
+ miner,
605
+ miner_state,
606
+ post_rand,
607
+ lookback));
577
608
if (info.sectors .empty ()) {
578
609
return cb (boost::none);
579
610
}
@@ -761,14 +792,15 @@ namespace fc::api {
761
792
OUTCOME_TRY (power_state, context.powerState ());
762
793
return power_state->claims .keys ();
763
794
}};
764
- api->StateListActors = {
765
- [=](auto &tipset_key) -> outcome::result<std::vector<Address>> {
766
- OUTCOME_TRY (context, tipsetContext (tipset_key));
767
- OUTCOME_TRY (root, context.state_tree .flush ());
768
- adt::Map<Actor, adt::AddressKeyer> actors{root, ipld};
795
+ api->StateListActors =
796
+ [=](auto &tsk) -> outcome::result<std::vector<Address>> {
797
+ OUTCOME_TRY (context, tipsetContext (tsk));
798
+ OUTCOME_TRY (root, context.state_tree .flush ());
799
+ OUTCOME_TRY (info, getCbor<StateTreeImpl::StateRoot>(context, root));
800
+ adt::Map<Actor, adt::AddressKeyer> actors{info.actor_tree_root , context};
769
801
770
- return actors.keys ();
771
- } };
802
+ return actors.keys ();
803
+ };
772
804
api->StateMarketBalance = {
773
805
[=](auto &address, auto &tipset_key) -> outcome::result<MarketBalance> {
774
806
OUTCOME_TRY (context, tipsetContext (tipset_key));
@@ -834,6 +866,22 @@ namespace fc::api {
834
866
}
835
867
return sectors;
836
868
};
869
+ api->StateMinerAvailableBalance =
870
+ [=](auto &miner, auto &tsk) -> outcome::result<TokenAmount> {
871
+ OUTCOME_TRY (context, tipsetContext (tsk));
872
+ OUTCOME_TRY (actor, context.state_tree .get (miner));
873
+ OUTCOME_TRY (state, getCbor<MinerActorStatePtr>(context, actor.head ));
874
+ // TODO(m.tagirov): older miner actor versions
875
+ OUTCOME_TRY (vested,
876
+ vm::actor::builtin::v5::miner::checkVestedFunds (
877
+ state, context.tipset ->height ()));
878
+ auto available{vm::actor::builtin::v5::miner::getAvailableBalance (
879
+ state, actor.balance )};
880
+ if (!available) {
881
+ return ERROR_TEXT (" negative unlocked balance" );
882
+ }
883
+ return vested + *available;
884
+ };
837
885
api->StateMinerDeadlines = {
838
886
[=](auto &address,
839
887
auto &tipset_key) -> outcome::result<std::vector<Deadline>> {
@@ -955,7 +1003,7 @@ namespace fc::api {
955
1003
OUTCOME_TRY (context, tipsetContext (tsk));
956
1004
OUTCOME_TRY (sector_size, getSectorSize (precommit.registered_proof ));
957
1005
OUTCOME_TRY (market, context.marketState ());
958
- // TODO(turuslan ): older market actor versions
1006
+ // TODO(m.tagirov ): older market actor versions
959
1007
OUTCOME_TRY (
960
1008
weights,
961
1009
vm::actor::builtin::v5::market::validate (market,
@@ -970,7 +1018,7 @@ namespace fc::api {
970
1018
weights.space_time_verified )};
971
1019
OUTCOME_TRY (power, context.powerState ());
972
1020
OUTCOME_TRY (reward, context.rewardState ());
973
- // TODO(turuslan ): older miner actor versions
1021
+ // TODO(m.tagirov ): older miner actor versions
974
1022
return kInitialPledgeNum
975
1023
* vm::actor::builtin::v5::miner::preCommitDepositForPower (
976
1024
reward->this_epoch_reward_smoothed ,
@@ -985,7 +1033,7 @@ namespace fc::api {
985
1033
OUTCOME_TRY (context, tipsetContext (tsk));
986
1034
OUTCOME_TRY (sector_size, getSectorSize (precommit.registered_proof ));
987
1035
OUTCOME_TRY (market, context.marketState ());
988
- // TODO(turuslan ): older market actor versions
1036
+ // TODO(m.tagirov ): older market actor versions
989
1037
OUTCOME_TRY (
990
1038
weights,
991
1039
vm::actor::builtin::v5::market::validate (market,
@@ -1005,7 +1053,7 @@ namespace fc::api {
1005
1053
env_context.circulating ->circulating (
1006
1054
std::make_shared<StateTreeImpl>(std::move (context.state_tree )),
1007
1055
context.tipset ->epoch ()));
1008
- // TODO(turuslan ): older miner actor versions
1056
+ // TODO(m.tagirov ): older miner actor versions
1009
1057
return kInitialPledgeNum
1010
1058
* vm::actor::builtin::v5::miner::initialPledgeForPower (
1011
1059
circ,
0 commit comments