diff --git a/build/actors/v15.tar.zst b/build/actors/v15.tar.zst index 76ca1a9d808..da7a31e18a3 100644 Binary files a/build/actors/v15.tar.zst and b/build/actors/v15.tar.zst differ diff --git a/build/buildconstants/params_mainnet.go b/build/buildconstants/params_mainnet.go index 505a823a163..c38f43132f3 100644 --- a/build/buildconstants/params_mainnet.go +++ b/build/buildconstants/params_mainnet.go @@ -109,8 +109,8 @@ const UpgradePhoenixHeight abi.ChainEpoch = UpgradeDragonHeight + 120 // 2024-08-06T12:00:00Z const UpgradeWaffleHeight abi.ChainEpoch = 4154640 -// ?????? -var UpgradeTuktukHeight = abi.ChainEpoch(9999999999) +// 2024-11-20T23:00:00Z +var UpgradeTuktukHeight = abi.ChainEpoch(4461240) // FIP-0081: for the power actor state for pledge calculations. // UpgradeTuktukPowerRampDurationEpochs ends up in the power actor state after diff --git a/build/builtin_actors_gen.go b/build/builtin_actors_gen.go index 12995bb0403..0d6da2e28ee 100644 --- a/build/builtin_actors_gen.go +++ b/build/builtin_actors_gen.go @@ -166,7 +166,7 @@ var EmbeddedBuiltinActorsMetadata = []*BuiltinActorsMetadata{{ }, { Network: "butterflynet", Version: 15, - BundleGitTag: "v15.0.0-rc1", + BundleGitTag: "v15.0.0", ManifestCid: cid.MustParse("bafy2bzacearjal5rsmzloz3ny7aoju2rgw66wgxdrydgg27thcsazbmf5qihq"), Actors: map[string]cid.Cid{ "account": cid.MustParse("bafk2bzaceapjxl4kobnxn267u42nh2feouubkxcm62vzrk2nrfkqmtz6rgfw4"), @@ -341,7 +341,7 @@ var EmbeddedBuiltinActorsMetadata = []*BuiltinActorsMetadata{{ }, { Network: "calibrationnet", Version: 15, - BundleGitTag: "v15.0.0-rc1", + BundleGitTag: "v15.0.0", ManifestCid: cid.MustParse("bafy2bzaceax5zkysst7vtyup4whdxwzlpnaya3qp34rnoi6gyt4pongps7obw"), Actors: map[string]cid.Cid{ "account": cid.MustParse("bafk2bzacecwdkoknhok52hlddoetdkqfwohhv4bx6csu3x6o7aduryv5ufssu"), @@ -525,7 +525,7 @@ var EmbeddedBuiltinActorsMetadata = []*BuiltinActorsMetadata{{ }, { Network: "caterpillarnet", Version: 15, - BundleGitTag: "v15.0.0-rc1", + BundleGitTag: "v15.0.0", ManifestCid: cid.MustParse("bafy2bzaceaw24gctg3dx6pzrymhggsp32c7mofjscwnylk4pzsqmilolygwhi"), Actors: map[string]cid.Cid{ "account": cid.MustParse("bafk2bzacecmm4ymqjjbonet2yxe7l4jqg3uphcxmiz6vwyza4d4tfiy7hu3j4"), @@ -700,7 +700,7 @@ var EmbeddedBuiltinActorsMetadata = []*BuiltinActorsMetadata{{ }, { Network: "devnet", Version: 15, - BundleGitTag: "v15.0.0-rc1", + BundleGitTag: "v15.0.0", ManifestCid: cid.MustParse("bafy2bzacedlusqjwf7chvl2ve2fum5noyqrtjzcrzkhpbzpkg7puiru7dj4ug"), Actors: map[string]cid.Cid{ "account": cid.MustParse("bafk2bzaceb7f7gjyz2fkzkbf6jlwttjinny4nci4zdoby7r246xuyc4e2n7me"), @@ -898,7 +898,7 @@ var EmbeddedBuiltinActorsMetadata = []*BuiltinActorsMetadata{{ }, { Network: "mainnet", Version: 15, - BundleGitTag: "v15.0.0-rc1", + BundleGitTag: "v15.0.0", ManifestCid: cid.MustParse("bafy2bzaceakwje2hyinucrhgtsfo44p54iw4g6otbv5ghov65vajhxgntr53u"), Actors: map[string]cid.Cid{ "account": cid.MustParse("bafk2bzacecia5zacqt4gvd4z7275lnkhgraq75shy63cphakphhw6crf4joii"), @@ -1073,7 +1073,7 @@ var EmbeddedBuiltinActorsMetadata = []*BuiltinActorsMetadata{{ }, { Network: "testing", Version: 15, - BundleGitTag: "v15.0.0-rc1", + BundleGitTag: "v15.0.0", ManifestCid: cid.MustParse("bafy2bzacedio6qbcgxduz3y2zksor5dgyt3ieiugnugvsz6k2jdzwvugwahag"), Actors: map[string]cid.Cid{ "account": cid.MustParse("bafk2bzaceabav73gljoyhtozycl5dqwomg4vviuy2jimte545yx3vgg3vfnyo"), @@ -1248,7 +1248,7 @@ var EmbeddedBuiltinActorsMetadata = []*BuiltinActorsMetadata{{ }, { Network: "testing-fake-proofs", Version: 15, - BundleGitTag: "v15.0.0-rc1", + BundleGitTag: "v15.0.0", ManifestCid: cid.MustParse("bafy2bzacea3jtzs4jz75ht3ncdyvabef4spz7w375ja7spp36yy3zwp5ji2wi"), Actors: map[string]cid.Cid{ "account": cid.MustParse("bafk2bzaceabav73gljoyhtozycl5dqwomg4vviuy2jimte545yx3vgg3vfnyo"), diff --git a/build/params_shared_funcs.go b/build/params_shared_funcs.go index a0981cf4782..05dbe7817fa 100644 --- a/build/params_shared_funcs.go +++ b/build/params_shared_funcs.go @@ -55,3 +55,24 @@ func IsF3Enabled() bool { return false } } + +func IsF3PassiveTestingEnabled() bool { + if !IsF3Enabled() { + return false + } + const F3DisablePassiveTesting = "LOTUS_DISABLE_F3_PASSIVE_TESTING" + + v, disableEnvVarSet := os.LookupEnv(F3DisablePassiveTesting) + if !disableEnvVarSet { + // Environment variable to disable F3 passive testing is not set. + return true + } + switch strings.TrimSpace(strings.ToLower(v)) { + case "", "0", "false", "no": + // Consider these values as "do not disable". + return true + default: + // Consider any other value as disable. + return false + } +} diff --git a/chain/lf3/manifest.go b/chain/lf3/manifest.go index 2b64cc4b224..b242edb371d 100644 --- a/chain/lf3/manifest.go +++ b/chain/lf3/manifest.go @@ -13,6 +13,7 @@ import ( "github.com/filecoin-project/go-f3/ec" "github.com/filecoin-project/go-f3/manifest" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" @@ -35,7 +36,7 @@ func (hg *headGetter) GetHead(context.Context) (ec.TipSet, error) { var MaxDynamicManifestChangesAllowed = 1000 func NewManifestProvider(mctx helpers.MetricsCtx, config *Config, cs *store.ChainStore, ps *pubsub.PubSub, mds dtypes.MetadataDS) (prov manifest.ManifestProvider, err error) { - if config.DynamicManifestProvider == "" { + if config.DynamicManifestProvider == "" || !build.IsF3PassiveTestingEnabled() { if config.StaticManifest == nil { return manifest.NoopManifestProvider{}, nil } diff --git a/chain/lf3/participation.go b/chain/lf3/participation.go index 280b44b9450..0c36a2cc9cb 100644 --- a/chain/lf3/participation.go +++ b/chain/lf3/participation.go @@ -14,6 +14,7 @@ import ( "github.com/filecoin-project/go-f3/manifest" "github.com/filecoin-project/lotus/api" + cliutil "github.com/filecoin-project/lotus/cli/util" "github.com/filecoin-project/lotus/node/modules/dtypes" ) @@ -89,6 +90,11 @@ func (p *Participant) run(ctx context.Context) (_err error) { } }() + // Try to make send all requests to the same node. If a request fails, we'll switch nodes. + // This interacts with the FullNodeProxy, which is how we support multi-node setups by + // default. + ctx = cliutil.OnSingleNode(ctx) + var ticket api.F3ParticipationTicket for ctx.Err() == nil { var err error diff --git a/chain/lf3/participation_lease.go b/chain/lf3/participation_lease.go index ab3d1c60135..efd29929cbb 100644 --- a/chain/lf3/participation_lease.go +++ b/chain/lf3/participation_lease.go @@ -104,6 +104,8 @@ func (l *leaser) participate(ticket api.F3ParticipationTicket) (api.F3Participat if found { // short-circuite for reparticipation. if currentLease == newLease { + newLease.ValidityTerm = newLease.ToInstance() - instant.ID + newLease.FromInstance = instant.ID return newLease, nil } if currentLease.Network == newLease.Network && currentLease.FromInstance > newLease.FromInstance { diff --git a/chain/lf3/participation_lease_test.go b/chain/lf3/participation_lease_test.go index c9dc11ac29e..ff1627c57aa 100644 --- a/chain/lf3/participation_lease_test.go +++ b/chain/lf3/participation_lease_test.go @@ -34,6 +34,15 @@ func TestLeaser(t *testing.T) { require.Equal(t, issuer.String(), lease.Issuer) require.Equal(t, uint64(10), lease.FromInstance) // Current instance (10) + offset (5) require.Equal(t, uint64(5), lease.ValidityTerm) // Current instance (10) + offset (5) + + progress.currentInstance += 2 + + lease, err = subject.participate(ticket) + require.NoError(t, err) + require.Equal(t, uint64(123), lease.MinerID) + require.Equal(t, issuer.String(), lease.Issuer) + require.Equal(t, uint64(12), lease.FromInstance) // Current instance (10) + offset (5) + require.Equal(t, uint64(3), lease.ValidityTerm) // Current instance (10) + offset (5) }) t.Run("get participants", func(t *testing.T) { progress.currentInstance = 11 diff --git a/cli/clicommands/cmd.go b/cli/clicommands/cmd.go index 791a11927d7..44709de45fb 100644 --- a/cli/clicommands/cmd.go +++ b/cli/clicommands/cmd.go @@ -23,6 +23,7 @@ var Commands = []*cli.Command{ lcli.WithCategory("developer", lcli.EvmCmd), lcli.WithCategory("network", lcli.NetCmd), lcli.WithCategory("network", lcli.SyncCmd), + lcli.WithCategory("network", lcli.F3Cmd), lcli.WithCategory("status", lcli.StatusCmd), lcli.PprofCmd, lcli.VersionCmd, diff --git a/cli/f3.go b/cli/f3.go index 4e7b376c805..7ffd8bae419 100644 --- a/cli/f3.go +++ b/cli/f3.go @@ -135,8 +135,9 @@ An omitted value is always interpreted as 0, and an omitted value indicates the latest instance. If both are specified, must never exceed . -If no range is specified all certificates are listed, i.e. the range -of '0..'. +If no range is specified, the latest 10 certificates are listed, i.e. +the range of '0..' with limit of 10. Otherwise, all certificates in +the specified range are listed unless limit is explicitly specified. Examples: * All certificates from newest to oldest: @@ -181,6 +182,10 @@ Examples: fromTo := cctx.Args().First() if fromTo == "" { fromTo = "0.." + if !cctx.IsSet(f3FlagInstanceLimit.Name) { + // Default to limit of 10 if no explicit range and limit is given. + limit = 10 + } } r, err := newRanger(fromTo, limit, reverse, func() (uint64, error) { latest, err := api.F3GetLatestCertificate(cctx.Context) @@ -306,7 +311,7 @@ Examples: f3FlagInstanceLimit = &cli.IntFlag{ Name: "limit", Usage: "The maximum number of instances. A value less than 0 indicates no limit.", - DefaultText: "No limit", + DefaultText: "10 when no range is specified. Otherwise, unlimited.", Value: -1, } f3FlagReverseOrder = &cli.BoolFlag{ diff --git a/cli/util/api.go b/cli/util/api.go index ef7a021f52e..cfe3b29d947 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -10,6 +10,7 @@ import ( "os/signal" "reflect" "strings" + "sync/atomic" "syscall" "time" @@ -229,9 +230,12 @@ func GetFullNodeAPI(ctx *cli.Context) (v0api.FullNode, jsonrpc.ClientCloser, err type contextKey string -// OnSingleNode is not thread safe +// OnSingleNode returns a modified context that, when passed to a method on a FullNodeProxy, will +// cause all calls to be directed at the same node when possible. +// +// Think "sticky sessions". func OnSingleNode(ctx context.Context) context.Context { - return context.WithValue(ctx, contextKey("retry-node"), new(*int)) + return context.WithValue(ctx, contextKey("retry-node"), new(atomic.Int32)) } func FullNodeProxy[T api.FullNode](ins []T, outstr *api.FullNodeStruct) { @@ -262,27 +266,29 @@ func FullNodeProxy[T api.FullNode](ins []T, outstr *api.FullNodeStruct) { ctx := args[0].Interface().(context.Context) - curr := -1 - // for calls that need to be performed on the same node // primarily for miner when calling create block and submit block subsequently - key := contextKey("retry-node") - if ctx.Value(key) != nil { - if (*ctx.Value(key).(**int)) == nil { - *ctx.Value(key).(**int) = &curr - } else { - curr = **ctx.Value(key).(**int) - 1 - } + var curr *atomic.Int32 + if v, ok := ctx.Value(contextKey("retry-node")).(*atomic.Int32); ok { + curr = v + } else { + curr = new(atomic.Int32) } - total := len(rins) + total := int32(len(rins)) result, _ := retry.Retry(ctx, 5, initialBackoff, errorsToRetry, func() ([]reflect.Value, error) { - curr = (curr + 1) % total - - result := fns[curr].Call(args) + idx := curr.Load() + result := fns[idx].Call(args) if result[len(result)-1].IsNil() { return result, nil } + // On failure, switch to the next node. + // + // We CAS instead of incrementing because this might have + // already been incremented by a concurrent call if we have + // a shared `curr` (we're sticky to a single node). + curr.CompareAndSwap(idx, (idx+1)%total) + e := result[len(result)-1].Interface().(error) return result, e }) diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index ab8df8f3327..14dea2e2015 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -34,6 +34,7 @@ COMMANDS: NETWORK: net Manage P2P Network sync Inspect or interact with the chain syncer + f3 Manages Filecoin Fast Finality (F3) interactions STATUS: status Check node status @@ -2718,6 +2719,177 @@ OPTIONS: --help, -h show help ``` +## lotus f3 +``` +NAME: + lotus f3 - Manages Filecoin Fast Finality (F3) interactions + +USAGE: + lotus f3 command [command options] [arguments...] + +COMMANDS: + list-miners, lm Lists the miners that currently participate in F3 via this node. + certs, c Manages interactions with F3 finality certificates. + manifest Gets the current manifest used by F3. + status Checks the F3 status. + help, h Shows a list of commands or help for one command + +OPTIONS: + --help, -h show help +``` + +### lotus f3 list-miners +``` +NAME: + lotus f3 list-miners - Lists the miners that currently participate in F3 via this node. + +USAGE: + lotus f3 list-miners [command options] [arguments...] + +OPTIONS: + --help, -h show help +``` + +### lotus f3 certs +``` +NAME: + lotus f3 certs - Manages interactions with F3 finality certificates. + +USAGE: + lotus f3 certs command [command options] [arguments...] + +COMMANDS: + get Gets an F3 finality certificate to a given instance ID, or the latest certificate if no instance is specified. + list Lists a range of F3 finality certificates. + + By default the certificates are listed in newest to oldest order, + i.e. descending instance IDs. The order may be reversed using the + '--reverse' flag. + + A range may optionally be specified as the first argument to indicate + inclusive range of 'from' and 'to' instances in following notation: + '..'. Either or may be omitted, but not both. + An omitted value is always interpreted as 0, and an omitted + value indicates the latest instance. If both are specified, + must never exceed . + + If no range is specified, the latest 10 certificates are listed, i.e. + the range of '0..' with limit of 10. Otherwise, all certificates in + the specified range are listed unless limit is explicitly specified. + + Examples: + * All certificates from newest to oldest: + $ lotus f3 certs list 0.. + + * Three newest certificates: + $ lotus f3 certs list --limit 3 0.. + + * Three oldest certificates: + $ lotus f3 certs list --limit 3 --reverse 0.. + + * Up to three certificates starting from instance 1413 to the oldest: + $ lotus f3 certs list --limit 3 ..1413 + + * Up to 3 certificates starting from instance 1413 to the newest: + $ lotus f3 certs list --limit 3 --reverse 1413.. + + * All certificates from instance 3 to 1413 in order of newest to oldest: + $ lotus f3 certs list 3..1413 + + help, h Shows a list of commands or help for one command + +OPTIONS: + --help, -h show help +``` + +#### lotus f3 certs get +``` +NAME: + lotus f3 certs get - Gets an F3 finality certificate to a given instance ID, or the latest certificate if no instance is specified. + +USAGE: + lotus f3 certs get [command options] [instance] + +OPTIONS: + --output value The output format. Supported formats: text, json (default: "text") + --help, -h show help +``` + +#### lotus f3 certs list +``` +NAME: + lotus f3 certs list - Lists a range of F3 finality certificates. + + By default the certificates are listed in newest to oldest order, + i.e. descending instance IDs. The order may be reversed using the + '--reverse' flag. + + A range may optionally be specified as the first argument to indicate + inclusive range of 'from' and 'to' instances in following notation: + '..'. Either or may be omitted, but not both. + An omitted value is always interpreted as 0, and an omitted + value indicates the latest instance. If both are specified, + must never exceed . + + If no range is specified, the latest 10 certificates are listed, i.e. + the range of '0..' with limit of 10. Otherwise, all certificates in + the specified range are listed unless limit is explicitly specified. + + Examples: + * All certificates from newest to oldest: + $ lotus f3 certs list 0.. + + * Three newest certificates: + $ lotus f3 certs list --limit 3 0.. + + * Three oldest certificates: + $ lotus f3 certs list --limit 3 --reverse 0.. + + * Up to three certificates starting from instance 1413 to the oldest: + $ lotus f3 certs list --limit 3 ..1413 + + * Up to 3 certificates starting from instance 1413 to the newest: + $ lotus f3 certs list --limit 3 --reverse 1413.. + + * All certificates from instance 3 to 1413 in order of newest to oldest: + $ lotus f3 certs list 3..1413 + + +USAGE: + lotus f3 certs list [command options] [range] + +OPTIONS: + --output value The output format. Supported formats: text, json (default: "text") + --limit value The maximum number of instances. A value less than 0 indicates no limit. (default: 10 when no range is specified. Otherwise, unlimited.) + --reverse Reverses the default order of output. (default: false) + --help, -h show help +``` + +### lotus f3 manifest +``` +NAME: + lotus f3 manifest - Gets the current manifest used by F3. + +USAGE: + lotus f3 manifest [command options] [arguments...] + +OPTIONS: + --output value The output format. Supported formats: text, json (default: "text") + --help, -h show help +``` + +### lotus f3 status +``` +NAME: + lotus f3 status - Checks the F3 status. + +USAGE: + lotus f3 status [command options] [arguments...] + +OPTIONS: + --help, -h show help +``` + ## lotus status ``` NAME: diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 815fb3a20fd..62131ac060d 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 815fb3a20fda47cad556ba2045b16021610cd02c +Subproject commit 62131ac060d4d0cb8f963c1de5b291fba704079c diff --git a/go.mod b/go.mod index 20ffc40a649..70a208e50cf 100644 --- a/go.mod +++ b/go.mod @@ -37,20 +37,20 @@ require ( github.com/elastic/gosigar v0.14.2 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.15.0 - github.com/filecoin-project/filecoin-ffi v1.28.0-rc2 + github.com/filecoin-project/filecoin-ffi v1.30.0 github.com/filecoin-project/go-address v1.2.0 github.com/filecoin-project/go-amt-ipld/v4 v4.4.0 github.com/filecoin-project/go-bitfield v0.2.4 github.com/filecoin-project/go-cbor-util v0.0.1 github.com/filecoin-project/go-commp-utils/v2 v2.1.0 github.com/filecoin-project/go-crypto v0.1.0 - github.com/filecoin-project/go-f3 v0.7.1 + github.com/filecoin-project/go-f3 v0.7.2 github.com/filecoin-project/go-fil-commcid v0.2.0 github.com/filecoin-project/go-hamt-ipld/v3 v3.4.0 github.com/filecoin-project/go-jsonrpc v0.6.0 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 - github.com/filecoin-project/go-state-types v0.15.0-rc1 + github.com/filecoin-project/go-state-types v0.15.0 github.com/filecoin-project/go-statemachine v1.0.3 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 @@ -136,7 +136,7 @@ require ( github.com/triplewz/poseidon v0.0.2-0.20240407130934-5265fab9d889 github.com/urfave/cli/v2 v2.25.5 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba - github.com/whyrusleeping/cbor-gen v0.1.2 + github.com/whyrusleeping/cbor-gen v0.2.0 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/xeipuuv/gojsonschema v1.2.0 github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 @@ -155,12 +155,12 @@ require ( go.uber.org/fx v1.22.1 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/mod v0.20.0 golang.org/x/net v0.29.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.25.0 - golang.org/x/term v0.24.0 + golang.org/x/sys v0.26.0 + golang.org/x/term v0.25.0 golang.org/x/time v0.5.0 golang.org/x/tools v0.24.0 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da @@ -332,7 +332,7 @@ require ( go.uber.org/mock v0.4.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/text v0.19.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect google.golang.org/grpc v1.64.0 // indirect diff --git a/go.sum b/go.sum index 339374b1282..2fba839ad93 100644 --- a/go.sum +++ b/go.sum @@ -273,8 +273,8 @@ github.com/filecoin-project/go-commp-utils/v2 v2.1.0/go.mod h1:NbxJYlhxtWaNhlVCj github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.1.0 h1:Pob2MphoipMbe/ksxZOMcQvmBHAd3sI/WEqcbpIsGI0= github.com/filecoin-project/go-crypto v0.1.0/go.mod h1:K9UFXvvoyAVvB+0Le7oGlKiT9mgA5FHOJdYQXEE8IhI= -github.com/filecoin-project/go-f3 v0.7.1 h1:3xCxKgVtlQVTZooeUWIL1isk5MK/BGcdrhZlR0ZbIIU= -github.com/filecoin-project/go-f3 v0.7.1/go.mod h1:QoxuoK4aktNZD1R/unlhNbhV6TnlNTAbA/QODCnAjak= +github.com/filecoin-project/go-f3 v0.7.2 h1:YQgxxSMzCSQniZqwDjyNkIRz3pnzCtOrtaS5ldIaUDA= +github.com/filecoin-project/go-f3 v0.7.2/go.mod h1:QoxuoK4aktNZD1R/unlhNbhV6TnlNTAbA/QODCnAjak= github.com/filecoin-project/go-fil-commcid v0.2.0 h1:B+5UX8XGgdg/XsdUpST4pEBviKkFOw+Fvl2bLhSKGpI= github.com/filecoin-project/go-fil-commcid v0.2.0/go.mod h1:8yigf3JDIil+/WpqR5zoKyP0jBPCOGtEqq/K1CcMy9Q= github.com/filecoin-project/go-fil-commp-hashhash v0.2.0 h1:HYIUugzjq78YvV3vC6rL95+SfC/aSTVSnZSZiDV5pCk= @@ -298,8 +298,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.15.0-rc1 h1:tfXvhMAAo4jBQIEM1AjQzDCbwqvsxVMOLhIcDYf10fA= -github.com/filecoin-project/go-state-types v0.15.0-rc1/go.mod h1:YcWoJE/24XGEL6w9FjUoMBu7+eHEkgwKnkGZkTBX9TE= +github.com/filecoin-project/go-state-types v0.15.0 h1:GaUSCti0tGMzLg7fVpRjtNVGBvirbMFzLfyWbR+qzWE= +github.com/filecoin-project/go-state-types v0.15.0/go.mod h1:2okQFn4DVOt5Bs6OFh0lLSzn8p7Vczh8XjgaKLKhKgI= github.com/filecoin-project/go-statemachine v1.0.3 h1:N07o6alys+V1tNoSTi4WuuoeNC4erS/6jE74+NsgQuk= github.com/filecoin-project/go-statemachine v1.0.3/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= @@ -1306,8 +1306,8 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200810223238-211df3b9e24c/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20200812213548-958ddffe352c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.1.2 h1:WQFlrPhpcQl+M2/3dP5cvlTLWPVsL6LGBb9jJt6l/cA= -github.com/whyrusleeping/cbor-gen v0.1.2/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= +github.com/whyrusleeping/cbor-gen v0.2.0 h1:v8DREoK/1qQBSc6/UZ4OgU06+9FkywTh8glX0Hi+jkc= +github.com/whyrusleeping/cbor-gen v0.2.0/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= @@ -1447,8 +1447,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1665,8 +1665,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1680,8 +1680,8 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1695,8 +1695,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/itests/merged_api_test.go b/itests/merged_api_test.go new file mode 100644 index 00000000000..0b92e7206d0 --- /dev/null +++ b/itests/merged_api_test.go @@ -0,0 +1,71 @@ +package itests + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/types" + cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/itests/kit" +) + +func TestAPIMergeProxy(t *testing.T) { + ctx := context.Background() + + // The default is too high for many nodes. + initialBalance := types.MustParseFIL("100000FIL") + + nopts := []kit.NodeOpt{ + kit.ThroughRPC(), + kit.WithAllSubsystems(), + kit.OwnerBalance(big.Int(initialBalance)), + } + ens := kit.NewEnsemble(t, kit.MockProofs()) + nodes := make([]*kit.TestFullNode, 10) + for i := range nodes { + var nd kit.TestFullNode + ens.FullNode(&nd, nopts...) + nodes[i] = &nd + } + merged := kit.MergeFullNodes(nodes) + + var miner kit.TestMiner + ens.Miner(&miner, merged, nopts...) + + ens.Start() + + nd1ID, err := nodes[0].ID(ctx) + require.NoError(t, err) + nd2ID, err := nodes[1].ID(ctx) + require.NoError(t, err) + + // Expect to start on node 1, and switch to node 2 on failure. + mergedID, err := merged.ID(ctx) + require.NoError(t, err) + require.Equal(t, nd1ID, mergedID) + require.NoError(t, nodes[0].Stop(ctx)) + mergedID, err = merged.ID(ctx) + require.NoError(t, err) + require.Equal(t, nd2ID, mergedID) + + // Now see if sticky sessions work + stickyCtx := cliutil.OnSingleNode(ctx) + for i, nd := range nodes[1:] { + // kill off the previous node. + require.NoError(t, nodes[i].Stop(ctx)) + + got, err := merged.ID(stickyCtx) + require.NoError(t, err) + expected, err := nd.ID(ctx) + require.NoError(t, err) + require.Equal(t, expected, got) + } + + // This should fail because we'll run out of retries because it's _not_ sticky! + _, err = merged.ID(ctx) + require.Error(t, err) +}