Compare commits

..
Author SHA1 Message Date
i-norden 3a1abdab0f geth debug tracing boilerplate 2023-11-12 11:30:10 -06:00
Aayush Rajasekaran 7344dd5eb3 Merge pull request #11407 from filecoin-project/asr/calibnet-master
chore: forward-port calibnet hotfix to master
2023-11-10 10:26:38 -05:00
Aayush 5b5dd525f5 skip migration cache correctly 2023-11-09 14:14:46 -05:00
Aayush 410bdc389e fix: nv21fix migration: correctly upgrade system actor 2023-11-09 14:14:41 -05:00
Phi-rjan fbafe1c507 Merge pull request #11395 from filecoin-project/fix/update-premigration
fix: migration: set premigration to 90 minutes
2023-11-08 10:22:59 +01:00
Phi 24a714d123 Move premigration to 90 minutes
Move premigration to 90 minutes before upgrade epoch.
2023-11-08 08:22:15 +01:00
Łukasz Magiera b243c405b4 Merge pull request #11353 from CIDgravity/improve-sectors-summary-call
feat: sealing: load SectorsSummary from sealing SectorStats instead of calling API each time
2023-11-07 13:22:18 +01:00
Steven Allen cff785fa37 fix: eth: correctly encode and simplify native input/output encoding (#11382)
* chore: eth: move & rename input/output encoding functions

These are shared functions, so I'm moving them to the utils library.

* fix: eth: correctly encode and simplify native input/output encoding

When generating eth traces, we encode "native" message inputs/outputs
to "solidity ABI" by formatting the inputs/outputs the same way we do in
FEVM's "handle_native_method". However, we had quite a few bugs with the
implementation:

1. We were right-aligning 64bit values in 256bit words, instead of
left-aligning (as we should given that these values are big-endian).
2. The return-value encoding wasn't correctly handling lengths.

This patch:

1. Fixes those bugs.
2. Deduplicates the logic (we're doing _basically_ the same thing in
both cases).
3. Removes all error paths (these functions can't fail).
2023-11-06 09:41:22 -08:00
Florian RUEN c0c4e6bf35 fix: add lk.Lock() and move the map copy to avoid miner crash 2023-11-03 15:38:20 +01:00
Florian RUEN 02929dd166 feat: load SectorsSummmary from SectorStats instead of calling API (faster) 2023-11-03 15:38:19 +01:00
Phi-rjan 12b30c0069 Merge pull request #11361 from filecoin-project/feat/add-mpool-metrics
feat: metric: export Mpool message count
2023-11-03 14:44:19 +01:00
Phi-rjan b1228b51ef fix: worker: listen for interrupt signals in GetStorageMinerAPI loop (#11309)
- Added a goroutine to listen for interrupt signals, which will cancel the current context when an interrupt signal is received. This allows for graceful shutdown of ongoing operations.
2023-11-03 06:39:28 -07:00
Phi 9d58fff806 Update unreleased changelog
Update unreleased changelog
2023-11-03 14:33:31 +01:00
Phi d121760172 Record currentSize on addLocked
Record currentSize on addLocked
2023-11-03 08:59:01 +01:00
Anton Evangelatov e8455567fd readme: bump up golang version (#11347) 2023-11-02 05:39:37 -07:00
Aayush Rajasekaran 29fbfaf13d fix: sync: iterate over returned messages directly (#11373) 2023-11-01 15:08:23 -07:00
Jiaying Wang 5f593b3ae1 Merge pull request #11374 from filecoin-project/jennijuju-patch-5
chore: watermelon: upgrade epoch
2023-11-02 05:30:06 +08:00
Jiaying Wang ad8cfe1da2 update both mainnet and calib upgrade epoch 2023-11-02 03:52:31 +08:00
Jiaying Wang 64a9453db8 Update params_mainnet.go
add main net upgrade epoch
2023-11-02 03:37:43 +08:00
Mikers 72c5a9a574 add support for v12 check invariants and also a default case to reduce future confusion (#11371) 2023-11-01 09:36:00 -07:00
Aayush Rajasekaran 77b6b7ef10 feat: chain: light-weight patch to fix calibrationnet (#11363)
* refactor: make GetEmbeddedBuiltinActorsBundle take network bundle name

* update calibnet actor bundle to v12.0.0-rc.2, but include v12.0.0-rc.1 as calibrationnet-buggy.car

* wip: calibnet unbork migration

* calibnet: add buggy miner actor CID to actorMeta

* fix incorrect buggy calibnet manifest

* make UpgradeWatermelonFixHeight a build param

* calibnet patch: check whether network is calibration from init actor state

* add sanity checks to the v12 calibnet patch upgrade

* address review
2023-10-31 18:29:09 -04:00
Phi d1b8af338e Export Mpool-count
Record the current size of the mpool and export through Prometheus
2023-10-31 08:09:00 +00:00
Steven Allen 48a3076876 test: drand: switch tests to drand testnet (from devnet) (#11359)
At the request of the drand team.
2023-10-30 17:05:02 -07:00
Andrew Jackson (Ajax) 8bb6d423ff Merge pull request #11250 from filecoin-project/release-template-easier
Update RELEASE_ISSUE_TEMPLATE.md
2023-10-30 18:30:17 -05:00
Andrew Jackson (Ajax) 9387ffc593 Update RELEASE_ISSUE_TEMPLATE.md 2023-10-30 18:18:42 -05:00
Łukasz Magiera 3720e79806 Merge pull request #11360 from filecoin-project/fix/add-udp-alert
fix: alert: Check UDPbuffer-size
2023-10-30 12:21:47 +01:00
Phi 7b473f60ae Handle errors from Close() in CheckUDPBufferSize
Added error handling for the Close() method calls in the CheckUDPBufferSize function to satisfy linting rules and improve error logging.
2023-10-30 09:59:59 +00:00
Phi a6ae497c02 Check UDP-buffer-size
Raise alert if UDP-buffer size is not high enough
2023-10-30 09:36:15 +00:00
Steven Allen 87801b5855 feat: shed: fix blockstore prune (#11197)
1. Implement a pass-through for garbage collection on the idstore.
2. Fix the `lotus-shed state-prune` command.

NOTE: the new performance of running a full prune will be significantly
less as this version doesn't batch. However, it should now actually
_work_ and most users will be using the splitstore anyways.
2023-10-27 11:33:18 -07:00
Alejandro Criado-Pérez b6a77dfafc Fix/texts (#11298)
* documentation text corrections

* Text corrections in go files

* make docsgen-cli
2023-10-27 11:32:42 -07:00
Hubert 368278b19c fix typo in rate-limit flag description (#11316) 2023-10-27 11:31:07 -07:00
Volker MischeandSteven Allen 21f8f642c9 refactor:ffi: replace ClearLayerData with ClearCache (#11352)
* refactor: replace ClearLayerData with ClearCache

The `ClearLayerData` FFI call was accidentally introduced with the
Synthetic PoRep. The call does under the hood exactly what `ClearCache`
is doing. This is a first step to remove `ClearLayerData`t also from
the FFI again, in order to reduce the API surface.

* fix types

---------

Co-authored-by: Steven Allen <steven@stebalien.com>
2023-10-27 11:30:07 -07:00
Steven Allen 3f00691f26 fix: api: compute gasUsedRatio based on max gas in the tipset (#11354)
We were computing this based on the max block gas, but this is
incorrect. The new value isn't entirely correct either (we should
probably compute an average of the gas used in each block in the
tipset?), but it's good enough.

fixes #10515
2023-10-27 07:37:51 -07:00
Steven Allen 420f33017e fix: api: compute the effective gas cost with the correct base-fee (#11357)
fixes #11252
2023-10-27 07:37:16 -07:00
Steven Allen 6e22c08c1d fix: api: return errors on failure to lookup an eth txn receipt (#11329)
All these cases here are actually errors and returning `nil` makes this
hard to debug. We likely returned nil in the past to be "best effort"
but, as far as I can tell, we should only hit these error cases if
something is actually wrong.

part of #11325
2023-10-24 12:13:45 -07:00
Ian Norden 84b07519c2 fix: api: exclude reverted events in eth_getLogs results (#11318)
* exclude reverted events from results returned by eth_getLogs

* unit test

* update CHANGELOG.md
2023-10-24 10:05:20 -07:00
Aayush Rajasekaran 018c4e8a38 feat: cli: sort actor CIDs alphabetically before printing (#11345) 2023-10-24 10:03:03 -07:00
guangwu 2d8dbf5bc1 chore: slice loop replace (#11349) 2023-10-24 10:02:28 -07:00
Andrew Jackson (Ajax) d02b91e610 Update RELEASE_ISSUE_TEMPLATE.md 2023-09-06 11:58:35 -05:00
85 changed files with 1519 additions and 374 deletions
+3 -1
View File
@@ -2,6 +2,8 @@
# UNRELEASED
- chore: Auto remove local chain data when importing chain file or snapshot ([filecoin-project/lotus#11277](https://github.com/filecoin-project/lotus/pull/11277))
- feat: metric: export Mpool message count ([filecoin-project/lotus#11361](https://github.com/filecoin-project/lotus/pull/11361))
- feat: sealing: load SectorsSummary from sealing SectorStats instead of calling API each time ([filecoin-project/lotus#11353](https://github.com/filecoin-project/lotus/pull/11353))
## New features
- feat: Added new tracing API (**HIGHLY EXPERIMENTAL**) supporting two RPC methods: `trace_block` and `trace_replayBlockTransactions` ([filecoin-project/lotus#11100](https://github.com/filecoin-project/lotus/pull/11100))
@@ -9,7 +11,7 @@
## Improvements
- fix: Add time slicing to splitstore purging step during compaction to reduce lock congestion [filecoin-project/lotus#11269](https://github.com/filecoin-project/lotus/pull/11269)
- feat: Added instructions on how to setup Prometheus/Grafana for monitoring a local Lotus node [filecoin-project/lotus#11276](https://github.com/filecoin-project/lotus/pull/11276)
- feat: Add a `FilterThresholdEpoch` configuration option [filecoin-project/lotus#11346](https://github.com/filecoin-project/lotus/pull/11346)
- fix: Exclude reverted events in `eth_getLogs` results [filecoin-project/lotus#11318](https://github.com/filecoin-project/lotus/pull/11318)
## New features
- feat: Add move-partition command ([filecoin-project/lotus#11290](https://github.com/filecoin-project/lotus/pull/11290))
+2 -2
View File
@@ -71,10 +71,10 @@ For other distributions you can find the required dependencies [here.](https://l
#### Go
To build Lotus, you need a working installation of [Go 1.19.12 or higher](https://golang.org/dl/):
To build Lotus, you need a working installation of [Go 1.20.10 or higher](https://golang.org/dl/):
```bash
wget -c https://golang.org/dl/go1.19.12.linux-amd64.tar.gz -O - | sudo tar -xz -C /usr/local
wget -c https://golang.org/dl/go1.20.10.linux-amd64.tar.gz -O - | sudo tar -xz -C /usr/local
```
**TIP:**
+5
View File
@@ -874,6 +874,11 @@ type FullNode interface {
// Replays all transactions in a block returning the requested traces for each transaction
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) //perm:read
// go-ethereum "debug" trace endpoints
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
// CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
+3
View File
@@ -129,4 +129,7 @@ type Gateway interface {
Web3ClientVersion(ctx context.Context) (string, error)
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
}
+4
View File
@@ -43,6 +43,10 @@ func CreateEthRPCAliases(as apitypes.Aliaser) {
as.AliasMethod("trace_block", "Filecoin.EthTraceBlock")
as.AliasMethod("trace_replayBlockTransactions", "Filecoin.EthTraceReplayBlockTransactions")
as.AliasMethod("debug_traceCall", "Filecoin.EthDebugTraceCall")
as.AliasMethod("debug_traceBlockByHash", "Filecoin.EthDebugTraceBlockByHash")
as.AliasMethod("debug_traceBlockByNumber", "Filecoin.EthDebugTraceBlockByNumber")
as.AliasMethod("net_version", "Filecoin.NetVersion")
as.AliasMethod("net_listening", "Filecoin.NetListening")
+45
View File
@@ -1500,12 +1500,57 @@ func (m *MockFullNode) EthTraceBlock(arg0 context.Context, arg1 string) ([]*etht
return ret0, ret1
}
// EthDebugTraceCall mocks base method.
func (m *MockFullNode) EthDebugTraceCall(ctx context.Context, arg0 ethtypes.EthTxArgs, arg1 ethtypes.EthBlockNumberOrHash, arg2 *ethtypes.TraceCallConfig) (interface{}, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthDebugTraceCall", arg0, arg1, arg2)
ret0, _ := ret[0].(interface{})
ret1, _ := ret[1].(error)
return ret0, ret1
}
// EthDebugTraceBlockByNumber mocks base method.
func (m *MockFullNode) EthDebugTraceBlockByNumber(ctx context.Context, arg0 string, arg1 *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthDebugTraceBlockByNumber", arg0, arg1)
ret0, _ := ret[0].([]*ethtypes.TxTraceResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// EthDebugTraceBlockByHash mocks base method.
func (m *MockFullNode) EthDebugTraceBlockByHash(ctx context.Context, arg0 ethtypes.EthHash, arg1 *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthDebugTraceBlockByHash", arg0, arg1)
ret0, _ := ret[0].([]*ethtypes.TxTraceResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// EthTraceBlock indicates an expected call of EthTraceBlock.
func (mr *MockFullNodeMockRecorder) EthTraceBlock(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthTraceBlock", reflect.TypeOf((*MockFullNode)(nil).EthTraceBlock), arg0, arg1)
}
// EthDebugTraceCall indicates an expected of EthDebugTraceCall
func (mr *MockFullNodeMockRecorder) EthDebugTraceCall(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthDebugTraceCall", reflect.TypeOf((*MockFullNode)(nil).EthDebugTraceCall), arg0, arg1, arg2)
}
// EthDebugTraceBlockByHash indicates an expected of EthDebugTraceBlockByHash
func (mr *MockFullNodeMockRecorder) EthDebugTraceBlockByHash(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthDebugTraceBlockByHash", reflect.TypeOf((*MockFullNode)(nil).EthDebugTraceBlockByHash), arg0, arg1)
}
// EthDebugTraceBlockByNumber indicates an expected of EthDebugTraceBlockByHash
func (mr *MockFullNodeMockRecorder) EthDebugTraceBlockByNumber(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthDebugTraceBlockByNumber", reflect.TypeOf((*MockFullNode)(nil).EthDebugTraceBlockByNumber), arg0, arg1)
}
// EthTraceReplayBlockTransactions mocks base method.
func (m *MockFullNode) EthTraceReplayBlockTransactions(arg0 context.Context, arg1 string, arg2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
m.ctrl.T.Helper()
+14
View File
@@ -183,3 +183,17 @@ func (b *idstore) Close() error {
func (b *idstore) Flush(ctx context.Context) error {
return b.bs.Flush(ctx)
}
func (b *idstore) CollectGarbage(ctx context.Context, options ...BlockstoreGCOption) error {
if bs, ok := b.bs.(BlockstoreGC); ok {
return bs.CollectGarbage(ctx, options...)
}
return xerrors.Errorf("not supported")
}
func (b *idstore) GCOnce(ctx context.Context, options ...BlockstoreGCOption) error {
if bs, ok := b.bs.(BlockstoreGCOnce); ok {
return bs.GCOnce(ctx, options...)
}
return xerrors.Errorf("not supported")
}
Binary file not shown.
+14 -2
View File
@@ -42,6 +42,12 @@ func init() {
if err := loadManifests(NetworkBundle); err != nil {
panic(err)
}
// The following code cid existed temporarily on the calibnet testnet, as a "buggy" storage miner actor implementation.
// We include it in our builtin bundle, but intentionally omit from metadata.
if NetworkBundle == "calibrationnet" {
actors.AddActorMeta("storageminer", cid.MustParse("bafk2bzacecnh2ouohmonvebq7uughh4h3ppmg4cjsk74dzxlbbtlcij4xbzxq"), actorstypes.Version12)
}
}
// UseNetworkBundle switches to a different network bundle, by name.
@@ -183,6 +189,12 @@ func readEmbeddedBuiltinActorsMetadata(bundle string) ([]*BuiltinActorsMetadata,
if err != nil {
return nil, xerrors.Errorf("error loading builtin actors bundle: %w", err)
}
// The following manifest cid existed temporarily on the calibnet testnet
// We include it in our builtin bundle, but intentionally omit from metadata
if root == cid.MustParse("bafy2bzacedrunxfqta5skb7q7x32lnp4efz2oq7fn226ffm7fu5iqs62jkmvs") {
continue
}
bundles = append(bundles, &BuiltinActorsMetadata{
Network: name,
Version: actorstypes.Version(version),
@@ -232,7 +244,7 @@ func readBundleManifest(r io.Reader) (cid.Cid, map[string]cid.Cid, error) {
}
// GetEmbeddedBuiltinActorsBundle returns the builtin-actors bundle for the given actors version.
func GetEmbeddedBuiltinActorsBundle(version actorstypes.Version) ([]byte, bool) {
func GetEmbeddedBuiltinActorsBundle(version actorstypes.Version, networkBundleName string) ([]byte, bool) {
fi, err := embeddedBuiltinActorReleases.Open(fmt.Sprintf("actors/v%d.tar.zst", version))
if err != nil {
return nil, false
@@ -243,7 +255,7 @@ func GetEmbeddedBuiltinActorsBundle(version actorstypes.Version) ([]byte, bool)
defer uncompressed.Close() //nolint
tarReader := tar.NewReader(uncompressed)
targetFileName := fmt.Sprintf("builtin-actors-%s.car", NetworkBundle)
targetFileName := fmt.Sprintf("builtin-actors-%s.car", networkBundleName)
for {
header, err := tarReader.Next()
switch err {
+21 -21
View File
@@ -97,8 +97,8 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
}, {
Network: "butterflynet",
Version: 12,
BundleGitTag: "v12.0.0-rc.1",
ManifestCid: MustParseCid("bafy2bzaceb7s3k6zyuubqil7s2rwdcdyslqqx2fn2cj536yh3hexlyi4syyk6"),
BundleGitTag: "v12.0.0-rc.2",
ManifestCid: MustParseCid("bafy2bzaceabeegs5mhrxwqodyt7u2ulxr2jg6eh5g3545ganqzkncnxzserue"),
Actors: map[string]cid.Cid{
"account": MustParseCid("bafk2bzacebp7anjdtg2sohyt6lromx4xs7nujtwdfcsffnptphaayabx7ysxs"),
"cron": MustParseCid("bafk2bzacecu2y3awtemmglpkroiglulc2fj3gpdn6eazdqr6avcautiaighrg"),
@@ -112,7 +112,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
"placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"),
"reward": MustParseCid("bafk2bzacedebvitdsztwebi44t5es4ls3p3hor252igzawr3s6uznmbvzh2ou"),
"storagemarket": MustParseCid("bafk2bzaceb2tdeqtt2eqpzeb3gezuchb7g7uzbd52bgvcdt6bg3ckq7oisb74"),
"storageminer": MustParseCid("bafk2bzaceaaztuglvw6pw5xohwfekbw47iyugbyftxrp6hwygsaiu6rebtcty"),
"storageminer": MustParseCid("bafk2bzacea2jzzulmz6ktj6vndjheybz2io3vznnhsb32zberpaqeo7s7xa56"),
"storagepower": MustParseCid("bafk2bzacedxvlj5xmhytdjrjqyonz37duvxb2ioyzk75c27yypkqalxuh3xh6"),
"system": MustParseCid("bafk2bzacec3vwj2chzaram3iqupkbfiein5h2l5qiltlrngbju2vg5umelclm"),
"verifiedregistry": MustParseCid("bafk2bzacedv2irkql7nil3w5v3ohqq3e54w62pxeoppjmaktzokolaaoh5ksu"),
@@ -203,8 +203,8 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
}, {
Network: "calibrationnet",
Version: 12,
BundleGitTag: "v12.0.0-rc.1",
ManifestCid: MustParseCid("bafy2bzacedrunxfqta5skb7q7x32lnp4efz2oq7fn226ffm7fu5iqs62jkmvs"),
BundleGitTag: "v12.0.0-rc.2",
ManifestCid: MustParseCid("bafy2bzacebl4w5ptfvuw6746w7ev562idkbf5ppq72e6zub22435ws2rukzru"),
Actors: map[string]cid.Cid{
"account": MustParseCid("bafk2bzacechwwxdqvggkdylm37zldjsra2ivkdzwp7fee56bzxbzs544wv6u6"),
"cron": MustParseCid("bafk2bzacec4gdxxkqwxqqodsv6ug5dmdbqdfqwyqfek3yhxc2wweh5psxaeq6"),
@@ -218,7 +218,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
"placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"),
"reward": MustParseCid("bafk2bzacedra77pcglf7vdca2itcaa4vd6xrxynxmgfgdjdxqxfwqyhtoxehy"),
"storagemarket": MustParseCid("bafk2bzacea7g46y7xxu2zjq2h75x6mmx3utz2uxnlvnwi6tzpsvulna3bmiva"),
"storageminer": MustParseCid("bafk2bzacecnh2ouohmonvebq7uughh4h3ppmg4cjsk74dzxlbbtlcij4xbzxq"),
"storageminer": MustParseCid("bafk2bzaced7emkbbnrewv5uvrokxpf5tlm4jslu2jsv77ofw2yqdglg657uie"),
"storagepower": MustParseCid("bafk2bzacedd3ka44k7d46ckbinjhv3diyuu2epgbyvhqqyjkc64qlrg3wlgzi"),
"system": MustParseCid("bafk2bzacecioupndtcnyw6iq2hbrxag3aufvczlv5nobnfbkbywqzcyfaa376"),
"verifiedregistry": MustParseCid("bafk2bzaceavldupmf7bimeeacs67z5xdfdlfca6p7sn6bev3mt5ggepfqvhqo"),
@@ -318,8 +318,8 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
}, {
Network: "caterpillarnet",
Version: 12,
BundleGitTag: "v12.0.0-rc.1",
ManifestCid: MustParseCid("bafy2bzacedrimdbavexkdqldjwczbhlx4k5byshl363z62rrt6vkt7mbvnulu"),
BundleGitTag: "v12.0.0-rc.2",
ManifestCid: MustParseCid("bafy2bzacechvmc3iy6qrsbb6xwjhjibqpznqnkajowjsdmrq42ie5hysqemqa"),
Actors: map[string]cid.Cid{
"account": MustParseCid("bafk2bzacecereuhejfvodut5357cai4lmhsyr7uenhcxvmw6jpmhe6auuly32"),
"cron": MustParseCid("bafk2bzacebo2whgy6jla4jsf5j4ovlqm2e4eepedlpw5wadas33yxmunis4b4"),
@@ -333,7 +333,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
"placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"),
"reward": MustParseCid("bafk2bzaceb2x5zgkrho373l3ippp6krs7brugssg6hj2tib22xmqjzdm2o25a"),
"storagemarket": MustParseCid("bafk2bzaced5j6drzmsebpxbf2dtptrc5tyidlbftdljqxavxqb57s2qpbvdek"),
"storageminer": MustParseCid("bafk2bzacedozwxc3c6nqqajafs3hsjviyijhthysd5two5ptm5fcdbwh224ag"),
"storageminer": MustParseCid("bafk2bzacec7al5izu3ynnb7wg6fxxck3hebtkvlgynufjwcio57jd3n4ke2ue"),
"storagepower": MustParseCid("bafk2bzaceagp6ilkltsltwii66nz6a4zen4qtfk7rdkvdv3gzq7fbv4ivox3u"),
"system": MustParseCid("bafk2bzacedye5j5uxox7knb6zlnhseaadztyav76mjbyk5qslhhbpiy5cdtt2"),
"verifiedregistry": MustParseCid("bafk2bzacecduww5pirr7dvaijjijw4gf6ygf7vipgxh4scvv6vseo46gueb46"),
@@ -424,8 +424,8 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
}, {
Network: "devnet",
Version: 12,
BundleGitTag: "v12.0.0-rc.1",
ManifestCid: MustParseCid("bafy2bzacebk6yiirh4ennphzyka7b6g6jzn3lt4lr5ht7rjwulnrcthjihapo"),
BundleGitTag: "v12.0.0-rc.2",
ManifestCid: MustParseCid("bafy2bzaceau5i7eanhvss22z5ixmyrihilfniqn22tvkecjj56akz4xj7fvku"),
Actors: map[string]cid.Cid{
"account": MustParseCid("bafk2bzacedki4apynvdxxuoigmqkgaktgy2erjftoxqxqaklnelgveyaqknfu"),
"cron": MustParseCid("bafk2bzacebjpczf7qtcisy3zdp3sqoohxe75tgupmdo5dr26vh7orzrsjn3b2"),
@@ -439,7 +439,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
"placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"),
"reward": MustParseCid("bafk2bzacebzso6xkjxdscbpncw7el2d4hap6lfkgwqzrbc76lzp33vkwk6obc"),
"storagemarket": MustParseCid("bafk2bzacebzg74vyk3gzbhnz4zviwvxblyar574mtd6ayognmsvlkriejmunu"),
"storageminer": MustParseCid("bafk2bzaceajgt523lr2sf6cacvzo3goyalljlkaoeehyhxlv57wevkljw2cps"),
"storageminer": MustParseCid("bafk2bzaceckqrzomdnfb35byrhabrmmapxplj66cv3efw7u62qswjaqsuxah4"),
"storagepower": MustParseCid("bafk2bzacebbtj2m2ajawfuzxqz5nmdep7xevjo2qfjqa5tx3vr5m6qojolya4"),
"system": MustParseCid("bafk2bzacecnau5wddulbsvwn75tc3w75jrlvkybgrlxs4ngonqab6xq3eowvg"),
"verifiedregistry": MustParseCid("bafk2bzacec37mddea65nvh4htsagtryfa3sq6i67utcupslyhzbhjhoy6hopa"),
@@ -553,8 +553,8 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
}, {
Network: "mainnet",
Version: 12,
BundleGitTag: "v12.0.0-rc.1",
ManifestCid: MustParseCid("bafy2bzacebxmnxdgt2usdrcrpotgodr75culawwv4eklaun4lu6vlxecql6h2"),
BundleGitTag: "v12.0.0-rc.2",
ManifestCid: MustParseCid("bafy2bzacecooh5cjxkmraawn7wvmrx7k5hwdmbvqdteujr33mnaeclsazyb6a"),
Actors: map[string]cid.Cid{
"account": MustParseCid("bafk2bzaceboftg75mdiba7xbo2i3uvgtca4brhnr3u5ptihonixgpnrvhpxoa"),
"cron": MustParseCid("bafk2bzacechxjkfe2cehx4s7skj3wzfpzf7zolds64khrrrs66bhazsemktls"),
@@ -568,7 +568,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
"placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"),
"reward": MustParseCid("bafk2bzacealqnxn5lwzwexd6reav4dppypquklx2ujlnvaxiqk2tzstyvkp5u"),
"storagemarket": MustParseCid("bafk2bzacedylkg5am446lcuih4voyzdn4yjeqfsxfzh5b6mcuhx4mok5ph5c4"),
"storageminer": MustParseCid("bafk2bzacea56yi2khvvorofkf2t4rb5fbmltahrjtauszirdjz4jbunt55xsk"),
"storageminer": MustParseCid("bafk2bzacedio7wfaqutc4w6gl2dwqkgpcatz2r223ms74zxiovbjrfxmzeiou"),
"storagepower": MustParseCid("bafk2bzacecsij5tpfzjpfuckxvccv2p3bdqjklkrfyyoei6lx5dyj5j4fvjm6"),
"system": MustParseCid("bafk2bzacebfqrja2hip7esf4eafxjmu6xcogoqu5xxtgdg7xa5szgvvdguchu"),
"verifiedregistry": MustParseCid("bafk2bzacedudgflxc75c77c6zkmfyq4u2xuk7k6xw6dfdccarjrvxx453b77q"),
@@ -659,8 +659,8 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
}, {
Network: "testing",
Version: 12,
BundleGitTag: "v12.0.0-rc.1",
ManifestCid: MustParseCid("bafy2bzacebzcqzzlb5iwrledyuyy7pvob3xwzoxqsrvrbrnpaiejb52na5eza"),
BundleGitTag: "v12.0.0-rc.2",
ManifestCid: MustParseCid("bafy2bzacec7artlmtdmfuhurd2i7dgturiveblruub5xh3yizjtp5qzye3dly"),
Actors: map[string]cid.Cid{
"account": MustParseCid("bafk2bzacea74qqkfvacykmq5emzqblh4f4nmxdkiyixxpzs7kkcfnbfa7cb6m"),
"cron": MustParseCid("bafk2bzacecotbu7k6awdzfzakf7g5iaas6gswtunjnnb2xm2klqoshjgb4imy"),
@@ -674,7 +674,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
"placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"),
"reward": MustParseCid("bafk2bzaceaajyncjxcrl7wbb6ukzkueyqz4uyekxpmtn4mpndkf7ksmggopzq"),
"storagemarket": MustParseCid("bafk2bzaced6cexdcinwjhtfvuxgkxukiejp3goylaxtvhqfd24rs5z7g2z7dm"),
"storageminer": MustParseCid("bafk2bzacecw6jvvfu62jkwsa4vzmn262cjrrxh6wza6nvjsyg5aeix7rzgmbe"),
"storageminer": MustParseCid("bafk2bzaceclcbtu6edh73cn7ga7kzkmxcfnjt7jnxolkc5id6l6f7sztevm24"),
"storagepower": MustParseCid("bafk2bzacedexrf5qplrrl5xzijfrthjdqwodfs5e6zj5kpztc7qnywbqdyiii"),
"system": MustParseCid("bafk2bzacecp4roanbxq3bflftlkipsoqqxio5etjjnzxus5pcu7lq43fnxb34"),
"verifiedregistry": MustParseCid("bafk2bzaceandytrgcnuvizfi47sijbqh6c243vjtzlzumexm6kjv7s7hye45g"),
@@ -765,8 +765,8 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
}, {
Network: "testing-fake-proofs",
Version: 12,
BundleGitTag: "v12.0.0-rc.1",
ManifestCid: MustParseCid("bafy2bzacedtskkmrkkzairdi66syrmvfpydg63ro4dlmmqeta5krnur4hcp3a"),
BundleGitTag: "v12.0.0-rc.2",
ManifestCid: MustParseCid("bafy2bzaceand7owcb3omq7zjwir2q3lqapprl2eyiwpzv6oqs5bok4vzzqjbu"),
Actors: map[string]cid.Cid{
"account": MustParseCid("bafk2bzacea74qqkfvacykmq5emzqblh4f4nmxdkiyixxpzs7kkcfnbfa7cb6m"),
"cron": MustParseCid("bafk2bzacecotbu7k6awdzfzakf7g5iaas6gswtunjnnb2xm2klqoshjgb4imy"),
@@ -780,7 +780,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
"placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"),
"reward": MustParseCid("bafk2bzaceaajyncjxcrl7wbb6ukzkueyqz4uyekxpmtn4mpndkf7ksmggopzq"),
"storagemarket": MustParseCid("bafk2bzaced6cexdcinwjhtfvuxgkxukiejp3goylaxtvhqfd24rs5z7g2z7dm"),
"storageminer": MustParseCid("bafk2bzacea54x727xteh3tl46mitigy6cldqusqjxiwni65wrpofidh62k2ds"),
"storageminer": MustParseCid("bafk2bzacebbusvtnyhi7mimbnx2tw2uyvrr3fbmncbf6frx6e4kvjvoqllu36"),
"storagepower": MustParseCid("bafk2bzacecdwijcbbryinjtm27pdinqqkyzoskri24pwsvsadwcq2alkkjpnc"),
"system": MustParseCid("bafk2bzacecp4roanbxq3bflftlkipsoqqxio5etjjnzxus5pcu7lq43fnxb34"),
"verifiedregistry": MustParseCid("bafk2bzaceandytrgcnuvizfi47sijbqh6c243vjtzlzumexm6kjv7s7hye45g"),
+3
View File
@@ -67,6 +67,9 @@ var UpgradeThunderHeight = abi.ChainEpoch(-23)
var UpgradeWatermelonHeight = abi.ChainEpoch(200)
// This fix upgrade only ran on calibrationnet
const UpgradeWatermelonFixHeight = -100
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
+3
View File
@@ -57,6 +57,9 @@ const UpgradeThunderHeight = -23
const UpgradeWatermelonHeight = 400
// This fix upgrade only ran on calibrationnet
const UpgradeWatermelonFixHeight = -100
var SupportedProofTypes = []abi.RegisteredSealProof{
abi.RegisteredSealProof_StackedDrg512MiBV1,
abi.RegisteredSealProof_StackedDrg32GiBV1,
+3
View File
@@ -82,6 +82,9 @@ const UpgradeThunderHeight = UpgradeLightningHeight + 3120
// 2023-10-19T13:00:00Z
const UpgradeWatermelonHeight = 1013134
// 2023-11-07T13:00:00Z
const UpgradeWatermelonFixHeight = 1070494
var SupportedProofTypes = []abi.RegisteredSealProof{
abi.RegisteredSealProof_StackedDrg32GiBV1,
abi.RegisteredSealProof_StackedDrg64GiBV1,
+3
View File
@@ -56,6 +56,9 @@ var UpgradeThunderHeight = abi.ChainEpoch(-23)
const UpgradeWatermelonHeight = 50
// This fix upgrade only ran on calibrationnet
const UpgradeWatermelonFixHeight = -1
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
+5 -2
View File
@@ -95,8 +95,11 @@ const UpgradeLightningHeight = 2809800
// 2023-05-18T13:00:00Z
const UpgradeThunderHeight = UpgradeLightningHeight + 2880*21
// ???????
var UpgradeWatermelonHeight = abi.ChainEpoch(9999999999)
// 2023-11-29T13:30:00Z
var UpgradeWatermelonHeight = abi.ChainEpoch(3431940)
// This fix upgrade only ran on calibrationnet
const UpgradeWatermelonFixHeight = -1
var SupportedProofTypes = []abi.RegisteredSealProof{
abi.RegisteredSealProof_StackedDrg32GiBV1,
+24 -23
View File
@@ -87,29 +87,30 @@ var (
UpgradeBreezeHeight abi.ChainEpoch = -1
BreezeGasTampingDuration abi.ChainEpoch = 0
UpgradeSmokeHeight abi.ChainEpoch = -1
UpgradeIgnitionHeight abi.ChainEpoch = -2
UpgradeRefuelHeight abi.ChainEpoch = -3
UpgradeTapeHeight abi.ChainEpoch = -4
UpgradeAssemblyHeight abi.ChainEpoch = 10
UpgradeLiftoffHeight abi.ChainEpoch = -5
UpgradeKumquatHeight abi.ChainEpoch = -6
UpgradeCalicoHeight abi.ChainEpoch = -8
UpgradePersianHeight abi.ChainEpoch = -9
UpgradeOrangeHeight abi.ChainEpoch = -10
UpgradeClausHeight abi.ChainEpoch = -11
UpgradeTrustHeight abi.ChainEpoch = -12
UpgradeNorwegianHeight abi.ChainEpoch = -13
UpgradeTurboHeight abi.ChainEpoch = -14
UpgradeHyperdriveHeight abi.ChainEpoch = -15
UpgradeChocolateHeight abi.ChainEpoch = -16
UpgradeOhSnapHeight abi.ChainEpoch = -17
UpgradeSkyrHeight abi.ChainEpoch = -18
UpgradeSharkHeight abi.ChainEpoch = -19
UpgradeHyggeHeight abi.ChainEpoch = -20
UpgradeLightningHeight abi.ChainEpoch = -21
UpgradeThunderHeight abi.ChainEpoch = -22
UpgradeWatermelonHeight abi.ChainEpoch = -23
UpgradeSmokeHeight abi.ChainEpoch = -1
UpgradeIgnitionHeight abi.ChainEpoch = -2
UpgradeRefuelHeight abi.ChainEpoch = -3
UpgradeTapeHeight abi.ChainEpoch = -4
UpgradeAssemblyHeight abi.ChainEpoch = 10
UpgradeLiftoffHeight abi.ChainEpoch = -5
UpgradeKumquatHeight abi.ChainEpoch = -6
UpgradeCalicoHeight abi.ChainEpoch = -8
UpgradePersianHeight abi.ChainEpoch = -9
UpgradeOrangeHeight abi.ChainEpoch = -10
UpgradeClausHeight abi.ChainEpoch = -11
UpgradeTrustHeight abi.ChainEpoch = -12
UpgradeNorwegianHeight abi.ChainEpoch = -13
UpgradeTurboHeight abi.ChainEpoch = -14
UpgradeHyperdriveHeight abi.ChainEpoch = -15
UpgradeChocolateHeight abi.ChainEpoch = -16
UpgradeOhSnapHeight abi.ChainEpoch = -17
UpgradeSkyrHeight abi.ChainEpoch = -18
UpgradeSharkHeight abi.ChainEpoch = -19
UpgradeHyggeHeight abi.ChainEpoch = -20
UpgradeLightningHeight abi.ChainEpoch = -21
UpgradeThunderHeight abi.ChainEpoch = -22
UpgradeWatermelonHeight abi.ChainEpoch = -23
UpgradeWatermelonFixHeight abi.ChainEpoch = -24
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
+1
View File
@@ -23,6 +23,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors"
)
var InitActorAddr = builtin.InitActorAddr
var SystemActorAddr = builtin.SystemActorAddr
var BurntFundsActorAddr = builtin.BurntFundsActorAddr
var CronActorAddr = builtin.CronActorAddr
+1
View File
@@ -23,6 +23,7 @@ import (
smoothingtypes "github.com/filecoin-project/go-state-types/builtin/v8/util/smoothing"
)
var InitActorAddr = builtin.InitActorAddr
var SystemActorAddr = builtin.SystemActorAddr
var BurntFundsActorAddr = builtin.BurntFundsActorAddr
var CronActorAddr = builtin.CronActorAddr
+1 -1
View File
@@ -72,7 +72,7 @@ func (s *state{{.v}}) AvailableBalance(bal abi.TokenAmount) (available abi.Token
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available{{if (ge .v 2)}}, err{{end}} = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state0) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state10) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmou
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state11) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmou
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state12) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmou
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -61,7 +61,7 @@ func (s *state2) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state3) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state4) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state5) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state6) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state7) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state8) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (s *state9) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
// this panics if the miner doesn't have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}
+1 -1
View File
@@ -29,7 +29,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
// Load returns an abstract copy of payment channel state, irregardless of actor version
// Load returns an abstract copy of payment channel state, regardless of actor version
func Load(store adt.Store, act *types.Actor) (State, error) {
if name, av, ok := actors.GetActorMetaByCode(act.Code); ok {
if name != manifest.PaychKey {
+1 -1
View File
@@ -29,7 +29,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
// Load returns an abstract copy of payment channel state, irregardless of actor version
// Load returns an abstract copy of payment channel state, regardless of actor version
func Load(store adt.Store, act *types.Actor) (State, error) {
if name, av, ok := actors.GetActorMetaByCode(act.Code); ok {
if name != manifest.PaychKey {
+6
View File
@@ -51,6 +51,12 @@ func RegisterManifest(av actorstypes.Version, manifestCid cid.Cid, entries map[s
}
}
func AddActorMeta(name string, codeId cid.Cid, av actorstypes.Version) {
manifestMx.Lock()
defer manifestMx.Unlock()
actorMeta[codeId] = actorEntry{name: name, version: av}
}
// GetManifest gets a loaded manifest.
func GetManifest(av actorstypes.Version) (cid.Cid, bool) {
manifestMx.RLock()
+1 -1
View File
@@ -13,7 +13,7 @@ import (
func SerializeParams(i cbg.CBORMarshaler) ([]byte, aerrors.ActorError) {
buf := new(bytes.Buffer)
if err := i.MarshalCBOR(buf); err != nil {
// TODO: shouldnt this be a fatal error?
// TODO: shouldn't this be a fatal error?
return nil, aerrors.Absorb(err, exitcode.ErrSerialization, "failed to encode parameter")
}
return buf.Bytes(), nil
+2 -2
View File
@@ -17,7 +17,7 @@ import (
)
func TestPrintGroupInfo(t *testing.T) {
server := build.DrandConfigs[build.DrandDevnet].Servers[0]
server := build.DrandConfigs[build.DrandTestnet].Servers[0]
c, err := hclient.New(server, nil, nil)
assert.NoError(t, err)
cg := c.(interface {
@@ -31,7 +31,7 @@ func TestPrintGroupInfo(t *testing.T) {
func TestMaxBeaconRoundForEpoch(t *testing.T) {
todayTs := uint64(1652222222)
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandDevnet])
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandTestnet])
assert.NoError(t, err)
mbr15 := db.MaxBeaconRoundForEpoch(network.Version15, 100)
mbr16 := db.MaxBeaconRoundForEpoch(network.Version16, 100)
+197 -5
View File
@@ -1,6 +1,7 @@
package filcns
import (
"bytes"
"context"
_ "embed"
"fmt"
@@ -19,7 +20,9 @@ import (
actorstypes "github.com/filecoin-project/go-state-types/actors"
"github.com/filecoin-project/go-state-types/big"
nv18 "github.com/filecoin-project/go-state-types/builtin/v10/migration"
init11 "github.com/filecoin-project/go-state-types/builtin/v11/init"
nv19 "github.com/filecoin-project/go-state-types/builtin/v11/migration"
system11 "github.com/filecoin-project/go-state-types/builtin/v11/system"
nv21 "github.com/filecoin-project/go-state-types/builtin/v12/migration"
nv17 "github.com/filecoin-project/go-state-types/builtin/v9/migration"
"github.com/filecoin-project/go-state-types/manifest"
@@ -268,11 +271,15 @@ func DefaultUpgradeSchedule() stmgr.UpgradeSchedule {
Migration: UpgradeActorsV12,
PreMigrations: []stmgr.PreMigration{{
PreMigration: PreUpgradeActorsV12,
StartWithin: 120,
StartWithin: 180,
DontStartWithin: 15,
StopWithin: 10,
}},
Expensive: true,
}, {
Height: build.UpgradeWatermelonFixHeight,
Network: network.Version21,
Migration: upgradeActorsV12Fix,
},
}
@@ -1869,6 +1876,8 @@ func UpgradeActorsV12(ctx context.Context, sm *stmgr.StateManager, cache stmgr.M
return newRoot, nil
}
var calibnetv12BuggyBundle = cid.MustParse("bafy2bzacedrunxfqta5skb7q7x32lnp4efz2oq7fn226ffm7fu5iqs62jkmvs")
func upgradeActorsV12Common(
ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache,
root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet,
@@ -1894,13 +1903,50 @@ func upgradeActorsV12Common(
)
}
manifest, ok := actors.GetManifest(actorstypes.Version12)
if !ok {
return cid.Undef, xerrors.Errorf("no manifest CID for v12 upgrade")
// check whether or not this is a calibnet upgrade
// we do this because calibnet upgraded to a "wrong" actors bundle, which was then corrected
// we thus upgrade to calibrationnet-buggy in this upgrade
actorsIn, err := state.LoadStateTree(adtStore, root)
if err != nil {
return cid.Undef, xerrors.Errorf("loading state tree: %w", err)
}
initActor, err := actorsIn.GetActor(builtin.InitActorAddr)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to get system actor: %w", err)
}
var initState init11.State
if err := adtStore.Get(ctx, initActor.Head, &initState); err != nil {
return cid.Undef, xerrors.Errorf("failed to get system actor state: %w", err)
}
var manifestCid cid.Cid
if initState.NetworkName == "calibrationnet" {
embedded, ok := build.GetEmbeddedBuiltinActorsBundle(actorstypes.Version12, "calibrationnet-buggy")
if !ok {
return cid.Undef, xerrors.Errorf("didn't find buggy calibrationnet bundle")
}
var err error
manifestCid, err = bundle.LoadBundle(ctx, writeStore, bytes.NewReader(embedded))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to load buggy calibnet bundle: %w", err)
}
if manifestCid != calibnetv12BuggyBundle {
return cid.Undef, xerrors.Errorf("didn't find expected buggy calibnet bundle manifest: %s != %s", manifestCid, calibnetv12BuggyBundle)
}
} else {
ok := false
manifestCid, ok = actors.GetManifest(actorstypes.Version12)
if !ok {
return cid.Undef, xerrors.Errorf("no manifest CID for v12 upgrade")
}
}
// Perform the migration
newHamtRoot, err := nv21.MigrateStateTree(ctx, adtStore, manifest, stateRoot.Actors, epoch, config,
newHamtRoot, err := nv21.MigrateStateTree(ctx, adtStore, manifestCid, stateRoot.Actors, epoch, config,
migrationLogger{}, cache)
if err != nil {
return cid.Undef, xerrors.Errorf("upgrading to actors v12: %w", err)
@@ -1928,6 +1974,152 @@ func upgradeActorsV12Common(
return newRoot, nil
}
//////////////////////
var calibnetv12BuggyMinerCID = cid.MustParse("bafk2bzacecnh2ouohmonvebq7uughh4h3ppmg4cjsk74dzxlbbtlcij4xbzxq")
func upgradeActorsV12Fix(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, cb stmgr.ExecMonitor,
root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
stateStore := sm.ChainStore().StateBlockstore()
adtStore := store.ActorStore(ctx, stateStore)
// ensure that the manifest is loaded in the blockstore
if err := bundle.LoadBundles(ctx, stateStore, actorstypes.Version12); err != nil {
return cid.Undef, xerrors.Errorf("failed to load manifest bundle: %w", err)
}
// Load input state tree
actorsIn, err := state.LoadStateTree(adtStore, root)
if err != nil {
return cid.Undef, xerrors.Errorf("loading state tree: %w", err)
}
// load old manifest data
systemActor, err := actorsIn.GetActor(builtin.SystemActorAddr)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to get system actor: %w", err)
}
var systemState system11.State
if err := adtStore.Get(ctx, systemActor.Head, &systemState); err != nil {
return cid.Undef, xerrors.Errorf("failed to get system actor state: %w", err)
}
var oldManifestData manifest.ManifestData
if err := adtStore.Get(ctx, systemState.BuiltinActors, &oldManifestData); err != nil {
return cid.Undef, xerrors.Errorf("failed to get old manifest data: %w", err)
}
newManifestCID, ok := actors.GetManifest(actorstypes.Version12)
if !ok {
return cid.Undef, xerrors.Errorf("no manifest CID for v12 upgrade")
}
// load new manifest
var newManifest manifest.Manifest
if err := adtStore.Get(ctx, newManifestCID, &newManifest); err != nil {
return cid.Undef, xerrors.Errorf("error reading actor manifest: %w", err)
}
if err := newManifest.Load(ctx, adtStore); err != nil {
return cid.Undef, xerrors.Errorf("error loading actor manifest: %w", err)
}
// build the CID mapping
codeMapping := make(map[cid.Cid]cid.Cid, len(oldManifestData.Entries))
for _, oldEntry := range oldManifestData.Entries {
newCID, ok := newManifest.Get(oldEntry.Name)
if !ok {
return cid.Undef, xerrors.Errorf("missing manifest entry for %s", oldEntry.Name)
}
// Note: we expect newCID to be the same as oldEntry.Code for all actors except the miner actor
codeMapping[oldEntry.Code] = newCID
}
// Create empty actorsOut
actorsOut, err := state.NewStateTree(adtStore, actorsIn.Version())
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create new tree: %w", err)
}
// Perform the migration
err = actorsIn.ForEach(func(a address.Address, actor *types.Actor) error {
newCid, ok := codeMapping[actor.Code]
if !ok {
return xerrors.Errorf("didn't find mapping for %s", actor.Code)
}
return actorsOut.SetActor(a, &types.ActorV5{
Code: newCid,
Head: actor.Head,
Nonce: actor.Nonce,
Balance: actor.Balance,
Address: actor.Address,
})
})
if err != nil {
return cid.Undef, xerrors.Errorf("failed to perform migration: %w", err)
}
systemState.BuiltinActors = newManifest.Data
newSystemHead, err := adtStore.Put(ctx, &systemState)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to put new system state: %w", err)
}
systemActor.Head = newSystemHead
if err = actorsOut.SetActor(builtin.SystemActorAddr, systemActor); err != nil {
return cid.Undef, xerrors.Errorf("failed to put new system actor: %w", err)
}
// Sanity checking
err = actorsIn.ForEach(func(a address.Address, inActor *types.Actor) error {
outActor, err := actorsOut.GetActor(a)
if err != nil {
return xerrors.Errorf("failed to get actor in outTree: %w", err)
}
if inActor.Nonce != outActor.Nonce {
return xerrors.Errorf("mismatched nonce for actor %s", a)
}
if !inActor.Balance.Equals(outActor.Balance) {
return xerrors.Errorf("mismatched balance for actor %s: %d != %d", a, inActor.Balance, outActor.Balance)
}
if inActor.Address != outActor.Address && inActor.Address.String() != outActor.Address.String() {
return xerrors.Errorf("mismatched address for actor %s: %s != %s", a, inActor.Address, outActor.Address)
}
if inActor.Head != outActor.Head && a != builtin.SystemActorAddr {
return xerrors.Errorf("mismatched head for actor %s", a)
}
// This is the hard-coded "buggy" miner actor Code ID
if inActor.Code != calibnetv12BuggyMinerCID && inActor.Code != outActor.Code {
return xerrors.Errorf("unexpected change in code for actor %s", a)
}
return nil
})
if err != nil {
return cid.Undef, xerrors.Errorf("failed to sanity check migration: %w", err)
}
// Persist the result.
newRoot, err := actorsOut.Flush(ctx)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err)
}
return newRoot, nil
}
////////////////////
// Example upgrade function if upgrade requires only code changes
//func UpgradeActorsV9(ctx context.Context, sm *stmgr.StateManager, _ stmgr.MigrationCache, _ stmgr.ExecMonitor, root cid.Cid, _ abi.ChainEpoch, _ *types.TipSet) (cid.Cid, error) {
// buf := blockstore.NewTieredBstore(sm.ChainStore().StateBlockstore(), blockstore.NewMemorySync())
+1 -1
View File
@@ -180,7 +180,7 @@ func (e *heightEventsObserver) Revert(ctx context.Context, from, to *types.TipSe
// Update the head first so we don't accidental skip reverting a concurrent call to ChainAt.
e.updateHead(to)
// Call revert on all hights between the two tipsets, handling empty tipsets.
// Call revert on all heights between the two tipsets, handling empty tipsets.
for h := from.Height(); h > to.Height(); h-- {
e.lk.Lock()
triggers := e.tsHeights[h]
+4 -4
View File
@@ -673,7 +673,7 @@ func TestCalled(t *testing.T) {
}, 3, 20, matchAddrMethod(t0123, 5))
require.NoError(t, err)
// create few blocks to make sure nothing get's randomly called
// create few blocks to make sure nothing gets randomly called
fcs.advance(0, 4, 0, nil) // H=5
require.Equal(t, false, applied)
@@ -991,7 +991,7 @@ func TestCalledNull(t *testing.T) {
}, 3, 20, matchAddrMethod(t0123, 5))
require.NoError(t, err)
// create few blocks to make sure nothing get's randomly called
// create few blocks to make sure nothing gets randomly called
fcs.advance(0, 4, 0, nil) // H=5
require.Equal(t, false, applied)
@@ -1050,7 +1050,7 @@ func TestRemoveTriggersOnMessage(t *testing.T) {
}, 3, 20, matchAddrMethod(t0123, 5))
require.NoError(t, err)
// create few blocks to make sure nothing get's randomly called
// create few blocks to make sure nothing gets randomly called
fcs.advance(0, 4, 0, nil) // H=5
require.Equal(t, false, applied)
@@ -1155,7 +1155,7 @@ func TestStateChanged(t *testing.T) {
})
require.NoError(t, err)
// create few blocks to make sure nothing get's randomly called
// create few blocks to make sure nothing gets randomly called
fcs.advance(0, 4, 0, nil) // H=5
require.Equal(t, false, applied)
+1 -1
View File
@@ -388,7 +388,7 @@ func (m *EventFilterManager) Install(ctx context.Context, minHeight, maxHeight a
if m.EventIndex != nil && minHeight != -1 && minHeight < currentHeight {
// Filter needs historic events
if err := m.EventIndex.PrefillFilter(ctx, f); err != nil {
if err := m.EventIndex.PrefillFilter(ctx, f, true); err != nil {
return nil, err
}
}
+6 -1
View File
@@ -481,7 +481,7 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
}
// PrefillFilter fills a filter's collection of events from the historic index
func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error {
func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter, excludeReverted bool) error {
clauses := []string{}
values := []any{}
joins := []string{}
@@ -500,6 +500,11 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error {
}
}
if excludeReverted {
clauses = append(clauses, "event.reverted=?")
values = append(values, false)
}
if len(f.addresses) > 0 {
subclauses := []string{}
for _, addr := range f.addresses {
+617 -1
View File
@@ -272,7 +272,7 @@ func TestEventIndexPrefillFilter(t *testing.T) {
for _, tc := range testCases {
tc := tc // appease lint
t.Run(tc.name, func(t *testing.T) {
if err := ei.PrefillFilter(context.Background(), tc.filter); err != nil {
if err := ei.PrefillFilter(context.Background(), tc.filter, false); err != nil {
require.NoError(t, err, "prefill filter events")
}
@@ -281,3 +281,619 @@ func TestEventIndexPrefillFilter(t *testing.T) {
})
}
}
func TestEventIndexPrefillFilterExcludeReverted(t *testing.T) {
rng := pseudo.New(pseudo.NewSource(299792458))
a1 := randomF4Addr(t, rng)
a2 := randomF4Addr(t, rng)
a3 := randomF4Addr(t, rng)
a1ID := abi.ActorID(1)
a2ID := abi.ActorID(2)
addrMap := addressMap{}
addrMap.add(a1ID, a1)
addrMap.add(a2ID, a2)
ev1 := fakeEvent(
a1ID,
[]kv{
{k: "type", v: []byte("approval")},
{k: "signer", v: []byte("addr1")},
},
[]kv{
{k: "amount", v: []byte("2988181")},
},
)
ev2 := fakeEvent(
a2ID,
[]kv{
{k: "type", v: []byte("approval")},
{k: "signer", v: []byte("addr2")},
},
[]kv{
{k: "amount", v: []byte("2988182")},
},
)
st := newStore()
events := []*types.Event{ev1}
revertedEvents := []*types.Event{ev2}
em := executedMessage{
msg: fakeMessage(randomF4Addr(t, rng), randomF4Addr(t, rng)),
rct: fakeReceipt(t, rng, st, events),
evs: events,
}
revertedEm := executedMessage{
msg: fakeMessage(randomF4Addr(t, rng), randomF4Addr(t, rng)),
rct: fakeReceipt(t, rng, st, revertedEvents),
evs: revertedEvents,
}
events14000 := buildTipSetEvents(t, rng, 14000, em)
revertedEvents14000 := buildTipSetEvents(t, rng, 14000, revertedEm)
cid14000, err := events14000.msgTs.Key().Cid()
require.NoError(t, err, "tipset cid")
reveredCID14000, err := revertedEvents14000.msgTs.Key().Cid()
require.NoError(t, err, "tipset cid")
noCollectedEvents := []*CollectedEvent{}
oneCollectedEvent := []*CollectedEvent{
{
Entries: ev1.Entries,
EmitterAddr: a1,
EventIdx: 0,
Reverted: false,
Height: 14000,
TipSetKey: events14000.msgTs.Key(),
MsgIdx: 0,
MsgCid: em.msg.Cid(),
},
}
twoCollectedEvent := []*CollectedEvent{
{
Entries: ev1.Entries,
EmitterAddr: a1,
EventIdx: 0,
Reverted: false,
Height: 14000,
TipSetKey: events14000.msgTs.Key(),
MsgIdx: 0,
MsgCid: em.msg.Cid(),
},
{
Entries: ev2.Entries,
EmitterAddr: a2,
EventIdx: 0,
Reverted: true,
Height: 14000,
TipSetKey: revertedEvents14000.msgTs.Key(),
MsgIdx: 0,
MsgCid: revertedEm.msg.Cid(),
},
}
oneCollectedRevertedEvent := []*CollectedEvent{
{
Entries: ev2.Entries,
EmitterAddr: a2,
EventIdx: 0,
Reverted: true,
Height: 14000,
TipSetKey: revertedEvents14000.msgTs.Key(),
MsgIdx: 0,
MsgCid: revertedEm.msg.Cid(),
},
}
workDir, err := os.MkdirTemp("", "lotusevents")
require.NoError(t, err, "create temporary work directory")
defer func() {
_ = os.RemoveAll(workDir)
}()
t.Logf("using work dir %q", workDir)
dbPath := filepath.Join(workDir, "actorevents.db")
ei, err := NewEventIndex(context.Background(), dbPath, nil)
require.NoError(t, err, "create event index")
if err := ei.CollectEvents(context.Background(), revertedEvents14000, false, addrMap.ResolveAddress); err != nil {
require.NoError(t, err, "collect reverted events")
}
if err := ei.CollectEvents(context.Background(), revertedEvents14000, true, addrMap.ResolveAddress); err != nil {
require.NoError(t, err, "revert reverted events")
}
if err := ei.CollectEvents(context.Background(), events14000, false, addrMap.ResolveAddress); err != nil {
require.NoError(t, err, "collect events")
}
inclusiveTestCases := []struct {
name string
filter *EventFilter
te *TipSetEvents
want []*CollectedEvent
}{
{
name: "nomatch tipset min height",
filter: &EventFilter{
minHeight: 14001,
maxHeight: -1,
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch tipset max height",
filter: &EventFilter{
minHeight: -1,
maxHeight: 13999,
},
te: events14000,
want: noCollectedEvents,
},
{
name: "match tipset min height",
filter: &EventFilter{
minHeight: 14000,
maxHeight: -1,
},
te: events14000,
want: twoCollectedEvent,
},
{
name: "match tipset cid",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
tipsetCid: cid14000,
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "match tipset cid",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
tipsetCid: reveredCID14000,
},
te: revertedEvents14000,
want: oneCollectedRevertedEvent,
},
{
name: "nomatch address",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
addresses: []address.Address{a3},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "match address 2",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
addresses: []address.Address{a2},
},
te: revertedEvents14000,
want: oneCollectedRevertedEvent,
},
{
name: "match address 1",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
addresses: []address.Address{a1},
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "match one entry",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
},
},
te: events14000,
want: twoCollectedEvent,
},
{
name: "match one entry with alternate values",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("cancel"),
[]byte("propose"),
[]byte("approval"),
},
},
},
te: events14000,
want: twoCollectedEvent,
},
{
name: "nomatch one entry by missing value",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("cancel"),
[]byte("propose"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry by missing key",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"method": {
[]byte("approval"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "match one entry with multiple keys",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"signer": {
[]byte("addr1"),
},
},
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "match one entry with multiple keys",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"signer": {
[]byte("addr2"),
},
},
},
te: revertedEvents14000,
want: oneCollectedRevertedEvent,
},
{
name: "nomatch one entry with one mismatching key",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"approver": {
[]byte("addr1"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry with one mismatching value",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"signer": {
[]byte("addr3"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry with one unindexed key",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"amount": {
[]byte("2988181"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry with one unindexed key",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"amount": {
[]byte("2988182"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
}
exclusiveTestCases := []struct {
name string
filter *EventFilter
te *TipSetEvents
want []*CollectedEvent
}{
{
name: "nomatch tipset min height",
filter: &EventFilter{
minHeight: 14001,
maxHeight: -1,
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch tipset max height",
filter: &EventFilter{
minHeight: -1,
maxHeight: 13999,
},
te: events14000,
want: noCollectedEvents,
},
{
name: "match tipset min height",
filter: &EventFilter{
minHeight: 14000,
maxHeight: -1,
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "match tipset cid",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
tipsetCid: cid14000,
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "match tipset cid but reverted",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
tipsetCid: reveredCID14000,
},
te: revertedEvents14000,
want: noCollectedEvents,
},
{
name: "nomatch address",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
addresses: []address.Address{a3},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch address 2 but reverted",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
addresses: []address.Address{a2},
},
te: revertedEvents14000,
want: noCollectedEvents,
},
{
name: "match address",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
addresses: []address.Address{a1},
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "match one entry",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
},
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "match one entry with alternate values",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("cancel"),
[]byte("propose"),
[]byte("approval"),
},
},
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "nomatch one entry by missing value",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("cancel"),
[]byte("propose"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry by missing key",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"method": {
[]byte("approval"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "match one entry with multiple keys",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"signer": {
[]byte("addr1"),
},
},
},
te: events14000,
want: oneCollectedEvent,
},
{
name: "nomatch one entry with one mismatching key",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"approver": {
[]byte("addr1"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry with matching reverted value",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"signer": {
[]byte("addr2"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry with one mismatching value",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"type": {
[]byte("approval"),
},
"signer": {
[]byte("addr3"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
{
name: "nomatch one entry with one unindexed key",
filter: &EventFilter{
minHeight: -1,
maxHeight: -1,
keys: map[string][][]byte{
"amount": {
[]byte("2988181"),
},
},
},
te: events14000,
want: noCollectedEvents,
},
}
for _, tc := range inclusiveTestCases {
tc := tc // appease lint
t.Run(tc.name, func(t *testing.T) {
if err := ei.PrefillFilter(context.Background(), tc.filter, false); err != nil {
require.NoError(t, err, "prefill filter events")
}
coll := tc.filter.TakeCollectedEvents(context.Background())
require.ElementsMatch(t, coll, tc.want, tc.name)
})
}
for _, tc := range exclusiveTestCases {
tc := tc // appease lint
t.Run(tc.name, func(t *testing.T) {
if err := ei.PrefillFilter(context.Background(), tc.filter, true); err != nil {
require.NoError(t, err, "prefill filter events")
}
coll := tc.filter.TakeCollectedEvents(context.Background())
require.ElementsMatch(t, coll, tc.want, tc.name)
})
}
}
+1 -1
View File
@@ -242,7 +242,7 @@ func (c *client) processResponse(req *Request, res *Response, tipsets []*types.T
// If we didn't request the headers they should have been provided
// by the caller.
if len(tipsets) < len(res.Chain) {
return nil, xerrors.Errorf("not enought tipsets provided for message response validation, needed %d, have %d", len(res.Chain), len(tipsets))
return nil, xerrors.Errorf("not enough tipsets provided for message response validation, needed %d, have %d", len(res.Chain), len(tipsets))
}
chain := make([]*BSTipSet, 0, resLength)
for i, resChain := range res.Chain {
+1 -1
View File
@@ -131,7 +131,7 @@ func NewMsgIndex(lctx context.Context, basePath string, cs ChainStore) (MsgIndex
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
// TODO [nice to have]: automaticaly delete corrupt databases
// TODO [nice to have]: automatically delete corrupt databases
// but for now we can just error and let the operator delete.
return nil, xerrors.Errorf("error opening msgindex database: %w", err)
}
+7
View File
@@ -21,6 +21,7 @@ import (
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/minio/blake2b-simd"
"github.com/raulk/clock"
"go.opencensus.io/stats"
"golang.org/x/xerrors"
ffi "github.com/filecoin-project/filecoin-ffi"
@@ -1021,6 +1022,9 @@ func (mp *MessagePool) addLocked(ctx context.Context, m *types.SignedMessage, st
}
})
// Record the current size of the Mpool
stats.Record(ctx, metrics.MpoolMessageCount.M(int64(mp.currentSize)))
return nil
}
@@ -1213,6 +1217,9 @@ func (mp *MessagePool) remove(ctx context.Context, from address.Address, nonce u
return
}
}
// Record the current size of the Mpool
stats.Record(ctx, metrics.MpoolMessageCount.M(int64(mp.currentSize)))
}
func (mp *MessagePool) Pending(ctx context.Context) ([]*types.SignedMessage, *types.TipSet) {
+2 -2
View File
@@ -570,7 +570,7 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
}
// no need to record anything here, there are no duplicates in the actors HAMT
// iself.
// itself.
if _, ok := seen[addr]; ok {
return nil
}
@@ -588,7 +588,7 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
}
// no need to record anything here, there are no duplicates in the actors HAMT
// iself.
// itself.
if _, ok := seen[addr]; ok {
return nil
}
+12 -9
View File
@@ -178,16 +178,18 @@ func (sm *StateManager) HandleStateForks(ctx context.Context, root cid.Cid, heig
retCid := root
u := sm.stateMigrations[height]
if u != nil && u.upgrade != nil {
migCid, ok, err := u.migrationResultCache.Get(ctx, root)
if err == nil {
if ok {
log.Infow("CACHED migration", "height", height, "from", root, "to", migCid)
return migCid, nil
if height != build.UpgradeWatermelonFixHeight {
migCid, ok, err := u.migrationResultCache.Get(ctx, root)
if err == nil {
if ok {
log.Infow("CACHED migration", "height", height, "from", root, "to", migCid)
return migCid, nil
}
} else if !errors.Is(err, datastore.ErrNotFound) {
log.Errorw("failed to lookup previous migration result", "err", err)
} else {
log.Debug("no cached migration found, migrating from scratch")
}
} else if !errors.Is(err, datastore.ErrNotFound) {
log.Errorw("failed to lookup previous migration result", "err", err)
} else {
log.Debug("no cached migration found, migrating from scratch")
}
startTime := time.Now()
@@ -195,6 +197,7 @@ func (sm *StateManager) HandleStateForks(ctx context.Context, root cid.Cid, heig
// Yes, we clone the cache, even for the final upgrade epoch. Why? Reverts. We may
// have to migrate multiple times.
tmpCache := u.cache.Clone()
var err error
retCid, err = u.upgrade(ctx, sm, tmpCache, cb, root, height, ts)
if err != nil {
log.Errorw("FAILED migration", "height", height, "from", root, "error", err)
+2 -7
View File
@@ -212,13 +212,8 @@ func (cs *ChainStore) MessagesForTipset(ctx context.Context, ts *types.TipSet) (
var out []types.ChainMsg
for _, bm := range bmsgs {
for _, blsm := range bm.BlsMessages {
out = append(out, blsm)
}
for _, secm := range bm.SecpkMessages {
out = append(out, secm)
}
out = append(out, bm.BlsMessages...)
out = append(out, bm.SecpkMessages...)
}
return out, nil
+2 -4
View File
@@ -167,7 +167,7 @@ func (t walkSchedTaskType) String() string {
case dagTask:
return "dag"
}
panic(fmt.Sprintf("unknow task %d", t))
panic(fmt.Sprintf("unknown task %d", t))
}
type walkTask struct {
@@ -656,9 +656,7 @@ func (cs *ChainStore) WalkSnapshot(ctx context.Context, ts *types.TipSet, inclRe
}
if b.Height > 0 {
for _, p := range b.Parents {
blocksToWalk = append(blocksToWalk, p)
}
blocksToWalk = append(blocksToWalk, b.Parents...)
} else {
// include the genesis block
cids = append(cids, b.Parents...)
+2 -2
View File
@@ -516,7 +516,7 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg
return pubsub.ValidationReject
}
if len(idxrMsg.ExtraData) == 0 {
log.Debugw("ignoring messsage missing miner id", "peer", originPeer)
log.Debugw("ignoring message missing miner id", "peer", originPeer)
return pubsub.ValidationIgnore
}
@@ -552,7 +552,7 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg
// Check that the miner ID maps to the peer that sent the message.
err = v.authenticateMessage(ctx, minerAddr, originPeer)
if err != nil {
log.Warnw("cannot authenticate messsage", "err", err, "peer", originPeer, "minerID", minerAddr)
log.Warnw("cannot authenticate message", "err", err, "peer", originPeer, "minerID", minerAddr)
stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1))
return pubsub.ValidationReject
}
+3 -3
View File
@@ -844,7 +844,7 @@ loop:
return nil, xerrors.Errorf("failed to load next local tipset: %w", err)
}
if base.IsChildOf(knownParent) {
// common case: receiving a block thats potentially part of the same tipset as our best block
// common case: receiving a block that's potentially part of the same tipset as our best block
return blockSet, nil
}
@@ -1094,8 +1094,8 @@ func (syncer *Syncer) fetchMessages(ctx context.Context, headers []*types.TipSet
requestErr = multierror.Append(requestErr, err)
} else {
isGood := true
for index, ts := range headers[nextI:lastI] {
cm := result[index]
for index, cm := range result {
ts := headers[nextI+index]
if err := checkMsgMeta(ts, cm.Bls, cm.Secpk, cm.BlsIncludes, cm.SecpkIncludes); err != nil {
log.Errorf("fetched messages not as expected: %s", err)
isGood = false
+4
View File
@@ -102,6 +102,10 @@ func (e EthBigInt) MarshalJSON() ([]byte, error) {
return json.Marshal(e.String())
}
func (e EthBigInt) ToInt() big.Int {
return (big.Int)(e)
}
func (e *EthBigInt) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
+120
View File
@@ -0,0 +1,120 @@
package ethtypes
import (
"encoding/json"
"math/big"
logger "github.com/ipfs/go-log/v2"
)
// TraceConfig holds extra parameters to trace functions.
type TraceConfig struct {
*logger.Config
Tracer *string
Timeout *string
Reexec *uint64
// Config specific to given tracer. Note struct logger
// config are historically embedded in main object.
TracerConfig json.RawMessage
}
// TraceCallConfig is the config for traceCall API. It holds one more
// field to override the state for tracing.
type TraceCallConfig struct {
TraceConfig
StateOverrides *StateOverride
BlockOverrides *BlockOverrides
}
// OverrideAccount indicates the overriding fields of account during the execution
// of a message call.
// Note, state and stateDiff can't be specified at the same time. If state is
// set, message execution will only use the data in the given state. Otherwise
// if statDiff is set, all diff will be applied first and then execute the call
// message.
type OverrideAccount struct {
Nonce *EthUint64 `json:"nonce"`
Code *EthBytes `json:"code"`
Balance **EthBigInt `json:"balance"`
State *map[EthHash]EthHash `json:"state"`
StateDiff *map[EthHash]EthHash `json:"stateDiff"`
}
// StateOverride is the collection of overridden accounts.
type StateOverride map[EthHash]OverrideAccount
// BlockOverrides is a set of header fields to override.
type BlockOverrides struct {
Number *EthBigInt
Difficulty *EthBigInt
Time *EthUint64
GasLimit *EthUint64
Coinbase *EthAddress
Random *EthHash
BaseFee *EthUint64
}
// Apply overrides the given header fields into the given block context.
func (diff *BlockOverrides) Apply(blockCtx *BlockContext) {
if diff == nil {
return
}
if diff.Number != nil {
blockCtx.BlockNumber = diff.Number.Int
}
if diff.Difficulty != nil {
blockCtx.Difficulty = diff.Difficulty.Int
}
if diff.Time != nil {
blockCtx.Time = uint64(*diff.Time)
}
if diff.GasLimit != nil {
blockCtx.GasLimit = uint64(*diff.GasLimit)
}
if diff.Coinbase != nil {
blockCtx.Coinbase = *diff.Coinbase
}
if diff.Random != nil {
blockCtx.Random = diff.Random
}
if diff.BaseFee != nil {
blockCtx.BaseFee = new(big.Int).SetUint64((uint64)(*diff.BaseFee))
}
}
type (
// CanTransferFunc is the signature of a transfer guard function
CanTransferFunc func(StateDB, EthAddress, *big.Int) bool
// TransferFunc is the signature of a transfer function
TransferFunc func(StateDB, EthAddress, EthAddress, *big.Int)
// GetHashFunc returns the n'th block hash in the blockchain
// and is used by the BLOCKHASH EVM op code.
GetHashFunc func(uint64) EthAddress
)
// BlockContext provides the EVM with auxiliary information. Once provided
// it shouldn't be modified.
type BlockContext struct {
// CanTransfer returns whether the account contains
// sufficient ether to transfer the value
CanTransfer CanTransferFunc
// Transfer transfers ether from one account to the other
Transfer TransferFunc
// GetHash returns the hash corresponding to n
GetHash GetHashFunc
// Block information
Coinbase EthAddress // Provides information for COINBASE
GasLimit uint64 // Provides information for GASLIMIT
BlockNumber *big.Int // Provides information for NUMBER
Time uint64 // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
BaseFee *big.Int // Provides information for BASEFEE
Random *EthHash // Provides information for PREVRANDAO
}
// TxTraceResult is the result of a single transaction trace.
type TxTraceResult struct {
Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
Error string `json:"error,omitempty"` // Trace failure produced by the tracer
}
+4 -4
View File
@@ -140,7 +140,7 @@ func (t *messageReceiptV0) UnmarshalCBOR(r io.Reader) (err error) {
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
return fmt.Errorf("int64 negative overflow")
}
extraI = -1 - extraI
default:
@@ -186,7 +186,7 @@ func (t *messageReceiptV0) UnmarshalCBOR(r io.Reader) (err error) {
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
return fmt.Errorf("int64 negative overflow")
}
extraI = -1 - extraI
default:
@@ -278,7 +278,7 @@ func (t *messageReceiptV1) UnmarshalCBOR(r io.Reader) (err error) {
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
return fmt.Errorf("int64 negative overflow")
}
extraI = -1 - extraI
default:
@@ -324,7 +324,7 @@ func (t *messageReceiptV1) UnmarshalCBOR(r io.Reader) (err error) {
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
return fmt.Errorf("int64 negative overflow")
}
extraI = -1 - extraI
default:
+9
View File
@@ -92,6 +92,15 @@ func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte
log.Info("invalid consensus fault: submitted blocks are the same")
return ret, totalGas
}
// workaround chain halt
if build.IsNearUpgrade(blockA.Height, build.UpgradeWatermelonFixHeight) {
return ret, totalGas
}
if build.IsNearUpgrade(blockB.Height, build.UpgradeWatermelonFixHeight) {
return ret, totalGas
}
// (1) check conditions necessary to any consensus fault
// were blocks mined by same miner?
+23 -2
View File
@@ -1920,8 +1920,29 @@ var StateSysActorCIDsCmd = &cli.Command{
if err != nil {
return err
}
for name, cid := range actorsCids {
_, _ = fmt.Fprintf(tw, "%v\t%v\n", name, cid)
var actorsCidTuples []struct {
actorName string
actorCid cid.Cid
}
for name, actorCid := range actorsCids {
keyVal := struct {
actorName string
actorCid cid.Cid
}{
actorName: name,
actorCid: actorCid,
}
actorsCidTuples = append(actorsCidTuples, keyVal)
}
sort.Slice(actorsCidTuples, func(i, j int) bool {
return actorsCidTuples[i].actorName < actorsCidTuples[j].actorName
})
for _, keyVal := range actorsCidTuples {
_, _ = fmt.Fprintf(tw, "%v\t%v\n", keyVal.actorName, keyVal.actorCid)
}
return tw.Flush()
},
+1 -1
View File
@@ -143,7 +143,7 @@ var runCmd = &cli.Command{
},
&cli.DurationFlag{
Name: "rate-limit-timeout",
Usage: "the maximum time to wait for the rate limter before returning an error to clients",
Usage: "the maximum time to wait for the rate limiter before returning an error to clients",
Value: gateway.DefaultRateLimitTimeout,
},
&cli.Int64Flag{
+8
View File
@@ -16,6 +16,7 @@ import (
"github.com/filecoin-project/go-state-types/builtin"
v10 "github.com/filecoin-project/go-state-types/builtin/v10"
v11 "github.com/filecoin-project/go-state-types/builtin/v11"
v12 "github.com/filecoin-project/go-state-types/builtin/v12"
v8 "github.com/filecoin-project/go-state-types/builtin/v8"
v9 "github.com/filecoin-project/go-state-types/builtin/v9"
@@ -149,6 +150,13 @@ var invariantsCmd = &cli.Command{
if err != nil {
return xerrors.Errorf("checking state invariants: %w", err)
}
case actorstypes.Version12:
messages, err = v12.CheckStateInvariants(actorTree, abi.ChainEpoch(epoch), actorCodeCids)
if err != nil {
return xerrors.Errorf("checking state invariants: %w", err)
}
default:
return xerrors.Errorf("unsupported actor version: %v", av)
}
fmt.Println("completed, took ", time.Since(startTime))
+14 -22
View File
@@ -12,7 +12,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
badgerbs "github.com/filecoin-project/lotus/blockstore/badger"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/node/repo"
@@ -144,13 +144,6 @@ var stateTreePruneCmd = &cli.Command{
}
}()
// After migrating to native blockstores, this has been made
// database-specific.
badgbs, ok := bs.(*badgerbs.Blockstore)
if !ok {
return fmt.Errorf("only badger blockstores are supported")
}
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
if err != nil {
return err
@@ -160,8 +153,12 @@ var stateTreePruneCmd = &cli.Command{
const DiscardRatio = 0.2
if cctx.Bool("only-ds-gc") {
fmt.Println("running datastore gc....")
gbs, ok := bs.(blockstore.BlockstoreGCOnce)
if !ok {
return xerrors.Errorf("blockstore %T does not support GC", bs)
}
for i := 0; i < cctx.Int("gc-count"); i++ {
if err := badgbs.DB().RunValueLogGC(DiscardRatio); err != nil {
if err := gbs.GCOnce(ctx, blockstore.WithThreshold(DiscardRatio)); err != nil {
return xerrors.Errorf("datastore GC failed: %w", err)
}
}
@@ -208,13 +205,6 @@ var stateTreePruneCmd = &cli.Command{
return nil
}
b := badgbs.DB().NewWriteBatch()
defer b.Cancel()
markForRemoval := func(c cid.Cid) error {
return b.Delete(badgbs.StorageKey(nil, c))
}
keys, err := bs.AllKeysChan(context.Background())
if err != nil {
return xerrors.Errorf("failed to query blockstore: %w", err)
@@ -225,12 +215,12 @@ var stateTreePruneCmd = &cli.Command{
var deleteCount int
var goodHits int
for k := range keys {
if goodSet.HasRaw(k.Bytes()) {
if goodSet.Has(k) {
goodHits++
continue
}
if err := markForRemoval(k); err != nil {
if err := bs.DeleteBlock(ctx, k); err != nil {
return fmt.Errorf("failed to remove cid %s: %w", k, err)
}
@@ -243,13 +233,15 @@ var stateTreePruneCmd = &cli.Command{
}
}
if err := b.Flush(); err != nil {
return xerrors.Errorf("failed to flush final batch delete: %w", err)
fmt.Println("running datastore gc....")
gbs, ok := bs.(blockstore.BlockstoreGCOnce)
if !ok {
fmt.Println("gc not supported...")
return nil
}
fmt.Println("running datastore gc....")
for i := 0; i < cctx.Int("gc-count"); i++ {
if err := badgbs.DB().RunValueLogGC(DiscardRatio); err != nil {
if err := gbs.GCOnce(ctx, blockstore.WithThreshold(DiscardRatio)); err != nil {
return xerrors.Errorf("datastore GC failed: %w", err)
}
}
+18 -6
View File
@@ -7,6 +7,7 @@ import (
"net"
"net/http"
"os"
"os/signal"
"path/filepath"
"reflect"
"strings"
@@ -348,6 +349,18 @@ var runCmd = &cli.Command{
// Connect to storage-miner
ctx := lcli.ReqContext(cctx)
// Create a new context with cancel function
ctx, cancel := context.WithCancel(ctx)
defer cancel()
// Listen for interrupt signals
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
cancel()
}()
var nodeApi api.StorageMiner
var closer func()
for {
@@ -359,14 +372,13 @@ var runCmd = &cli.Command{
}
}
fmt.Printf("\r\x1b[0KConnecting to miner API... (%s)", err)
time.Sleep(time.Second)
continue
select {
case <-ctx.Done():
return xerrors.New("Interrupted by user")
case <-time.After(time.Second):
}
}
defer closer()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
// Register all metric views
if err := view.Register(
metrics.DefaultViews...,
+2 -2
View File
@@ -104,9 +104,9 @@ domain separation tag.
### Winning PoSt proof
Draw randomness for current epoch with `WinningPoSt` domain separation tag.
Get list of sectors challanged in this epoch for this miner, based on the randomness drawn.
Get list of sectors challenged in this epoch for this miner, based on the randomness drawn.
`V`: Use filecoin proofs system to verify that miner prooved access to sealed versions of these sectors.
`V`: Use filecoin proofs system to verify that miner proved access to sealed versions of these sectors.
## `(*StateManager).TipSetState()`
@@ -380,21 +380,6 @@
# env var: LOTUS_FEVM_EVENTS_MAXFILTERHEIGHTRANGE
#MaxFilterHeightRange = 2880
# FilterThresholdSet signals whether a FilterThresholdEpoch is set. If it is it will be used instead of
# MaxFilterHeightRange to define the supported range.
#
# type: bool
# env var: LOTUS_FEVM_EVENTS_FILTERTHRESHOLDSET
#FilterThresholdSet = false
# FilterThresholdEpoch specifies an epoch above which the node will support returning filtered logs.
# This is useful for setting a static start epoch for support, rather than a static window size with a start epoch
# that shifts as the chain progresses.
#
# type: uint64
# env var: LOTUS_FEVM_EVENTS_FILTERTHRESHOLDEPOCH
#FilterThresholdEpoch = 2683348
# 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
+6 -3
View File
@@ -14,11 +14,13 @@
**Note for whoever is owning the release:** please capture notes as comments in this issue for anything you noticed that could be improved for future releases. There is a *Post Release* step below for incorporating changes back into the [RELEASE_ISSUE_TEMPLATE](https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md), and this is easier done by collecting notes from along the way rather than just thinking about it at the end.
First steps:
- [ ] FFI: Fork a new branch (`release/lotus-vX.Y.Z`) from the filecoin-ffi `master` branch
- [ ] FFI: Tag the head of `release/lotus-vX.Y.Z` as `vX.Y.Z-pre1`
- [ ] Set shell variables vX.Y.Z `export X=1 && export Y=24 && export Z=3`
- [ ] FFI: Fork a new branch (`release/lotus-vX.Y.Z`) from the filecoin-ffi `master` branch: `git checkout master && git checkout -b release/lotus-v$X.$Y.$Z`
- [ ] FFI: Tag the head of `release/lotus-vX.Y.Z` as `vX.Y.Z-pre1`: `git tag -a v$X.$Y.$Z-pre1 -m"release"`
- [ ] Open and land a PR in lotus `master` that updates the FFI dependency to `vX.Y.Z-pre1` as cut in the previous step
- [ ] Fork a new branch (`release/vX.Y.Z`) from `master` and make any further release related changes to this branch. If any "non-trivial" changes get added to the release, uncheck all the checkboxes and return to this stage.
- [ ] Bump the version in `build/version.go` in the `master` branch to `vX.Y.(Z+1)-dev` (bump from feature release) or `vX.(Y+1).0-dev` (bump from mandatory release). Run make gen and make docsgen-cli before committing changes
- [ ] Bump the version in `build/version.go` in the `master` branch to `vX.Y.(Z+1)-dev` (bump from feature release) or `vX.(Y+1).0-dev` (bump from mandatory release).
- [ ] Run `make gen && make docsgen-cli` before committing changes
**Prepping an RC**:
@@ -26,6 +28,7 @@ First steps:
- [ ] run `make gen && make docsgen-cli`
- [ ] Generate changelog using the script at scripts/mkreleaselog
- [ ] Add contents of generated text to lotus/CHANGELOG.md in addition to other details
- [ ] Commit using PR
- [ ] tag commit with `vX.Y.Z-rcN`
- [ ] cut a pre-release [here](https://github.com/filecoin-project/lotus/releases/new?prerelease=true)
+3
View File
@@ -146,6 +146,9 @@ type TargetAPI interface {
Web3ClientVersion(ctx context.Context) (string, error)
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
}
var _ TargetAPI = *new(api.FullNode) // gateway depends on latest
+36
View File
@@ -606,6 +606,42 @@ func (gw *Node) EthTraceReplayBlockTransactions(ctx context.Context, blkNum stri
return gw.target.EthTraceReplayBlockTransactions(ctx, blkNum, traceTypes)
}
func (gw *Node) EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkEthBlockParam(ctx, blockNrOrHash, 0); err != nil {
return nil, err
}
return gw.target.EthDebugTraceCall(ctx, args, blockNrOrHash, config)
}
func (gw *Node) EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkBlkHash(ctx, hash); err != nil {
return nil, err
}
return gw.target.EthDebugTraceBlockByHash(ctx, hash, config)
}
func (gw *Node) EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err
}
if err := gw.checkBlkParam(ctx, number, 0); err != nil {
return nil, err
}
return gw.target.EthDebugTraceBlockByNumber(ctx, number, config)
}
var EthMaxFiltersPerConn = 16 // todo make this configurable
func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, error)) (ethtypes.EthFilterID, error) {
+16 -1
View File
@@ -81,12 +81,16 @@ func TestValueTransferValidSignature(t *testing.T) {
receipt, err := waitForEthTxReceipt(ctx, client, hash)
require.NoError(t, err)
require.NotNil(t, receipt)
require.EqualValues(t, ethAddr, receipt.From)
require.EqualValues(t, ethAddr2, *receipt.To)
require.EqualValues(t, hash, receipt.TransactionHash)
// Success.
require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status)
// Validate that we sent the expected transaction.
ethTx, err := client.EthGetTransactionByHash(ctx, &hash)
require.Nil(t, err)
require.NoError(t, err)
require.EqualValues(t, ethAddr, ethTx.From)
require.EqualValues(t, ethAddr2, *ethTx.To)
require.EqualValues(t, tx.ChainID, ethTx.ChainID)
@@ -269,6 +273,17 @@ func TestContractInvocation(t *testing.T) {
// Success.
require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status)
// Validate that we correctly computed the gas outputs.
mCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash)
require.NoError(t, err)
require.NotNil(t, mCid)
invokResult, err := client.StateReplay(ctx, types.EmptyTSK, *mCid)
require.NoError(t, err)
require.EqualValues(t, invokResult.GasCost.GasUsed, big.NewInt(int64(receipt.GasUsed)))
effectiveGasPrice := big.Div(invokResult.GasCost.TotalCost, invokResult.GasCost.GasUsed)
require.EqualValues(t, effectiveGasPrice, big.Int(receipt.EffectiveGasPrice))
}
func TestGetBlockByNumber(t *testing.T) {
+6
View File
@@ -106,6 +106,7 @@ var (
MpoolAddTsDuration = stats.Float64("mpool/addts_ms", "Duration of addTs in mpool", stats.UnitMilliseconds)
MpoolAddDuration = stats.Float64("mpool/add_ms", "Duration of Add in mpool", stats.UnitMilliseconds)
MpoolPushDuration = stats.Float64("mpool/push_ms", "Duration of Push in mpool", stats.UnitMilliseconds)
MpoolMessageCount = stats.Int64("mpool/message_count", "Number of messages in the mpool", stats.UnitDimensionless)
BlockPublished = stats.Int64("block/published", "Counter for total locally published blocks", stats.UnitDimensionless)
BlockReceived = stats.Int64("block/received", "Counter for total received blocks", stats.UnitDimensionless)
BlockValidationFailure = stats.Int64("block/failure", "Counter for block validation failures", stats.UnitDimensionless)
@@ -307,6 +308,10 @@ var (
Measure: MpoolPushDuration,
Aggregation: defaultMillisecondsDistribution,
}
MpoolMessageCountView = &view.View{
Measure: MpoolMessageCount,
Aggregation: view.LastValue(),
}
PeerCountView = &view.View{
Measure: PeerCount,
Aggregation: view.LastValue(),
@@ -761,6 +766,7 @@ var ChainNodeViews = append([]*view.View{
MpoolAddTsDurationView,
MpoolAddDurationView,
MpoolPushDurationView,
MpoolMessageCountView,
PubsubPublishMessageView,
PubsubDeliverMessageView,
PubsubRejectMessageView,
+1 -1
View File
@@ -325,7 +325,7 @@ minerLoop:
"block-time", btime, "time", build.Clock.Now(), "difference", build.Clock.Since(btime))
}
if os.Getenv("LOTUS_MINER_NO_SLASHFILTER") != "_yes_i_know_i_can_and_probably_will_lose_all_my_fil_and_power_" {
if os.Getenv("LOTUS_MINER_NO_SLASHFILTER") != "_yes_i_know_i_can_and_probably_will_lose_all_my_fil_and_power_" && !build.IsNearUpgrade(base.TipSet.Height(), build.UpgradeWatermelonFixHeight) {
witness, fault, err := m.sf.MinedBlock(ctx, b.Header, base.TipSet.Height()+base.NullRounds)
if err != nil {
log.Errorf("<!!> SLASH FILTER ERRORED: %s", err)
+2
View File
@@ -90,6 +90,7 @@ const (
// health checks
CheckFDLimit
CheckFvmConcurrency
CheckUDPBufferSize
LegacyMarketsEOL
// libp2p
@@ -169,6 +170,7 @@ func defaults() []Option {
Override(CheckFDLimit, modules.CheckFdLimit(build.DefaultFDLimit)),
Override(CheckFvmConcurrency, modules.CheckFvmConcurrency()),
Override(CheckUDPBufferSize, modules.CheckUDPBufferSize(2048*1024)),
Override(new(system.MemoryConstraints), modules.MemoryConstraints),
Override(InitMemoryWatchdog, modules.MemoryWatchdog),
+1 -1
View File
@@ -69,7 +69,7 @@ func LoadBundles(ctx context.Context, bs blockstore.Blockstore, versions ...acto
)
if path, ok := build.BundleOverrides[av]; ok {
root, err = LoadBundleFromFile(ctx, bs, path)
} else if embedded, ok := build.GetEmbeddedBuiltinActorsBundle(av); ok {
} else if embedded, ok := build.GetEmbeddedBuiltinActorsBundle(av, build.NetworkBundle); ok {
root, err = LoadBundle(ctx, bs, bytes.NewReader(embedded))
} else {
err = xerrors.Errorf("bundle for actors version v%d not found", av)
+1 -3
View File
@@ -116,9 +116,7 @@ func DefaultFullNode() *FullNode {
FilterTTL: Duration(time.Hour * 24),
MaxFilters: 100,
MaxFilterResults: 10000,
MaxFilterHeightRange: 2880, // conservative limit of one day
FilterThresholdSet: false, // use MaxFilterHeightRange by default
FilterThresholdEpoch: 2683348, // FEVM start epoch
MaxFilterHeightRange: 2880, // conservative limit of one day
},
},
}
-15
View File
@@ -383,21 +383,6 @@ this time become eligible for automatic deletion.`,
Comment: `MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
the entire chain)`,
},
{
Name: "FilterThresholdSet",
Type: "bool",
Comment: `FilterThresholdSet signals whether a FilterThresholdEpoch is set. If it is it will be used instead of
MaxFilterHeightRange to define the supported range.`,
},
{
Name: "FilterThresholdEpoch",
Type: "uint64",
Comment: `FilterThresholdEpoch specifies an epoch above which the node will support returning filtered logs.
This is useful for setting a static start epoch for support, rather than a static window size with a start epoch
that shifts as the chain progresses.`,
},
{
Name: "DatabasePath",
-9
View File
@@ -717,15 +717,6 @@ type Events struct {
// the entire chain)
MaxFilterHeightRange uint64
// FilterThresholdSet signals whether a FilterThresholdEpoch is set. If it is it will be used instead of
// MaxFilterHeightRange to define the supported range.
FilterThresholdSet bool
// FilterThresholdEpoch specifies an epoch above which the node will support returning filtered logs.
// This is useful for setting a static start epoch for support, rather than a static window size with a start epoch
// that shifts as the chain progresses.
FilterThresholdEpoch uint64
// 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
+12
View File
@@ -186,5 +186,17 @@ func (e *EthModuleDummy) EthTraceReplayBlockTransactions(ctx context.Context, bl
return nil, ErrModuleDisabled
}
func (e *EthModuleDummy) EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
return nil, ErrModuleDisabled
}
func (e *EthModuleDummy) EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
return nil, ErrModuleDisabled
}
func (e *EthModuleDummy) EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error) {
return nil, ErrModuleDisabled
}
var _ EthModuleAPI = &EthModuleDummy{}
var _ EthEventAPI = &EthModuleDummy{}
+44 -54
View File
@@ -73,6 +73,9 @@ type EthModuleAPI interface {
Web3ClientVersion(ctx context.Context) (string, error)
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
}
type EthEventAPI interface {
@@ -143,8 +146,6 @@ type EthEvent struct {
FilterStore filter.FilterStore
SubManager *EthSubscriptionManager
MaxFilterHeightRange abi.ChainEpoch
FilterThresholdSet bool
FilterThresholdEpoch abi.ChainEpoch
SubscribtionCtx context.Context
}
@@ -399,26 +400,31 @@ func (a *EthModule) EthGetTransactionReceiptLimited(ctx context.Context, txHash
}
msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, c, limit, true)
if err != nil || msgLookup == nil {
if err != nil {
return nil, xerrors.Errorf("failed to lookup Eth Txn %s as %s: %w", txHash, c, err)
}
if msgLookup == nil {
// This is the best we can do. In theory, we could have just not indexed this
// transaction, but there's no way to check that here.
return nil, nil
}
tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI)
if err != nil {
return nil, nil
return nil, xerrors.Errorf("failed to convert %s into an Eth Txn: %w", txHash, err)
}
var events []types.Event
if rct := msgLookup.Receipt; rct.EventsRoot != nil {
events, err = a.ChainAPI.ChainGetEvents(ctx, *rct.EventsRoot)
if err != nil {
return nil, nil
return nil, xerrors.Errorf("failed get events for %s", txHash)
}
}
receipt, err := newEthTxReceipt(ctx, tx, msgLookup, events, a.Chain, a.StateAPI)
if err != nil {
return nil, nil
return nil, xerrors.Errorf("failed to convert %s into an Eth Receipt: %w", txHash, err)
}
return &receipt, nil
@@ -730,10 +736,11 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (eth
}
rewards, totalGasUsed := calculateRewardsAndGasUsed(rewardPercentiles, txGasRewards)
maxGas := build.BlockGasLimit * int64(len(ts.Blocks()))
// arrays should be reversed at the end
baseFeeArray = append(baseFeeArray, ethtypes.EthBigInt(basefee))
gasUsedRatioArray = append(gasUsedRatioArray, float64(totalGasUsed)/float64(build.BlockGasLimit))
gasUsedRatioArray = append(gasUsedRatioArray, float64(totalGasUsed)/float64(maxGas))
rewardsArray = append(rewardsArray, rewards)
oldestBlkHeight = uint64(ts.Height())
blocksIncluded++
@@ -944,10 +951,7 @@ func (a *EthModule) EthTraceReplayBlockTransactions(ctx context.Context, blkNum
return nil, xerrors.Errorf("failed to decode payload: %w", err)
}
} else {
output, err = handleFilecoinMethodOutput(ir.ExecutionTrace.MsgRct.ExitCode, ir.ExecutionTrace.MsgRct.ReturnCodec, ir.ExecutionTrace.MsgRct.Return)
if err != nil {
return nil, xerrors.Errorf("could not convert output: %w", err)
}
output = encodeFilecoinReturnAsABI(ir.ExecutionTrace.MsgRct.ExitCode, ir.ExecutionTrace.MsgRct.ReturnCodec, ir.ExecutionTrace.MsgRct.Return)
}
t := ethtypes.EthTraceReplayBlockTransaction{
@@ -968,6 +972,18 @@ func (a *EthModule) EthTraceReplayBlockTransactions(ctx context.Context, blkNum
return allTraces, nil
}
func (a *EthModule) EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error) {
panic("implement me")
}
func (a *EthModule) EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
panic("implement me")
}
func (a *EthModule) EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
panic("implement me")
}
func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (res *api.InvocResult, err error) {
ts, err := a.Chain.GetTipSetFromKey(ctx, tsk)
if err != nil {
@@ -1294,53 +1310,27 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype
}
// Validate height ranges are within limits set by node operator
if e.FilterThresholdSet {
if minHeight == -1 && maxHeight > 0 {
// Here the client is looking for events between the head and some future height
ts := e.Chain.GetHeaviestTipSet()
if maxHeight < ts.Height() {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, ts.Height())
}
if ts.Height() < e.FilterThresholdEpoch {
return nil, xerrors.Errorf("invalid epoch range: from block (%d) is below the set FilterThresholdEpoch (%d)", ts.Height(), e.FilterThresholdEpoch)
}
} else if minHeight >= 0 && maxHeight == -1 {
// Here the client is looking for events between some time in the past and the current head
if minHeight < e.FilterThresholdEpoch {
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (minimum from epoch: %d)", e.FilterThresholdEpoch)
}
} else if minHeight >= 0 && maxHeight >= 0 {
if minHeight > maxHeight {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, minHeight)
} else if minHeight < e.FilterThresholdEpoch {
return nil, xerrors.Errorf("invalid epoch range: from block (%d) is below the set FilterThresholdEpoch (%d)", minHeight, e.FilterThresholdEpoch)
}
if minHeight == -1 && maxHeight > 0 {
// Here the client is looking for events between the head and some future height
ts := e.Chain.GetHeaviestTipSet()
if maxHeight-ts.Height() > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: to block is too far in the future (maximum: %d)", e.MaxFilterHeightRange)
}
} else if minHeight >= 0 && maxHeight == -1 {
// Here the client is looking for events between some time in the past and the current head
ts := e.Chain.GetHeaviestTipSet()
if ts.Height()-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (maximum: %d)", e.MaxFilterHeightRange)
}
} else {
if minHeight == -1 && maxHeight > 0 {
// Here the client is looking for events between the head and some future height
ts := e.Chain.GetHeaviestTipSet()
if maxHeight < ts.Height() {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, ts.Height())
}
if maxHeight-ts.Height() > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: to block is too far in the future (maximum: %d)", e.MaxFilterHeightRange)
}
} else if minHeight >= 0 && maxHeight == -1 {
// Here the client is looking for events between some time in the past and the current head
ts := e.Chain.GetHeaviestTipSet()
if ts.Height()-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (maximum: %d)", e.MaxFilterHeightRange)
}
} else if minHeight >= 0 && maxHeight >= 0 {
if minHeight > maxHeight {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, minHeight)
} else if maxHeight-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: range between to and from blocks is too large (maximum: %d)", e.MaxFilterHeightRange)
}
} else if minHeight >= 0 && maxHeight >= 0 {
if minHeight > maxHeight {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", minHeight, maxHeight)
} else if maxHeight-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: range between to and from blocks is too large (maximum: %d)", e.MaxFilterHeightRange)
}
}
}
// Convert all addresses to filecoin f4 addresses
+15
View File
@@ -1,6 +1,7 @@
package full
import (
"encoding/hex"
"testing"
"github.com/ipfs/go-cid"
@@ -162,3 +163,17 @@ func TestRewardPercentiles(t *testing.T) {
require.Equal(t, ans, rewards)
}
}
func TestABIEncoding(t *testing.T) {
// Generated from https://abi.hashex.org/
const expected = "000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001b1111111111111111111020200301000000044444444444444444010000000000"
const data = "111111111111111111102020030100000004444444444444444401"
expectedBytes, err := hex.DecodeString(expected)
require.NoError(t, err)
dataBytes, err := hex.DecodeString(data)
require.NoError(t, err)
require.Equal(t, expectedBytes, encodeAsABIHelper(22, 81, dataBytes))
}
+2 -106
View File
@@ -3,18 +3,13 @@ package full
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"io"
"github.com/multiformats/go-multicodec"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/builtin/v10/evm"
"github.com/filecoin-project/go-state-types/exitcode"
builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
@@ -124,14 +119,8 @@ func buildTraces(ctx context.Context, traces *[]*ethtypes.EthTrace, parent *etht
} else {
// we are going to assume a native method, but we may change it in one of the edge cases below
// TODO: only do this if we know it's a native method (optimization)
trace.Action.Input, err = handleFilecoinMethodInput(et.Msg.Method, et.Msg.ParamsCodec, et.Msg.Params)
if err != nil {
return xerrors.Errorf("buildTraces: %w", err)
}
trace.Result.Output, err = handleFilecoinMethodOutput(et.MsgRct.ExitCode, et.MsgRct.ReturnCodec, et.MsgRct.Return)
if err != nil {
return xerrors.Errorf("buildTraces: %w", err)
}
trace.Action.Input = encodeFilecoinParamsAsABI(et.Msg.Method, et.Msg.ParamsCodec, et.Msg.Params)
trace.Result.Output = encodeFilecoinReturnAsABI(et.MsgRct.ExitCode, et.MsgRct.ReturnCodec, et.MsgRct.Return)
}
// TODO: is it OK to check this here or is this only specific to certain edge case (evm to evm)?
@@ -258,96 +247,3 @@ func buildTraces(ctx context.Context, traces *[]*ethtypes.EthTrace, parent *etht
return nil
}
func writePadded(w io.Writer, data any, size int) error {
tmp := &bytes.Buffer{}
// first write data to tmp buffer to get the size
err := binary.Write(tmp, binary.BigEndian, data)
if err != nil {
return fmt.Errorf("writePadded: failed writing tmp data to buffer: %w", err)
}
if tmp.Len() > size {
return fmt.Errorf("writePadded: data is larger than size")
}
// write tailing zeros to pad up to size
cnt := size - tmp.Len()
for i := 0; i < cnt; i++ {
err = binary.Write(w, binary.BigEndian, uint8(0))
if err != nil {
return fmt.Errorf("writePadded: failed writing tailing zeros to buffer: %w", err)
}
}
// finally write the actual value
err = binary.Write(w, binary.BigEndian, tmp.Bytes())
if err != nil {
return fmt.Errorf("writePadded: failed writing data to buffer: %w", err)
}
return nil
}
func handleFilecoinMethodInput(method abi.MethodNum, codec uint64, params []byte) ([]byte, error) {
NATIVE_METHOD_SELECTOR := []byte{0x86, 0x8e, 0x10, 0xc4}
EVM_WORD_SIZE := 32
staticArgs := []uint64{
uint64(method),
codec,
uint64(EVM_WORD_SIZE) * 3,
uint64(len(params)),
}
totalWords := len(staticArgs) + (len(params) / EVM_WORD_SIZE)
if len(params)%EVM_WORD_SIZE != 0 {
totalWords++
}
len := 4 + totalWords*EVM_WORD_SIZE
w := &bytes.Buffer{}
err := binary.Write(w, binary.BigEndian, NATIVE_METHOD_SELECTOR)
if err != nil {
return nil, fmt.Errorf("handleFilecoinMethodInput: failed writing method selector: %w", err)
}
for _, arg := range staticArgs {
err := writePadded(w, arg, 32)
if err != nil {
return nil, fmt.Errorf("handleFilecoinMethodInput: %w", err)
}
}
err = binary.Write(w, binary.BigEndian, params)
if err != nil {
return nil, fmt.Errorf("handleFilecoinMethodInput: failed writing params: %w", err)
}
remain := len - w.Len()
for i := 0; i < remain; i++ {
err = binary.Write(w, binary.BigEndian, uint8(0))
if err != nil {
return nil, fmt.Errorf("handleFilecoinMethodInput: failed writing tailing zeros: %w", err)
}
}
return w.Bytes(), nil
}
func handleFilecoinMethodOutput(exitCode exitcode.ExitCode, codec uint64, data []byte) ([]byte, error) {
w := &bytes.Buffer{}
values := []interface{}{uint32(exitCode), codec, uint32(w.Len()), uint32(len(data))}
for _, v := range values {
err := writePadded(w, v, 32)
if err != nil {
return nil, fmt.Errorf("handleFilecoinMethodOutput: %w", err)
}
}
err := binary.Write(w, binary.BigEndian, data)
if err != nil {
return nil, fmt.Errorf("handleFilecoinMethodOutput: failed writing data: %w", err)
}
return w.Bytes(), nil
}
+51 -1
View File
@@ -3,6 +3,7 @@ package full
import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
@@ -15,6 +16,7 @@ import (
builtintypes "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/builtin/v10/eam"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
@@ -627,7 +629,13 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", lookup.TipSet, err)
}
baseFee := ts.Blocks()[0].ParentBaseFee
// The tx is located in the parent tipset
parentTs, err := cs.LoadTipSet(ctx, ts.Parents())
if err != nil {
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", ts.Parents(), err)
}
baseFee := parentTs.Blocks()[0].ParentBaseFee
gasOutputs := vm.ComputeGasOutputs(lookup.Receipt.GasUsed, int64(tx.Gas), baseFee, big.Int(tx.MaxFeePerGas), big.Int(tx.MaxPriorityFeePerGas), true)
totalSpent := big.Sum(gasOutputs.BaseFeeBurn, gasOutputs.MinerTip, gasOutputs.OverEstimationBurn)
@@ -688,3 +696,45 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
return receipt, nil
}
func encodeFilecoinParamsAsABI(method abi.MethodNum, codec uint64, params []byte) []byte {
buf := []byte{0x86, 0x8e, 0x10, 0xc4} // Native method selector.
return append(buf, encodeAsABIHelper(uint64(method), codec, params)...)
}
func encodeFilecoinReturnAsABI(exitCode exitcode.ExitCode, codec uint64, data []byte) []byte {
return encodeAsABIHelper(uint64(exitCode), codec, data)
}
// Format 2 numbers followed by an arbitrary byte array as solidity ABI. Both our native
// inputs/outputs follow the same pattern, so we can reuse this code.
func encodeAsABIHelper(param1 uint64, param2 uint64, data []byte) []byte {
const EVM_WORD_SIZE = 32
// The first two params are "static" numbers. Then, we record the offset of the "data" arg,
// then, at that offset, we record the length of the data.
//
// In practice, this means we have 4 256-bit words back to back where the third arg (the
// offset) is _always_ '32*3'.
staticArgs := []uint64{param1, param2, EVM_WORD_SIZE * 3, uint64(len(data))}
// We always pad out to the next EVM "word" (32 bytes).
totalWords := len(staticArgs) + (len(data) / EVM_WORD_SIZE)
if len(data)%EVM_WORD_SIZE != 0 {
totalWords++
}
len := totalWords * EVM_WORD_SIZE
buf := make([]byte, len)
offset := 0
// Below, we use copy instead of "appending" to preserve all the zero padding.
for _, arg := range staticArgs {
// Write each "arg" into the last 8 bytes of each 32 byte word.
offset += EVM_WORD_SIZE
start := offset - 8
binary.BigEndian.PutUint64(buf[start:offset], arg)
}
// Finally, we copy in the data.
copy(buf[offset:], data)
return buf
}
+1 -1
View File
@@ -57,7 +57,7 @@ func (a *SyncAPI) SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) erro
return xerrors.Errorf("loading parent block: %w", err)
}
if a.SlashFilter != nil && os.Getenv("LOTUS_NO_SLASHFILTER") != "_yes_i_know_i_can_and_probably_will_lose_all_my_fil_and_power_" {
if a.SlashFilter != nil && os.Getenv("LOTUS_NO_SLASHFILTER") != "_yes_i_know_i_can_and_probably_will_lose_all_my_fil_and_power_" && !build.IsNearUpgrade(blk.Header.Height, build.UpgradeWatermelonFixHeight) {
witness, fault, err := a.SlashFilter.MinedBlock(ctx, blk.Header, parent.Height)
if err != nil {
log.Errorf("<!!> SLASH FILTER ERRORED: %s", err)
+2 -12
View File
@@ -336,19 +336,9 @@ func (sm *StorageMinerAPI) SectorsListInStates(ctx context.Context, states []api
return sns, nil
}
// Use SectorsSummary from stats (prometheus) for faster result
func (sm *StorageMinerAPI) SectorsSummary(ctx context.Context) (map[api.SectorState]int, error) {
sectors, err := sm.Miner.ListSectors()
if err != nil {
return nil, err
}
out := make(map[api.SectorState]int)
for i := range sectors {
state := api.SectorState(sectors[i].State)
out[state]++
}
return out, nil
return sm.Miner.SectorsSummary(ctx), nil
}
func (sm *StorageMinerAPI) StorageLocal(ctx context.Context) (map[storiface.ID]string, error) {
-2
View File
@@ -40,8 +40,6 @@ func EthEventAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo
ee := &full.EthEvent{
Chain: cs,
MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange),
FilterThresholdSet: cfg.Events.FilterThresholdSet,
FilterThresholdEpoch: abi.ChainEpoch(cfg.Events.FilterThresholdEpoch),
SubscribtionCtx: ctx,
}
+65
View File
@@ -1,8 +1,10 @@
package modules
import (
"net"
"os"
"strconv"
"syscall"
"github.com/filecoin-project/lotus/journal/alerting"
"github.com/filecoin-project/lotus/lib/ulimit"
@@ -35,6 +37,69 @@ func CheckFdLimit(min uint64) func(al *alerting.Alerting) {
}
}
func CheckUDPBufferSize(wanted int) func(al *alerting.Alerting) {
return func(al *alerting.Alerting) {
conn, err := net.Dial("udp", "localhost:0")
if err != nil {
alert := al.AddAlertType("process", "udp-buffer-size")
al.Raise(alert, map[string]string{
"message": "Failed to create UDP connection",
"error": err.Error(),
})
return
}
defer func() {
if err := conn.Close(); err != nil {
log.Warnf("Failed to close connection: %s", err)
}
}()
udpConn, ok := conn.(*net.UDPConn)
if !ok {
alert := al.AddAlertType("process", "udp-buffer-size")
al.Raise(alert, map[string]string{
"message": "Failed to cast connection to UDPConn",
})
return
}
file, err := udpConn.File()
if err != nil {
alert := al.AddAlertType("process", "udp-buffer-size")
al.Raise(alert, map[string]string{
"message": "Failed to get file descriptor from UDPConn",
"error": err.Error(),
})
return
}
defer func() {
if err := file.Close(); err != nil {
log.Warnf("Failed to close file: %s", err)
}
}()
size, err := syscall.GetsockoptInt(int(file.Fd()), syscall.SOL_SOCKET, syscall.SO_RCVBUF)
if err != nil {
alert := al.AddAlertType("process", "udp-buffer-size")
al.Raise(alert, map[string]string{
"message": "Failed to get UDP buffer size",
"error": err.Error(),
})
return
}
if size < wanted {
alert := al.AddAlertType("process", "udp-buffer-size")
al.Raise(alert, map[string]interface{}{
"message": "UDP buffer size is low",
"current_size": size,
"wanted_size": wanted,
"help": "See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details.",
})
}
}
}
func LegacyMarketsEOL(al *alerting.Alerting) {
// Add alert if lotus-miner legacy markets subsystem is still in use
alert := al.AddAlertType("system", "EOL")
+1 -1
View File
@@ -482,7 +482,7 @@ func (ca *channelAccessor) listVouchers(ctx context.Context, ch address.Address)
// the data store over the chain state
func (ca *channelAccessor) laneState(ctx context.Context, state lpaych.State, ch address.Address) (map[uint64]lpaych.LaneState, error) {
// TODO: we probably want to call UpdateChannelState with all vouchers to be fully correct
// (but technically dont't need to)
// (but technically don't need to)
laneCount, err := state.LaneCount()
if err != nil {
+14
View File
@@ -304,6 +304,20 @@ func (m *Sealing) TerminateSector(ctx context.Context, sid abi.SectorNumber) err
return m.sectors.Send(uint64(sid), SectorTerminate{})
}
func (m *Sealing) SectorsSummary(ctx context.Context) map[api.SectorState]int {
m.stats.lk.Lock()
defer m.stats.lk.Unlock()
out := make(map[api.SectorState]int)
for st, count := range m.stats.byState {
state := api.SectorState(st)
out[state] = int(count)
}
return out
}
func (m *Sealing) TerminateFlush(ctx context.Context) (*cid.Cid, error) {
return m.terminator.Flush(ctx)
}
+1 -1
View File
@@ -928,7 +928,7 @@ func (sb *Sealer) SealPreCommit2(ctx context.Context, sector storiface.SectorRef
return storiface.SectorCids{}, xerrors.Errorf("generate synth proofs: %w", err)
}
if err = ffi.ClearLayerData(ssize, paths.Cache); err != nil {
if err = ffi.ClearCache(uint64(ssize), paths.Cache); err != nil {
log.Warn("failed to GenerateSynthProofs(): ", err)
log.Warnf("num:%d tkt:%v, sealedCID:%v, unsealedCID:%v", sector.ID.Number, ticket, sealedCID, unsealedCID)
return storiface.SectorCids{