diff --git a/CHANGELOG.md b/CHANGELOG.md index 08bdd3fa86f..c5937df8281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ - feat: automatically detect if the genesis is zstd compressed. ([filecoin-project/lotus#12885](https://github.com/filecoin-project/lotus/pull/12885) +- chore: upgrade to the latest go-f3 and allow F3 chain exchange topics ([filecoin-project/lotus#12893](https://github.com/filecoin-project/lotus/pull/12893) + + # UNRELEASED v.1.32.0 See https://github.com/filecoin-project/lotus/blob/release/v1.32.0/CHANGELOG.md diff --git a/api/docgen-openrpc/openrpc.go b/api/docgen-openrpc/openrpc.go index 27f59fb63b4..3b2d86a290c 100644 --- a/api/docgen-openrpc/openrpc.go +++ b/api/docgen-openrpc/openrpc.go @@ -13,6 +13,8 @@ import ( "github.com/ipfs/go-cid" meta_schema "github.com/open-rpc/meta-schema" + "github.com/filecoin-project/go-f3/gpbft" + "github.com/filecoin-project/lotus/api/docgen" "github.com/filecoin-project/lotus/build" ) @@ -29,6 +31,40 @@ const integerD = `{ "description": "Number is a number" }` +const f3ECChain = `{ +"items": { + "additionalProperties": false, + "properties": { + "Commitments": { + "items": { + "description": "Number is a number", + "title": "number", + "type": "number" + }, + "maxItems": 32, + "minItems": 32, + "type": "array" + }, + "Epoch": { + "title": "number", + "type": "number" + }, + "Key": { + "media": { + "binaryEncoding": "base64" + }, + "type": "string" + }, + "PowerTable": { + "title": "Content Identifier", + "type": "string" + } + }, + "type": "object" +}, +"type": "array" +}` + const cidCidD = `{"title": "Content Identifier", "type": "string", "description": "Cid represents a self-describing content addressed identifier. It is formed by a Version, a Codec (which indicates a multicodec-packed content type) and a Multihash."}` func Generate(out io.Writer, iface, pkg string, ainfo docgen.ApiASTInfo, outGzip bool) error { @@ -84,6 +120,7 @@ func OpenRPCSchemaTypeMapper(ty reflect.Type) *jsonschema.Type { // Use a slice instead of a map because it preserves order, as a logic safeguard/fallback. dict := []schemaDictEntry{ {cid.Cid{}, cidCidD}, + {gpbft.ECChain{}, f3ECChain}, } for _, d := range dict { diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index cecc79886e0..f2bc8cf0023 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -107,11 +107,13 @@ func init() { f3Cert := certs.FinalityCertificate{ GPBFTInstance: 0, - ECChain: []gpbft.TipSet{ - { - Epoch: 0, - Key: tsk.Bytes(), - PowerTable: c, + ECChain: &gpbft.ECChain{ + TipSets: []*gpbft.TipSet{ + { + Epoch: 0, + Key: tsk.Bytes(), + PowerTable: c, + }, }, }, SupplementalData: gpbft.SupplementalData{ diff --git a/build/genesis/butterflynet.car.zst b/build/genesis/butterflynet.car.zst index db55bd8cc47..bfb4e3ce3aa 100644 Binary files a/build/genesis/butterflynet.car.zst and b/build/genesis/butterflynet.car.zst differ diff --git a/build/openrpc/full.json b/build/openrpc/full.json index 7c66df80c16..d05aa5b13c4 100644 --- a/build/openrpc/full.json +++ b/build/openrpc/full.json @@ -7588,7 +7588,9 @@ "Gpbft": { "Delta": 0, "DeltaBackOffExponent": 0, + "QualityDeltaMultiplier": 0, "MaxLookaheadRounds": 0, + "ChainProposedLength": 0, "RebroadcastBackoffBase": 0, "RebroadcastBackoffExponent": 0, "RebroadcastBackoffSpread": 0, @@ -7607,6 +7609,18 @@ "ServerRequestTimeout": 0, "MinimumPollInterval": 0, "MaximumPollInterval": 0 + }, + "PubSub": { + "CompressionEnabled": false + }, + "ChainExchange": { + "SubscriptionBufferSize": 0, + "MaxChainLength": 0, + "MaxInstanceLookahead": 0, + "MaxDiscoveredChainsPerInstance": 0, + "MaxWantedChainsPerInstance": 0, + "RebroadcastInterval": 0, + "MaxTimestampAge": 0 } } ], @@ -7642,6 +7656,40 @@ }, "type": "object" }, + "ChainExchange": { + "additionalProperties": false, + "properties": { + "MaxChainLength": { + "title": "number", + "type": "number" + }, + "MaxDiscoveredChainsPerInstance": { + "title": "number", + "type": "number" + }, + "MaxInstanceLookahead": { + "title": "number", + "type": "number" + }, + "MaxTimestampAge": { + "title": "number", + "type": "number" + }, + "MaxWantedChainsPerInstance": { + "title": "number", + "type": "number" + }, + "RebroadcastInterval": { + "title": "number", + "type": "number" + }, + "SubscriptionBufferSize": { + "title": "number", + "type": "number" + } + }, + "type": "object" + }, "CommitteeLookback": { "title": "number", "type": "number" @@ -7704,6 +7752,10 @@ "Gpbft": { "additionalProperties": false, "properties": { + "ChainProposedLength": { + "title": "number", + "type": "number" + }, "Delta": { "title": "number", "type": "number" @@ -7715,6 +7767,9 @@ "title": "number", "type": "number" }, + "QualityDeltaMultiplier": { + "type": "number" + }, "RebroadcastBackoffBase": { "title": "number", "type": "number" @@ -7752,6 +7807,15 @@ "ProtocolVersion": { "title": "number", "type": "number" + }, + "PubSub": { + "additionalProperties": false, + "properties": { + "CompressionEnabled": { + "type": "boolean" + } + }, + "type": "object" } }, "type": [ diff --git a/chain/lf3/config.go b/chain/lf3/config.go index aa329bbbc12..e008c2b3a25 100644 --- a/chain/lf3/config.go +++ b/chain/lf3/config.go @@ -66,6 +66,8 @@ func NewManifest( MinimumPollInterval: ecPeriod, MaximumPollInterval: 4 * ecPeriod, }, + PubSub: manifest.DefaultPubSubConfig, + ChainExchange: manifest.DefaultChainExchangeConfig, } } diff --git a/chain/lf3/f3.go b/chain/lf3/f3.go index 96767ba8a6f..fa3b195ada8 100644 --- a/chain/lf3/f3.go +++ b/chain/lf3/f3.go @@ -187,7 +187,7 @@ func (fff *F3) GetLatestCert(ctx context.Context) (*certs.FinalityCertificate, e func (fff *F3) GetManifest(ctx context.Context) (*manifest.Manifest, error) { m := fff.inner.Manifest() if m == nil { - return nil, xerrors.New("no known network manifest") + return nil, manifest.ErrNoManifest } if m.InitialPowerTable.Defined() { return m, nil diff --git a/cli/templates/f3_finality_cert.go.tmpl b/cli/templates/f3_finality_cert.go.tmpl index 37f0acaaae2..945b96740c8 100644 --- a/cli/templates/f3_finality_cert.go.tmpl +++ b/cli/templates/f3_finality_cert.go.tmpl @@ -3,12 +3,12 @@ Power Table: Next: {{.SupplementalData.PowerTable}} Delta: {{ptDiffToString .PowerTableDelta}} Finalized Chain: - Length: {{ $chainLength := len .ECChain -}}{{ $chainLength }} + Length: {{ $chainLength := len .ECChain.TipSets -}}{{ $chainLength }} Epochs: {{ .ECChain.Base.Epoch -}}-{{ .ECChain.Head.Epoch }} Chain: {{- $maxTipSets := 10 -}} {{- $maxTipSetKeys := 2 -}} -{{- range $i, $tipset := .ECChain -}} +{{- range $i, $tipset := .ECChain.TipSets -}} {{- if lt $i $maxTipSets -}} {{- if lt (add $i 1) $chainLength }} ├── diff --git a/cli/templates/f3_manifest.go.tmpl b/cli/templates/f3_manifest.go.tmpl index 9bb2a61bc9c..e0b22e62b35 100644 --- a/cli/templates/f3_manifest.go.tmpl +++ b/cli/templates/f3_manifest.go.tmpl @@ -11,7 +11,9 @@ Manifest: GPBFT Delta: {{.Gpbft.Delta}} GPBFT Delta BackOff Exponent: {{.Gpbft.DeltaBackOffExponent}} + GPBFT Quality Delta Multiplier: {{.Gpbft.QualityDeltaMultiplier}} GPBFT Max Lookahead Rounds: {{.Gpbft.MaxLookaheadRounds}} + GPBFT Chain Proposed Length: {{.Gpbft.ChainProposedLength}} GPBFT Rebroadcast Backoff Base: {{.Gpbft.RebroadcastBackoffBase}} GPBFT Rebroadcast Backoff Exponent: {{.Gpbft.RebroadcastBackoffExponent}} GPBFT Rebroadcast Backoff Spread: {{.Gpbft.RebroadcastBackoffSpread}} @@ -27,3 +29,13 @@ Manifest: Certificate Exchange Server Timeout: {{.CertificateExchange.ServerRequestTimeout}} Certificate Exchange Min Poll Interval: {{.CertificateExchange.MinimumPollInterval}} Certificate Exchange Max Poll Interval: {{.CertificateExchange.MaximumPollInterval}} + + PubSub Compression Enabled: {{.PubSub.CompressionEnabled}} + + Chain Exchange Subscription Buffer Size: {{.ChainExchange.SubscriptionBufferSize}} + Chain Exchange Max Chain Length: {{.ChainExchange.MaxChainLength}} + Chain Exchange Max Instance Lookahead: {{.ChainExchange.MaxInstanceLookahead}} + Chain Exchange Max Discovered Chains Per Instance: {{.ChainExchange.MaxDiscoveredChainsPerInstance}} + Chain Exchange Max Wanted Chains Per Instance: {{.ChainExchange.MaxWantedChainsPerInstance}} + Chain Exchange Rebroadcast Interval: {{.ChainExchange.RebroadcastInterval}} + Chain Exchange Max Timestamp Age: {{.ChainExchange.MaxTimestampAge}} diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index e5abeafb7d7..8a75d764000 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -2624,7 +2624,9 @@ Response: "Gpbft": { "Delta": 0, "DeltaBackOffExponent": 0, + "QualityDeltaMultiplier": 0, "MaxLookaheadRounds": 0, + "ChainProposedLength": 0, "RebroadcastBackoffBase": 0, "RebroadcastBackoffExponent": 0, "RebroadcastBackoffSpread": 0, @@ -2643,6 +2645,18 @@ Response: "ServerRequestTimeout": 0, "MinimumPollInterval": 0, "MaximumPollInterval": 0 + }, + "PubSub": { + "CompressionEnabled": false + }, + "ChainExchange": { + "SubscriptionBufferSize": 0, + "MaxChainLength": 0, + "MaxInstanceLookahead": 0, + "MaxDiscoveredChainsPerInstance": 0, + "MaxWantedChainsPerInstance": 0, + "RebroadcastInterval": 0, + "MaxTimestampAge": 0 } } ``` diff --git a/go.mod b/go.mod index b529e330bd9..030b7f5495b 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( 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.3 + github.com/filecoin-project/go-f3 v0.8.0 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.7.0 diff --git a/go.sum b/go.sum index 8ef4d586a42..a686a2c2879 100644 --- a/go.sum +++ b/go.sum @@ -279,8 +279,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.3 h1:nwRYRKaJs7AV3di/OQyj6tABeixBeL06DkJeoQrr5+0= -github.com/filecoin-project/go-f3 v0.7.3/go.mod h1:wDo5mPi4KXVuA7kvwLpmfVVv2Aw2ZwZk3iqMWr5BOT0= +github.com/filecoin-project/go-f3 v0.8.0 h1:Zm2NIhryHFudh3QZ5X0qXAqGm/rMc9zjndGLd4vL07A= +github.com/filecoin-project/go-f3 v0.8.0/go.mod h1:zNFGuBM+fYuGXk2fpzl6wW4g2Gyrxgg6z2IVSoGt+60= 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= diff --git a/itests/f3_test.go b/itests/f3_test.go index eb2ba79a472..84a9bf3cb91 100644 --- a/itests/f3_test.go +++ b/itests/f3_test.go @@ -15,6 +15,7 @@ import ( "golang.org/x/sync/errgroup" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-f3" "github.com/filecoin-project/go-f3/certs" "github.com/filecoin-project/go-f3/gpbft" "github.com/filecoin-project/go-f3/manifest" @@ -99,10 +100,10 @@ func TestF3_InactiveModes(t *testing.T) { expectedErrors: map[string]any{ "F3GetOrRenewParticipationTicket": api.ErrF3NotReady, "F3Participate": api.ErrF3NotReady, - "F3GetCertificate": "F3 is not running", - "F3GetLatestCertificate": "F3 is not running", - "F3GetManifest": "no known network manifest", - "F3GetF3PowerTable": "no known network manifest", + "F3GetCertificate": f3.ErrF3NotRunning.Error(), + "F3GetLatestCertificate": f3.ErrF3NotRunning.Error(), + "F3GetManifest": manifest.ErrNoManifest.Error(), + "F3GetF3PowerTable": manifest.ErrNoManifest.Error(), }, expectedValues: map[string]any{ "F3GetOrRenewParticipationTicket": (api.F3ParticipationTicket)(nil), @@ -343,7 +344,7 @@ func (e *testEnv) waitTillF3Instance(i uint64, timeout time.Duration) { e.waitFor(func(n *kit.TestFullNode) bool { c, err := n.F3GetLatestCertificate(e.testCtx) if err != nil { - require.ErrorContains(e.t, err, "F3 is not running") + require.ErrorContains(e.t, err, f3.ErrF3NotRunning.Error()) return false } return c != nil && c.GPBFTInstance >= i @@ -451,7 +452,9 @@ func newTestManifest(networkName gpbft.NetworkName, bootstrapEpoch int64, blockt // Use smaller time intervals for more responsive test progress/assertion. Delta: 250 * time.Millisecond, DeltaBackOffExponent: 1.3, + QualityDeltaMultiplier: manifest.DefaultGpbftConfig.QualityDeltaMultiplier, MaxLookaheadRounds: 5, + ChainProposedLength: manifest.DefaultGpbftConfig.ChainProposedLength, RebroadcastBackoffBase: 500 * time.Millisecond, RebroadcastBackoffSpread: 0.1, RebroadcastBackoffExponent: 1.3, @@ -471,6 +474,8 @@ func newTestManifest(networkName gpbft.NetworkName, bootstrapEpoch int64, blockt MinimumPollInterval: blocktime, MaximumPollInterval: 4 * blocktime, }, + PubSub: manifest.DefaultPubSubConfig, + ChainExchange: manifest.DefaultChainExchangeConfig, } } diff --git a/itests/gateway_test.go b/itests/gateway_test.go index 16945d3ff66..80cfcecb9c4 100644 --- a/itests/gateway_test.go +++ b/itests/gateway_test.go @@ -18,6 +18,7 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-f3" "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" @@ -576,11 +577,11 @@ func TestGatewayF3(t *testing.T) { nodes := startNodes(ctx, t) cert, err := nodes.lite.F3GetLatestCertificate(ctx) - require.ErrorContains(t, err, "F3 is not running") + require.ErrorContains(t, err, f3.ErrF3NotRunning.Error()) require.Nil(t, cert) cert, err = nodes.lite.F3GetCertificate(ctx, 2) - require.ErrorContains(t, err, "F3 is not running") + require.ErrorContains(t, err, f3.ErrF3NotRunning.Error()) require.Nil(t, cert) }) diff --git a/node/modules/lp2p/pubsub.go b/node/modules/lp2p/pubsub.go index a8560a539ea..f8ea1839d98 100644 --- a/node/modules/lp2p/pubsub.go +++ b/node/modules/lp2p/pubsub.go @@ -369,14 +369,18 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) { if in.F3Config != nil { if in.F3Config.StaticManifest != nil { - f3TopicName := manifest.PubSubTopicFromNetworkName(in.F3Config.StaticManifest.NetworkName) - allowTopics = append(allowTopics, f3TopicName) + gpbftTopic := manifest.PubSubTopicFromNetworkName(in.F3Config.StaticManifest.NetworkName) + chainexTopic := manifest.ChainExchangeTopicFromNetworkName(in.F3Config.StaticManifest.NetworkName) + allowTopics = append(allowTopics, gpbftTopic, chainexTopic) } if in.F3Config.DynamicManifestProvider != "" { - f3BaseTopicName := manifest.PubSubTopicFromNetworkName(in.F3Config.BaseNetworkName) + gpbftTopicPrefix := manifest.PubSubTopicFromNetworkName(in.F3Config.BaseNetworkName) + chainexTopicPrefix := manifest.ChainExchangeTopicFromNetworkName(in.F3Config.BaseNetworkName) allowTopics = append(allowTopics, manifest.ManifestPubSubTopicName) - for i := 0; i < lf3.MaxDynamicManifestChangesAllowed; i++ { - allowTopics = append(allowTopics, fmt.Sprintf("%s/%d", f3BaseTopicName, i)) + for i := range lf3.MaxDynamicManifestChangesAllowed { + gpbftTopic := fmt.Sprintf("%s/%d", gpbftTopicPrefix, i) + chainexTopic := fmt.Sprintf("%s/%d", chainexTopicPrefix, i) + allowTopics = append(allowTopics, gpbftTopic, chainexTopic) } } }