diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f6fd69a2..5281c3315 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,14 @@ ## Improvements -# v1.28.0-rc2 / 2024-07-04 +# v1.28.0-rc3 / 2024-07-04 -This is the second release candidate of the upcoming MANDATORY Lotus v1.28.0 release, which will deliver the Filecoin network version 23, codenamed Waffle 🧇. +This is the third release candidate of the upcoming MANDATORY Lotus v1.28.0 release, which will deliver the Filecoin network version 23, codenamed Waffle 🧇. **This release candidate sets the calibration network to upgrade at epoch 1779094, corresponding to 2024-07-11T12:00:00Z.** This release does NOT set the mainnet upgrade epoch yet, in which will be updated in the final release. +Compared to `Lotus v1.28.0-rc2`, the `Lotus v1.28.0-rc3` introduces the manifest for the "control" nodes for F3 passive testing. This change shouldn't have any impact on production nodes. + ☢️ Upgrade Warnings ☢️ If you are running the `v1.26.0` or an earlier version of Lotus, please go through the `Upgrade Warnings` section for the `v1.27.*` releases, before upgrading to this RC. @@ -90,7 +92,7 @@ For certain node operators, such as full archival nodes or systems that need to - Ignore market balance after nv23 (https://github.com/filecoin-project/lotus/pull/11976) - Add finality-related params for `eth_getBlockByNumber` (https://github.com/filecoin-project/lotus/pull/12110) - rename `Actor.Address` to `Actor.DelegatedAddress` and only use it for f4 addresses (https://github.com/filecoin-project/lotus/pull/12155) - +- feat:ec: integrate F3 dynamic manifest #12185 # v1.27.1 / 2024-06-24 diff --git a/build/openrpc/full.json b/build/openrpc/full.json index c2a69e8eb..3c235358c 100644 --- a/build/openrpc/full.json +++ b/build/openrpc/full.json @@ -2,7 +2,7 @@ "openrpc": "1.2.6", "info": { "title": "Lotus RPC API", - "version": "1.28.0-rc2" + "version": "1.28.0-rc3" }, "methods": [ { diff --git a/build/openrpc/gateway.json b/build/openrpc/gateway.json index 3cfaff6b6..fa68c9eed 100644 --- a/build/openrpc/gateway.json +++ b/build/openrpc/gateway.json @@ -2,7 +2,7 @@ "openrpc": "1.2.6", "info": { "title": "Lotus RPC API", - "version": "1.28.0-rc2" + "version": "1.28.0-rc3" }, "methods": [ { diff --git a/build/openrpc/miner.json b/build/openrpc/miner.json index 5becb021f..d323e9f46 100644 --- a/build/openrpc/miner.json +++ b/build/openrpc/miner.json @@ -2,7 +2,7 @@ "openrpc": "1.2.6", "info": { "title": "Lotus RPC API", - "version": "1.28.0-rc2" + "version": "1.28.0-rc3" }, "methods": [ { diff --git a/build/openrpc/worker.json b/build/openrpc/worker.json index bfa3734d8..046dedb2a 100644 --- a/build/openrpc/worker.json +++ b/build/openrpc/worker.json @@ -2,7 +2,7 @@ "openrpc": "1.2.6", "info": { "title": "Lotus RPC API", - "version": "1.28.0-rc2" + "version": "1.28.0-rc3" }, "methods": [ { diff --git a/build/params_2k.go b/build/params_2k.go index c1c132cda..8ac5ab569 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -190,4 +190,5 @@ const Eip155ChainId = 31415926 var WhitelistedBlock = cid.Undef const f3Enabled = true +const ManifestServerID = "12D3KooWHcNBkqXEBrsjoveQvj6zDF3vK5S9tAfqyYaQF1LGSJwG" const F3BootstrapEpoch abi.ChainEpoch = 100 diff --git a/build/params_butterfly.go b/build/params_butterfly.go index 118c7b108..124d0b298 100644 --- a/build/params_butterfly.go +++ b/build/params_butterfly.go @@ -107,4 +107,5 @@ const Eip155ChainId = 3141592 var WhitelistedBlock = cid.Undef const f3Enabled = true +const ManifestServerID = "12D3KooWJr9jy4ngtJNR7JC1xgLFra3DjEtyxskRYWvBK9TC3Yn6" const F3BootstrapEpoch abi.ChainEpoch = 200 diff --git a/build/params_calibnet.go b/build/params_calibnet.go index b6cb730c7..b2232c046 100644 --- a/build/params_calibnet.go +++ b/build/params_calibnet.go @@ -153,4 +153,5 @@ const Eip155ChainId = 314159 var WhitelistedBlock = cid.Undef const f3Enabled = true +const ManifestServerID = "12D3KooWS9vD9uwm8u2uPyJV32QBAhKAmPYwmziAgr3Xzk2FU1Mr" const F3BootstrapEpoch abi.ChainEpoch = UpgradeWaffleHeight + 100 diff --git a/build/params_interop.go b/build/params_interop.go index 8742e635e..fefe9b5b7 100644 --- a/build/params_interop.go +++ b/build/params_interop.go @@ -146,4 +146,5 @@ const Eip155ChainId = 3141592 var WhitelistedBlock = cid.Undef const f3Enabled = true +const ManifestServerID = "12D3KooWQJ2rdVnG4okDUB6yHQhAjNutGNemcM7XzqC9Eo4z9Jce" const F3BootstrapEpoch abi.ChainEpoch = 1000 diff --git a/build/params_mainnet.go b/build/params_mainnet.go index 5da53b15a..e99fc89a5 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -170,4 +170,5 @@ const Eip155ChainId = 314 var WhitelistedBlock = MustParseCid("bafy2bzaceapyg2uyzk7vueh3xccxkuwbz3nxewjyguoxvhx77malc2lzn2ybi") const f3Enabled = false +const ManifestServerID = "12D3KooWENMwUF9YxvQxar7uBWJtZkA6amvK4xWmKXfSiHUo2Qq7" const F3BootstrapEpoch abi.ChainEpoch = -1 diff --git a/build/version.go b/build/version.go index 174f9635f..ab7d743f9 100644 --- a/build/version.go +++ b/build/version.go @@ -39,7 +39,7 @@ func BuildTypeString() string { } // NodeBuildVersion is the local build version of the Lotus daemon -const NodeBuildVersion string = "1.28.0-rc2" +const NodeBuildVersion string = "1.28.0-rc3" func NodeUserVersion() BuildVersion { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { @@ -50,7 +50,7 @@ func NodeUserVersion() BuildVersion { } // MinerBuildVersion is the local build version of the Lotus miner -const MinerBuildVersion = "1.28.0-rc2" +const MinerBuildVersion = "1.28.0-rc3" func MinerUserVersion() BuildVersion { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/chain/lf3/ec.go b/chain/lf3/ec.go index c3feb0b4e..910057442 100644 --- a/chain/lf3/ec.go +++ b/chain/lf3/ec.go @@ -8,7 +8,7 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-f3" + "github.com/filecoin-project/go-f3/ec" "github.com/filecoin-project/go-f3/gpbft" "github.com/filecoin-project/go-state-types/abi" @@ -23,7 +23,6 @@ import ( type ecWrapper struct { ChainStore *store.ChainStore StateManager *stmgr.StateManager - Manifest f3.Manifest } type f3TipSet types.TipSet @@ -57,7 +56,7 @@ func (ts *f3TipSet) Timestamp() time.Time { return time.Unix(int64(ts.cast().Blocks()[0].Timestamp), 0) } -func wrapTS(ts *types.TipSet) f3.TipSet { +func wrapTS(ts *types.TipSet) ec.TipSet { if ts == nil { return nil } @@ -66,7 +65,7 @@ func wrapTS(ts *types.TipSet) f3.TipSet { // GetTipsetByEpoch should return a tipset before the one requested if the requested // tipset does not exist due to null epochs -func (ec *ecWrapper) GetTipsetByEpoch(ctx context.Context, epoch int64) (f3.TipSet, error) { +func (ec *ecWrapper) GetTipsetByEpoch(ctx context.Context, epoch int64) (ec.TipSet, error) { ts, err := ec.ChainStore.GetTipsetByHeight(ctx, abi.ChainEpoch(epoch), nil, true) if err != nil { return nil, xerrors.Errorf("getting tipset by height: %w", err) @@ -74,7 +73,7 @@ func (ec *ecWrapper) GetTipsetByEpoch(ctx context.Context, epoch int64) (f3.TipS return wrapTS(ts), nil } -func (ec *ecWrapper) GetTipset(ctx context.Context, tsk gpbft.TipSetKey) (f3.TipSet, error) { +func (ec *ecWrapper) GetTipset(ctx context.Context, tsk gpbft.TipSetKey) (ec.TipSet, error) { tskLotus, err := types.TipSetKeyFromBytes(tsk) if err != nil { return nil, xerrors.Errorf("decoding tsk: %w", err) @@ -88,16 +87,16 @@ func (ec *ecWrapper) GetTipset(ctx context.Context, tsk gpbft.TipSetKey) (f3.Tip return wrapTS(ts), nil } -func (ec *ecWrapper) GetHead(_ context.Context) (f3.TipSet, error) { +func (ec *ecWrapper) GetHead(_ context.Context) (ec.TipSet, error) { return wrapTS(ec.ChainStore.GetHeaviestTipSet()), nil } -func (ec *ecWrapper) GetParent(ctx context.Context, tsF3 f3.TipSet) (f3.TipSet, error) { +func (ec *ecWrapper) GetParent(ctx context.Context, tsF3 ec.TipSet) (ec.TipSet, error) { var ts *types.TipSet if tsW, ok := tsF3.(*f3TipSet); ok { ts = tsW.cast() } else { - // There are only two implementations of F3.TipSet: f3TipSet, and one in fake EC + // There are only two implementations of ec.TipSet: f3TipSet, and one in fake EC // backend. // // TODO: Revisit the type check here and remove as needed once testing diff --git a/chain/lf3/f3.go b/chain/lf3/f3.go index bf17118cc..0449bf8dd 100644 --- a/chain/lf3/f3.go +++ b/chain/lf3/f3.go @@ -3,13 +3,13 @@ package lf3 import ( "context" "errors" - "time" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" logging "github.com/ipfs/go-log/v2" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/peer" "go.uber.org/fx" "golang.org/x/xerrors" @@ -17,6 +17,7 @@ import ( "github.com/filecoin-project/go-f3/blssig" "github.com/filecoin-project/go-f3/certs" "github.com/filecoin-project/go-f3/gpbft" + "github.com/filecoin-project/go-f3/manifest" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -35,39 +36,39 @@ type F3 struct { type F3Params struct { fx.In - NetworkName dtypes.NetworkName - PubSub *pubsub.PubSub - Host host.Host - ChainStore *store.ChainStore - StateManager *stmgr.StateManager - Datastore dtypes.MetadataDS - Wallet api.Wallet + NetworkName dtypes.NetworkName + ManifestProvider manifest.ManifestProvider + PubSub *pubsub.PubSub + Host host.Host + ChainStore *store.ChainStore + StateManager *stmgr.StateManager + Datastore dtypes.MetadataDS + Wallet api.Wallet } var log = logging.Logger("f3") func New(mctx helpers.MetricsCtx, lc fx.Lifecycle, params F3Params) (*F3, error) { - manifest := f3.LocalnetManifest() - manifest.NetworkName = gpbft.NetworkName(params.NetworkName) - manifest.ECDelay = 2 * time.Duration(build.BlockDelaySecs) * time.Second - manifest.ECPeriod = manifest.ECDelay - manifest.BootstrapEpoch = int64(build.F3BootstrapEpoch) - manifest.ECFinality = int64(build.Finality) ds := namespace.Wrap(params.Datastore, datastore.NewKey("/f3")) ec := &ecWrapper{ ChainStore: params.ChainStore, StateManager: params.StateManager, - Manifest: manifest, } verif := blssig.VerifierWithKeyOnG1() - module, err := f3.New(mctx, manifest, ds, - params.Host, params.PubSub, verif, ec, log, nil) + senderID, err := peer.Decode(build.ManifestServerID) + if err != nil { + return nil, xerrors.Errorf("decoding F3 manifest server identity: %w", err) + } + + module, err := f3.New(mctx, params.ManifestProvider, ds, + params.Host, senderID, params.PubSub, verif, ec, log, nil) if err != nil { return nil, xerrors.Errorf("creating F3: %w", err) } + params.ManifestProvider.SetManifestChangeCallback(f3.ManifestChangeCallback(module)) fff := &F3{ inner: module, diff --git a/chain/lf3/manifest.go b/chain/lf3/manifest.go new file mode 100644 index 000000000..7a658b6cf --- /dev/null +++ b/chain/lf3/manifest.go @@ -0,0 +1,39 @@ +package lf3 + +import ( + "time" + + pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p/core/peer" + + "github.com/filecoin-project/go-f3/gpbft" + "github.com/filecoin-project/go-f3/manifest" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/stmgr" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/node/modules/dtypes" +) + +func NewManifestProvider(nn dtypes.NetworkName, cs *store.ChainStore, sm *stmgr.StateManager, ps *pubsub.PubSub) manifest.ManifestProvider { + m := manifest.LocalDevnetManifest() + m.NetworkName = gpbft.NetworkName(nn) + m.ECDelay = 2 * time.Duration(build.BlockDelaySecs) * time.Second + m.ECPeriod = m.ECDelay + m.BootstrapEpoch = int64(build.F3BootstrapEpoch) + m.ECFinality = int64(build.Finality) + m.CommiteeLookback = 5 + + ec := &ecWrapper{ + ChainStore: cs, + StateManager: sm, + } + + switch manifestServerID, err := peer.Decode(build.ManifestServerID); { + case err != nil: + log.Warnw("Cannot decode F3 manifest sever identity; falling back on static manifest provider", "err", err) + return manifest.NewStaticManifestProvider(m) + default: + return manifest.NewDynamicManifestProvider(m, ps, ec, manifestServerID) + } +} diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 2356908ca..61325c9f6 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.28.0-rc2 + 1.28.0-rc3 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index 345977dc0..02cc8801b 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.28.0-rc2 + 1.28.0-rc3 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 5f240488e..d7fdc3a2f 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.28.0-rc2 + 1.28.0-rc3 COMMANDS: daemon Start a lotus daemon process diff --git a/go.mod b/go.mod index 1e4c1d4e5..24d4eb48b 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/filecoin-project/go-commp-utils v0.1.3 github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837 github.com/filecoin-project/go-crypto v0.0.1 - github.com/filecoin-project/go-f3 v0.0.2 + github.com/filecoin-project/go-f3 v0.0.3-0.20240702063402-d48771055cf4 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 github.com/filecoin-project/go-jsonrpc v0.3.2 diff --git a/go.sum b/go.sum index 778dee484..65289f2a1 100644 --- a/go.sum +++ b/go.sum @@ -270,8 +270,8 @@ github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= -github.com/filecoin-project/go-f3 v0.0.2 h1:bzw/GndxntJnUYA+WCaXwHE2qwGRwrFVo9umz3unTUs= -github.com/filecoin-project/go-f3 v0.0.2/go.mod h1:Wry0mNa8z767TBHb7N0cVb+9j00KsHbD2pzsC3li4R8= +github.com/filecoin-project/go-f3 v0.0.3-0.20240702063402-d48771055cf4 h1:eQW2fyKyMuiweuySEb/zMIc3WLSAnIOY8lpqCVQM7pU= +github.com/filecoin-project/go-f3 v0.0.3-0.20240702063402-d48771055cf4/go.mod h1:Wry0mNa8z767TBHb7N0cVb+9j00KsHbD2pzsC3li4R8= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= diff --git a/node/builder_chain.go b/node/builder_chain.go index 957adeadb..deda10304 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -6,6 +6,8 @@ import ( "go.uber.org/fx" "golang.org/x/xerrors" + "github.com/filecoin-project/go-f3/manifest" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" @@ -151,7 +153,10 @@ var ChainNode = Options( Override(HandleIncomingBlocksKey, modules.HandleIncomingBlocks), ), - If(build.IsF3Enabled(), Override(new(*lf3.F3), lf3.New)), + If(build.IsF3Enabled(), + Override(new(manifest.ManifestProvider), lf3.NewManifestProvider), + Override(new(*lf3.F3), lf3.New), + ), ) func ConfigFullNode(c interface{}) Option { diff --git a/node/modules/lp2p/pubsub.go b/node/modules/lp2p/pubsub.go index f77f11468..67dcb5134 100644 --- a/node/modules/lp2p/pubsub.go +++ b/node/modules/lp2p/pubsub.go @@ -3,6 +3,7 @@ package lp2p import ( "context" "encoding/json" + "fmt" "net" "time" @@ -17,6 +18,7 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-f3/gpbft" + "github.com/filecoin-project/go-f3/manifest" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/metrics" @@ -46,6 +48,12 @@ const ( GraylistScoreThreshold = -2500 AcceptPXScoreThreshold = 1000 OpportunisticGraftScoreThreshold = 3.5 + + // Determines the max. number of configuration changes + // that are allowed for the dynamic manifest. + // If the manifest changes more than this number, the F3 + // message topic will be filtered + MaxDynamicManifestChangesAllowed = 1000 ) func ScoreKeeper() *dtypes.ScoreKeeper { @@ -382,7 +390,28 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) { } if build.IsF3Enabled() { - allowTopics = append(allowTopics, gpbft.NetworkName(in.Nn).PubSubTopic()) + f3TopicName := manifest.PubSubTopicFromNetworkName(gpbft.NetworkName(in.Nn)) + allowTopics = append(allowTopics, f3TopicName) + + // allow dynamic manifest topic and the new topic names after a reconfiguration. + // Note: This is pretty ugly, but I tried to use a regex subscription filter + // as the commented code below, but unfortunately it overwrites previous filters. A simple fix would + // be to allow combining several topic filters, but for now this works. + // + // pattern := fmt.Sprintf(`^\/f3\/%s\/0\.0\.1\/?[0-9]*$`, in.Nn) + // rx, err := regexp.Compile(pattern) + // if err != nil { + // return nil, xerrors.Errorf("failed to compile manifest topic regex: %w", err) + // } + // options = append(options, + // pubsub.WithSubscriptionFilter( + // pubsub.WrapLimitSubscriptionFilter( + // pubsub.NewRegexpSubscriptionFilter(rx), + // 100))) + allowTopics = append(allowTopics, manifest.ManifestPubSubTopicName) + for i := 0; i < MaxDynamicManifestChangesAllowed; i++ { + allowTopics = append(allowTopics, f3TopicName+"/"+fmt.Sprintf("%d", i)) + } } allowTopics = append(allowTopics, drandTopics...)