Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1266e6faa | ||
|
|
9ff77553b3 | ||
|
|
eda093319a | ||
|
|
610a892364 | ||
|
|
97662e8d63 | ||
|
|
bfb36026c5 | ||
|
|
be2bb0a588 | ||
|
|
f929ae17d7 | ||
|
|
ea2d0790b4 | ||
|
|
a617f81f4c | ||
|
|
e5ccf1915d | ||
|
|
b4e7374cd5 |
@@ -945,6 +945,7 @@ workflows:
|
||||
- build
|
||||
suite: itest-sector_pledge
|
||||
target: "./itests/sector_pledge_test.go"
|
||||
resource_class: 2xlarge
|
||||
get-params: true
|
||||
|
||||
- test:
|
||||
|
||||
@@ -551,7 +551,7 @@ workflows:
|
||||
- build
|
||||
suite: itest-[[ $name ]]
|
||||
target: "./itests/[[ $file ]]"
|
||||
[[- if or (eq $name "worker") (eq $name "deals_concurrent") (eq $name "wdpost_worker_config")]]
|
||||
[[- if or (eq $name "worker") (eq $name "deals_concurrent") (eq $name "wdpost_worker_config") (eq $name "sector_pledge")]]
|
||||
resource_class: 2xlarge
|
||||
[[- end]]
|
||||
[[- if or (eq $name "wdpost") (eq $name "sector_pledge")]]
|
||||
|
||||
+24
-7
@@ -6,12 +6,12 @@
|
||||
|
||||
## Improvements
|
||||
|
||||
# v1.26.0-rc2 / 2024-03-0y
|
||||
# v1.26.0-rc3 / 2024-03-13
|
||||
|
||||
This is a release candidate of the upcoming MANDATORY Lotus v1.26.0 release, which will deliver the Filecoin network version 22, codenamed Dragon 🐉.
|
||||
This is the third release candidate of the upcoming MANDATORY Lotus v1.26.0 release, which will deliver the Filecoin network version 22, codenamed Dragon 🐉. This third release candidate brings in multiple storage provider fixes, and cleanups for issues encountered during testing in the Calibration network.
|
||||
|
||||
**This release candidate only has the calibration network to upgrade set, which happened at epoch 1427974, 2024-03-11T14:00:00Z. This release does NOT set the mainnet upgrade epoch, which will be updated in the final release.**
|
||||
|
||||
**This release candidate sets the calibration network to upgrade at epoch 1427974, which is 2024-03-11T14:00:00Z**
|
||||
This release does NOT set the mainnet upgrade epoch yet, in which will be updated in the final release.
|
||||
The Filecoin network version 22 delivers the following FIPs:
|
||||
|
||||
- [FIP-0063: Switching to new Drand mainnet network](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0063.md)
|
||||
@@ -68,6 +68,14 @@ For certain node operators, such as full archival nodes or systems that need to
|
||||
- feat: events: Add Lotus APIs to consume smart contract and built-in actor events ([filecoin-project/lotus#11618](https://github.com/filecoin-project/lotus/pull/11618))
|
||||
|
||||
## Improvements
|
||||
- fix: commit batch: Always go through commit batcher ([filecoin-project/lotus#11704](https://github.com/filecoin-project/lotus/pull/11704))
|
||||
- sealing pipeline: Fix panic on padding pieces in WaitDeals ([filecoin-project/lotus#11708](https://github.com/filecoin-project/lotus/pull/11708))
|
||||
- sealing pipeline: Output DDO pieces in SectorStatus ([filecoin-project/lotus#11709](https://github.com/filecoin-project/lotus/pull/11709))
|
||||
- sealing pipeline: Fix failing ProveCommit3 aggregate ([filecoin-project/lotus#11710](https://github.com/filecoin-project/lotus/pull/11710))
|
||||
- fix: beacon: validate drand change at nv16 correctly ([filecoin-project/lotus#11690](https://github.com/filecoin-project/lotus/pull/11690))
|
||||
- fix: events: properly disable actor events API via cfg ([filecoin-project/lotus#11701](https://github.com/filecoin-project/lotus/pull/11701))
|
||||
- fix: events: Enable event storage config for Actor events as well ([filecoin-project/lotus#11712](https://github.com/filecoin-project/lotus/pull/11712))
|
||||
|
||||
|
||||
## Tracing API
|
||||
|
||||
@@ -136,7 +144,7 @@ Additionally, Filecoin is not Ethereum no matter how much we try to provide API/
|
||||
|
||||
[FIP-0049](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0049.md) introduced _Actor Events_ that can be emitted by user programmed actors. [FIP-0083](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0083.md) introduces new events emitted by the builtin Verified Registry, Miner and Market Actors. These new events for builtin actors are being activated with network version 22 to coincide with _Direct Data Onboarding_ as defined in [FIP-0076](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0076.md) which introduces additional flexibility for data onboarding. Sector, Deal and DataCap lifecycles can be tracked with these events, providing visibility and options for programmatic responses to changes in state.
|
||||
|
||||
Actor events are available on message receipts, but can now be retrieved from a node using the new `GetActorEvents` and `SubscribeActorEvents` methods. These methods allow for querying and subscribing to actor events, respectively. They depend on the Lotus node both collecting events (with `Fevm.Events.RealTimeFilterAPI` and `Fevm.Events.HistoricFilterAPI`) and being enabled with the new configuration option `Events.EnableActorEventsAPI`. Note that a Lotus node can only respond to requests for historic events that it retains in its event store.
|
||||
Actor events are available on message receipts, but can now be retrieved from a node using the new `GetActorEvents` and `SubscribeActorEvents` methods. These methods allow for querying and subscribing to actor events, respectively. They depend on the Lotus node both collecting events (with `Events.RealTimeFilterAPI` and `Events.HistoricFilterAPI`) and being enabled with the new configuration option `Events.EnableActorEventsAPI`. Note that a Lotus node can only respond to requests for historic events that it retains in its event store.
|
||||
|
||||
Both `GetActorEvents` and `SubscribeActorEvents` take a filter parameter which can optionally filter events on:
|
||||
|
||||
@@ -147,7 +155,14 @@ Both `GetActorEvents` and `SubscribeActorEvents` take a filter parameter which c
|
||||
|
||||
`GetActorEvents` provides a one-time query for actor events, while `SubscribeActorEvents` provides a long-lived connection (via websockets) to the Lotus node, allowing for real-time updates on actor events. The subscription can be cancelled by the client at any time.
|
||||
|
||||
### Events Configuration Changes
|
||||
|
||||
All configuration options previously under `Fevm.Events` are now in the top-level `Events` section along with the new `Events.EnableActorEventsAPI` option mentioned above. If you have non-default options in `[Events]` under `[Fevm]` in your configuration file, please move them to the top-level `[Events]`.
|
||||
|
||||
While `Fevm.Events.*` options are deprecated and replaced by `Events.*`, any existing custom values will be respected if their new form isn't set, but a warning will be printed to standard error upon startup. Support for these deprecated options will be removed in a future Lotus release, so please migrate your configuration promptly.
|
||||
|
||||
### GetAllClaims and GetAllAlocations
|
||||
|
||||
Additionally the methods `GetAllAllocations` and `GetAllClaims` has been added to the Lotus API. These methods lists all the available allocations and claims available in the actor state.
|
||||
|
||||
### Lotus CLI
|
||||
@@ -196,6 +211,9 @@ OPTIONS:
|
||||
- fix: add UpgradePhoenixHeight to StateGetNetworkParams (#11648) ([filecoin-project/lotus#11648](https://github.com/filecoin-project/lotus/pull/11648))
|
||||
- feat: drand quicknet: allow scheduling drand quicknet upgrade before nv22 on 2k devnet ([filecoin-project/lotus#11667]https://github.com/filecoin-project/lotus/pull/11667)
|
||||
- chore: backport #11632 to release/v1.26.0 ([filecoin-project/lotus#11667](https://github.com/filecoin-project/lotus/pull/11667))
|
||||
- release: bump to v1.26.0-rc2 ([filecoin-project/lotus#11691](https://github.com/filecoin-project/lotus/pull/11691))
|
||||
- Docs: Drand: document the meaning of "IsChained ([filecoin-project/lotus#11692](https://github.com/filecoin-project/lotus/pull/11692))
|
||||
- chore: remove old calibnet bootstrappers ([filecoin-project/lotus#11702](https://github.com/filecoin-project/lotus/pull/11702))
|
||||
|
||||
# v1.25.2 / 2024-01-11
|
||||
|
||||
@@ -389,8 +407,6 @@ This patch release allows for up to 10k messages per block. Additionally, it int
|
||||
## Improvements
|
||||
- fix: exchange: allow up to 10k messages per block ([filecoin-project/lotus#11506](https://github.com/filecoin-project/lotus/pull/11506))
|
||||
|
||||
>>>>>>> releases
|
||||
|
||||
# v 1.25.0 / 2023-11-22
|
||||
|
||||
This is a highly recommended feature release of Lotus. This optional release supports the Filecoin network version 21 upgrade, codenamed Watermelon 🍉, in addition to the numerous improvements and enhancements for node operators, ETH RPC-providers and storage providers.
|
||||
@@ -478,6 +494,7 @@ Lotus-workers can now be built to leverage the SupraSeal C2 sealing optimization
|
||||
- fix: lotus-provider: lotus-provider msg sending ([filecoin-project/lotus#11480](https://github.com/filecoin-project/lotus/pull/11480))
|
||||
- fix: lotus-provider: Fix winning PoSt ([filecoin-project/lotus#11483](https://github.com/filecoin-project/lotus/pull/11483))
|
||||
- chore: fix: sql Scan cannot write to an object ([filecoin-project/lotus#11487](https://github.com/filecoin-project/lotus/pull/11487))
|
||||
- fix: Exclude reverted events in `eth_getLogs` results [filecoin-project/lotus#11318](https://github.com/filecoin-project/lotus/pull/11318)
|
||||
|
||||
## Dependencies
|
||||
- deps: update go-libp2p to v0.28.1 ([filecoin-project/lotus#10998](https://github.com/filecoin-project/lotus/pull/10998))
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/dns4/bootstrap-0.calibration.fildev.network/tcp/1347/p2p/12D3KooWCi2w8U4DDB9xqrejb5KYHaQv2iA2AJJ6uzG3iQxNLBMy
|
||||
/dns4/bootstrap-1.calibration.fildev.network/tcp/1347/p2p/12D3KooWDTayrBojBn9jWNNUih4nNQQBGJD7Zo3gQCKgBkUsS6dp
|
||||
/dns4/bootstrap-2.calibration.fildev.network/tcp/1347/p2p/12D3KooWNRxTHUn8bf7jz1KEUPMc2dMgGfa4f8ZJTsquVSn3vHCG
|
||||
/dns4/bootstrap-3.calibration.fildev.network/tcp/1347/p2p/12D3KooWFWUqE9jgXvcKHWieYs9nhyp6NF4ftwLGAHm4sCv73jjK
|
||||
/dns4/calibration.node.glif.io/tcp/1237/p2p/12D3KooWQPYouEAsUQKzvFUA9sQ8tz4rfpqtTzh2eL6USd9bwg7x
|
||||
/dns4/bootstrap-calibnet-0.chainsafe-fil.io/tcp/34000/p2p/12D3KooWABQ5gTDHPWyvhJM7jPhtNwNJruzTEo32Lo4gcS5ABAMm
|
||||
/dns4/bootstrap-calibnet-1.chainsafe-fil.io/tcp/34000/p2p/12D3KooWS3ZRhMYL67b4bD5XQ6fcpTyVQXnDe8H89LvwrDqaSbiT
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -37,7 +37,7 @@ func BuildTypeString() string {
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version
|
||||
const BuildVersion = "1.26.0-rc2"
|
||||
const BuildVersion = "1.26.0-rc3"
|
||||
|
||||
func UserVersion() string {
|
||||
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
|
||||
|
||||
@@ -53,6 +53,9 @@ type DrandBeacon struct {
|
||||
localCache *lru.Cache[uint64, *types.BeaconEntry]
|
||||
}
|
||||
|
||||
// IsChained tells us whether this particular beacon operates in "chained mode". Prior to Drand
|
||||
// quicknet, beacons form a chain. After the introduction of quicknet, they do not, so we need to
|
||||
// change how we interact with beacon entries. (See FIP-0063)
|
||||
func (db *DrandBeacon) IsChained() bool {
|
||||
return db.isChained
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ var ddls = []string{
|
||||
)`,
|
||||
|
||||
`CREATE INDEX IF NOT EXISTS height_tipset_key ON event (height,tipset_key)`,
|
||||
`CREATE INDEX IF NOT EXISTS event_emitter_addr ON event (emitter_addr)`,
|
||||
|
||||
`CREATE TABLE IF NOT EXISTS event_entry (
|
||||
event_id INTEGER,
|
||||
@@ -56,6 +57,8 @@ var ddls = []string{
|
||||
value BLOB NOT NULL
|
||||
)`,
|
||||
|
||||
`CREATE INDEX IF NOT EXISTS event_entry_key_index ON event_entry (key)`,
|
||||
|
||||
// metadata containing version of schema
|
||||
`CREATE TABLE IF NOT EXISTS _meta (
|
||||
version UINT64 NOT NULL UNIQUE
|
||||
@@ -63,6 +66,7 @@ var ddls = []string{
|
||||
|
||||
`INSERT OR IGNORE INTO _meta (version) VALUES (1)`,
|
||||
`INSERT OR IGNORE INTO _meta (version) VALUES (2)`,
|
||||
`INSERT OR IGNORE INTO _meta (version) VALUES (3)`,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -70,7 +74,7 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
schemaVersion = 2
|
||||
schemaVersion = 3
|
||||
|
||||
eventExists = `SELECT MAX(id) FROM event WHERE height=? AND tipset_key=? AND tipset_key_cid=? AND emitter_addr=? AND event_index=? AND message_cid=? AND message_index=?`
|
||||
insertEvent = `INSERT OR IGNORE INTO event(height, tipset_key, tipset_key_cid, emitter_addr, event_index, message_cid, message_index, reverted) VALUES(?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
@@ -321,6 +325,22 @@ func NewEventIndex(ctx context.Context, path string, chainStore *store.ChainStor
|
||||
version = 2
|
||||
}
|
||||
|
||||
if version == 2 {
|
||||
log.Infof("upgrading event index from version 2 to version 3")
|
||||
|
||||
// to upgrade to version 3 we only need to create an index on the event_entry.key column
|
||||
// and on the event.emitter_addr column
|
||||
// which means we can just reapply the schema (it will not have any effect on existing data)
|
||||
for _, ddl := range ddls {
|
||||
if _, err := db.Exec(ddl); err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("could not upgrade index to version 3, exec ddl %q: %w", ddl, err)
|
||||
}
|
||||
}
|
||||
|
||||
version = 3
|
||||
}
|
||||
|
||||
if version != schemaVersion {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("invalid database version: got %d, expected %d", version, schemaVersion)
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus-miner [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.26.0-rc2
|
||||
1.26.0-rc3
|
||||
|
||||
COMMANDS:
|
||||
init Initialize a lotus miner repo
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus-provider [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.26.0-rc2
|
||||
1.26.0-rc3
|
||||
|
||||
COMMANDS:
|
||||
run Start a lotus provider process
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus-worker [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.26.0-rc2
|
||||
1.26.0-rc3
|
||||
|
||||
COMMANDS:
|
||||
run Start lotus worker
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.26.0-rc2
|
||||
1.26.0-rc3
|
||||
|
||||
COMMANDS:
|
||||
daemon Start a lotus daemon process
|
||||
|
||||
@@ -337,68 +337,67 @@
|
||||
# env var: LOTUS_FEVM_ETHTXHASHMAPPINGLIFETIMEDAYS
|
||||
#EthTxHashMappingLifetimeDays = 0
|
||||
|
||||
[Fevm.Events]
|
||||
# DisableRealTimeFilterAPI will disable the RealTimeFilterAPI that can create and query filters for actor events as they are emitted.
|
||||
# The API is enabled when EnableEthRPC or Events.EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_FEVM_EVENTS_DISABLEREALTIMEFILTERAPI
|
||||
#DisableRealTimeFilterAPI = false
|
||||
|
||||
# DisableHistoricFilterAPI will disable the HistoricFilterAPI that can create and query filters for actor events
|
||||
# that occurred in the past. HistoricFilterAPI maintains a queryable index of events.
|
||||
# The API is enabled when EnableEthRPC or Events.EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_FEVM_EVENTS_DISABLEHISTORICFILTERAPI
|
||||
#DisableHistoricFilterAPI = false
|
||||
|
||||
# FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
# this time become eligible for automatic deletion.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_FEVM_EVENTS_FILTERTTL
|
||||
#FilterTTL = "24h0m0s"
|
||||
|
||||
# MaxFilters specifies the maximum number of filters that may exist at any one time.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_FEVM_EVENTS_MAXFILTERS
|
||||
#MaxFilters = 100
|
||||
|
||||
# MaxFilterResults specifies the maximum number of results that can be accumulated by an actor event filter.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_FEVM_EVENTS_MAXFILTERRESULTS
|
||||
#MaxFilterResults = 10000
|
||||
|
||||
# MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
|
||||
# the entire chain)
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_FEVM_EVENTS_MAXFILTERHEIGHTRANGE
|
||||
#MaxFilterHeightRange = 2880
|
||||
|
||||
# DatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
# support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
# the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
# relative to the CWD (current working directory).
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_FEVM_EVENTS_DATABASEPATH
|
||||
#DatabasePath = ""
|
||||
|
||||
|
||||
[Events]
|
||||
# DisableRealTimeFilterAPI will disable the RealTimeFilterAPI that can create and query filters for actor events as they are emitted.
|
||||
# The API is enabled when Fevm.EnableEthRPC or EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_EVENTS_DISABLEREALTIMEFILTERAPI
|
||||
#DisableRealTimeFilterAPI = false
|
||||
|
||||
# DisableHistoricFilterAPI will disable the HistoricFilterAPI that can create and query filters for actor events
|
||||
# that occurred in the past. HistoricFilterAPI maintains a queryable index of events.
|
||||
# The API is enabled when Fevm.EnableEthRPC or EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_EVENTS_DISABLEHISTORICFILTERAPI
|
||||
#DisableHistoricFilterAPI = false
|
||||
|
||||
# EnableActorEventsAPI enables the Actor events API that enables clients to consume events
|
||||
# emitted by (smart contracts + built-in Actors).
|
||||
# This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be
|
||||
# disabled by setting their respective Disable* options in Fevm.Events.
|
||||
# disabled by setting their respective Disable* options.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_EVENTS_ENABLEACTOREVENTSAPI
|
||||
#EnableActorEventsAPI = false
|
||||
|
||||
# FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
# this time become eligible for automatic deletion.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_EVENTS_FILTERTTL
|
||||
#FilterTTL = "24h0m0s"
|
||||
|
||||
# MaxFilters specifies the maximum number of filters that may exist at any one time.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_EVENTS_MAXFILTERS
|
||||
#MaxFilters = 100
|
||||
|
||||
# MaxFilterResults specifies the maximum number of results that can be accumulated by an actor event filter.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_EVENTS_MAXFILTERRESULTS
|
||||
#MaxFilterResults = 10000
|
||||
|
||||
# MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
|
||||
# the entire chain)
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_EVENTS_MAXFILTERHEIGHTRANGE
|
||||
#MaxFilterHeightRange = 2880
|
||||
|
||||
# DatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
# support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
# the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
# relative to the CWD (current working directory).
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_EVENTS_DATABASEPATH
|
||||
#DatabasePath = ""
|
||||
|
||||
|
||||
[Index]
|
||||
# EXPERIMENTAL FEATURE. USE WITH CAUTION
|
||||
|
||||
@@ -35,7 +35,13 @@ var DefaultEnsembleOpts = ensembleOpts{
|
||||
}
|
||||
|
||||
// MockProofs activates mock proofs for the entire ensemble.
|
||||
func MockProofs() EnsembleOpt {
|
||||
func MockProofs(e ...bool) EnsembleOpt {
|
||||
if len(e) > 0 && !e[0] {
|
||||
return func(opts *ensembleOpts) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return func(opts *ensembleOpts) error {
|
||||
opts.mockProofs = true
|
||||
// since we're using mock proofs, we don't need to download
|
||||
|
||||
@@ -65,7 +65,7 @@ var DefaultNodeOpts = nodeOpts{
|
||||
// test defaults
|
||||
|
||||
cfg.Fevm.EnableEthRPC = true
|
||||
cfg.Fevm.Events.MaxFilterHeightRange = math.MaxInt64
|
||||
cfg.Events.MaxFilterHeightRange = math.MaxInt64
|
||||
cfg.Events.EnableActorEventsAPI = true
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
@@ -39,7 +40,7 @@ func TestPledgeSectors(t *testing.T) {
|
||||
defer cancel()
|
||||
|
||||
_, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
ens.InterconnectAll().BeginMiningMustPost(blockTime)
|
||||
|
||||
miner.PledgeSectors(ctx, nSectors, 0, nil)
|
||||
}
|
||||
@@ -65,12 +66,18 @@ func TestPledgeBatching(t *testing.T) {
|
||||
//stm: @SECTOR_PRE_COMMIT_FLUSH_001, @SECTOR_COMMIT_FLUSH_001
|
||||
blockTime := 50 * time.Millisecond
|
||||
|
||||
runTest := func(t *testing.T, nSectors int) {
|
||||
runTest := func(t *testing.T, nSectors int, aggregate bool) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(!aggregate), kit.MutateSealingConfig(func(sc *config.SealingConfig) {
|
||||
if aggregate {
|
||||
sc.AggregateAboveBaseFee = types.FIL(big.Zero())
|
||||
}
|
||||
}))
|
||||
ens.InterconnectAll().BeginMiningMustPost(blockTime)
|
||||
|
||||
client.WaitTillChain(ctx, kit.HeightAtLeast(10))
|
||||
|
||||
@@ -114,7 +121,10 @@ func TestPledgeBatching(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("100", func(t *testing.T) {
|
||||
runTest(t, 100)
|
||||
runTest(t, 100, false)
|
||||
})
|
||||
t.Run("10-agg", func(t *testing.T) {
|
||||
runTest(t, 10, true)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ func ConfigFullNode(c interface{}) Option {
|
||||
// If the Eth JSON-RPC is enabled, enable storing events at the ChainStore.
|
||||
// This is the case even if real-time and historic filtering are disabled,
|
||||
// as it enables us to serve logs in eth_getTransactionReceipt.
|
||||
If(cfg.Fevm.EnableEthRPC, Override(StoreEventsKey, modules.EnableStoringEvents)),
|
||||
If(cfg.Fevm.EnableEthRPC || cfg.Events.EnableActorEventsAPI, Override(StoreEventsKey, modules.EnableStoringEvents)),
|
||||
|
||||
Override(new(dtypes.ClientImportMgr), modules.ClientImportMgr),
|
||||
|
||||
@@ -266,13 +266,13 @@ func ConfigFullNode(c interface{}) Option {
|
||||
|
||||
// Actor event filtering support
|
||||
Override(new(events.EventHelperAPI), From(new(modules.EventHelperAPI))),
|
||||
Override(new(*filter.EventFilterManager), modules.EventFilterManager(cfg.Fevm)),
|
||||
Override(new(*filter.EventFilterManager), modules.EventFilterManager(cfg.Events)),
|
||||
|
||||
// in lite-mode Eth api is provided by gateway
|
||||
ApplyIf(isFullNode,
|
||||
If(cfg.Fevm.EnableEthRPC,
|
||||
Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm)),
|
||||
Override(new(full.EthEventAPI), modules.EthEventHandler(cfg.Fevm)),
|
||||
Override(new(full.EthEventAPI), modules.EthEventHandler(cfg.Events, cfg.Fevm.EnableEthRPC)),
|
||||
),
|
||||
If(!cfg.Fevm.EnableEthRPC,
|
||||
Override(new(full.EthModuleAPI), &full.EthModuleDummy{}),
|
||||
@@ -282,7 +282,7 @@ func ConfigFullNode(c interface{}) Option {
|
||||
|
||||
ApplyIf(isFullNode,
|
||||
If(cfg.Events.EnableActorEventsAPI,
|
||||
Override(new(full.ActorEventAPI), modules.ActorEventHandler(cfg.Events.EnableActorEventsAPI, cfg.Fevm)),
|
||||
Override(new(full.ActorEventAPI), modules.ActorEventHandler(cfg.Events)),
|
||||
),
|
||||
If(!cfg.Events.EnableActorEventsAPI,
|
||||
Override(new(full.ActorEventAPI), &full.ActorEventDummy{}),
|
||||
|
||||
@@ -74,6 +74,11 @@ func run() error {
|
||||
name := f[0]
|
||||
typ := f[1]
|
||||
|
||||
if len(comment) > 0 && strings.HasPrefix(comment[0], fmt.Sprintf("%s is DEPRECATED", name)) {
|
||||
// don't document deprecated fields
|
||||
continue
|
||||
}
|
||||
|
||||
out[currentType] = append(out[currentType], field{
|
||||
Name: name,
|
||||
Type: typ,
|
||||
|
||||
+7
-9
@@ -110,17 +110,15 @@ func DefaultFullNode() *FullNode {
|
||||
Fevm: FevmConfig{
|
||||
EnableEthRPC: false,
|
||||
EthTxHashMappingLifetimeDays: 0,
|
||||
Events: Events{
|
||||
DisableRealTimeFilterAPI: false,
|
||||
DisableHistoricFilterAPI: false,
|
||||
FilterTTL: Duration(time.Hour * 24),
|
||||
MaxFilters: 100,
|
||||
MaxFilterResults: 10000,
|
||||
MaxFilterHeightRange: 2880, // conservative limit of one day
|
||||
},
|
||||
},
|
||||
Events: EventsConfig{
|
||||
EnableActorEventsAPI: false,
|
||||
DisableRealTimeFilterAPI: false,
|
||||
DisableHistoricFilterAPI: false,
|
||||
EnableActorEventsAPI: false,
|
||||
FilterTTL: Duration(time.Hour * 24),
|
||||
MaxFilters: 100,
|
||||
MaxFilterResults: 10000,
|
||||
MaxFilterHeightRange: 2880, // conservative limit of one day
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+13
-15
@@ -357,13 +357,13 @@ see https://lotus.filecoin.io/storage-providers/advanced-configurations/market/#
|
||||
Comment: ``,
|
||||
},
|
||||
},
|
||||
"Events": {
|
||||
"EventsConfig": {
|
||||
{
|
||||
Name: "DisableRealTimeFilterAPI",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `DisableRealTimeFilterAPI will disable the RealTimeFilterAPI that can create and query filters for actor events as they are emitted.
|
||||
The API is enabled when EnableEthRPC or Events.EnableActorEventsAPI is true, but can be disabled selectively with this flag.`,
|
||||
The API is enabled when Fevm.EnableEthRPC or EnableActorEventsAPI is true, but can be disabled selectively with this flag.`,
|
||||
},
|
||||
{
|
||||
Name: "DisableHistoricFilterAPI",
|
||||
@@ -371,7 +371,16 @@ The API is enabled when EnableEthRPC or Events.EnableActorEventsAPI is true, but
|
||||
|
||||
Comment: `DisableHistoricFilterAPI will disable the HistoricFilterAPI that can create and query filters for actor events
|
||||
that occurred in the past. HistoricFilterAPI maintains a queryable index of events.
|
||||
The API is enabled when EnableEthRPC or Events.EnableActorEventsAPI is true, but can be disabled selectively with this flag.`,
|
||||
The API is enabled when Fevm.EnableEthRPC or EnableActorEventsAPI is true, but can be disabled selectively with this flag.`,
|
||||
},
|
||||
{
|
||||
Name: "EnableActorEventsAPI",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `EnableActorEventsAPI enables the Actor events API that enables clients to consume events
|
||||
emitted by (smart contracts + built-in Actors).
|
||||
This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be
|
||||
disabled by setting their respective Disable* options.`,
|
||||
},
|
||||
{
|
||||
Name: "FilterTTL",
|
||||
@@ -409,17 +418,6 @@ the database must already exist and be writeable. If a relative path is provided
|
||||
relative to the CWD (current working directory).`,
|
||||
},
|
||||
},
|
||||
"EventsConfig": {
|
||||
{
|
||||
Name: "EnableActorEventsAPI",
|
||||
Type: "bool",
|
||||
|
||||
Comment: `EnableActorEventsAPI enables the Actor events API that enables clients to consume events
|
||||
emitted by (smart contracts + built-in Actors).
|
||||
This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be
|
||||
disabled by setting their respective Disable* options in Fevm.Events.`,
|
||||
},
|
||||
},
|
||||
"FaultReporterConfig": {
|
||||
{
|
||||
Name: "EnableConsensusFaultReporter",
|
||||
@@ -474,7 +472,7 @@ Set to 0 to keep all mappings`,
|
||||
},
|
||||
{
|
||||
Name: "Events",
|
||||
Type: "Events",
|
||||
Type: "DeprecatedEvents",
|
||||
|
||||
Comment: ``,
|
||||
},
|
||||
|
||||
+132
-10
@@ -18,12 +18,9 @@ import (
|
||||
// FromFile loads config from a specified file overriding defaults specified in
|
||||
// the def parameter. If file does not exist or is empty defaults are assumed.
|
||||
func FromFile(path string, opts ...LoadCfgOpt) (interface{}, error) {
|
||||
var loadOpts cfgLoadOpts
|
||||
var err error
|
||||
for _, opt := range opts {
|
||||
if err = opt(&loadOpts); err != nil {
|
||||
return nil, xerrors.Errorf("failed to apply load cfg option: %w", err)
|
||||
}
|
||||
loadOpts, err := applyOpts(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var def interface{}
|
||||
if loadOpts.defaultCfg != nil {
|
||||
@@ -56,16 +53,43 @@ func FromFile(path string, opts ...LoadCfgOpt) (interface{}, error) {
|
||||
return nil, xerrors.Errorf("config failed validation: %w", err)
|
||||
}
|
||||
}
|
||||
return FromReader(buf, def)
|
||||
return FromReader(buf, def, opts...)
|
||||
}
|
||||
|
||||
// FromReader loads config from a reader instance.
|
||||
func FromReader(reader io.Reader, def interface{}) (interface{}, error) {
|
||||
cfg := def
|
||||
_, err := toml.NewDecoder(reader).Decode(cfg)
|
||||
func FromReader(reader io.Reader, def interface{}, opts ...LoadCfgOpt) (interface{}, error) {
|
||||
loadOpts, err := applyOpts(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg := def
|
||||
md, err := toml.NewDecoder(reader).Decode(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// find any fields with a tag: `moved:"New.Config.Location"` and move any set values there over to
|
||||
// the new location if they are not already set there.
|
||||
movedFields := findMovedFields(nil, cfg)
|
||||
var warningOut io.Writer = os.Stderr
|
||||
if loadOpts.warningWriter != nil {
|
||||
warningOut = loadOpts.warningWriter
|
||||
}
|
||||
for _, d := range movedFields {
|
||||
if md.IsDefined(d.Field...) {
|
||||
fmt.Fprintf(
|
||||
warningOut,
|
||||
"WARNING: Use of deprecated configuration option '%s' will be removed in a future release, use '%s' instead\n",
|
||||
strings.Join(d.Field, "."),
|
||||
strings.Join(d.NewField, "."))
|
||||
if !md.IsDefined(d.NewField...) {
|
||||
// new value isn't set but old is, we should move what the user set there
|
||||
if err := moveFieldValue(cfg, d.Field, d.NewField); err != nil {
|
||||
return nil, fmt.Errorf("failed to move field value: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = envconfig.Process("LOTUS", cfg)
|
||||
if err != nil {
|
||||
@@ -75,14 +99,105 @@ func FromReader(reader io.Reader, def interface{}) (interface{}, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// move a value from the location in the valPtr struct specified by oldPath, to the location
|
||||
// specified by newPath; where the path is an array of nested field names.
|
||||
func moveFieldValue(valPtr interface{}, oldPath []string, newPath []string) error {
|
||||
oldValue, err := getFieldValue(valPtr, oldPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val := reflect.ValueOf(valPtr).Elem()
|
||||
for {
|
||||
field := val.FieldByName(newPath[0])
|
||||
if !field.IsValid() {
|
||||
return fmt.Errorf("unexpected error fetching field value")
|
||||
}
|
||||
if len(newPath) == 1 {
|
||||
if field.Kind() != oldValue.Kind() {
|
||||
return fmt.Errorf("unexpected error, old kind != new kind")
|
||||
}
|
||||
// set field on val to be the new one, and we're done
|
||||
field.Set(oldValue)
|
||||
return nil
|
||||
}
|
||||
if field.Kind() != reflect.Struct {
|
||||
return fmt.Errorf("unexpected error fetching field value, is not a struct")
|
||||
}
|
||||
newPath = newPath[1:]
|
||||
val = field
|
||||
}
|
||||
}
|
||||
|
||||
// recursively iterate into `path` to find the terminal value
|
||||
func getFieldValue(val interface{}, path []string) (reflect.Value, error) {
|
||||
if reflect.ValueOf(val).Kind() == reflect.Ptr {
|
||||
val = reflect.ValueOf(val).Elem().Interface()
|
||||
}
|
||||
field := reflect.ValueOf(val).FieldByName(path[0])
|
||||
if !field.IsValid() {
|
||||
return reflect.Value{}, fmt.Errorf("unexpected error fetching field value")
|
||||
}
|
||||
if len(path) > 1 {
|
||||
if field.Kind() != reflect.Struct {
|
||||
return reflect.Value{}, fmt.Errorf("unexpected error fetching field value, is not a struct")
|
||||
}
|
||||
return getFieldValue(field.Interface(), path[1:])
|
||||
}
|
||||
return field, nil
|
||||
}
|
||||
|
||||
type movedField struct {
|
||||
Field []string
|
||||
NewField []string
|
||||
}
|
||||
|
||||
// inspect the fields recursively within a struct and find any with "moved" tags
|
||||
func findMovedFields(path []string, val interface{}) []movedField {
|
||||
dep := make([]movedField, 0)
|
||||
if reflect.ValueOf(val).Kind() == reflect.Ptr {
|
||||
val = reflect.ValueOf(val).Elem().Interface()
|
||||
}
|
||||
t := reflect.TypeOf(val)
|
||||
if t.Kind() != reflect.Struct {
|
||||
return nil
|
||||
}
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
// could also do a "deprecated" in here
|
||||
if idx := field.Tag.Get("moved"); idx != "" && idx != "-" {
|
||||
dep = append(dep, movedField{
|
||||
Field: append(path, field.Name),
|
||||
NewField: strings.Split(idx, "."),
|
||||
})
|
||||
}
|
||||
if field.Type.Kind() == reflect.Struct && reflect.ValueOf(val).FieldByName(field.Name).IsValid() {
|
||||
deps := findMovedFields(append(path, field.Name), reflect.ValueOf(val).FieldByName(field.Name).Interface())
|
||||
dep = append(dep, deps...)
|
||||
}
|
||||
}
|
||||
return dep
|
||||
}
|
||||
|
||||
type cfgLoadOpts struct {
|
||||
defaultCfg func() (interface{}, error)
|
||||
canFallbackOnDefault func() error
|
||||
validate func(string) error
|
||||
warningWriter io.Writer
|
||||
}
|
||||
|
||||
type LoadCfgOpt func(opts *cfgLoadOpts) error
|
||||
|
||||
func applyOpts(opts ...LoadCfgOpt) (cfgLoadOpts, error) {
|
||||
var loadOpts cfgLoadOpts
|
||||
var err error
|
||||
for _, opt := range opts {
|
||||
if err = opt(&loadOpts); err != nil {
|
||||
return loadOpts, fmt.Errorf("failed to apply load cfg option: %w", err)
|
||||
}
|
||||
}
|
||||
return loadOpts, nil
|
||||
}
|
||||
|
||||
func SetDefault(f func() (interface{}, error)) LoadCfgOpt {
|
||||
return func(opts *cfgLoadOpts) error {
|
||||
opts.defaultCfg = f
|
||||
@@ -104,6 +219,13 @@ func SetValidate(f func(string) error) LoadCfgOpt {
|
||||
}
|
||||
}
|
||||
|
||||
func SetWarningWriter(w io.Writer) LoadCfgOpt {
|
||||
return func(opts *cfgLoadOpts) error {
|
||||
opts.warningWriter = w
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func NoDefaultForSplitstoreTransition() error {
|
||||
return xerrors.Errorf("FullNode config not found and fallback to default disallowed while we transition to splitstore discard default. Use `lotus config default` to set this repo up with a default config. Be sure to set `EnableSplitstore` to `false` if you are running a full archive node")
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func fullNodeDefault() (interface{}, error) { return DefaultFullNode(), nil }
|
||||
@@ -138,3 +139,77 @@ func TestFailToFallbackToDefault(t *testing.T) {
|
||||
_, err = FromFile(nonExistantFileName, SetDefault(fullNodeDefault), SetCanFallbackOnDefault(NoDefaultForSplitstoreTransition))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestPrintDeprecated(t *testing.T) {
|
||||
type ChildCfg struct {
|
||||
Field string `moved:"Bang"`
|
||||
NewField string
|
||||
}
|
||||
type Old struct {
|
||||
Thing1 int `moved:"New.Thing1"`
|
||||
Thing2 int `moved:"New.Thing2"`
|
||||
}
|
||||
type New struct {
|
||||
Thing1 int
|
||||
Thing2 int
|
||||
}
|
||||
type ParentCfg struct {
|
||||
Child ChildCfg
|
||||
Old Old
|
||||
New New
|
||||
Foo int
|
||||
Baz string `moved:"Child.NewField"`
|
||||
Boom int `moved:"Foo"`
|
||||
Bang string
|
||||
}
|
||||
|
||||
t.Run("warning output", func(t *testing.T) {
|
||||
cfg := `
|
||||
Baz = "baz"
|
||||
Foo = 100
|
||||
[Child]
|
||||
Field = "bip"
|
||||
NewField = "bop"
|
||||
`
|
||||
|
||||
warningWriter := bytes.NewBuffer(nil)
|
||||
|
||||
v, err := FromReader(bytes.NewReader([]byte(cfg)), &ParentCfg{Boom: 200, Bang: "300"}, SetWarningWriter(warningWriter))
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &ParentCfg{
|
||||
Child: ChildCfg{
|
||||
Field: "bip",
|
||||
NewField: "bop",
|
||||
},
|
||||
Baz: "baz",
|
||||
Foo: 100,
|
||||
Boom: 200,
|
||||
Bang: "bip",
|
||||
}, v)
|
||||
require.Regexp(t, `\WChild\.Field\W.+use 'Bang' instead`, warningWriter.String())
|
||||
require.Regexp(t, `\WBaz\W.+use 'Child\.NewField' instead`, warningWriter.String())
|
||||
require.NotContains(t, warningWriter.String(), "don't use this at all")
|
||||
require.NotContains(t, warningWriter.String(), "Boom")
|
||||
})
|
||||
|
||||
defaultNew := New{Thing1: 42, Thing2: 800}
|
||||
testCases := []struct {
|
||||
name string
|
||||
cfg string
|
||||
expected New
|
||||
}{
|
||||
{"simple", ``, defaultNew},
|
||||
{"set new", "[New]\nThing1 = 101\nThing2 = 102\n", New{Thing1: 101, Thing2: 102}},
|
||||
// should move old to new fields if new isn't set
|
||||
{"set old", "[Old]\nThing1 = 101\nThing2 = 102\n", New{Thing1: 101, Thing2: 102}},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
v, err := FromReader(bytes.NewReader([]byte(tc.cfg)), &ParentCfg{New: defaultNew})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expected, v.(*ParentCfg).New)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+33
-12
@@ -791,19 +791,48 @@ type FevmConfig struct {
|
||||
// Set to 0 to keep all mappings
|
||||
EthTxHashMappingLifetimeDays int
|
||||
|
||||
Events Events
|
||||
Events DeprecatedEvents `toml:"Events,omitempty"`
|
||||
}
|
||||
|
||||
type Events struct {
|
||||
type DeprecatedEvents struct {
|
||||
// DisableRealTimeFilterAPI is DEPRECATED and will be removed in a future release. Use Events.DisableRealTimeFilterAPI instead.
|
||||
DisableRealTimeFilterAPI bool `moved:"Events.DisableRealTimeFilterAPI" toml:"DisableRealTimeFilterAPI,omitempty"`
|
||||
|
||||
// DisableHistoricFilterAPI is DEPRECATED and will be removed in a future release. Use Events.DisableHistoricFilterAPI instead.
|
||||
DisableHistoricFilterAPI bool `moved:"Events.DisableHistoricFilterAPI" toml:"DisableHistoricFilterAPI,omitempty"`
|
||||
|
||||
// FilterTTL is DEPRECATED and will be removed in a future release. Use Events.FilterTTL instead.
|
||||
FilterTTL Duration `moved:"Events.FilterTTL" toml:"FilterTTL,omitzero"`
|
||||
|
||||
// MaxFilters is DEPRECATED and will be removed in a future release. Use Events.MaxFilters instead.
|
||||
MaxFilters int `moved:"Events.MaxFilters" toml:"MaxFilters,omitzero"`
|
||||
|
||||
// MaxFilterResults is DEPRECATED and will be removed in a future release. Use Events.MaxFilterResults instead.
|
||||
MaxFilterResults int `moved:"Events.MaxFilterResults" toml:"MaxFilterResults,omitzero"`
|
||||
|
||||
// MaxFilterHeightRange is DEPRECATED and will be removed in a future release. Use Events.MaxFilterHeightRange instead.
|
||||
MaxFilterHeightRange uint64 `moved:"Events.MaxFilterHeightRange" toml:"MaxFilterHeightRange,omitzero"`
|
||||
|
||||
// DatabasePath is DEPRECATED and will be removed in a future release. Use Events.DatabasePath instead.
|
||||
DatabasePath string `moved:"Events.DatabasePath" toml:"DatabasePath,omitempty"`
|
||||
}
|
||||
|
||||
type EventsConfig struct {
|
||||
// DisableRealTimeFilterAPI will disable the RealTimeFilterAPI that can create and query filters for actor events as they are emitted.
|
||||
// The API is enabled when EnableEthRPC or Events.EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
// The API is enabled when Fevm.EnableEthRPC or EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
DisableRealTimeFilterAPI bool
|
||||
|
||||
// DisableHistoricFilterAPI will disable the HistoricFilterAPI that can create and query filters for actor events
|
||||
// that occurred in the past. HistoricFilterAPI maintains a queryable index of events.
|
||||
// The API is enabled when EnableEthRPC or Events.EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
// The API is enabled when Fevm.EnableEthRPC or EnableActorEventsAPI is true, but can be disabled selectively with this flag.
|
||||
DisableHistoricFilterAPI bool
|
||||
|
||||
// EnableActorEventsAPI enables the Actor events API that enables clients to consume events
|
||||
// emitted by (smart contracts + built-in Actors).
|
||||
// This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be
|
||||
// disabled by setting their respective Disable* options.
|
||||
EnableActorEventsAPI bool
|
||||
|
||||
// FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
// this time become eligible for automatic deletion.
|
||||
FilterTTL Duration
|
||||
@@ -830,14 +859,6 @@ type Events struct {
|
||||
// Set upper bound on index size
|
||||
}
|
||||
|
||||
type EventsConfig struct {
|
||||
// EnableActorEventsAPI enables the Actor events API that enables clients to consume events
|
||||
// emitted by (smart contracts + built-in Actors).
|
||||
// This will also enable the RealTimeFilterAPI and HistoricFilterAPI by default, but they can be
|
||||
// disabled by setting their respective Disable* options in Fevm.Events.
|
||||
EnableActorEventsAPI bool
|
||||
}
|
||||
|
||||
type IndexConfig struct {
|
||||
// EXPERIMENTAL FEATURE. USE WITH CAUTION
|
||||
// EnableMsgIndex enables indexing of messages on chain.
|
||||
|
||||
@@ -42,6 +42,8 @@ import (
|
||||
|
||||
var ErrUnsupported = errors.New("unsupported method")
|
||||
|
||||
const maxEthFeeHistoryRewardPercentiles = 100
|
||||
|
||||
type EthModuleAPI interface {
|
||||
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
|
||||
EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error)
|
||||
@@ -698,6 +700,9 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (eth
|
||||
}
|
||||
rewardPercentiles := make([]float64, 0)
|
||||
if params.RewardPercentiles != nil {
|
||||
if len(*params.RewardPercentiles) > maxEthFeeHistoryRewardPercentiles {
|
||||
return ethtypes.EthFeeHistory{}, errors.New("length of the reward percentile array cannot be greater than 100")
|
||||
}
|
||||
rewardPercentiles = append(rewardPercentiles, *params.RewardPercentiles...)
|
||||
}
|
||||
for i, rp := range rewardPercentiles {
|
||||
|
||||
+21
-17
@@ -32,17 +32,17 @@ type EventHelperAPI struct {
|
||||
|
||||
var _ events.EventHelperAPI = &EventHelperAPI{}
|
||||
|
||||
func EthEventHandler(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *filter.EventFilterManager, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.EthEventHandler, error) {
|
||||
func EthEventHandler(cfg config.EventsConfig, enableEthRPC bool) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *filter.EventFilterManager, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.EthEventHandler, error) {
|
||||
return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, fm *filter.EventFilterManager, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventHelperAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI) (*full.EthEventHandler, error) {
|
||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||
|
||||
ee := &full.EthEventHandler{
|
||||
Chain: cs,
|
||||
MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange),
|
||||
MaxFilterHeightRange: abi.ChainEpoch(cfg.MaxFilterHeightRange),
|
||||
SubscribtionCtx: ctx,
|
||||
}
|
||||
|
||||
if !cfg.EnableEthRPC || cfg.Events.DisableRealTimeFilterAPI {
|
||||
if !enableEthRPC || cfg.DisableRealTimeFilterAPI {
|
||||
// all event functionality is disabled
|
||||
// the historic filter API relies on the real time one
|
||||
return ee, nil
|
||||
@@ -53,21 +53,21 @@ func EthEventHandler(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.Locked
|
||||
StateAPI: stateapi,
|
||||
ChainAPI: chainapi,
|
||||
}
|
||||
ee.FilterStore = filter.NewMemFilterStore(cfg.Events.MaxFilters)
|
||||
ee.FilterStore = filter.NewMemFilterStore(cfg.MaxFilters)
|
||||
|
||||
// Start garbage collection for filters
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(context.Context) error {
|
||||
go ee.GC(ctx, time.Duration(cfg.Events.FilterTTL))
|
||||
go ee.GC(ctx, time.Duration(cfg.FilterTTL))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
ee.TipSetFilterManager = &filter.TipSetFilterManager{
|
||||
MaxFilterResults: cfg.Events.MaxFilterResults,
|
||||
MaxFilterResults: cfg.MaxFilterResults,
|
||||
}
|
||||
ee.MemPoolFilterManager = &filter.MemPoolFilterManager{
|
||||
MaxFilterResults: cfg.Events.MaxFilterResults,
|
||||
MaxFilterResults: cfg.MaxFilterResults,
|
||||
}
|
||||
ee.EventFilterManager = fm
|
||||
|
||||
@@ -94,22 +94,22 @@ func EthEventHandler(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.Locked
|
||||
}
|
||||
}
|
||||
|
||||
func EventFilterManager(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, full.ChainAPI) (*filter.EventFilterManager, error) {
|
||||
func EventFilterManager(cfg config.EventsConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, full.ChainAPI) (*filter.EventFilterManager, error) {
|
||||
return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventHelperAPI, chainapi full.ChainAPI) (*filter.EventFilterManager, error) {
|
||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||
|
||||
// Enable indexing of actor events
|
||||
var eventIndex *filter.EventIndex
|
||||
if !cfg.Events.DisableHistoricFilterAPI {
|
||||
if !cfg.DisableHistoricFilterAPI {
|
||||
var dbPath string
|
||||
if cfg.Events.DatabasePath == "" {
|
||||
if cfg.DatabasePath == "" {
|
||||
sqlitePath, err := r.SqlitePath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbPath = filepath.Join(sqlitePath, "events.db")
|
||||
} else {
|
||||
dbPath = cfg.Events.DatabasePath
|
||||
dbPath = cfg.DatabasePath
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -144,7 +144,7 @@ func EventFilterManager(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.Loc
|
||||
return *actor.Address, true
|
||||
},
|
||||
|
||||
MaxFilterResults: cfg.Events.MaxFilterResults,
|
||||
MaxFilterResults: cfg.MaxFilterResults,
|
||||
}
|
||||
|
||||
lc.Append(fx.Hook{
|
||||
@@ -162,18 +162,22 @@ func EventFilterManager(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.Loc
|
||||
}
|
||||
}
|
||||
|
||||
func ActorEventHandler(enable bool, fevmCfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *filter.EventFilterManager, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.ActorEventHandler, error) {
|
||||
func ActorEventHandler(cfg config.EventsConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *filter.EventFilterManager, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.ActorEventHandler, error) {
|
||||
return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, fm *filter.EventFilterManager, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventHelperAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI) (*full.ActorEventHandler, error) {
|
||||
|
||||
if !enable || fevmCfg.Events.DisableRealTimeFilterAPI {
|
||||
fm = nil
|
||||
if !cfg.EnableActorEventsAPI || cfg.DisableRealTimeFilterAPI {
|
||||
return full.NewActorEventHandler(
|
||||
cs,
|
||||
nil, // no EventFilterManager disables API calls
|
||||
time.Duration(build.BlockDelaySecs)*time.Second,
|
||||
abi.ChainEpoch(cfg.MaxFilterHeightRange),
|
||||
), nil
|
||||
}
|
||||
|
||||
return full.NewActorEventHandler(
|
||||
cs,
|
||||
fm,
|
||||
time.Duration(build.BlockDelaySecs)*time.Second,
|
||||
abi.ChainEpoch(fevmCfg.Events.MaxFilterHeightRange),
|
||||
abi.ChainEpoch(cfg.MaxFilterHeightRange),
|
||||
), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ type DrandConfig struct {
|
||||
Servers []string
|
||||
Relays []string
|
||||
ChainInfoJSON string
|
||||
IsChained bool
|
||||
IsChained bool // Prior to Drand quicknet, beacons form a chain, post quicknet they do not (FIP-0063)
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ func (b *CommitBatcher) maybeStartBatch(notif bool) ([]sealiface.CommitBatchRes,
|
||||
return nil, xerrors.Errorf("getting config: %w", err)
|
||||
}
|
||||
|
||||
if notif && total < cfg.MaxCommitBatch {
|
||||
if notif && total < cfg.MaxCommitBatch && cfg.AggregateCommits {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ func (b *CommitBatcher) maybeStartBatch(notif bool) ([]sealiface.CommitBatchRes,
|
||||
return false
|
||||
}
|
||||
|
||||
individual := (total < cfg.MinCommitBatch) || (total < miner.MinAggregatedSectors) || blackedOut()
|
||||
individual := (total < cfg.MinCommitBatch) || (total < miner.MinAggregatedSectors) || blackedOut() || !cfg.AggregateCommits
|
||||
|
||||
if !individual && !cfg.AggregateAboveBaseFee.Equals(big.Zero()) {
|
||||
if ts.MinTicketBlock().ParentBaseFee.LessThan(cfg.AggregateAboveBaseFee) {
|
||||
@@ -331,6 +331,9 @@ func (b *CommitBatcher) processBatchV2(cfg sealiface.Config, sectors []abi.Secto
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sort sectors by number
|
||||
sort.Slice(sectors, func(i, j int) bool { return sectors[i] < sectors[j] })
|
||||
|
||||
total := len(sectors)
|
||||
|
||||
res := sealiface.CommitBatchRes{
|
||||
@@ -371,10 +374,6 @@ func (b *CommitBatcher) processBatchV2(cfg sealiface.Config, sectors []abi.Secto
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
sort.Slice(infos, func(i, j int) bool {
|
||||
return infos[i].Number < infos[j].Number
|
||||
})
|
||||
|
||||
proofs := make([][]byte, 0, total)
|
||||
for _, info := range infos {
|
||||
proofs = append(proofs, b.todo[info.Number].Proof)
|
||||
@@ -444,13 +443,13 @@ func (b *CommitBatcher) processBatchV2(cfg sealiface.Config, sectors []abi.Secto
|
||||
enc := new(bytes.Buffer)
|
||||
if err := params.MarshalCBOR(enc); err != nil {
|
||||
res.Error = err.Error()
|
||||
return []sealiface.CommitBatchRes{res}, xerrors.Errorf("couldn't serialize ProveCommitSectors2Params: %w", err)
|
||||
return []sealiface.CommitBatchRes{res}, xerrors.Errorf("couldn't serialize ProveCommitSectors3Params: %w", err)
|
||||
}
|
||||
|
||||
_, err = simulateMsgGas(b.mctx, b.api, from, b.maddr, builtin.MethodsMiner.ProveCommitSectors3, needFunds, maxFee, enc.Bytes())
|
||||
|
||||
if err != nil && (!api.ErrorIsIn(err, []error{&api.ErrOutOfGas{}}) || len(sectors) < miner.MinAggregatedSectors*2) {
|
||||
log.Errorf("simulating CommitBatch message failed: %s", err)
|
||||
log.Errorf("simulating CommitBatch message failed (%x): %s", enc.Bytes(), err)
|
||||
res.Error = err.Error()
|
||||
return []sealiface.CommitBatchRes{res}, xerrors.Errorf("simulating CommitBatch message failed: %w", err)
|
||||
}
|
||||
@@ -474,7 +473,7 @@ func (b *CommitBatcher) processBatchV2(cfg sealiface.Config, sectors []abi.Secto
|
||||
|
||||
res.Msg = &mcid
|
||||
|
||||
log.Infow("Sent ProveCommitSectors2 message", "cid", mcid, "from", from, "todo", total, "sectors", len(infos))
|
||||
log.Infow("Sent ProveCommitSectors3 message", "cid", mcid, "from", from, "todo", total, "sectors", len(infos))
|
||||
|
||||
return []sealiface.CommitBatchRes{res}, nil
|
||||
}
|
||||
@@ -591,7 +590,7 @@ func (b *CommitBatcher) processBatchV1(cfg sealiface.Config, sectors []abi.Secto
|
||||
_, err = simulateMsgGas(b.mctx, b.api, from, b.maddr, builtin.MethodsMiner.ProveCommitAggregate, needFunds, maxFee, enc.Bytes())
|
||||
|
||||
if err != nil && (!api.ErrorIsIn(err, []error{&api.ErrOutOfGas{}}) || len(sectors) < miner.MinAggregatedSectors*2) {
|
||||
log.Errorf("simulating CommitBatch message failed: %s", err)
|
||||
log.Errorf("simulating CommitBatch message failed (%x): %s", enc.Bytes(), err)
|
||||
res.Error = err.Error()
|
||||
return []sealiface.CommitBatchRes{res}, xerrors.Errorf("simulating CommitBatch message failed: %w", err)
|
||||
}
|
||||
|
||||
+25
-5
@@ -11,6 +11,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
@@ -39,8 +40,27 @@ func (m *Sealing) Plan(events []statemachine.Event, user interface{}) (interface
|
||||
return nil, processed, nil
|
||||
}
|
||||
|
||||
return func(ctx statemachine.Context, si SectorInfo) error {
|
||||
err := next(ctx, si)
|
||||
return func(ctx statemachine.Context, si SectorInfo) (err error) {
|
||||
// handle panics
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
buf := make([]byte, 1<<16)
|
||||
n := runtime.Stack(buf, false)
|
||||
buf = buf[:n]
|
||||
|
||||
l := Log{
|
||||
Timestamp: uint64(time.Now().Unix()),
|
||||
Message: fmt.Sprintf("panic: %v\n%s", r, buf),
|
||||
Kind: "panic",
|
||||
}
|
||||
si.logAppend(l)
|
||||
|
||||
err = fmt.Errorf("panic: %v\n%s", r, buf)
|
||||
}
|
||||
}()
|
||||
|
||||
// execute the next state
|
||||
err = next(ctx, si)
|
||||
if err != nil {
|
||||
log.Errorf("unhandled sector error (%d): %+v", si.SectorNumber, err)
|
||||
return nil
|
||||
@@ -127,8 +147,8 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto
|
||||
),
|
||||
Committing: planCommitting,
|
||||
CommitFinalize: planOne(
|
||||
on(SectorFinalized{}, SubmitCommit),
|
||||
on(SectorFinalizedAvailable{}, SubmitCommit),
|
||||
on(SectorFinalized{}, SubmitCommitAggregate),
|
||||
on(SectorFinalizedAvailable{}, SubmitCommitAggregate),
|
||||
on(SectorFinalizeFailed{}, CommitFinalizeFailed),
|
||||
),
|
||||
SubmitCommit: planOne(
|
||||
@@ -674,7 +694,7 @@ func planCommitting(events []statemachine.Event, state *SectorInfo) (uint64, err
|
||||
}
|
||||
case SectorCommitted: // the normal case
|
||||
e.apply(state)
|
||||
state.State = SubmitCommit
|
||||
state.State = SubmitCommitAggregate
|
||||
case SectorProofReady: // early finalize
|
||||
e.apply(state)
|
||||
state.State = CommitFinalize
|
||||
|
||||
@@ -70,10 +70,10 @@ func TestHappyPath(t *testing.T) {
|
||||
require.Equal(m.t, m.state.State, Committing)
|
||||
|
||||
m.planSingle(SectorCommitted{})
|
||||
require.Equal(m.t, m.state.State, SubmitCommit)
|
||||
require.Equal(m.t, m.state.State, SubmitCommitAggregate)
|
||||
|
||||
m.planSingle(SectorCommitSubmitted{})
|
||||
require.Equal(m.t, m.state.State, CommitWait)
|
||||
m.planSingle(SectorCommitAggregateSent{})
|
||||
require.Equal(m.t, m.state.State, CommitAggregateWait)
|
||||
|
||||
m.planSingle(SectorProving{})
|
||||
require.Equal(m.t, m.state.State, FinalizeSector)
|
||||
@@ -81,7 +81,7 @@ func TestHappyPath(t *testing.T) {
|
||||
m.planSingle(SectorFinalized{})
|
||||
require.Equal(m.t, m.state.State, Proving)
|
||||
|
||||
expected := []SectorState{Packing, GetTicket, PreCommit1, PreCommit2, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, SubmitCommit, CommitWait, FinalizeSector, Proving}
|
||||
expected := []SectorState{Packing, GetTicket, PreCommit1, PreCommit2, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, SubmitCommitAggregate, CommitAggregateWait, FinalizeSector, Proving}
|
||||
for i, n := range notif {
|
||||
if n.before.State != expected[i] {
|
||||
t.Fatalf("expected before state: %s, got: %s", expected[i], n.before.State)
|
||||
@@ -135,9 +135,6 @@ func TestHappyPathFinalizeEarly(t *testing.T) {
|
||||
require.Equal(m.t, m.state.State, CommitFinalize)
|
||||
|
||||
m.planSingle(SectorFinalized{})
|
||||
require.Equal(m.t, m.state.State, SubmitCommit)
|
||||
|
||||
m.planSingle(SectorSubmitCommitAggregate{})
|
||||
require.Equal(m.t, m.state.State, SubmitCommitAggregate)
|
||||
|
||||
m.planSingle(SectorCommitAggregateSent{})
|
||||
@@ -149,7 +146,7 @@ func TestHappyPathFinalizeEarly(t *testing.T) {
|
||||
m.planSingle(SectorFinalized{})
|
||||
require.Equal(m.t, m.state.State, Proving)
|
||||
|
||||
expected := []SectorState{Packing, GetTicket, PreCommit1, PreCommit2, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, CommitFinalize, SubmitCommit, SubmitCommitAggregate, CommitAggregateWait, FinalizeSector, Proving}
|
||||
expected := []SectorState{Packing, GetTicket, PreCommit1, PreCommit2, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, CommitFinalize, SubmitCommitAggregate, CommitAggregateWait, FinalizeSector, Proving}
|
||||
for i, n := range notif {
|
||||
if n.before.State != expected[i] {
|
||||
t.Fatalf("expected before state: %s, got: %s", expected[i], n.before.State)
|
||||
@@ -188,9 +185,9 @@ func TestCommitFinalizeFailed(t *testing.T) {
|
||||
require.Equal(m.t, m.state.State, CommitFinalize)
|
||||
|
||||
m.planSingle(SectorFinalized{})
|
||||
require.Equal(m.t, m.state.State, SubmitCommit)
|
||||
require.Equal(m.t, m.state.State, SubmitCommitAggregate)
|
||||
|
||||
expected := []SectorState{Committing, CommitFinalize, CommitFinalizeFailed, CommitFinalize, SubmitCommit}
|
||||
expected := []SectorState{Committing, CommitFinalize, CommitFinalizeFailed, CommitFinalize, SubmitCommitAggregate}
|
||||
for i, n := range notif {
|
||||
if n.before.State != expected[i] {
|
||||
t.Fatalf("expected before state: %s, got: %s", expected[i], n.before.State)
|
||||
@@ -242,10 +239,10 @@ func TestSeedRevert(t *testing.T) {
|
||||
// not changing the seed this time
|
||||
_, _, err = m.s.plan([]statemachine.Event{{User: SectorSeedReady{SeedValue: nil, SeedEpoch: 5}}, {User: SectorCommitted{}}}, m.state)
|
||||
require.NoError(t, err)
|
||||
require.Equal(m.t, m.state.State, SubmitCommit)
|
||||
require.Equal(m.t, m.state.State, SubmitCommitAggregate)
|
||||
|
||||
m.planSingle(SectorCommitSubmitted{})
|
||||
require.Equal(m.t, m.state.State, CommitWait)
|
||||
m.planSingle(SectorCommitAggregateSent{})
|
||||
require.Equal(m.t, m.state.State, CommitAggregateWait)
|
||||
|
||||
m.planSingle(SectorProving{})
|
||||
require.Equal(m.t, m.state.State, FinalizeSector)
|
||||
|
||||
@@ -34,12 +34,16 @@ func (m *Sealing) handleWaitDeals(ctx statemachine.Context, sector SectorInfo) e
|
||||
for _, piece := range sector.Pieces {
|
||||
used += piece.Piece().Size.Unpadded()
|
||||
|
||||
if !piece.HasDealInfo() {
|
||||
continue
|
||||
}
|
||||
|
||||
endEpoch, err := piece.EndEpoch()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("piece.EndEpoch: %w", err)
|
||||
}
|
||||
|
||||
if piece.HasDealInfo() && endEpoch > lastDealEnd {
|
||||
if endEpoch > lastDealEnd {
|
||||
lastDealEnd = endEpoch
|
||||
}
|
||||
}
|
||||
@@ -953,20 +957,30 @@ func (m *Sealing) SectorsStatus(ctx context.Context, sid abi.SectorNumber, showO
|
||||
return api.SectorInfo{}, err
|
||||
}
|
||||
|
||||
nv, err := m.Api.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return api.SectorInfo{}, xerrors.Errorf("getting network version: %w", err)
|
||||
}
|
||||
|
||||
deals := make([]abi.DealID, len(info.Pieces))
|
||||
pieces := make([]api.SectorPiece, len(info.Pieces))
|
||||
for i, piece := range info.Pieces {
|
||||
// todo make this work with DDO deals in some reasonable way
|
||||
|
||||
pieces[i].Piece = piece.Piece()
|
||||
if !piece.HasDealInfo() || piece.Impl().PublishCid == nil {
|
||||
|
||||
if !piece.HasDealInfo() {
|
||||
continue
|
||||
}
|
||||
|
||||
pdi := piece.Impl()
|
||||
if pdi.Valid(nv) != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pdi := piece.DealInfo().Impl() // copy
|
||||
pieces[i].DealInfo = &pdi
|
||||
|
||||
deals[i] = piece.DealInfo().Impl().DealID
|
||||
if pdi.PublishCid != nil {
|
||||
deals[i] = pdi.DealID
|
||||
}
|
||||
}
|
||||
|
||||
log := make([]api.SectorLog, len(info.Log))
|
||||
|
||||
@@ -94,7 +94,7 @@ const (
|
||||
CommitFinalizeFailed SectorState = "CommitFinalizeFailed"
|
||||
|
||||
// single commit
|
||||
SubmitCommit SectorState = "SubmitCommit" // send commit message to the chain
|
||||
SubmitCommit SectorState = "SubmitCommit" // send commit message to the chain (deprecated)
|
||||
CommitWait SectorState = "CommitWait" // wait for the commit message to land on chain
|
||||
|
||||
SubmitCommitAggregate SectorState = "SubmitCommitAggregate"
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
miner2 "github.com/filecoin-project/go-state-types/builtin/v13/miner"
|
||||
verifreg13 "github.com/filecoin-project/go-state-types/builtin/v13/verifreg"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v9/verifreg"
|
||||
@@ -740,89 +739,10 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo)
|
||||
}
|
||||
|
||||
func (m *Sealing) handleSubmitCommit(ctx statemachine.Context, sector SectorInfo) error {
|
||||
// TODO: Deprecate this path, always go through batcher, just respect the AggregateCommits config in there
|
||||
|
||||
cfg, err := m.getConfig()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting config: %w", err)
|
||||
}
|
||||
|
||||
if cfg.AggregateCommits {
|
||||
nv, err := m.Api.StateNetworkVersion(ctx.Context(), types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting network version: %w", err)
|
||||
}
|
||||
|
||||
if nv >= network.Version13 {
|
||||
return ctx.Send(SectorSubmitCommitAggregate{})
|
||||
}
|
||||
}
|
||||
|
||||
ts, err := m.Api.ChainHead(ctx.Context())
|
||||
if err != nil {
|
||||
log.Errorf("handleSubmitCommit: api error, not proceeding: %+v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := m.checkCommit(ctx.Context(), sector, sector.Proof, ts.Key()); err != nil {
|
||||
return ctx.Send(SectorCommitFailed{xerrors.Errorf("commit check error: %w", err)})
|
||||
}
|
||||
|
||||
enc := new(bytes.Buffer)
|
||||
params := &miner.ProveCommitSectorParams{
|
||||
SectorNumber: sector.SectorNumber,
|
||||
Proof: sector.Proof,
|
||||
}
|
||||
|
||||
if err := params.MarshalCBOR(enc); err != nil {
|
||||
return ctx.Send(SectorCommitFailed{xerrors.Errorf("could not serialize commit sector parameters: %w", err)})
|
||||
}
|
||||
|
||||
mi, err := m.Api.StateMinerInfo(ctx.Context(), m.maddr, ts.Key())
|
||||
if err != nil {
|
||||
log.Errorf("handleCommitting: api error, not proceeding: %+v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
pci, err := m.Api.StateSectorPreCommitInfo(ctx.Context(), m.maddr, sector.SectorNumber, ts.Key())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting precommit info: %w", err)
|
||||
}
|
||||
if pci == nil {
|
||||
return ctx.Send(SectorCommitFailed{error: xerrors.Errorf("precommit info not found on chain")})
|
||||
}
|
||||
|
||||
collateral, err := m.Api.StateMinerInitialPledgeCollateral(ctx.Context(), m.maddr, pci.Info, ts.Key())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting initial pledge collateral: %w", err)
|
||||
}
|
||||
|
||||
collateral = big.Sub(collateral, pci.PreCommitDeposit)
|
||||
if collateral.LessThan(big.Zero()) {
|
||||
collateral = big.Zero()
|
||||
}
|
||||
|
||||
collateral, err = collateralSendAmount(ctx.Context(), m.Api, m.maddr, cfg, collateral)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
goodFunds := big.Add(collateral, big.Int(m.feeCfg.MaxCommitGasFee))
|
||||
|
||||
from, _, err := m.addrSel.AddressFor(ctx.Context(), m.Api, mi, api.CommitAddr, goodFunds, collateral)
|
||||
if err != nil {
|
||||
return ctx.Send(SectorCommitFailed{xerrors.Errorf("no good address to send commit message from: %w", err)})
|
||||
}
|
||||
|
||||
// TODO: check seed / ticket / deals are up to date
|
||||
mcid, err := sendMsg(ctx.Context(), m.Api, from, m.maddr, builtin.MethodsMiner.ProveCommitSector, collateral, big.Int(m.feeCfg.MaxCommitGasFee), enc.Bytes())
|
||||
if err != nil {
|
||||
return ctx.Send(SectorCommitFailed{xerrors.Errorf("pushing message to mpool: %w", err)})
|
||||
}
|
||||
|
||||
return ctx.Send(SectorCommitSubmitted{
|
||||
Message: mcid,
|
||||
})
|
||||
// like precommit this is a deprecated state, but we keep it around for
|
||||
// existing state machines
|
||||
// todo: drop after nv21
|
||||
return ctx.Send(SectorSubmitCommitAggregate{})
|
||||
}
|
||||
|
||||
// processPieces returns either:
|
||||
|
||||
@@ -289,10 +289,18 @@ func (sp *SafeSectorPiece) handleDealInfo(params handleDealInfoParams) error {
|
||||
// SectorPiece Proxy
|
||||
|
||||
func (sp *SafeSectorPiece) Impl() piece.PieceDealInfo {
|
||||
if !sp.HasDealInfo() {
|
||||
return piece.PieceDealInfo{}
|
||||
}
|
||||
|
||||
return sp.real.DealInfo.Impl()
|
||||
}
|
||||
|
||||
func (sp *SafeSectorPiece) String() string {
|
||||
if !sp.HasDealInfo() {
|
||||
return "<no deal info>"
|
||||
}
|
||||
|
||||
return sp.real.DealInfo.String()
|
||||
}
|
||||
|
||||
@@ -305,21 +313,41 @@ func (sp *SafeSectorPiece) Valid(nv network.Version) error {
|
||||
}
|
||||
|
||||
func (sp *SafeSectorPiece) StartEpoch() (abi.ChainEpoch, error) {
|
||||
if !sp.HasDealInfo() {
|
||||
return 0, xerrors.Errorf("no deal info")
|
||||
}
|
||||
|
||||
return sp.real.DealInfo.StartEpoch()
|
||||
}
|
||||
|
||||
func (sp *SafeSectorPiece) EndEpoch() (abi.ChainEpoch, error) {
|
||||
if !sp.HasDealInfo() {
|
||||
return 0, xerrors.Errorf("no deal info")
|
||||
}
|
||||
|
||||
return sp.real.DealInfo.EndEpoch()
|
||||
}
|
||||
|
||||
func (sp *SafeSectorPiece) PieceCID() cid.Cid {
|
||||
if !sp.HasDealInfo() {
|
||||
return sp.real.Piece.PieceCID
|
||||
}
|
||||
|
||||
return sp.real.DealInfo.PieceCID()
|
||||
}
|
||||
|
||||
func (sp *SafeSectorPiece) KeepUnsealedRequested() bool {
|
||||
if !sp.HasDealInfo() {
|
||||
return false
|
||||
}
|
||||
|
||||
return sp.real.DealInfo.KeepUnsealedRequested()
|
||||
}
|
||||
|
||||
func (sp *SafeSectorPiece) GetAllocation(ctx context.Context, aapi piece.AllocationAPI, tsk types.TipSetKey) (*verifreg.Allocation, error) {
|
||||
if !sp.HasDealInfo() {
|
||||
return nil, xerrors.Errorf("no deal info")
|
||||
}
|
||||
|
||||
return sp.real.DealInfo.GetAllocation(ctx, aapi, tsk)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user